Space Taxi is finally starting to look viable on the GS!
This commit is contained in:
parent
46baf7ad5f
commit
5adf55e80f
61 changed files with 11072 additions and 810 deletions
BIN
21_!.wav
Normal file
BIN
21_!.wav
Normal file
Binary file not shown.
BIN
31_1.wav
Normal file
BIN
31_1.wav
Normal file
Binary file not shown.
BIN
32_2.wav
Normal file
BIN
32_2.wav
Normal file
Binary file not shown.
BIN
33_3.wav
Normal file
BIN
33_3.wav
Normal file
Binary file not shown.
BIN
34_4.wav
Normal file
BIN
34_4.wav
Normal file
Binary file not shown.
BIN
35_5.wav
Normal file
BIN
35_5.wav
Normal file
Binary file not shown.
BIN
36_6.wav
Normal file
BIN
36_6.wav
Normal file
Binary file not shown.
BIN
37_7.wav
Normal file
BIN
37_7.wav
Normal file
Binary file not shown.
BIN
38_8.wav
Normal file
BIN
38_8.wav
Normal file
Binary file not shown.
BIN
39_9.wav
Normal file
BIN
39_9.wav
Normal file
Binary file not shown.
BIN
3F_x.wav
Normal file
BIN
3F_x.wav
Normal file
Binary file not shown.
BIN
48_H.wav
Normal file
BIN
48_H.wav
Normal file
Binary file not shown.
BIN
50_P.wav
Normal file
BIN
50_P.wav
Normal file
Binary file not shown.
BIN
54_T.wav
Normal file
BIN
54_T.wav
Normal file
Binary file not shown.
BIN
55_U.wav
Normal file
BIN
55_U.wav
Normal file
Binary file not shown.
BIN
assets/RawTitle.png
(Stored with Git LFS)
Normal file
BIN
assets/RawTitle.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/TitleShr.png
(Stored with Git LFS)
Normal file
BIN
assets/TitleShr.png
(Stored with Git LFS)
Normal file
Binary file not shown.
81
assets/depackSpeechRam.py
Executable file
81
assets/depackSpeechRam.py
Executable file
|
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Run Space Taxi's depacker to produce a FLAT 64K RAM image.
|
||||
|
||||
Why this exists: the disk's "SPACE TAXI+" is a crunched single file (it
|
||||
matches the running game's memory in 0.6% of bytes), so the speech
|
||||
samples cannot be read out of it statically. And a VICE memory dump is
|
||||
no good either -- it captures the banked-IN view, so $A000-$BFFF comes
|
||||
back as BASIC ROM and 13 of the 15 utterances are missing. Every
|
||||
mem0000*.bin in this tree has that problem.
|
||||
|
||||
The way out needs no emulator install: stuff/spacetaxi/cpu6502.py is a
|
||||
plain 6502 core over a flat 64K bytearray with no banking and no I/O,
|
||||
which is all a depacker needs. Load the .prg, run from the BASIC SYS
|
||||
entry, and the depacked image IS the RAM -- $A000-$BFFF included.
|
||||
|
||||
Feed the result to extractSpeech.py.
|
||||
|
||||
Usage: depackSpeechRam.py [spaceTaxiPlus.prg] [out.bin]
|
||||
Defaults resolve inside stuff/spacetaxi/ (gitignored research
|
||||
area, same as genC64Data.py's inputs).
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
STUFF = os.path.join(HERE, "..", "..", "..", "stuff", "spacetaxi")
|
||||
|
||||
# The BASIC stub is `0B08 D307 9E "2059" 00` -- SYS 2059.
|
||||
ENTRY = 0x080B
|
||||
MAX_STEPS = 60000000
|
||||
CHECK_MASK = 0xFFFF # how often to test for completion
|
||||
|
||||
# Completion test: the $9B00 index table is populated and the first
|
||||
# utterance's $FE lead-in is in place.
|
||||
TABLE_ADDR = 0x9B00
|
||||
FIRST_UTT = 0x9B40
|
||||
|
||||
|
||||
def main():
|
||||
prgPath = sys.argv[1] if len(sys.argv) > 1 else os.path.join(STUFF, "extract", "SPACE TAXI+.prg")
|
||||
outPath = sys.argv[2] if len(sys.argv) > 2 else os.path.join(STUFF, "staxi-ram.bin")
|
||||
|
||||
sys.path.insert(0, STUFF)
|
||||
try:
|
||||
from cpu6502 import Cpu6502
|
||||
except ImportError:
|
||||
sys.exit("depackSpeechRam: need cpu6502.py in %s" % STUFF)
|
||||
|
||||
prg = open(prgPath, "rb").read()
|
||||
load = prg[0] | (prg[1] << 8)
|
||||
ram = bytearray(65536)
|
||||
ram[load:load + len(prg) - 2] = prg[2:]
|
||||
print("loaded %s at $%04X..$%04X" % (os.path.basename(prgPath), load, load + len(prg) - 3))
|
||||
|
||||
cpu = Cpu6502(ram)
|
||||
cpu.pc = ENTRY
|
||||
steps = 0
|
||||
done = False
|
||||
try:
|
||||
while steps < MAX_STEPS:
|
||||
cpu.step()
|
||||
steps += 1
|
||||
if (steps & CHECK_MASK) == 0:
|
||||
if ram[TABLE_ADDR] != 0 and ram[FIRST_UTT] == 0xFE:
|
||||
done = True
|
||||
break
|
||||
except Exception as exc:
|
||||
# A depacker that runs off into I/O or an undocumented opcode
|
||||
# still usually gets the data down first, so report and carry on
|
||||
# to the write rather than throwing the work away.
|
||||
print("6502 stopped after %d steps at PC=$%04X: %s" % (steps, cpu.pc, exc))
|
||||
|
||||
open(outPath, "wb").write(bytes(ram))
|
||||
print("%d steps, depack %s -> %s" % (steps, "detected" if done else "NOT detected", outPath))
|
||||
if not done:
|
||||
print("WARNING: completion check never fired; the image may be partial.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
225
assets/extractSpeech.py
Executable file
225
assets/extractSpeech.py
Executable file
|
|
@ -0,0 +1,225 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Extract Space Taxi's digitised speech from a C64 memory dump.
|
||||
|
||||
FORMAT (reverse-engineered from bankedSfxLoad at $9802, see
|
||||
stuff/spacetaxi/live-level1.lst). It is NOT 4-bit $D418 digi and it is
|
||||
NOT the SID speech synth. It is 1-BIT RUN-LENGTH audio:
|
||||
|
||||
* An index table at $9B00 holds [code, ptrLo, ptrHi] triples,
|
||||
terminated by a zero code. `code` is the PETSCII character the game
|
||||
asks for -- 'H' 'T' '!' spell "Hey Taxi!", 'P' + digit + '?' spell
|
||||
"Pad two, please", 'U' is "up".
|
||||
* Each utterance is a byte stream. For every byte the player busy-waits
|
||||
that many passes of a fixed delay loop and then TOGGLES bit 0 of
|
||||
$D417, which flips voice 1 in and out of the filter -- a 1-bit
|
||||
speaker. So each byte is the length of one half-cycle.
|
||||
* $FE is a raster sync (the player waits on $D011), $FF ends the
|
||||
utterance.
|
||||
|
||||
The delay loop at $98A1..$98AA costs 27 cycles per pass and the
|
||||
toggle/advance/fetch tail ($98AC..$987F) another 33, hence CYCLES().
|
||||
|
||||
LIMITATION: a plain VICE memory dump captures the BANKED-IN view, so
|
||||
$A000-$BFFF comes back as BASIC ROM ("CBMBASIC" at $A004) and most of the
|
||||
speech is missing -- the player banks BASIC out ($01 = $06) precisely
|
||||
because the samples live in the RAM underneath. Dump it with the ROMs
|
||||
banked out, e.g. in the VICE monitor:
|
||||
|
||||
bank ram
|
||||
save "staxi-ram.bin" 0 0000 ffff
|
||||
|
||||
Usage: extractSpeech.py <dump.bin> [outDir]
|
||||
The dump may have a 2-byte load address or not; both are handled.
|
||||
"""
|
||||
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import wave
|
||||
|
||||
NTSC_HZ = 1022727.0 # the port already uses this (ST_SID_HZ_NUM)
|
||||
OUT_RATE = 22050
|
||||
TABLE_ADDR = 0x9B00
|
||||
END_MARK = 0xFF
|
||||
SYNC_MARK = 0xFE
|
||||
|
||||
|
||||
def cyclesFor(count):
|
||||
"""Half-cycle length in CPU cycles for one stream byte."""
|
||||
return 27 * count + 33
|
||||
|
||||
|
||||
def loadDump(path):
|
||||
"""Return a 64K-addressable bytes object from a dump with or without
|
||||
a load-address header."""
|
||||
raw = open(path, "rb").read()
|
||||
if len(raw) in (65538, 65536 + 2):
|
||||
return raw[2:]
|
||||
if len(raw) == 65536:
|
||||
return raw
|
||||
# Headerless dump starting at $0801 (what mem0801.prg turned out to be).
|
||||
pad = bytearray(65536)
|
||||
pad[0x0801:0x0801 + len(raw)] = raw[:65536 - 0x0801]
|
||||
return bytes(pad)
|
||||
|
||||
|
||||
def readTable(mem):
|
||||
"""[(code, pointer)] from the $9B00 index."""
|
||||
out = []
|
||||
y = 0
|
||||
while y < 0x300:
|
||||
code = mem[TABLE_ADDR + y]
|
||||
if code == 0 or code == 0xFF:
|
||||
break
|
||||
out.append((code, mem[TABLE_ADDR + y + 1] | (mem[TABLE_ADDR + y + 2] << 8)))
|
||||
y += 3
|
||||
return out
|
||||
|
||||
|
||||
def decode(mem, ptr, limit=0x4000):
|
||||
"""Return (runs, byteCount, sawEnd). runs is [(level, cycles)]."""
|
||||
runs = []
|
||||
level = 0
|
||||
addr = ptr
|
||||
while addr - ptr < limit:
|
||||
b = mem[addr]
|
||||
addr += 1
|
||||
if b == END_MARK:
|
||||
return runs, addr - ptr, True
|
||||
if b == SYNC_MARK:
|
||||
runs.append((level, int(NTSC_HZ / 60.0)))
|
||||
continue
|
||||
runs.append((level, cyclesFor(b)))
|
||||
level ^= 1
|
||||
return runs, addr - ptr, False
|
||||
|
||||
|
||||
def writeWav(runs, path):
|
||||
samples = bytearray()
|
||||
carry = 0.0
|
||||
perOut = NTSC_HZ / OUT_RATE
|
||||
for level, cyc in runs:
|
||||
carry += cyc
|
||||
n = int(carry / perOut)
|
||||
carry -= n * perOut
|
||||
samples += struct.pack("<h", 12000 if level else -12000) * n
|
||||
w = wave.open(path, "wb")
|
||||
w.setnchannels(1)
|
||||
w.setsampwidth(2)
|
||||
w.setframerate(OUT_RATE)
|
||||
w.writeframes(bytes(samples))
|
||||
w.close()
|
||||
return len(samples) // 2 / float(OUT_RATE)
|
||||
|
||||
|
||||
def emitC(mem, table, romLo, outDir):
|
||||
"""Write stSpeechData.c/.h: the raw run-length streams plus an index.
|
||||
|
||||
The streams ship as-is (about 7.4 KB for all 15) and the game expands
|
||||
them to PCM on the fly -- rendering them at bake time would be ~38 KB
|
||||
at 5 kHz, which will not fit an IIgs bank alongside everything else.
|
||||
"""
|
||||
blobs = []
|
||||
index = []
|
||||
for code, ptr in table:
|
||||
if ptr >= romLo:
|
||||
continue
|
||||
runs, nbytes, sawEnd = decode(mem, ptr)
|
||||
nxt = next((q for _, q in sorted(table, key=lambda e: e[1]) if q > ptr), None)
|
||||
if not sawEnd or (nxt is not None and nbytes > nxt - ptr):
|
||||
continue
|
||||
index.append((code, sum(len(b) for b in blobs), nbytes))
|
||||
blobs.append(bytes(mem[ptr:ptr + nbytes]))
|
||||
data = b"".join(blobs)
|
||||
|
||||
h = os.path.join(outDir, "stSpeechData.h")
|
||||
c = os.path.join(outDir, "stSpeechData.c")
|
||||
with open(h, "w") as fp:
|
||||
fp.write("// Generated by assets/extractSpeech.py. Do not hand-edit.\n"
|
||||
"//\n"
|
||||
"// Space Taxi's digitised speech as the C64 stores it: 1-bit\n"
|
||||
"// run-length streams. Each byte is one half-cycle length; the\n"
|
||||
"// player toggles its output after each. $FE is a raster sync\n"
|
||||
"// and $FF ends an utterance. stAudio.c expands these to PCM\n"
|
||||
"// through the jlAudioPlaySfxStream fill callback.\n\n"
|
||||
"#ifndef ST_SPEECH_DATA_H\n#define ST_SPEECH_DATA_H\n\n"
|
||||
"#include <stdint.h>\n\n"
|
||||
"typedef struct {\n"
|
||||
" uint8_t code; // PETSCII: 'H' 'T' '!' 'P' '1'..'9' '?' 'U'\n"
|
||||
" uint16_t offset; // into kStSpeechRle\n"
|
||||
" uint16_t length;\n"
|
||||
"} StSpeechEntryT;\n\n"
|
||||
"#define ST_SPEECH_COUNT %du\n"
|
||||
"#define ST_SPEECH_RLE_BYTES %du\n\n"
|
||||
"extern const StSpeechEntryT kStSpeechIndex[ST_SPEECH_COUNT];\n"
|
||||
"extern const uint8_t kStSpeechRle[ST_SPEECH_RLE_BYTES];\n\n"
|
||||
"#endif\n" % (len(index), len(data)))
|
||||
with open(c, "w") as fp:
|
||||
fp.write('// Generated by assets/extractSpeech.py. Do not hand-edit.\n\n'
|
||||
'#include "stSpeechData.h"\n\n'
|
||||
'const StSpeechEntryT kStSpeechIndex[ST_SPEECH_COUNT] = {\n')
|
||||
for code, off, ln in index:
|
||||
fp.write(" { 0x%02Xu, %5du, %5du }, // '%s'\n"
|
||||
% (code, off, ln, chr(code) if 33 <= code < 127 else "?"))
|
||||
fp.write("};\n\nconst uint8_t kStSpeechRle[ST_SPEECH_RLE_BYTES] = {\n")
|
||||
for i in range(0, len(data), 16):
|
||||
fp.write(" " + " ".join("0x%02X," % b for b in data[i:i + 16]) + "\n")
|
||||
fp.write("};\n")
|
||||
print("\nemitted %s (%d entries) and %s (%d bytes)" % (h, len(index), c, len(data)))
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit(__doc__)
|
||||
emit = "--c" in sys.argv
|
||||
args = [a for a in sys.argv[1:] if a != "--c"]
|
||||
mem = loadDump(args[0])
|
||||
outDir = args[1] if len(args) > 1 else "speech"
|
||||
os.makedirs(outDir, exist_ok=True)
|
||||
|
||||
if mem[0xA004:0xA00C] == b"CBMBASIC":
|
||||
sys.stderr.write("WARNING: $A000 holds BASIC ROM, not the RAM under it.\n"
|
||||
" Utterances at $A000 and above will not decode.\n"
|
||||
" Re-dump with `bank ram` (see the module docstring).\n\n")
|
||||
|
||||
table = readTable(mem)
|
||||
romLo = 0xA000 if mem[0xA004:0xA00C] == b"CBMBASIC" else 0x10000
|
||||
ordered = sorted(p for _, p in table)
|
||||
good = 0
|
||||
|
||||
print("%-4s %-6s %7s %7s %s" % ("code", "ptr", "bytes", "dur(s)", "file"))
|
||||
for code, ptr in table:
|
||||
label = chr(code) if 33 <= code < 127 else "?"
|
||||
# Utterances are stored back to back, so the next pointer is the
|
||||
# expected end. Both checks matter: BASIC ROM is full of $FF, so
|
||||
# "found a terminator" alone happily reports success on garbage --
|
||||
# it claimed all 15 decoded from a ROM-shadowed dump.
|
||||
nxt = next((q for q in ordered if q > ptr), None)
|
||||
expected = (nxt - ptr) if nxt else None
|
||||
if ptr >= romLo:
|
||||
print("%-4s $%04X %7s %7s -- SKIPPED (shadowed by BASIC ROM in this dump)"
|
||||
% (label, ptr, "-", "-"))
|
||||
continue
|
||||
runs, nbytes, sawEnd = decode(mem, ptr)
|
||||
if not sawEnd:
|
||||
print("%-4s $%04X %7d %7s -- SKIPPED (no $FF terminator)" % (label, ptr, nbytes, "-"))
|
||||
continue
|
||||
# The terminator must land BEFORE the next utterance starts.
|
||||
# (Entries are back to back but may carry a pad byte, so this is
|
||||
# <= rather than ==.) Overrunning means the $FF we found was not
|
||||
# ours -- which is exactly what happens against a ROM shadow.
|
||||
if expected is not None and nbytes > expected:
|
||||
print("%-4s $%04X %7d %7s -- SKIPPED (ran %d bytes, next entry is %d away)"
|
||||
% (label, ptr, nbytes, "-", nbytes, expected))
|
||||
continue
|
||||
path = os.path.join(outDir, "%02X_%s.wav" % (code, label if label != "?" else "x"))
|
||||
dur = writeWav(runs, path)
|
||||
good += 1
|
||||
print("%-4s $%04X %7d %7.2f %s" % (label, ptr, nbytes, dur, os.path.basename(path)))
|
||||
print("\n%d of %d utterances decoded into %s" % (good, len(table), outDir))
|
||||
if emit:
|
||||
emitC(mem, table, romLo, outDir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -55,6 +55,21 @@ def c_bytes(data, per_line=16, indent=" "):
|
|||
return "\n".join(lines)
|
||||
|
||||
|
||||
# The cross-segment accessors the IIgs needs (see the block this emits
|
||||
# into stC64Data.c). These used to be hand-added to the GENERATED file,
|
||||
# which meant re-running this script silently deleted them and broke the
|
||||
# IIgs build -- the header kept declaring them and nothing defined them.
|
||||
# Prototype and return expression per accessor; the header prints the
|
||||
# prototypes aligned, so keep the spacing.
|
||||
ACCESSORS = [
|
||||
("const uint8_t *stC64Charset(void);", "&kStCharset[0][0]"),
|
||||
("const uint8_t *stC64SpriteBitmap(uint8_t idx);", "kStSpriteBitmaps[idx]"),
|
||||
("uint8_t stC64RngByte(uint8_t idx);", "kStRngTable[idx]"),
|
||||
("const uint8_t *stC64SfxProgram(uint8_t idx);", "kStSfxPrograms[idx]"),
|
||||
("uint8_t stC64FlameCel(uint8_t dirMask);", "kStFlameCelByDirMask[dirMask]"),
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
raw = load_raw()
|
||||
sprite_count = SPRITE_PTR_LAST - SPRITE_PTR_FIRST + 1
|
||||
|
|
@ -100,9 +115,11 @@ def main():
|
|||
h.append("// 8=RIGHT); 0 = no cel for that combination.")
|
||||
h.append("extern const uint8_t kStFlameCelByDirMask[16];")
|
||||
h.append("")
|
||||
h.append("// Level-intro star velocities per sprite 0..6 ($450C / $4513).")
|
||||
h.append("extern const int8_t kStIntroStarDx[7];")
|
||||
h.append("extern const int8_t kStIntroStarDy[7];")
|
||||
h.append("// Cross-segment-safe accessors (see stC64Data.c): reach the tables above")
|
||||
h.append("// by an inter-segment call on the IIgs, where a direct 2-byte data")
|
||||
h.append("// reference from another bank is not relocatable.")
|
||||
for decl in ACCESSORS:
|
||||
h.append(decl[0])
|
||||
h.append("")
|
||||
h.append("#endif")
|
||||
|
||||
|
|
@ -143,11 +160,25 @@ def main():
|
|||
c.append(c_bytes(flame))
|
||||
c.append("};")
|
||||
c.append("")
|
||||
dx = [b - 256 if b >= 128 else b for b in raw[0x450C:0x450C + 7]]
|
||||
dy = [b - 256 if b >= 128 else b for b in raw[0x4513:0x4513 + 7]]
|
||||
c.append("const int8_t kStIntroStarDx[7] = { " + ", ".join(str(v) for v in dx) + " };")
|
||||
c.append("const int8_t kStIntroStarDy[7] = { " + ", ".join(str(v) for v in dy) + " };")
|
||||
c.append("")
|
||||
c.append("// ---------------------------------------------------------------------------")
|
||||
c.append("// Accessors. On the IIgs the program is split across banks and a 2-byte")
|
||||
c.append("// data reference cannot cross a segment (only a 3-byte JSL/JML can). These")
|
||||
c.append("// tiny functions live in the same segment as the tables, so their reads")
|
||||
c.append("// are intra-segment; callers in other segments reach them by a supported")
|
||||
c.append("// inter-segment call. On the other ports they inline away to nothing.")
|
||||
c.append("// ---------------------------------------------------------------------------")
|
||||
first = True
|
||||
for decl, body in ACCESSORS:
|
||||
c.append("")
|
||||
if not first:
|
||||
c.append("")
|
||||
first = False
|
||||
# The header pads return types to align its prototypes; the
|
||||
# definitions here must not inherit that padding.
|
||||
c.append(" ".join(decl[:-1].split()) + " {")
|
||||
c.append(" return " + body + ";")
|
||||
c.append("}")
|
||||
|
||||
with open(OUT_H, "w", encoding="ascii") as fp:
|
||||
fp.write("\n".join(h) + "\n")
|
||||
|
|
|
|||
76
assets/genSongData.py
Normal file
76
assets/genSongData.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#!/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))
|
||||
106
assets/genSpeechPcm.py
Executable file
106
assets/genSpeechPcm.py
Executable file
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/env python3
|
||||
"""genSpeechPcm.py - bake Space Taxi's speech to 8-bit PCM.
|
||||
Reads the C64 run-length speech streams from stSpeechData.c (the output
|
||||
of extractSpeech.py) and writes speech.bin: every utterance decoded to
|
||||
5 kHz sample bytes for each passenger pitch the game can select, in BOTH
|
||||
polarities. The decode is the exact algorithm stAudio.c used to run per
|
||||
sample at play time; on the 65816 that took 2.4 s of CPU per second of
|
||||
speech (three run bytes per sample, each a multiply) and stalled the ride
|
||||
for half a second on every "HEY TAXI". A 1-bit intermediate format came
|
||||
next, but expanding bits still needed a per-byte loop (and an asm copy of
|
||||
it on the IIgs); with sample bytes the player is a block copy.
|
||||
Polarity: an utterance is decoded from a +100 start. The C64 keeps the
|
||||
output level running from one utterance into the next, so a phrase whose
|
||||
first word ends on the low level plays its second word inverted. Both
|
||||
versions are stored and the player picks by the running parity.
|
||||
speech.bin (little-endian):
|
||||
"STSP" u8 version(2) u8 pitchBase u8 pitchCount u8 count
|
||||
u8 format (0 = signed +/-100, 1 = 0x80-biased for the IIgs raw stream)
|
||||
u8 pad[3] u32 dataBytes
|
||||
entries[pitchCount * count * 2]: u8 code, u8 parity, u16 samples,
|
||||
u32 offset -- polarity is the innermost index (0 = as decoded,
|
||||
1 = inverted). parity = 1 when the utterance ends on the
|
||||
opposite level from the one it started on.
|
||||
data: sample bytes
|
||||
usage: genSpeechPcm.py stSpeechData.c speech.bin [--biased]
|
||||
"""
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
|
||||
SID_HZ = 1022727 # ST_SID_HZ_NUM
|
||||
RATE = 5000 # ST_SPEECH_RATE
|
||||
CYC_PER_SAMPLE = SID_HZ // RATE
|
||||
SYNC_CYCLES = SID_HZ // 60 // 8
|
||||
CYCLE_TAIL = 33
|
||||
SYNC = 0xFE
|
||||
END = 0xFF
|
||||
PITCH_BASE = 2 # stFare.c: stAudioSpeech(rng(3) + 2)
|
||||
PITCH_COUNT = 3
|
||||
|
||||
|
||||
def parseSource(path):
|
||||
text = open(path).read()
|
||||
idx = re.search(r"kStSpeechIndex\[[^\]]*\]\s*=\s*\{(.*?)\};", text, re.S).group(1)
|
||||
entries = [(int(c, 16), int(o), int(n)) for c, o, n in
|
||||
re.findall(r"\{\s*0x([0-9A-Fa-f]+)u,\s*(\d+)u,\s*(\d+)u\s*\}", idx)]
|
||||
rle = re.search(r"kStSpeechRle\[[^\]]*\]\s*=\s*\{(.*?)\};", text, re.S).group(1)
|
||||
data = bytes(int(x, 16) for x in re.findall(r"0x([0-9A-Fa-f]{2})", rle))
|
||||
return entries, data
|
||||
|
||||
|
||||
def decode(rle, perOn):
|
||||
"""speechDecode() for one utterance from a +100 start, remain 0."""
|
||||
remain = 0
|
||||
level = 100
|
||||
out = []
|
||||
i = 0
|
||||
n = len(rle)
|
||||
while True:
|
||||
while remain <= 0:
|
||||
if i >= n:
|
||||
return out, level
|
||||
b = rle[i]
|
||||
i += 1
|
||||
if b == END:
|
||||
i = n
|
||||
continue
|
||||
if b == SYNC:
|
||||
remain += SYNC_CYCLES
|
||||
continue
|
||||
remain += perOn * b + CYCLE_TAIL
|
||||
level = -100 if level > 0 else 100
|
||||
out.append(level)
|
||||
remain -= CYC_PER_SAMPLE
|
||||
|
||||
|
||||
def main():
|
||||
args = [a for a in sys.argv[1:] if not a.startswith("--")]
|
||||
biased = "--biased" in sys.argv[1:]
|
||||
src, dst = args[0], args[1]
|
||||
entries, data = parseSource(src)
|
||||
records = []
|
||||
blob = bytearray()
|
||||
for p in range(PITCH_COUNT):
|
||||
perOn = 5 * (PITCH_BASE + p) + 12
|
||||
for code, off, length in entries:
|
||||
samples, level = decode(data[off:off + length], perOn)
|
||||
parity = 1 if level < 0 else 0
|
||||
for pol in range(2):
|
||||
pcm = bytearray()
|
||||
for s in samples:
|
||||
v = -s if pol else s
|
||||
pcm.append((v + 0x80) & 0xFF if biased else v & 0xFF)
|
||||
records.append((code, parity, len(samples), len(blob)))
|
||||
blob += pcm
|
||||
with open(dst, "wb") as f:
|
||||
f.write(b"STSP" + struct.pack("<BBBBBBBBI", 2, PITCH_BASE, PITCH_COUNT, len(entries), 1 if biased else 0, 0, 0, 0, len(blob)))
|
||||
for code, parity, n, off in records:
|
||||
f.write(struct.pack("<BBHI", code, parity, n, off))
|
||||
f.write(blob)
|
||||
total = sum(n for _, _, n, _ in records)
|
||||
print(f"{dst}: {len(entries)} utterances x {PITCH_COUNT} pitches x 2 polarities, {total} samples, {len(blob)} data bytes, {'biased' if biased else 'signed'}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
57
assets/sidCapture.py
Normal file
57
assets/sidCapture.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Run the C64 Space Taxi music player and log every SID write per frame.
|
||||
|
||||
The player lives in the TITLE memory image at $CB00-$CFFF (its own relocated
|
||||
copy; the $7500 copy is gameplay-side). Rather than hand-decode its byte
|
||||
code, drive the real routines under cpu6502.py -- the same trick that
|
||||
extracted the speech:
|
||||
$CB00 select song ($CB01 = song number) and init (hooks the IRQ vector)
|
||||
$CF52 the IRQ body: first frame calls start ($CC28), then ticks the three
|
||||
voices via $CC6C, then JMPs to the KERNAL IRQ ($EA31) which is what
|
||||
advances the jiffy clock $A2. We poke an RTS at $EA31 and bump $A2
|
||||
ourselves, once per frame.
|
||||
A song is over when all three voice stream pointers' high bytes are zero
|
||||
(that is exactly what the game's play-and-wait loop at $44D5 spins on).
|
||||
"""
|
||||
import json, sys
|
||||
sys.path.insert(0, "/home/scott/claude/joeylib/stuff/spacetaxi")
|
||||
from cpu6502 import Cpu6502
|
||||
|
||||
RAM = bytearray(open(sys.argv[1], "rb").read()[:65536])
|
||||
OUT = sys.argv[2]
|
||||
MAX_FRAMES = 4000
|
||||
|
||||
|
||||
class SidTrap(Cpu6502):
|
||||
def __init__(self, ram):
|
||||
super().__init__(ram)
|
||||
self.log = []
|
||||
self.frame = 0
|
||||
|
||||
def write8(self, addr, val):
|
||||
a = addr & 0xFFFF
|
||||
if 0xD400 <= a <= 0xD418:
|
||||
self.log.append((self.frame, a - 0xD400, val & 0xFF))
|
||||
super().write8(addr, val)
|
||||
|
||||
|
||||
songs = {}
|
||||
for song in range(0, 9):
|
||||
ram = bytearray(RAM)
|
||||
ram[0xEA31] = 0x60 # KERNAL IRQ tail -> RTS
|
||||
cpu = SidTrap(ram)
|
||||
cpu.call(0xCC00) # full reset first
|
||||
ram[0xCB01] = song
|
||||
cpu.call(0xCB00) # select + arm
|
||||
for frame in range(MAX_FRAMES):
|
||||
cpu.frame = frame
|
||||
ram[0xA2] = (ram[0xA2] + 1) & 0xFF
|
||||
cpu.call(0xCF52)
|
||||
if ram[0xCB81] == 0 and ram[0xCB88] == 0 and ram[0xCB8F] == 0:
|
||||
break
|
||||
songs[song] = {"frames": frame + 1, "writes": cpu.log,
|
||||
"ptr": ram[0xCB40 + song * 2] | (ram[0xCB41 + song * 2] << 8)}
|
||||
print(f"song {song}: ptr=${songs[song]['ptr']:04X} frames={frame+1} "
|
||||
f"({(frame+1)/50:.1f}s PAL) sidWrites={len(cpu.log)}")
|
||||
|
||||
json.dump(songs, open(OUT, "w"))
|
||||
111
assets/sidToSong.py
Normal file
111
assets/sidToSong.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/env python3
|
||||
"""SID register log (sidCapture.py) -> JoeyLib .song text for songbake.
|
||||
|
||||
One row per PAL frame (tickms 20). Per voice, a note-on is a gate rising
|
||||
edge or a pitch change while gated; gate falling is 'off'. SID frequency ->
|
||||
Hz exactly (@Hz cells), so no equal-temperament rounding. Attenuation comes
|
||||
from the sustain nibble. A voice whose waveform is NOISE goes to the noise
|
||||
column instead of a tone column, with a pitch scaled from its frequency.
|
||||
Loop detection: the player is deterministic, so once the (frame-relative)
|
||||
event rows repeat with a fixed period, that period is the loop.
|
||||
"""
|
||||
import json, sys
|
||||
|
||||
PAL_CLOCK = 985248.0
|
||||
songs = json.load(open(sys.argv[1]))
|
||||
outDir = sys.argv[2]
|
||||
|
||||
|
||||
def sidHz(lo, hi):
|
||||
return ((hi << 8) | lo) * PAL_CLOCK / 16777216.0
|
||||
|
||||
|
||||
def rowsFor(writes, nframes):
|
||||
# replay register writes frame by frame, producing per-frame voice state
|
||||
regs = [0] * 0x19
|
||||
state = []
|
||||
byFrame = {}
|
||||
for f, r, v in writes:
|
||||
byFrame.setdefault(f, []).append((r, v))
|
||||
for f in range(nframes):
|
||||
for r, v in byFrame.get(f, []):
|
||||
regs[r] = v
|
||||
vs = []
|
||||
for vc in range(3):
|
||||
b = vc * 7
|
||||
vs.append(dict(hz=sidHz(regs[b], regs[b + 1]), gate=regs[b + 4] & 1,
|
||||
wave=regs[b + 4] & 0xF0, sus=regs[b + 6] >> 4))
|
||||
state.append(vs)
|
||||
return state
|
||||
|
||||
|
||||
def atten(sus):
|
||||
# SID sustain 0..15 -> AGI attenuation 14..0 (0 loudest)
|
||||
return max(0, min(14, round(14 - sus * 14 / 15)))
|
||||
|
||||
|
||||
def noisePitch(hz):
|
||||
# brighter hiss for higher SID "frequency"; 0..31, 0 = brightest
|
||||
p = int(31 - min(31, hz / 400.0))
|
||||
return max(0, min(31, p))
|
||||
|
||||
|
||||
def toRows(state):
|
||||
rows = []
|
||||
prev = [dict(hz=None, gate=0, wave=0, sus=0) for _ in range(3)]
|
||||
for vs in state:
|
||||
tone = ["---", "---", "---"]
|
||||
noise = "---"
|
||||
for vc in range(3):
|
||||
cur, was = vs[vc], prev[vc]
|
||||
isNoise = (cur["wave"] & 0x80) != 0
|
||||
on = cur["gate"] and (not was["gate"] or abs(cur["hz"] - was["hz"]) > 0.5
|
||||
or cur["wave"] != was["wave"])
|
||||
off = was["gate"] and not cur["gate"]
|
||||
if on:
|
||||
if isNoise:
|
||||
noise = f"N{noisePitch(cur['hz'])}:{atten(cur['sus'])}"
|
||||
else:
|
||||
hz = max(1, min(65535, int(round(cur["hz"]))))
|
||||
tone[vc] = f"@{hz}:{atten(cur['sus'])}"
|
||||
elif off:
|
||||
if (was["wave"] & 0x80):
|
||||
noise = "off"
|
||||
else:
|
||||
tone[vc] = "off"
|
||||
prev[vc] = dict(cur)
|
||||
rows.append((tone, noise))
|
||||
return rows
|
||||
|
||||
|
||||
def findLoop(rows):
|
||||
# smallest (offset, period) with rows[o+k] == rows[o+p+k] for the tail
|
||||
n = len(rows)
|
||||
for p in range(8, n // 2):
|
||||
for o in range(0, n - 2 * p):
|
||||
if rows[o:o + p] == rows[o + p:o + 2 * p] and rows[o:n - p] == rows[o + p:n]:
|
||||
return o, p
|
||||
return None
|
||||
|
||||
|
||||
for num, s in sorted(songs.items(), key=lambda kv: int(kv[0])):
|
||||
num = int(num)
|
||||
st = rowsFor(s["writes"], s["frames"])
|
||||
rows = toRows(st)
|
||||
loop = findLoop(rows) if s["frames"] >= 4000 else None
|
||||
if loop:
|
||||
o, p = loop
|
||||
rows = rows[:o + p]
|
||||
lines = ["; Space Taxi (C64) song %d, extracted by running the game's own" % num,
|
||||
"; player ($CB00/$CF52) under cpu6502.py and logging SID writes.",
|
||||
"; One row = one PAL frame.", "tickms 20"]
|
||||
for i, (tone, noise) in enumerate(rows):
|
||||
if loop and i == loop[0]:
|
||||
lines.append("loop")
|
||||
cells = tone + ([noise] if noise != "---" or True else [])
|
||||
lines.append(" ".join(cells))
|
||||
open(f"{outDir}/song{num}.song", "w").write("\n".join(lines) + "\n")
|
||||
events = sum(1 for t, n in rows for c in t + [n] if c != "---")
|
||||
waves = sorted({hex(v["wave"]) for vs in st for v in vs if v["gate"]})
|
||||
print(f"song {num}: {len(rows)} rows, {events} events, waveforms {waves}"
|
||||
+ (f", LOOP at row {loop[0]} period {loop[1]}" if loop else ""))
|
||||
94
assets/songs/song0.song
Normal file
94
assets/songs/song0.song
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
; Space Taxi (C64) song 0, extracted by running the game's own
|
||||
; player ($CB00/$CF52) under cpu6502.py and logging SID writes.
|
||||
; One row = one PAL frame.
|
||||
tickms 20
|
||||
--- --- --- ---
|
||||
@336:2 @424:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:2 @424:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@336:2 @424:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:2 @476:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@318:2 @252:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@283:2 @252:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@252:2 @252:2 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
94
assets/songs/song1.song
Normal file
94
assets/songs/song1.song
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
; Space Taxi (C64) song 1, extracted by running the game's own
|
||||
; player ($CB00/$CF52) under cpu6502.py and logging SID writes.
|
||||
; One row = one PAL frame.
|
||||
tickms 20
|
||||
--- --- --- ---
|
||||
@252:7 @159:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@283:7 @168:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@252:7 @189:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@283:7 @212:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@318:7 @189:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@336:7 @168:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@318:7 @159:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@336:7 @168:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@378:7 @189:7 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
86
assets/songs/song2.song
Normal file
86
assets/songs/song2.song
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
; Space Taxi (C64) song 2, extracted by running the game's own
|
||||
; player ($CB00/$CF52) under cpu6502.py and logging SID writes.
|
||||
; One row = one PAL frame.
|
||||
tickms 20
|
||||
--- --- --- ---
|
||||
@126:0 @159:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
@126:0 @168:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
@141:0 @189:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
@159:0 @159:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
@159:0 @168:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
@168:0 @189:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
@168:0 @159:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
@189:0 @168:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- @159:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @126:0 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
86
assets/songs/song3.song
Normal file
86
assets/songs/song3.song
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
; Space Taxi (C64) song 3, extracted by running the game's own
|
||||
; player ($CB00/$CF52) under cpu6502.py and logging SID writes.
|
||||
; One row = one PAL frame.
|
||||
tickms 20
|
||||
--- --- --- ---
|
||||
@252:0 @336:2 @336:2 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off off ---
|
||||
--- --- --- ---
|
||||
@283:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
@318:0 @336:2 @336:2 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off off ---
|
||||
--- --- --- ---
|
||||
@252:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
@283:0 @336:2 @336:2 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off off ---
|
||||
--- --- --- ---
|
||||
@252:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
@283:0 @336:2 @336:2 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off off ---
|
||||
--- --- --- ---
|
||||
@476:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- @318:2 @378:2 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @336:2 @378:2 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @283:2 @252:2 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @252:2 @476:2 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
126
assets/songs/song4.song
Normal file
126
assets/songs/song4.song
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
; Space Taxi (C64) song 4, extracted by running the game's own
|
||||
; player ($CB00/$CF52) under cpu6502.py and logging SID writes.
|
||||
; One row = one PAL frame.
|
||||
tickms 20
|
||||
--- --- --- ---
|
||||
@504:5 @449:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@504:5 @449:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@673:5 @504:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@504:5 @424:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@673:5 @504:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
@848:5 @673:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @635:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @673:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
736
assets/songs/song5.song
Normal file
736
assets/songs/song5.song
Normal file
|
|
@ -0,0 +1,736 @@
|
|||
; Space Taxi (C64) song 5, extracted by running the game's own
|
||||
; player ($CB00/$CF52) under cpu6502.py and logging SID writes.
|
||||
; One row = one PAL frame.
|
||||
tickms 20
|
||||
--- --- --- ---
|
||||
@504:2 @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
off --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@504:2 @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
off --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@504:2 @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @159:2 @106:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
off --- --- ---
|
||||
--- --- @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@566:2 @141:2 @100:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
off --- --- ---
|
||||
--- --- @200:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@566:2 @141:2 @100:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @200:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @141:2 @100:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @200:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @141:2 @100:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- @200:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- @141:2 @100:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
off --- --- ---
|
||||
--- --- @200:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@635:2 @504:2 @94:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @94:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@673:2 @566:2 @84:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- @168:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @84:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @168:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@755:2 @635:2 @79:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- @159:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @79:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @159:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@800:2 @635:2 @71:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- @141:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @71:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @141:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@848:2 @635:2 @67:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @133:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @67:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @133:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @67:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @133:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @67:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @133:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@424:2 @318:2 @67:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- @133:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@848:2 @336:2 @252:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@848:2 @336:2 @252:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@848:2 @336:2 @252:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@755:2 @318:2 @225:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@755:2 @318:2 @225:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@673:2 @283:2 @212:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@635:2 @252:2 @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@566:2 @283:2 @168:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@755:2 @318:2 @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@635:2 --- @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@504:2 --- @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@635:2 --- @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@755:2 @283:2 @119:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @119:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@848:2 --- @119:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @119:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@755:2 --- @119:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@673:2 --- @119:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@635:2 --- @119:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@566:2 --- @119:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- @189:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
@504:2 @318:2 @126:10 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
840
assets/songs/song6.song
Normal file
840
assets/songs/song6.song
Normal file
|
|
@ -0,0 +1,840 @@
|
|||
; Space Taxi (C64) song 6, extracted by running the game's own
|
||||
; player ($CB00/$CF52) under cpu6502.py and logging SID writes.
|
||||
; One row = one PAL frame.
|
||||
tickms 20
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@94:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@126:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@159:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@189:0 @336:1 @449:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @300:1 @400:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @336:1 @449:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@212:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@189:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@159:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@141:0 @424:1 @566:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @378:1 @504:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @424:1 @566:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@119:0 @476:1 @635:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:1 @635:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:1 @635:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:1 @635:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@59:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:1 @635:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:1 @635:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:1 @635:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @424:1 @566:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @476:1 @635:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@126:0 @504:1 @673:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @504:1 @673:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @504:1 @673:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @504:1 @673:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@63:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @504:1 @673:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off @504:1 @673:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@126:0 @566:1 @755:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @504:1 @673:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @566:1 @755:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@141:0 @635:1 @848:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@71:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @635:1 @848:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off @635:1 @848:1 ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@141:0 @566:1 @848:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @566:1 @848:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @566:1 @848:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- off off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@159:0 @534:1 @848:1 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- off ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
852
assets/songs/song7.song
Normal file
852
assets/songs/song7.song
Normal file
|
|
@ -0,0 +1,852 @@
|
|||
; Space Taxi (C64) song 7, extracted by running the game's own
|
||||
; player ($CB00/$CF52) under cpu6502.py and logging SID writes.
|
||||
; One row = one PAL frame.
|
||||
tickms 20
|
||||
--- --- --- ---
|
||||
@378:0 @1270:5 @126:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1346:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- @1132:5 @119:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1346:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@252:0 @1270:5 @106:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1346:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@283:0 @1008:5 @94:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@318:0 --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@336:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1008:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:0 --- @126:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @952:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @848:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @755:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1132:5 @119:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1346:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 @126:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@424:0 @1132:5 @94:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
@378:0 --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@336:0 @1132:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:0 @1270:5 @126:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@336:0 @952:5 @119:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
@318:0 --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@283:0 @952:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@318:0 @1008:5 @106:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@283:0 @755:5 @94:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
@252:0 --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@238:0 @755:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
@252:0 @1008:5 @126:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @952:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@318:0 @1008:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
@189:0 @1132:5 @119:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1008:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1132:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 @106:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1132:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@238:0 @1346:5 @94:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@252:0 @1270:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@283:0 @1346:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
@252:0 @1270:5 @126:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@238:0 @1510:5 @119:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@252:0 --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@283:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@318:0 --- @106:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@283:0 @1510:5 @94:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
@283:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:0 @1132:5 @141:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1008:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @952:5 @119:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1008:5 off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1132:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @755:5 @106:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:0 @1132:5 --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:0 --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:0 @1199:5 @94:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:0 --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
@378:0 --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
@378:0 @1270:5 @126:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @94:7 ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @126:7 ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- @94:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1510:5 --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- @1270:5 --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- @126:7 ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- off --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
off --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- off ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
--- --- --- ---
|
||||
1508
assets/songs/song8.song
Normal file
1508
assets/songs/song8.song
Normal file
File diff suppressed because it is too large
Load diff
479
spacetaxi.c
479
spacetaxi.c
|
|
@ -19,27 +19,20 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "spacetaxi.h"
|
||||
#include "stDemoStreams.h"
|
||||
#include <joey/file.h>
|
||||
|
||||
// Diagnostics. The logger drags in vsnprintf (with newlib that pulls the
|
||||
// whole formatted-output and float-conversion family, ~45 KB) plus a
|
||||
// multi-KB ring buffer, and the game has no need of either. That is
|
||||
// unaffordable on the IIgs, whose bank-0 BSS budget cannot spare the
|
||||
// ring, and on the X68000, which ships on a Human68k floppy with about
|
||||
// 330 KB of usable space for the binary AND its levels. Both compile it
|
||||
// out; the ports with room keep it.
|
||||
#if defined(__W65816__) || defined(JOEYLIB_PLATFORM_X68000)
|
||||
#define ST_LOG_RESET() ((void)0)
|
||||
#define ST_LOG(...) ((void)0)
|
||||
#else
|
||||
#define ST_LOG_RESET() jlLogReset()
|
||||
#define ST_LOG(...) jlLogF(__VA_ARGS__)
|
||||
#endif
|
||||
#include "spacetaxi.h"
|
||||
#include "stSongData.h"
|
||||
#include "stDemoStreams.h"
|
||||
|
||||
#define ST_TICK_HZ 30u
|
||||
#define ST_MAX_CATCHUP_TICKS 4u
|
||||
#define ST_LEVEL_COUNT 24u
|
||||
// Screens A..X, then screen Y -- the 25th, " MYSTERY SCREEN !!! " -- which
|
||||
// $5167 loads once the 24-hour shifts have cleared all of A..X. Files are
|
||||
// levels/level01.dat .. level25.dat, so Y is index 24.
|
||||
#define ST_LEVEL_COUNT 24u // A..X, the screens a shift sweeps
|
||||
#define ST_SCREEN_Y 24u // the 25th screen ($5171 LDA #$59)
|
||||
#define ST_LEVEL_FILES 25u // level01.dat .. level25.dat
|
||||
// "GET READY" shows over the old screen while the C64 cycles the
|
||||
// leaving-passenger sprites (three busy waits, about half a second).
|
||||
#define ST_GET_READY_TICKS 15u
|
||||
|
|
@ -48,6 +41,18 @@
|
|||
// Menu joystick repeat delay ($4101 with X = $82).
|
||||
#define ST_MENU_REPEAT_TICKS 8u
|
||||
|
||||
// The immortal cabbies ($4A89 image, $4E35 screen).
|
||||
#define ST_HS_ENTRIES 10u
|
||||
#define ST_HS_NAME_CHARS 15u
|
||||
#define ST_HS_ENTRY_BYTES 24u // score[7] 0 name[15] shift
|
||||
#define ST_HS_POINT_AT 4u // "dddd.dd"
|
||||
#define ST_HS_GREET_DIGIT_AT 23u // "CONGRATULATIONS CABBIE n,"
|
||||
#define ST_HS_NAME_COL 12u // $0664: row 15, column 12
|
||||
#define ST_HS_NAME_ROW 15u
|
||||
#define ST_HS_CURSOR '%' // $4F4D flips it against blank
|
||||
#define ST_HS_BLINK_TICKS 3u // $4101 x $1E between flips, ~55 ms
|
||||
#define ST_HS_SAVE_NAME "IMMORTAL"
|
||||
|
||||
typedef enum {
|
||||
ST_STATE_TITLE = 0,
|
||||
ST_STATE_HIGHSCORES,
|
||||
|
|
@ -57,7 +62,9 @@ typedef enum {
|
|||
ST_STATE_GET_READY,
|
||||
ST_STATE_INTRO,
|
||||
ST_STATE_PLAYING,
|
||||
ST_STATE_GAME_OVER
|
||||
ST_STATE_GAME_OVER,
|
||||
ST_STATE_JINGLE, // a $44CF tune sounding; sim frozen until it ends
|
||||
ST_STATE_NAME_ENTRY // $4E35: a top-ten cabbie types a name
|
||||
} StStateE;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -73,8 +80,39 @@ typedef struct {
|
|||
bool fireArmed; // $445D: FIRE must be released first
|
||||
uint8_t lastFrame;
|
||||
uint16_t paceAcc;
|
||||
StStateE afterJingle; // where ST_STATE_JINGLE returns to
|
||||
bool gameOverTune; // $5C24: song 5 started after the wait
|
||||
uint8_t hsSlot; // $4D51 table slot being named
|
||||
uint8_t hsLen; // $4D2C characters typed
|
||||
uint8_t hsCursor; // $4F4D the blinking cursor's current glyph
|
||||
uint8_t hsBlinkTicks; // ticks toward the next cursor flip
|
||||
bool paused; // $4FCB: SHIFT is holding the game
|
||||
} StGameT;
|
||||
|
||||
// The immortal cabbies ($4A89): ten entries of a right-aligned "dddd.dd"
|
||||
// score, a name of up to fifteen letters and the shift it was earned on.
|
||||
// The C64 keeps this table on its own disk (the $9948 IEC routines load
|
||||
// it at boot and save it after every entry); the port keeps the same
|
||||
// 240-byte image in a save file. Shipped contents as the dump has them.
|
||||
typedef struct {
|
||||
uint8_t score[ST_NUMBER_CHARS + 1u]; // ASCII, NUL-terminated
|
||||
uint8_t name[ST_HS_NAME_CHARS + 1u]; // ASCII, space-padded, NUL-terminated
|
||||
uint8_t shift; // 1..5
|
||||
} StHighScoreT;
|
||||
|
||||
static StHighScoreT gHighScores[ST_HS_ENTRIES] = {
|
||||
{ "3877.56", "MICHAEL PLATE ", 4u },
|
||||
{ "1809.51", "MICHAEL PLATE ", 2u },
|
||||
{ "1179.87", "ANDREAS PLATE ", 4u },
|
||||
{ " 892.65", "MICHAEL PLATE ", 1u },
|
||||
{ " 685.37", "ANDREAS PLATE ", 1u },
|
||||
{ " 629.45", "MICHAEL PLATE ", 4u },
|
||||
{ " 569.50", "MICHAEL PLATE ", 1u },
|
||||
{ " 504.97", "ANDREAS PLATE ", 2u },
|
||||
{ " 498.77", "ANDREAS PLATE ", 5u },
|
||||
{ " 490.85", "ANDREAS PLATE ", 2u },
|
||||
};
|
||||
|
||||
// Menu texts ($5347..$545D) in screen codes.
|
||||
static const uint8_t kTextGameVariations[] = "GAME VARIATIONS";
|
||||
static const uint8_t kTextCabbies[] = "SELECT NUMBER OF CABBIES:";
|
||||
|
|
@ -94,18 +132,14 @@ static const uint8_t kTextGetReady[] = " GET READY FOR A RIDE ";
|
|||
static const uint8_t kTextOnTheTaxi[] = " ON THE SPACE TAXI! ";
|
||||
static const uint8_t kTextGameOver[] = " GAME OVER! ";
|
||||
static const uint8_t kTextBlank12[] = " ";
|
||||
// $4C1F / $556A screens.
|
||||
// $4C1F (the table) and $4E35 (the name entry) screens.
|
||||
static const uint8_t kTextImmortal[] = "THE IMMORTAL CABBIES";
|
||||
static const uint8_t *kHighScores[8] = {
|
||||
(const uint8_t *)"3877.56 MICHAEL PLATE",
|
||||
(const uint8_t *)"1809.51 MICHAEL PLATE",
|
||||
(const uint8_t *)"1179.87 ANDREAS PLATE",
|
||||
(const uint8_t *)" 892.65 MICHAEL PLATE",
|
||||
(const uint8_t *)" 685.37 ANDREAS PLATE",
|
||||
(const uint8_t *)" 629.45 MICHAEL PLATE",
|
||||
(const uint8_t *)" 569.50 MICHAEL PLATE",
|
||||
(const uint8_t *)" 504.97 ANDREAS PLATE",
|
||||
};
|
||||
static const uint8_t kTextShift[] = "SHIFT";
|
||||
static const uint8_t kTextReturnTitle[] = "PRESS FIRE TO RETURN TO TITLE PAGE";
|
||||
static const uint8_t kTextCongrats[] = "CONGRATULATIONS CABBIE ,";
|
||||
static const uint8_t kTextRanks[] = "YOUR SCORE RANKS YOU AS ONE OF";
|
||||
static const uint8_t kTextTopTen[] = "THE TOP TEN CABBIES OF ALL TIME";
|
||||
static const uint8_t kTextEnterName[] = "ENTER YOUR NAME BELOW";
|
||||
static const uint8_t *kAboutLines[7] = {
|
||||
(const uint8_t *)"THIS PROGRAM DEVELOPED AND WRITTEN BY",
|
||||
(const uint8_t *)"JOHN F. KUTCHER",
|
||||
|
|
@ -117,8 +151,9 @@ static const uint8_t *kAboutLines[7] = {
|
|||
};
|
||||
static const uint8_t kTextReturn[] = "PRESS FIRE TO RETURN";
|
||||
|
||||
static StGameT gGame;
|
||||
static StSimT gSim;
|
||||
static StGameT gGame;
|
||||
static StSimT gSim;
|
||||
static jlSurfaceT *gStage;
|
||||
// One level buffer serves both gameplay and the title screen: the title
|
||||
// is another scene, and gameplay never needs it at the same time, so it
|
||||
// is loaded into gLevel on each return to the title. (Keeping a second
|
||||
|
|
@ -126,17 +161,25 @@ static StSimT gSim;
|
|||
static StLevelT gLevel;
|
||||
|
||||
|
||||
static void blankScreen(StSimT *sim);
|
||||
static void blankScreen(StSimT *sim, uint8_t border, uint8_t bg);
|
||||
static void enterTitle(void);
|
||||
static void gameOverEnter(void);
|
||||
static void gameOverFinish(void);
|
||||
static void highScoreDraw(void);
|
||||
static uint8_t highScoreInsert(const uint8_t *score);
|
||||
static void highScoreLoad(void);
|
||||
static void highScoreSave(void);
|
||||
static bool joyFire(void);
|
||||
static uint8_t joyMask(void);
|
||||
static bool loadLevel(uint8_t index);
|
||||
static uint8_t nextLevelForShift(void);
|
||||
static uint8_t paceTicks(void);
|
||||
static bool serviceJingle(void);
|
||||
static void runCabbiesMenu(uint8_t ticks);
|
||||
static void runDemoEnd(void);
|
||||
static void runIntro(uint8_t ticks);
|
||||
static void runNameEntry(uint8_t ticks);
|
||||
static bool nameEntryStart(void);
|
||||
static void runPlaying(uint8_t ticks);
|
||||
static void runShiftMenu(uint8_t ticks);
|
||||
static void runTitle(uint8_t ticks);
|
||||
|
|
@ -149,12 +192,12 @@ static void startNewScreen(void);
|
|||
|
||||
|
||||
// $40CA -- spaces everywhere, black.
|
||||
static void blankScreen(StSimT *sim) {
|
||||
static void blankScreen(StSimT *sim, uint8_t border, uint8_t bg) {
|
||||
memset(sim->screen, ST_CHAR_SPACE, ST_SCREEN_CELLS);
|
||||
memset(sim->color, 0, ST_SCREEN_CELLS);
|
||||
stSimDirtyAll(sim);
|
||||
sim->bgColor = 0u;
|
||||
sim->borderColor = 0u;
|
||||
sim->bgColor = bg;
|
||||
sim->borderColor = border;
|
||||
sim->frame.enableMask = 0u;
|
||||
stRenderSceneChanged(sim);
|
||||
}
|
||||
|
|
@ -166,16 +209,239 @@ static void enterTitle(void) {
|
|||
if (!stLevelLoad(&gLevel, "levels/title.dat")) {
|
||||
ST_LOG("spacetaxi: ! title load FAILED");
|
||||
}
|
||||
stRenderLevelCels(gStage, 0); // the last level's cels go
|
||||
stTitleEnter(&gSim, &gLevel);
|
||||
stRenderSceneChanged(&gSim);
|
||||
stRenderTitleLogo(&gSim);
|
||||
stAudioNoise(false);
|
||||
stAudioSilence();
|
||||
jlMusicStop();
|
||||
gGame.state = ST_STATE_TITLE;
|
||||
gGame.fireArmed = false;
|
||||
}
|
||||
|
||||
|
||||
// $6BD0 -- one more player done; everybody done -> title.
|
||||
static void gameOverFinish(void) {
|
||||
gSim.playersDone++;
|
||||
if (gSim.playersDone == gSim.playerCount) {
|
||||
enterTitle();
|
||||
} else {
|
||||
startNewScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// $4C1F -- the immortal cabbies: ten rows of shift, "$", score and name,
|
||||
// each entry drawn only while its last score digit is a digit (a blank
|
||||
// row is an unused slot). Song 7 plays under it until FIRE ($4D04).
|
||||
static void highScoreDraw(void) {
|
||||
uint8_t i;
|
||||
|
||||
blankScreen(&gSim, 3u, 14u);
|
||||
stSimDrawText(&gSim, 9u, 1u, kTextImmortal, 6u);
|
||||
stSimDrawText(&gSim, 32u, 3u, kTextShift, 15u);
|
||||
for (i = 0u; i < ST_HS_ENTRIES; i++) {
|
||||
const StHighScoreT *e = &gHighScores[i];
|
||||
uint8_t row = (uint8_t)(4u + i * 2u);
|
||||
if (e->score[ST_NUMBER_CHARS - 1u] < '0') {
|
||||
continue;
|
||||
}
|
||||
stSimPutChar(&gSim, 34u, row, (uint8_t)('0' + e->shift));
|
||||
stSimPutColor(&gSim, 34u, row, 15u);
|
||||
stSimPutChar(&gSim, 4u, row, '$');
|
||||
stSimPutColor(&gSim, 4u, row, 1u);
|
||||
stSimDrawText(&gSim, 5u, row, e->score, 1u);
|
||||
stSimDrawText(&gSim, 15u, row, e->name, 1u);
|
||||
}
|
||||
stSimDrawText(&gSim, 3u, 24u, kTextReturnTitle, 0u);
|
||||
stAudioMusic(ST_SONG_SCORES, false); // $4C29
|
||||
}
|
||||
|
||||
|
||||
// $4D92 -- where a score belongs in the table, or ST_HS_ENTRIES when it
|
||||
// does not make it. The table is only opened to scores of $50.00 and up
|
||||
// (second character a digit, or third character 5 or more). The scores
|
||||
// are right-aligned text, so a character compare orders them; a tie goes
|
||||
// above the older entry. The new entry is opened with a blank name.
|
||||
static uint8_t highScoreInsert(const uint8_t *score) {
|
||||
uint8_t slot;
|
||||
uint8_t k;
|
||||
|
||||
if (score[1] < '0' && score[2] < '5') {
|
||||
return ST_HS_ENTRIES;
|
||||
}
|
||||
for (slot = 0u; slot < ST_HS_ENTRIES; slot++) {
|
||||
const uint8_t *old = gHighScores[slot].score;
|
||||
for (k = 0u; k < ST_NUMBER_CHARS; k++) {
|
||||
if (score[k] != old[k]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == ST_NUMBER_CHARS || score[k] > old[k]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slot == ST_HS_ENTRIES) {
|
||||
return ST_HS_ENTRIES;
|
||||
}
|
||||
for (k = (uint8_t)(ST_HS_ENTRIES - 1u); k > slot; k--) {
|
||||
gHighScores[k] = gHighScores[k - 1u];
|
||||
}
|
||||
memcpy(gHighScores[slot].score, score, ST_NUMBER_CHARS + 1u);
|
||||
memset(gHighScores[slot].name, ' ', ST_HS_NAME_CHARS);
|
||||
gHighScores[slot].name[ST_HS_NAME_CHARS] = 0u;
|
||||
gHighScores[slot].shift = 0u;
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
||||
// $23E5 -> $9948 at boot: the table from disk, when there is one. The
|
||||
// image is the C64's own: per entry score[7], 0, name[15], shift.
|
||||
static void highScoreLoad(void) {
|
||||
uint8_t image[ST_HS_ENTRIES * ST_HS_ENTRY_BYTES];
|
||||
uint8_t i;
|
||||
|
||||
if (jlSaveRead(ST_HS_SAVE_NAME, image, sizeof(image)) != sizeof(image)) {
|
||||
return;
|
||||
}
|
||||
for (i = 0u; i < ST_HS_ENTRIES; i++) {
|
||||
const uint8_t *e = &image[i * ST_HS_ENTRY_BYTES];
|
||||
if (e[ST_NUMBER_CHARS] != 0u) {
|
||||
ST_LOG("spacetaxi: ! %s is not a score table", ST_HS_SAVE_NAME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0u; i < ST_HS_ENTRIES; i++) {
|
||||
const uint8_t *e = &image[i * ST_HS_ENTRY_BYTES];
|
||||
memcpy(gHighScores[i].score, e, ST_NUMBER_CHARS);
|
||||
gHighScores[i].score[ST_NUMBER_CHARS] = 0u;
|
||||
memcpy(gHighScores[i].name, &e[ST_NUMBER_CHARS + 1u], ST_HS_NAME_CHARS);
|
||||
gHighScores[i].name[ST_HS_NAME_CHARS] = 0u;
|
||||
gHighScores[i].shift = e[ST_HS_ENTRY_BYTES - 1u];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// $4E11 -> $9948 after an entry: the table back to disk.
|
||||
static void highScoreSave(void) {
|
||||
uint8_t image[ST_HS_ENTRIES * ST_HS_ENTRY_BYTES];
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0u; i < ST_HS_ENTRIES; i++) {
|
||||
uint8_t *e = &image[i * ST_HS_ENTRY_BYTES];
|
||||
memcpy(e, gHighScores[i].score, ST_NUMBER_CHARS);
|
||||
e[ST_NUMBER_CHARS] = 0u;
|
||||
memcpy(&e[ST_NUMBER_CHARS + 1u], gHighScores[i].name, ST_HS_NAME_CHARS);
|
||||
e[ST_HS_ENTRY_BYTES - 1u] = gHighScores[i].shift;
|
||||
}
|
||||
if (!jlSaveWrite(ST_HS_SAVE_NAME, image, sizeof(image))) {
|
||||
ST_LOG("spacetaxi: ! could not save %s", ST_HS_SAVE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// $4D52 -- after a player's GAME OVER: their score as "dddd.dd" text, and
|
||||
// if it ranks, the $4E35 screen: red border, grey field, the cabbie's
|
||||
// number in the greeting, the score at the top, song 6, and a blinking
|
||||
// cursor where the name goes. Returns false when the score did not rank
|
||||
// and the game moves straight on.
|
||||
static bool nameEntryStart(void) {
|
||||
uint8_t score[ST_NUMBER_CHARS + 1u];
|
||||
uint8_t greet[sizeof(kTextCongrats)];
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < ST_NUMBER_CHARS; k++) {
|
||||
uint8_t ch = gSim.scoreBackup[gSim.player][k];
|
||||
if (ch == ST_CHAR_BLANK) {
|
||||
score[k] = ' ';
|
||||
} else {
|
||||
uint8_t d = (uint8_t)(ch - ST_CHAR_DIGIT_BASE); // $4345
|
||||
score[k] = (uint8_t)('0' + ((d == 10u) ? 0u : d));
|
||||
}
|
||||
}
|
||||
score[ST_HS_POINT_AT] = '.';
|
||||
score[ST_NUMBER_CHARS] = 0u;
|
||||
gGame.hsSlot = highScoreInsert(score);
|
||||
if (gGame.hsSlot == ST_HS_ENTRIES) {
|
||||
return false;
|
||||
}
|
||||
blankScreen(&gSim, 2u, 15u);
|
||||
while (jlInputGetChar() >= 0) { // $0277 = 0: nothing typed earlier counts
|
||||
}
|
||||
memcpy(greet, kTextCongrats, sizeof(greet));
|
||||
greet[ST_HS_GREET_DIGIT_AT] = (uint8_t)('1' + gSim.player);
|
||||
stSimDrawText(&gSim, 7u, 3u, greet, 0u);
|
||||
stSimDrawText(&gSim, 5u, 5u, kTextRanks, 0u);
|
||||
stSimDrawText(&gSim, 4u, 7u, kTextTopTen, 0u);
|
||||
stSimDrawText(&gSim, 9u, 9u, kTextEnterName, 0u);
|
||||
stSimDrawText(&gSim, 16u, 0u, score, 6u);
|
||||
stSimPutChar(&gSim, 15u, 0u, '$');
|
||||
stSimPutColor(&gSim, 15u, 0u, 6u);
|
||||
stAudioMusic(ST_SONG_NAME_ENTRY, false); // $4EB6
|
||||
gGame.hsLen = 0u;
|
||||
gGame.hsCursor = ST_HS_CURSOR;
|
||||
gGame.hsBlinkTicks = 0u;
|
||||
gGame.state = ST_STATE_NAME_ENTRY;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// $4ED8 -- the entry loop: the cursor flips between "%" and blank, then
|
||||
// the keyboard: letters, space, ".", "!" and "," go in (fifteen at most),
|
||||
// DEL takes one back, RETURN keeps the name (a "*" when none was typed),
|
||||
// stamps the shift, stops the tune and saves the table.
|
||||
static void runNameEntry(uint8_t ticks) {
|
||||
StHighScoreT *e = &gHighScores[gGame.hsSlot];
|
||||
uint8_t col = (uint8_t)(ST_HS_NAME_COL + gGame.hsLen);
|
||||
int c;
|
||||
|
||||
gGame.hsBlinkTicks = (uint8_t)(gGame.hsBlinkTicks + ticks);
|
||||
if (gGame.hsBlinkTicks >= ST_HS_BLINK_TICKS) {
|
||||
gGame.hsBlinkTicks = 0u;
|
||||
gGame.hsCursor ^= ST_HS_CURSOR ^ ' ';
|
||||
stSimPutChar(&gSim, col, ST_HS_NAME_ROW, gGame.hsCursor);
|
||||
stSimPutColor(&gSim, col, ST_HS_NAME_ROW, 6u);
|
||||
}
|
||||
while ((c = jlInputGetChar()) >= 0) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
c = c - 'a' + 'A';
|
||||
}
|
||||
if (c == JL_CHAR_RETURN) {
|
||||
stSimPutChar(&gSim, col, ST_HS_NAME_ROW, ' ');
|
||||
if (gGame.hsLen == 0u) {
|
||||
e->name[0] = '*';
|
||||
}
|
||||
e->shift = gGame.variation;
|
||||
jlMusicStop(); // $44E1
|
||||
highScoreSave(); // $4E11
|
||||
gameOverFinish();
|
||||
return;
|
||||
}
|
||||
if (c == JL_CHAR_BACKSPACE || c == JL_CHAR_DELETE) {
|
||||
if (gGame.hsLen != 0u) {
|
||||
stSimPutChar(&gSim, col, ST_HS_NAME_ROW, ' ');
|
||||
gGame.hsLen--;
|
||||
col--;
|
||||
e->name[gGame.hsLen] = ' ';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c != ' ' && c != '.' && c != '!' && c != ',' && (c < 'A' || c > 'Z')) {
|
||||
continue;
|
||||
}
|
||||
if (gGame.hsLen == ST_HS_NAME_CHARS) {
|
||||
continue;
|
||||
}
|
||||
e->name[gGame.hsLen] = (uint8_t)c;
|
||||
stSimPutChar(&gSim, col, ST_HS_NAME_ROW, (uint8_t)c);
|
||||
stSimPutColor(&gSim, col, ST_HS_NAME_ROW, 6u);
|
||||
gGame.hsLen++;
|
||||
col++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// $5FBB -- "GAME OVER!" over the play field, sprites hidden.
|
||||
static void gameOverEnter(void) {
|
||||
stSimDrawText(&gSim, 14u, 10u, kTextBlank12, 1u);
|
||||
|
|
@ -184,8 +450,9 @@ static void gameOverEnter(void) {
|
|||
gSim.frame.enableMask = 0u;
|
||||
stAudioNoise(false);
|
||||
stAudioSilence();
|
||||
gGame.waitTicks = ST_GAME_OVER_TICKS;
|
||||
gGame.state = ST_STATE_GAME_OVER;
|
||||
gGame.waitTicks = ST_GAME_OVER_TICKS;
|
||||
gGame.gameOverTune = false;
|
||||
gGame.state = ST_STATE_GAME_OVER;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -222,7 +489,7 @@ static uint8_t joyMask(void) {
|
|||
static bool loadLevel(uint8_t index) {
|
||||
char path[32];
|
||||
|
||||
if (index >= ST_LEVEL_COUNT) {
|
||||
if (index >= ST_LEVEL_FILES) {
|
||||
return false;
|
||||
}
|
||||
// Hand-rolled "levels/levelNN.dat" (NN = index+1, 01..24) so the
|
||||
|
|
@ -238,6 +505,7 @@ static bool loadLevel(uint8_t index) {
|
|||
ST_LOG("spacetaxi: ! cannot load %s", path);
|
||||
return false;
|
||||
}
|
||||
stRenderLevelCels(gStage, &gLevel);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +522,13 @@ static uint8_t nextLevelForShift(void) {
|
|||
}
|
||||
return (uint8_t)((gGame.variation - 1u) * 8u + sim->levelState);
|
||||
}
|
||||
if (sim->levelState >= ST_LEVEL_COUNT) {
|
||||
// $5022/$5167: the 24-hour shifts play screen Y after A..X, and only
|
||||
// then is the shift over -- which is also what lights the "finished"
|
||||
// marker in the screens-completed field (levelState reaches 25).
|
||||
if (sim->levelState == ST_LEVEL_COUNT) {
|
||||
return ST_SCREEN_Y;
|
||||
}
|
||||
if (sim->levelState > ST_LEVEL_COUNT) {
|
||||
return 0xFFu;
|
||||
}
|
||||
if (gGame.variation == 4u) {
|
||||
|
|
@ -355,6 +629,7 @@ static void runIntro(uint8_t ticks) {
|
|||
}
|
||||
for (k = 0u; k < (uint8_t)(ticks * 2u); k++) {
|
||||
if (stIntroStep(&gSim)) {
|
||||
jlMusicStop(); // $4709
|
||||
stSimEnterLevel(&gSim, &gLevel);
|
||||
stRenderSceneChanged(&gSim);
|
||||
if (gGame.demo) {
|
||||
|
|
@ -362,6 +637,7 @@ static void runIntro(uint8_t ticks) {
|
|||
stSimSetDemoStream(&gSim, e->stream, e->length);
|
||||
}
|
||||
gGame.state = ST_STATE_PLAYING;
|
||||
serviceJingle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -377,6 +653,9 @@ static void runPlaying(uint8_t ticks) {
|
|||
StTickResultE r = stSimTick(&gSim);
|
||||
stAudioTick();
|
||||
if (r == ST_TICK_CONTINUE) {
|
||||
if (serviceJingle()) {
|
||||
return; // $70D4 bonus cab: the tune blocks
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (gGame.demo) {
|
||||
|
|
@ -390,6 +669,9 @@ static void runPlaying(uint8_t ticks) {
|
|||
case ST_TICK_LIFE_LOST:
|
||||
stSimRespawn(&gSim);
|
||||
stRenderSceneChanged(&gSim);
|
||||
if (serviceJingle()) {
|
||||
return; // $6906 on the new cab
|
||||
}
|
||||
break;
|
||||
case ST_TICK_PLAYER_OUT:
|
||||
gameOverEnter();
|
||||
|
|
@ -401,6 +683,27 @@ static void runPlaying(uint8_t ticks) {
|
|||
}
|
||||
|
||||
|
||||
// Start a tune the sim asked for and park the loop in ST_STATE_JINGLE
|
||||
// until it ends. Returns true when a tune was started, so callers can
|
||||
// stop ticking the sim for this frame -- the C64's $44CF blocks there.
|
||||
static bool serviceJingle(void) {
|
||||
uint8_t song;
|
||||
|
||||
if (gSim.jingleRequest == 0u) {
|
||||
return false;
|
||||
}
|
||||
song = (uint8_t)(gSim.jingleRequest - 1u);
|
||||
gSim.jingleRequest = 0u;
|
||||
stAudioJingle(song);
|
||||
if (!stAudioJingleActive()) {
|
||||
return false; // no audio: nothing to wait for
|
||||
}
|
||||
gGame.afterJingle = gGame.state;
|
||||
gGame.state = ST_STATE_JINGLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// $54F8 -- UP/DOWN pick the shift, FIRE confirms and starts the game.
|
||||
static void runShiftMenu(uint8_t ticks) {
|
||||
uint8_t mask = joyMask();
|
||||
|
|
@ -462,13 +765,7 @@ static void runTitle(uint8_t ticks) {
|
|||
return;
|
||||
}
|
||||
if ((mask & 0x01u) != 0u) {
|
||||
uint8_t i;
|
||||
blankScreen(&gSim);
|
||||
stSimDrawText(&gSim, 10u, 1u, kTextImmortal, 1u);
|
||||
for (i = 0u; i < 8u; i++) {
|
||||
stSimDrawText(&gSim, 9u, (uint8_t)(4u + i * 2u), kHighScores[i], 1u);
|
||||
}
|
||||
stSimDrawText(&gSim, 10u, 22u, kTextReturn, 1u);
|
||||
highScoreDraw();
|
||||
gGame.state = ST_STATE_HIGHSCORES;
|
||||
gGame.fireArmed = false;
|
||||
return;
|
||||
|
|
@ -477,7 +774,7 @@ static void runTitle(uint8_t ticks) {
|
|||
static const uint8_t kAboutCols[7] = { 1u, 12u, 15u, 4u, 5u, 6u, 1u };
|
||||
static const uint8_t kAboutRows[7] = { 3u, 5u, 7u, 10u, 12u, 14u, 18u };
|
||||
uint8_t i;
|
||||
blankScreen(&gSim);
|
||||
blankScreen(&gSim, 12u, 15u); // $558E: grey border, light-grey field
|
||||
for (i = 0u; i < 7u; i++) {
|
||||
stSimDrawText(&gSim, kAboutCols[i], kAboutRows[i], kAboutLines[i], 1u);
|
||||
}
|
||||
|
|
@ -500,7 +797,7 @@ static void shiftMenuColor(uint8_t sel, uint8_t color) {
|
|||
|
||||
// $5295 -- GAME VARIATIONS page 1.
|
||||
static void showCabbiesMenu(void) {
|
||||
blankScreen(&gSim);
|
||||
blankScreen(&gSim, 0u, 0u);
|
||||
stSimDrawText(&gSim, 13u, 0u, kTextGameVariations, 5u);
|
||||
stSimDrawText(&gSim, 1u, 2u, kTextCabbies, 7u);
|
||||
stSimDrawText(&gSim, 5u, 4u, kTextLeftRight, 11u);
|
||||
|
|
@ -518,7 +815,7 @@ static void showCabbiesMenu(void) {
|
|||
static void showShiftMenu(void) {
|
||||
uint8_t i;
|
||||
|
||||
blankScreen(&gSim);
|
||||
blankScreen(&gSim, 0u, 0u);
|
||||
stSimDrawText(&gSim, 1u, 8u, kTextSelectShift, 7u);
|
||||
for (i = 0u; i < 5u; i++) {
|
||||
stSimDrawText(&gSim, 2u, (uint8_t)(10u + i * 2u), kTextShifts[i], 6u);
|
||||
|
|
@ -560,6 +857,11 @@ static void startDemoScreen(void) {
|
|||
static void startIntro(void) {
|
||||
stIntroEnter(&gSim, &gLevel);
|
||||
stRenderSceneChanged(&gSim);
|
||||
// After the scene change, which turns it back off.
|
||||
stRenderIntroStars();
|
||||
// $459C: the intro's tune plays under the fly-in, not blocking; the
|
||||
// C64 leaves it to the IRQ player and stops it at $4709.
|
||||
stAudioMusic(ST_SONG_INTRO, true);
|
||||
gGame.state = ST_STATE_INTRO;
|
||||
}
|
||||
|
||||
|
|
@ -601,9 +903,15 @@ int main(void) {
|
|||
jlConfigT config;
|
||||
jlSurfaceT *stage;
|
||||
|
||||
#if defined(JOEYLIB_PLATFORM_IIGS)
|
||||
// One 64 KB bank: enough for the cab, exhaust and passenger cels.
|
||||
config.codegenBytes = 60UL * 1024;
|
||||
// The codegen arena holds every compiled cel, the baked ones too: the
|
||||
// 37 cab/exhaust/passenger cels plus a level's hook cels (level I has
|
||||
// 30). On the IIgs that is ~230 KB of 65816 code in 64 KB banks, and
|
||||
// the arena grants as many banks as the machine has (a 1 MB machine
|
||||
// gets one; whatever does not fit draws interpreted). The 68k ports'
|
||||
// cels are far larger (9-13 KB each) and their JIT is fast, so they
|
||||
// keep a modest arena and compile at level entry.
|
||||
#if defined(JOEYLIB_PLATFORM_IIGS) || defined(JOEYLIB_PLATFORM_DOS)
|
||||
config.codegenBytes = 256UL * 1024;
|
||||
#else
|
||||
config.codegenBytes = 160UL * 1024;
|
||||
#endif
|
||||
|
|
@ -618,6 +926,7 @@ int main(void) {
|
|||
jlShutdown();
|
||||
return 1;
|
||||
}
|
||||
gStage = stage;
|
||||
memset(&gGame, 0, sizeof(gGame));
|
||||
memset(&gSim, 0, sizeof(gSim));
|
||||
stRenderInit(stage);
|
||||
|
|
@ -630,6 +939,7 @@ int main(void) {
|
|||
stSimSeedDemoBuffer(&gSim, kDemoBufferInit, ST_DEMO_BUFFER_BYTES);
|
||||
gSim.waveIdx = 3u;
|
||||
stRenderPrewarm(stage, &gSim);
|
||||
highScoreLoad(); // $23E5
|
||||
enterTitle();
|
||||
gGame.lastFrame = (uint8_t)jlFrameCount();
|
||||
|
||||
|
|
@ -637,8 +947,39 @@ int main(void) {
|
|||
uint8_t ticks;
|
||||
|
||||
jlInputPoll();
|
||||
if (jlKeyPressed(KEY_ESCAPE)) {
|
||||
break;
|
||||
// $4FCB runStopWatcher, on the game tick, the intro and the menus:
|
||||
// SHIFT held freezes everything with the sound gated off and any
|
||||
// tune stopped (the intro's restarts on release); RUN/STOP -- ESC
|
||||
// here -- abandons the game for the title, and on the title it
|
||||
// leaves the program (the C64 had nowhere else to go).
|
||||
if (gGame.state != ST_STATE_JINGLE && gGame.state != ST_STATE_GAME_OVER && gGame.state != ST_STATE_NAME_ENTRY) {
|
||||
if (jlKeyDown(KEY_LSHIFT) || jlKeyDown(KEY_RSHIFT)) {
|
||||
if (!gGame.paused) {
|
||||
gGame.paused = true;
|
||||
stAudioSilence();
|
||||
stAudioNoise(false);
|
||||
jlMusicStop();
|
||||
}
|
||||
stRenderFrame(stage, &gSim);
|
||||
jlAudioFrameTick();
|
||||
continue;
|
||||
}
|
||||
if (gGame.paused) {
|
||||
gGame.paused = false;
|
||||
gGame.lastFrame = (uint8_t)jlFrameCount(); // the held time is not owed
|
||||
gGame.paceAcc = 0u;
|
||||
if (gGame.state == ST_STATE_INTRO) {
|
||||
stAudioMusic(ST_SONG_INTRO, true); // $46B5
|
||||
}
|
||||
}
|
||||
if (jlKeyPressed(KEY_ESCAPE)) {
|
||||
if (gGame.state == ST_STATE_TITLE) {
|
||||
break;
|
||||
}
|
||||
jlMusicStop(); // $5000
|
||||
gGame.demo = false;
|
||||
enterTitle();
|
||||
}
|
||||
}
|
||||
ticks = paceTicks();
|
||||
switch (gGame.state) {
|
||||
|
|
@ -677,19 +1018,33 @@ int main(void) {
|
|||
case ST_STATE_PLAYING:
|
||||
runPlaying(ticks);
|
||||
break;
|
||||
case ST_STATE_JINGLE:
|
||||
// The C64 spins in $44D5 until the tune ends. A joystick
|
||||
// press ends the attract demo here too ($4FE2 stops the
|
||||
// music on input).
|
||||
if (gGame.demo && (joyMask() & 0x1Fu) != 0u) {
|
||||
jlMusicStop();
|
||||
runDemoEnd();
|
||||
} else if (!stAudioJingleActive()) {
|
||||
gGame.state = gGame.afterJingle;
|
||||
}
|
||||
break;
|
||||
case ST_STATE_GAME_OVER:
|
||||
if (gGame.waitTicks > ticks) {
|
||||
gGame.waitTicks = (uint16_t)(gGame.waitTicks - ticks);
|
||||
} else {
|
||||
// $6BD0: one more player done; everybody done -> title.
|
||||
gSim.playersDone++;
|
||||
if (gSim.playersDone == gSim.playerCount) {
|
||||
enterTitle();
|
||||
} else {
|
||||
startNewScreen();
|
||||
}
|
||||
} else if (!gGame.gameOverTune) {
|
||||
// $5C24: after the GAME OVER! wait, song 5 plays out.
|
||||
gGame.gameOverTune = true;
|
||||
stAudioJingle(ST_SONG_GAME_OVER);
|
||||
} else if (stAudioJingleActive()) {
|
||||
// still sounding
|
||||
} else if (!nameEntryStart()) {
|
||||
gameOverFinish();
|
||||
}
|
||||
break;
|
||||
case ST_STATE_NAME_ENTRY:
|
||||
runNameEntry(ticks);
|
||||
break;
|
||||
default:
|
||||
enterTitle();
|
||||
break;
|
||||
|
|
|
|||
21
spacetaxi.h
21
spacetaxi.h
|
|
@ -15,6 +15,21 @@
|
|||
|
||||
#include "stSim.h"
|
||||
|
||||
// Diagnostics. The logger drags in vsnprintf (with newlib that pulls the
|
||||
// whole formatted-output and float-conversion family, ~45 KB) plus a
|
||||
// multi-KB ring buffer, and the game has no need of either. That is
|
||||
// unaffordable on the IIgs, whose bank-0 BSS budget cannot spare the
|
||||
// ring, and on the X68000, which ships on a Human68k floppy with about
|
||||
// 330 KB of usable space for the binary AND its levels. Both compile it
|
||||
// out; the ports with room keep it.
|
||||
#if defined(__W65816__) || defined(JOEYLIB_PLATFORM_X68000)
|
||||
#define ST_LOG_RESET() ((void)0)
|
||||
#define ST_LOG(...) ((void)0)
|
||||
#else
|
||||
#define ST_LOG_RESET() jlLogReset()
|
||||
#define ST_LOG(...) jlLogF(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
// Level loading through the JoeyLib data path (DATA/levels/...).
|
||||
bool stLevelLoad(StLevelT *out, const char *path);
|
||||
|
||||
|
|
@ -35,7 +50,13 @@ void stRenderSceneChanged(StSimT *sim);
|
|||
// cycle are palette writes instead of repainting 103 (and 407) cells.
|
||||
// Call after stRenderSceneChanged, which turns it back off.
|
||||
void stRenderTitleLogo(StSimT *sim);
|
||||
// Level intro only: cycle the starfield's ring palette slots so the warp
|
||||
// animates without a single pixel moving. Call after
|
||||
// stRenderSceneChanged, which turns it back off.
|
||||
void stRenderIntroStars(void);
|
||||
void stRenderPrewarm(jlSurfaceT *stage, StSimT *sim);
|
||||
// Ready a level's hook cels before its ride (evicts the previous level's).
|
||||
void stRenderLevelCels(jlSurfaceT *stage, const StLevelT *level);
|
||||
|
||||
// Audio sink setup and the per-tick release timers ($4320).
|
||||
void stAudioInit(void);
|
||||
|
|
|
|||
421
stAudio.c
421
stAudio.c
|
|
@ -8,8 +8,18 @@
|
|||
// time; envelopes and waveforms are approximated with an attenuation
|
||||
// ramp. The speech samples of the original are not extracted; each
|
||||
// spoken character becomes a short chirp so the cues still land.
|
||||
//
|
||||
// UPDATE: the speech IS extracted now (assets/extractSpeech.py), so the
|
||||
// chirp is gone. stSpeechData.c carries the C64's own 1-bit run-length
|
||||
// streams; assets/genSpeechPcm.py bakes them to sample bytes
|
||||
// (DATA/speech.bin) and speechFill below streams those through
|
||||
// jlAudioPlaySfxStream.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "spacetaxi.h"
|
||||
#include <joey/file.h>
|
||||
#include "stSongData.h"
|
||||
|
||||
|
||||
// SID voice index in a program's byte 8 -> JoeyLib voice slot.
|
||||
|
|
@ -25,10 +35,44 @@
|
|||
#define ST_SID_HZ_NUM 1022727UL
|
||||
#define ST_SID_HZ_DEN 16777216UL
|
||||
|
||||
// Speech chirp: one short tone per character, pitched by the character.
|
||||
#define ST_SPEECH_TICKS 3u
|
||||
#define ST_SPEECH_BASE_HZ 300u
|
||||
#define ST_SPEECH_STEP_HZ 9u
|
||||
// ---- speech ----
|
||||
//
|
||||
// The C64 player ($9802) busy-waits a delay loop per stream byte and then
|
||||
// toggles its 1-bit output, so a byte is one half-cycle. The loop costs
|
||||
// (5k + 12) cycles per pass plus a 33-cycle tail, where k is the inner
|
||||
// count at $98A2 -- normally 3, giving 27. A code below $09 does not
|
||||
// speak: it REWRITES k, which is how the original gives each fare a
|
||||
// slightly different voice pitch. stAudioSpeech honours that.
|
||||
#define ST_SPEECH_SLOT 0u // slots 1..3 are the SID voices
|
||||
#define ST_SPEECH_RATE 5000u // enough for a 1-bit source
|
||||
#define ST_SPEECH_PITCH_BASE 3u // $98A2's power-on value
|
||||
#define ST_SPEECH_PITCH_MAX 15u // the player's AND #$0F
|
||||
// Longest phrase is "PX?" -- pad, digit, please.
|
||||
#define ST_SPEECH_QUEUE 4u
|
||||
// The speech is baked to sample bytes per pitch, in both polarities, by
|
||||
// assets/genSpeechPcm.py (DATA/speech.bin, format in that script), so
|
||||
// playing it is a block copy. Decoding the C64's run-length stream at
|
||||
// play time cost the 65816 2.4 s of CPU per second of speech and stalled
|
||||
// the ride half a second on every "HEY TAXI"; the 1-bit intermediate
|
||||
// format that followed still needed a per-byte expansion loop.
|
||||
#define ST_SPEECH_FILE "speech.bin"
|
||||
#define ST_SPEECH_VERSION 2u
|
||||
#define ST_SPEECH_HEADER_BYTES 16u
|
||||
#define ST_SPEECH_ENTRY_BYTES 8u
|
||||
#define ST_SPEECH_POLARITIES 2u
|
||||
#define ST_SPEECH_FORMAT_SIGNED 0u
|
||||
#define ST_SPEECH_FORMAT_BIASED 1u
|
||||
#define ST_SPEECH_LOAD_CHUNK 16384u
|
||||
#define ST_SPEECH_STAGE_MASK (ST_SPEECH_STAGE_BYTES - 1u)
|
||||
// Decode-ahead staging: a whole engine chunk (7168 at 5 kHz, 1.4 s) plus
|
||||
// slack. The per-tick slice covers playback (5000/s is ~330 a tick)
|
||||
// with room to spare and is cheap enough to never need a burst; a
|
||||
// starved pull still copies ST_SPEECH_STARVED_SLICE on the spot rather
|
||||
// than ending the stream.
|
||||
#define ST_SPEECH_STAGE_BYTES 8192u
|
||||
#define ST_SPEECH_TICK_SLICE 384u
|
||||
#define ST_SPEECH_STARVED_SLICE 1024u
|
||||
#define ST_SPEECH_ARM_SLICE 1024u
|
||||
|
||||
// Thrust sweep register value -> Hz: the C64 writes the same byte to
|
||||
// both frequency bytes, so the word is value * 257.
|
||||
|
|
@ -44,10 +88,46 @@ typedef struct {
|
|||
static StSfxSlotT gSfx; // SID voice 1 (programs + sweep)
|
||||
static StSfxSlotT gTone; // SID voice 2
|
||||
static bool gNoiseOn;
|
||||
static uint16_t gSpeechTicks;
|
||||
|
||||
// Speech playback state. The fill callback walks a queue of utterances so
|
||||
// a phrase like "HT" ("Hey" + "Taxi") runs as one continuous stream
|
||||
// instead of each character cutting off the last.
|
||||
static uint8_t gSpeechQueue[ST_SPEECH_QUEUE];
|
||||
static uint8_t gSpeechHead;
|
||||
static uint8_t gSpeechTail;
|
||||
static bool gSpeechActive;
|
||||
static uint8_t gSpeechPitch = ST_SPEECH_PITCH_BASE;
|
||||
// DATA/speech.bin, whole: header, entry table, sample bytes. The bytes
|
||||
// are already in the port's raw stream format (jlAudioSfxRawFormat):
|
||||
// signed +/-100, or 0x80-biased on the IIgs so a chunk needs no
|
||||
// conversion; speechLoad refuses a file baked for the other one.
|
||||
static uint8_t *gSpeechBlob;
|
||||
static uint8_t gSpeechPitchBase;
|
||||
static uint8_t gSpeechPitchCount;
|
||||
static uint8_t gSpeechCount; // utterances per pitch
|
||||
static const uint8_t *gSpeechPcm; // current utterance's samples
|
||||
static uint16_t gSpeechSample; // next sample index in it
|
||||
static uint16_t gSpeechSamples; // its length
|
||||
static uint8_t gSpeechParity; // it ends on the opposite level
|
||||
static uint8_t gSpeechPol; // 0 / 1: which baked polarity the next utterance plays
|
||||
// Copied-ahead PCM ring for the stream (see speechFill). Allocated by
|
||||
// stAudioInit rather than static: 8 KB of BSS is a fifth of the IIgs
|
||||
// entry bank, which text, rodata, BSS and the C heap all share.
|
||||
static uint8_t *gSpeechStage;
|
||||
static uint16_t gSpeechStageRead; // byte index of the next unread sample
|
||||
static uint16_t gSpeechStageWrite; // byte index of the next free byte
|
||||
static uint16_t gSpeechStageCount; // bytes staged and unread
|
||||
static bool gSpeechDecoding; // the decoder still has stream left
|
||||
|
||||
|
||||
static uint16_t sidHz(uint16_t word);
|
||||
static void speechLoad(void);
|
||||
static bool speechNext(void);
|
||||
static void speechArm(void);
|
||||
static uint16_t speechDecode(uint8_t *dst, uint16_t count);
|
||||
static uint32_t speechFill(void *ctx, int8_t *dst, uint32_t count);
|
||||
static void speechPumpSlice(uint16_t samples);
|
||||
static bool speechQueue(uint8_t ch);
|
||||
static void voiceOff(StSfxSlotT *slot);
|
||||
|
||||
|
||||
|
|
@ -61,6 +141,208 @@ static uint16_t sidHz(uint16_t word) {
|
|||
}
|
||||
|
||||
|
||||
// Point the decoder at the next queued utterance. False when the queue
|
||||
// is empty, which ends the stream.
|
||||
// DATA/speech.bin into one jlAlloc block; without it the game is mute
|
||||
// but otherwise fine.
|
||||
static void speechLoad(void) {
|
||||
FILE *fp = jlDataOpen(ST_SPEECH_FILE, "rb");
|
||||
uint8_t head[ST_SPEECH_HEADER_BYTES];
|
||||
uint8_t format;
|
||||
uint32_t dataBytes;
|
||||
uint32_t total;
|
||||
uint32_t done;
|
||||
|
||||
gSpeechBlob = 0;
|
||||
if (fp == 0) {
|
||||
return;
|
||||
}
|
||||
format = (jlAudioSfxRawFormat() == JL_SFX_RAW_UNSIGNED8_NOZERO) ? ST_SPEECH_FORMAT_BIASED : ST_SPEECH_FORMAT_SIGNED;
|
||||
if (fread(head, 1u, sizeof(head), fp) != sizeof(head) || head[0] != 'S' || head[1] != 'T' || head[2] != 'S' || head[3] != 'P' || head[4] != ST_SPEECH_VERSION || head[8] != format) {
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
gSpeechPitchBase = head[5];
|
||||
gSpeechPitchCount = head[6];
|
||||
gSpeechCount = head[7];
|
||||
dataBytes = (uint32_t)head[12] | ((uint32_t)head[13] << 8) | ((uint32_t)head[14] << 16) | ((uint32_t)head[15] << 24);
|
||||
total = ST_SPEECH_HEADER_BYTES + (uint32_t)gSpeechPitchCount * gSpeechCount * ST_SPEECH_POLARITIES * ST_SPEECH_ENTRY_BYTES + dataBytes;
|
||||
gSpeechBlob = (uint8_t *)jlAlloc(total);
|
||||
if (gSpeechBlob == 0) {
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
memcpy(gSpeechBlob, head, sizeof(head));
|
||||
// The block spans banks on the IIgs; read it in bank-safe pieces.
|
||||
done = ST_SPEECH_HEADER_BYTES;
|
||||
while (done < total) {
|
||||
uint32_t want = total - done;
|
||||
|
||||
if (want > ST_SPEECH_LOAD_CHUNK) {
|
||||
want = ST_SPEECH_LOAD_CHUNK;
|
||||
}
|
||||
if (fread(gSpeechBlob + done, 1u, (size_t)want, fp) != (size_t)want) {
|
||||
jlFree(gSpeechBlob);
|
||||
gSpeechBlob = 0;
|
||||
break;
|
||||
}
|
||||
done += want;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
static bool speechNext(void) {
|
||||
uint8_t row = 0u;
|
||||
|
||||
if (gSpeechBlob == 0) {
|
||||
return false;
|
||||
}
|
||||
if (gSpeechPitch > gSpeechPitchBase) {
|
||||
row = (uint8_t)(gSpeechPitch - gSpeechPitchBase);
|
||||
if (row >= gSpeechPitchCount) {
|
||||
row = (uint8_t)(gSpeechPitchCount - 1u);
|
||||
}
|
||||
}
|
||||
while (gSpeechHead != gSpeechTail) {
|
||||
uint8_t code = gSpeechQueue[gSpeechHead];
|
||||
const uint8_t *e = gSpeechBlob + ST_SPEECH_HEADER_BYTES + (uint16_t)row * gSpeechCount * ST_SPEECH_POLARITIES * ST_SPEECH_ENTRY_BYTES;
|
||||
uint8_t k;
|
||||
|
||||
gSpeechHead = (uint8_t)((gSpeechHead + 1u) % ST_SPEECH_QUEUE);
|
||||
for (k = 0u; k < gSpeechCount; k++, e += ST_SPEECH_POLARITIES * ST_SPEECH_ENTRY_BYTES) {
|
||||
if (e[0] == code) {
|
||||
const uint8_t *v = e + (uint16_t)gSpeechPol * ST_SPEECH_ENTRY_BYTES;
|
||||
uint32_t offset = (uint32_t)v[4] | ((uint32_t)v[5] << 8) | ((uint32_t)v[6] << 16) | ((uint32_t)v[7] << 24);
|
||||
|
||||
gSpeechParity = v[1];
|
||||
gSpeechSamples = (uint16_t)(v[2] | ((uint16_t)v[3] << 8));
|
||||
gSpeechSample = 0u;
|
||||
gSpeechPcm = gSpeechBlob + ST_SPEECH_HEADER_BYTES + (uint32_t)gSpeechPitchCount * gSpeechCount * ST_SPEECH_POLARITIES * ST_SPEECH_ENTRY_BYTES + offset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Unknown code: skip it rather than dropping the whole phrase.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Copy up to `count` samples of the queued utterances into `dst`, fewer
|
||||
// when they run out (0 = none left). jlMemCopy is an MVN on the IIgs;
|
||||
// the utterance bytes are already in the stream's format, so this is
|
||||
// the whole of the play-time speech work.
|
||||
static uint16_t speechDecode(uint8_t *dst, uint16_t count) {
|
||||
uint16_t n = 0u;
|
||||
|
||||
while (n < count) {
|
||||
uint16_t left = (uint16_t)(gSpeechSamples - gSpeechSample);
|
||||
uint16_t take = (uint16_t)(count - n);
|
||||
|
||||
if (left == 0u) {
|
||||
// The next utterance carries on from the level this one left.
|
||||
if (gSpeechParity != 0u) {
|
||||
gSpeechPol ^= 1u;
|
||||
}
|
||||
if (!speechNext()) {
|
||||
return n;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (take > left) {
|
||||
take = left;
|
||||
}
|
||||
jlMemCopy(dst + n, gSpeechPcm + gSpeechSample, take);
|
||||
gSpeechSample = (uint16_t)(gSpeechSample + take);
|
||||
n = (uint16_t)(n + take);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
// The audio engine's chunk pull. It used to decode the whole chunk right
|
||||
// here -- 7168 samples, ~1.5 s of speech, in ONE frame: every "HEY
|
||||
// TAXI" froze the ride for over a second on the IIgs. Now the chunk is
|
||||
// copied out of the staging buffer that speechPumpSlice fills a slice at
|
||||
// a time across the ticks before it is due, and only a stream that has
|
||||
// outrun the pump decodes here, a bounded slice, so it never starves.
|
||||
static uint32_t speechFill(void *ctx, int8_t *dst, uint32_t count) {
|
||||
uint16_t want = (count > ST_SPEECH_STAGE_BYTES) ? (uint16_t)ST_SPEECH_STAGE_BYTES : (uint16_t)count;
|
||||
uint16_t n;
|
||||
|
||||
(void)ctx;
|
||||
if (gSpeechStageCount == 0u && gSpeechDecoding) {
|
||||
speechPumpSlice(ST_SPEECH_STARVED_SLICE);
|
||||
}
|
||||
n = (gSpeechStageCount < want) ? gSpeechStageCount : want;
|
||||
if (n != 0u) {
|
||||
// jlMemCopy (MVN on the IIgs; libc memcpy is a byte loop there),
|
||||
// in two runs when the unread bytes wrap the ring's end.
|
||||
uint8_t *to = (uint8_t *)dst;
|
||||
uint16_t left = n;
|
||||
|
||||
while (left != 0u) {
|
||||
uint16_t run = (uint16_t)(ST_SPEECH_STAGE_BYTES - gSpeechStageRead);
|
||||
|
||||
if (run > left) {
|
||||
run = left;
|
||||
}
|
||||
jlMemCopy(to, gSpeechStage + gSpeechStageRead, run);
|
||||
to += run;
|
||||
gSpeechStageRead = (uint16_t)((gSpeechStageRead + run) & ST_SPEECH_STAGE_MASK);
|
||||
left = (uint16_t)(left - run);
|
||||
}
|
||||
gSpeechStageCount = (uint16_t)(gSpeechStageCount - n);
|
||||
}
|
||||
if (n == 0u) {
|
||||
// Out of queued utterances. Only END the stream if this chunk
|
||||
// produced nothing at all -- a phrase is fed one character at a
|
||||
// time ("HT" is "Hey" then "Taxi"), and the first arm decodes
|
||||
// all of 'H' before 'T' has even been queued. Ending here would
|
||||
// let the 'T' arm a NEW stream that cut 'H' off, so the player
|
||||
// only ever heard the last character. Returning a short chunk
|
||||
// keeps the slot armed and the next pull picks up whatever
|
||||
// arrived since.
|
||||
gSpeechActive = false;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
// Decode up to `samples` more into the staging buffer. Once the decoder
|
||||
// reports nothing left it stays quiet until the next speechArm. Reads
|
||||
// and writes stay even so the chunk copy can move words.
|
||||
static void speechPumpSlice(uint16_t samples) {
|
||||
uint16_t room = (uint16_t)(ST_SPEECH_STAGE_BYTES - gSpeechStageCount);
|
||||
|
||||
if (!gSpeechDecoding || room == 0u) {
|
||||
return;
|
||||
}
|
||||
if (samples > room) {
|
||||
samples = room;
|
||||
}
|
||||
// Fill towards the ring's end, then from its start.
|
||||
while (samples != 0u) {
|
||||
uint16_t run = (uint16_t)(ST_SPEECH_STAGE_BYTES - gSpeechStageWrite);
|
||||
uint16_t got;
|
||||
|
||||
if (run > samples) {
|
||||
run = samples;
|
||||
}
|
||||
got = speechDecode(gSpeechStage + gSpeechStageWrite, run);
|
||||
if (got < run) {
|
||||
gSpeechDecoding = false;
|
||||
}
|
||||
gSpeechStageWrite = (uint16_t)((gSpeechStageWrite + got) & ST_SPEECH_STAGE_MASK);
|
||||
gSpeechStageCount = (uint16_t)(gSpeechStageCount + got);
|
||||
samples = (uint16_t)(samples - got);
|
||||
if (!gSpeechDecoding) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void voiceOff(StSfxSlotT *slot) {
|
||||
if (slot->ticksLeft != 0u) {
|
||||
jlAudioVoice(slot->voice, 0u, ST_ATTEN_OFF);
|
||||
|
|
@ -71,6 +353,9 @@ static void voiceOff(StSfxSlotT *slot) {
|
|||
|
||||
// Once per game tick: run the release timers ($4320 sfxEnvelopeTick).
|
||||
void stAudioTick(void) {
|
||||
if (gSpeechActive) {
|
||||
speechPumpSlice(ST_SPEECH_TICK_SLICE);
|
||||
}
|
||||
if (gSfx.ticksLeft != 0u) {
|
||||
gSfx.ticksLeft--;
|
||||
if (gSfx.ticksLeft == 0u) {
|
||||
|
|
@ -83,23 +368,23 @@ void stAudioTick(void) {
|
|||
jlAudioVoice(gTone.voice, 0u, ST_ATTEN_OFF);
|
||||
}
|
||||
}
|
||||
if (gSpeechTicks != 0u) {
|
||||
gSpeechTicks--;
|
||||
if (gSpeechTicks == 0u) {
|
||||
jlAudioVoice(ST_VOICE_TONE, 0u, ST_ATTEN_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stAudioInit(void) {
|
||||
(void)jlAudioInit();
|
||||
gSpeechStage = (uint8_t *)jlAlloc(ST_SPEECH_STAGE_BYTES);
|
||||
speechLoad();
|
||||
gSfx.voice = ST_VOICE_SFX;
|
||||
gSfx.ticksLeft = 0u;
|
||||
gTone.voice = ST_VOICE_TONE;
|
||||
gTone.ticksLeft = 0u;
|
||||
gNoiseOn = false;
|
||||
gSpeechTicks = 0u;
|
||||
gSpeechHead = 0u;
|
||||
gSpeechTail = 0u;
|
||||
gSpeechActive = false;
|
||||
gSpeechPitch = ST_SPEECH_PITCH_BASE;
|
||||
gSpeechPol = 0u;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -108,6 +393,10 @@ void stAudioShutdown(void) {
|
|||
voiceOff(&gTone);
|
||||
jlAudioNoise(0u, ST_ATTEN_OFF);
|
||||
jlAudioShutdown();
|
||||
jlFree(gSpeechStage);
|
||||
gSpeechStage = 0;
|
||||
jlFree(gSpeechBlob);
|
||||
gSpeechBlob = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -151,10 +440,112 @@ void stAudioSilence(void) {
|
|||
}
|
||||
|
||||
|
||||
// $9802 -- one spoken character (a chirp here).
|
||||
// $44CF -- play one of the game's tunes and block. The C64 silences the
|
||||
// SID first ($5C1A / $6906) and then spins until the song ends; the host
|
||||
// does the spinning (ST_STATE_JINGLE), so here it is just the start.
|
||||
void stAudioJingle(uint8_t song) {
|
||||
stAudioMusic(song, false);
|
||||
}
|
||||
|
||||
|
||||
// $CB02 -- start a tune and leave it to the player: the level intro's
|
||||
// song and the high-score table's. Speech is cancelled too: it streams
|
||||
// on the slot the tracker's voice 0 rides.
|
||||
void stAudioMusic(uint8_t song, bool loop) {
|
||||
if (song >= ST_SONG_COUNT) {
|
||||
return;
|
||||
}
|
||||
stAudioSilence();
|
||||
stAudioNoise(false);
|
||||
gSpeechActive = false;
|
||||
gSpeechDecoding = false;
|
||||
gSpeechStageRead = 0u;
|
||||
gSpeechStageWrite = 0u;
|
||||
gSpeechStageCount = 0u;
|
||||
gSpeechHead = gSpeechTail;
|
||||
jlAudioStopSfx(ST_SPEECH_SLOT);
|
||||
jlMusicPlay(kStSongs[song].data, kStSongs[song].length, loop);
|
||||
}
|
||||
|
||||
|
||||
bool stAudioJingleActive(void) {
|
||||
return jlMusicIsPlaying();
|
||||
}
|
||||
|
||||
|
||||
// Queue one utterance code. Returns false when the code is not speech (a
|
||||
// pitch change) or the queue is full.
|
||||
static bool speechQueue(uint8_t ch) {
|
||||
uint8_t next;
|
||||
|
||||
if (ch < 9u) {
|
||||
// Below $09 the original does not speak: it rewrites the delay
|
||||
// loop's inner count, re-pitching every later utterance. That is
|
||||
// where the passenger's voice variation comes from, so keep it.
|
||||
gSpeechPitch = (uint8_t)(ch & ST_SPEECH_PITCH_MAX);
|
||||
if (gSpeechPitch == 0u) {
|
||||
gSpeechPitch = ST_SPEECH_PITCH_BASE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
next = (uint8_t)((gSpeechTail + 1u) % ST_SPEECH_QUEUE);
|
||||
if (next == gSpeechHead) {
|
||||
return false; // queue full; drop rather than stall
|
||||
}
|
||||
gSpeechQueue[gSpeechTail] = ch;
|
||||
gSpeechTail = next;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Start the stream if it is idle. Call this ONCE, after the whole phrase is
|
||||
// queued: arming decodes everything queued so far into a single chunk, and
|
||||
// each extra chunk costs a refill deadline of dead air, because the refill
|
||||
// only happens when the game next calls jlAudioFrameTick -- once per rendered
|
||||
// frame. Arming per character is what broke phrases into words with silence
|
||||
// between them.
|
||||
static void speechArm(void) {
|
||||
if (gSpeechActive || gSpeechStage == 0 || gSpeechBlob == 0) {
|
||||
return;
|
||||
}
|
||||
if (!speechNext()) {
|
||||
return;
|
||||
}
|
||||
gSpeechPol = 0u; // a phrase starts on +100
|
||||
gSpeechActive = true;
|
||||
gSpeechDecoding = true;
|
||||
gSpeechStageRead = 0u;
|
||||
gSpeechStageWrite = 0u;
|
||||
gSpeechStageCount = 0u;
|
||||
// A first slice now, so the opening chunk sounds this tick.
|
||||
speechPumpSlice(ST_SPEECH_ARM_SLICE);
|
||||
jlAudioPlaySfxStreamRaw(ST_SPEECH_SLOT, speechFill, (void *)0, ST_SPEECH_RATE);
|
||||
}
|
||||
|
||||
|
||||
// $9802 -- one spoken character. Speaks immediately; prefer
|
||||
// stAudioSpeechPhrase for anything longer than a single code.
|
||||
void stAudioSpeech(uint8_t ch) {
|
||||
jlAudioVoice(ST_VOICE_TONE, (uint16_t)(ST_SPEECH_BASE_HZ + (uint16_t)(ch & 0x1Fu) * ST_SPEECH_STEP_HZ), ST_ATTEN_LOUD);
|
||||
gSpeechTicks = ST_SPEECH_TICKS;
|
||||
if (speechQueue(ch)) {
|
||||
speechArm();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// A whole phrase: queue every code FIRST, then arm once, so the phrase
|
||||
// decodes into as few chunks as it fits into.
|
||||
void stAudioSpeechPhrase(const uint8_t *speech) {
|
||||
bool any = false;
|
||||
|
||||
while (*speech != 0u) {
|
||||
if (speechQueue(*speech)) {
|
||||
any = true;
|
||||
}
|
||||
speech++;
|
||||
}
|
||||
if (any) {
|
||||
speechArm();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
14
stC64Data.c
14
stC64Data.c
|
|
@ -1322,10 +1322,6 @@ const uint8_t kStFlameCelByDirMask[16] = {
|
|||
0x00, 0xD8, 0xD4, 0x00, 0xD5, 0xD2, 0xD1, 0x00, 0xD7, 0xD3, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const int8_t kStIntroStarDx[7] = { 0, 6, 6, 6, -6, -6, -6 };
|
||||
const int8_t kStIntroStarDy[7] = { -4, -4, 0, 4, 4, 0, -4 };
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Accessors. On the IIgs the program is split across banks and a 2-byte
|
||||
|
|
@ -1358,13 +1354,3 @@ const uint8_t *stC64SfxProgram(uint8_t idx) {
|
|||
uint8_t stC64FlameCel(uint8_t dirMask) {
|
||||
return kStFlameCelByDirMask[dirMask];
|
||||
}
|
||||
|
||||
|
||||
int8_t stC64IntroStarDx(uint8_t idx) {
|
||||
return kStIntroStarDx[idx];
|
||||
}
|
||||
|
||||
|
||||
int8_t stC64IntroStarDy(uint8_t idx) {
|
||||
return kStIntroStarDy[idx];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,10 +44,6 @@ extern const uint8_t kStSfxPrograms[ST_SFX_COUNT][ST_SFX_PROGRAM_BYTES];
|
|||
// 8=RIGHT); 0 = no cel for that combination.
|
||||
extern const uint8_t kStFlameCelByDirMask[16];
|
||||
|
||||
// Level-intro star velocities per sprite 0..6 ($450C / $4513).
|
||||
extern const int8_t kStIntroStarDx[7];
|
||||
extern const int8_t kStIntroStarDy[7];
|
||||
|
||||
// Cross-segment-safe accessors (see stC64Data.c): reach the tables above
|
||||
// by an inter-segment call on the IIgs, where a direct 2-byte data
|
||||
// reference from another bank is not relocatable.
|
||||
|
|
@ -56,7 +52,5 @@ const uint8_t *stC64SpriteBitmap(uint8_t idx);
|
|||
uint8_t stC64RngByte(uint8_t idx);
|
||||
const uint8_t *stC64SfxProgram(uint8_t idx);
|
||||
uint8_t stC64FlameCel(uint8_t dirMask);
|
||||
int8_t stC64IntroStarDx(uint8_t idx);
|
||||
int8_t stC64IntroStarDy(uint8_t idx);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
7
stCels.h
7
stCels.h
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "stSim.h"
|
||||
|
||||
// 3x3 tiles = 24x24 px; 32 bytes per 8x8 tile, tile-major (matches
|
||||
// jlSpriteCreateFromSurface / the .spr cel layout).
|
||||
#define ST_CEL_TILES 3u
|
||||
|
|
@ -29,6 +31,11 @@ typedef struct {
|
|||
extern const StCelDefT kStCels[];
|
||||
extern const uint16_t kStCelCount;
|
||||
|
||||
// The cels a level's hook program can show (stLevelCels.c): at most `max`
|
||||
// into `out`, no duplicates. 0 for a level without hook sprites.
|
||||
#define ST_LEVEL_CELS_MAX 40u
|
||||
uint8_t stLevelCelList(const StLevelT *level, StCelDefT *out, uint8_t max);
|
||||
|
||||
// Expand a VIC bitmap (63 bytes, 21 rows x 3, or NULL) into the 288-byte
|
||||
// tile-major 4bpp-packed cel blob. Colours as in the C64 multicolour
|
||||
// rules; hires uses `color` for a set bit.
|
||||
|
|
|
|||
95
stFare.c
95
stFare.c
|
|
@ -11,17 +11,16 @@
|
|||
#include "stSim.h"
|
||||
|
||||
// Screen-code strings ($6C1E..$6C7D). All ASCII-compatible glyphs.
|
||||
static const uint8_t kTextPadPlease[] = { 0x50, 0x41, 0x44, 0x20, 0x20, 0x20, 0x50, 0x4C, 0x45, 0x41, 0x53, 0x45, 0 }; // $6C1E "PAD PLEASE"
|
||||
static const uint8_t kTextUpPlease[] = { 0x20, 0x55, 0x50, 0x20, 0x50, 0x4C, 0x45, 0x41, 0x53, 0x45, 0x21, 0x20, 0 }; // $6C2B " UP PLEASE! "
|
||||
static const uint8_t kTextBlank[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0 }; // $6C38
|
||||
static const uint8_t kTextHeyTaxi[] = { 0x20, 0x48, 0x45, 0x59, 0x2C, 0x20, 0x54, 0x41, 0x58, 0x49, 0x21, 0x20, 0 }; // $6C45 " HEY, TAXI! "
|
||||
static const uint8_t kTextThanks[] = { 0x20, 0x20, 0x20, 0x54, 0x48, 0x41, 0x4E, 0x4B, 0x53, 0x20, 0x20, 0x20, 0 }; // $6C5F " THANKS "
|
||||
static const uint8_t kTextPadPlease[] = "PAD PLEASE"; // $6C1E
|
||||
static const uint8_t kTextUpPlease[] = " UP PLEASE! "; // $6C2B
|
||||
static const uint8_t kTextHeyTaxi[] = " HEY, TAXI! "; // $6C45
|
||||
static const uint8_t kTextThanks[] = " THANKS "; // $6C5F
|
||||
// Speech cue strings fed to the sample player one character at a time.
|
||||
static const uint8_t kSpeechHeyTaxi[] = { 0x48, 0x54, 0 }; // $6C6C "HT"
|
||||
static const uint8_t kSpeechUp[] = { 0x55, 0x3F, 0 }; // $6C6F "U?"
|
||||
static const uint8_t kSpeechPad[] = { 0x50, 0x58, 0x3F, 0 }; // $6C72 "PX?" (X = digit)
|
||||
static const uint8_t kSpeechThanks[] = { 0x21, 0 }; // $6C76 "!"
|
||||
static const uint8_t kSpeechHey[] = { 0x48, 0 }; // $6C78 "H"
|
||||
static const uint8_t kSpeechHeyTaxi[] = "HT"; // $6C6C
|
||||
static const uint8_t kSpeechUp[] = "U?"; // $6C6F
|
||||
static const uint8_t kSpeechPad[] = "PX?"; // $6C72 (X = digit)
|
||||
static const uint8_t kSpeechThanks[] = "!"; // $6C76
|
||||
static const uint8_t kSpeechHey[] = "H"; // $6C78
|
||||
// Waiting wave cycle ($66D6) and the base-fare blob ($43B9 = +5.00).
|
||||
static const uint8_t kWaveCels[4] = { 0xC6, 0xC7, 0xD9, 0xC7 };
|
||||
static const uint8_t kFareBlob[7] = { 0x66, 0x66, 0x66, 0x6F, 0x77, 0x74, 0x74 };
|
||||
|
|
@ -45,12 +44,12 @@ static void beamIn(StSimT *sim) {
|
|||
return;
|
||||
}
|
||||
sim->spr[1].ptr--;
|
||||
if (sim->spr[1].ptr != 0xC7u) {
|
||||
if (sim->spr[1].ptr != ST_SPRITE_PASS_STAND) {
|
||||
return;
|
||||
}
|
||||
if (sim->collisionPhase != 0u) {
|
||||
sim->stage = ST_STAGE_LEAVE;
|
||||
sim->spr[1].ptr = 0xC7u;
|
||||
sim->spr[1].ptr = ST_SPRITE_PASS_STAND;
|
||||
sim->spriteSlots[sim->activeSpriteIdx] = 0u;
|
||||
sim->activeSpriteIdx = 0u;
|
||||
sim->fareSlotCount--;
|
||||
|
|
@ -60,15 +59,9 @@ static void beamIn(StSimT *sim) {
|
|||
stSimDrawText(sim, 14u, 24u, kTextHeyTaxi, 1u);
|
||||
stFareBoardingSound(sim, kSpeechHeyTaxi);
|
||||
// $43D1: the meter starts at $10.00..$19.00.
|
||||
{
|
||||
uint8_t k;
|
||||
static const uint8_t kTemplate[7] = { 0x66, 0x66, 0x66, 0x74, 0x77, 0x74, 0x74 };
|
||||
for (k = 0u; k < ST_NUMBER_CHARS; k++) {
|
||||
stSimPutChar(sim, (uint8_t)(32u + k), 24u, kTemplate[k]);
|
||||
}
|
||||
stSimPutChar(sim, 35u, 24u, (uint8_t)(ST_CHAR_DIGIT_BASE + stSimRng(sim, 10u)));
|
||||
stSimPutChar(sim, 34u, 24u, (uint8_t)(ST_CHAR_DIGIT_BASE + 1u));
|
||||
}
|
||||
stSimHudInit(sim);
|
||||
stSimPutChar(sim, 35u, 24u, (uint8_t)(ST_CHAR_DIGIT_BASE + stSimRng(sim, 10u)));
|
||||
stSimPutChar(sim, 34u, 24u, (uint8_t)(ST_CHAR_DIGIT_BASE + 1u));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -125,7 +118,7 @@ static void newFare(StSimT *sim) {
|
|||
sim->spr[1].enable = 1u;
|
||||
sim->stage = ST_STAGE_BEAM_IN;
|
||||
sim->decayTimer = sim->decayReload;
|
||||
sim->spr[1].ptr = 0xCBu;
|
||||
sim->spr[1].ptr = ST_SPRITE_PASS_BEAM;
|
||||
stAudioSpeech((uint8_t)(stSimRng(sim, 3u) + 2u));
|
||||
}
|
||||
|
||||
|
|
@ -136,14 +129,14 @@ static void stageBoard(StSimT *sim) {
|
|||
return;
|
||||
}
|
||||
sim->spr[1].ptr++;
|
||||
if (sim->spr[1].ptr != 0xCCu) {
|
||||
if (sim->spr[1].ptr != ST_SPRITE_PASS_GONE) {
|
||||
return;
|
||||
}
|
||||
sim->spr[1].enable = 0u;
|
||||
sim->stage++;
|
||||
sim->activeDyingSlot = sim->activePad;
|
||||
(void)stFareChooseDestination(sim);
|
||||
if (sim->activeSpriteIdx == 0x0Bu) {
|
||||
if (sim->activeSpriteIdx == ST_FARE_DEST_UP) {
|
||||
return;
|
||||
}
|
||||
stSimDrawText(sim, 14u, 24u, kTextPadPlease, 1u);
|
||||
|
|
@ -164,7 +157,7 @@ static void stageCleanup(StSimT *sim) {
|
|||
sim->deathInProgress = 0u;
|
||||
sim->stage = ST_STAGE_IDLE;
|
||||
stSimPadLight(sim, false);
|
||||
stSimDrawText(sim, 14u, 24u, kTextBlank, 1u);
|
||||
stSimClearMessage(sim);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -176,7 +169,7 @@ static void stageDropIn(StSimT *sim) {
|
|||
return;
|
||||
}
|
||||
sim->spr[1].ptr--;
|
||||
if (sim->spr[1].ptr != 0xC7u) {
|
||||
if (sim->spr[1].ptr != ST_SPRITE_PASS_STAND) {
|
||||
return;
|
||||
}
|
||||
sim->stage++;
|
||||
|
|
@ -184,13 +177,7 @@ static void stageDropIn(StSimT *sim) {
|
|||
stFareBoardingSound(sim, kSpeechThanks);
|
||||
stSimBcdAdd(sim, ST_CELL_SCORE, kFareBlob);
|
||||
stSimBcdAdd(sim, ST_CELL_SCORE, &sim->screen[ST_CELL_FARE]);
|
||||
{
|
||||
static const uint8_t kTemplate[7] = { 0x66, 0x66, 0x66, 0x74, 0x77, 0x74, 0x74 };
|
||||
uint8_t k;
|
||||
for (k = 0u; k < ST_NUMBER_CHARS; k++) {
|
||||
stSimPutChar(sim, (uint8_t)(32u + k), 24u, kTemplate[k]);
|
||||
}
|
||||
}
|
||||
stSimHudInit(sim);
|
||||
if (sim->fareSlotCount != 0u) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -204,7 +191,7 @@ void stFareLeaveStep(StSimT *sim) {
|
|||
return;
|
||||
}
|
||||
sim->spr[1].ptr++;
|
||||
if (sim->spr[1].ptr != 0xCCu) {
|
||||
if (sim->spr[1].ptr != ST_SPRITE_PASS_GONE) {
|
||||
return;
|
||||
}
|
||||
sim->spr[1].enable = 0u;
|
||||
|
|
@ -227,24 +214,19 @@ void stFareWaveStep(StSimT *sim) {
|
|||
void stFareWalkStep(StSimT *sim) {
|
||||
int16_t passX;
|
||||
int16_t targetX;
|
||||
uint16_t sum;
|
||||
|
||||
sim->walkParity ^= 1u;
|
||||
passX = (int16_t)(((int16_t)sim->spr[1].msb << 8) | sim->spr[1].col);
|
||||
passX = (int16_t)stSimSpriteX(sim, 1u);
|
||||
targetX = (int16_t)(((int16_t)sim->hoverXFrac << 8) | sim->hoverXCol);
|
||||
if ((int16_t)(passX - targetX) < 0) {
|
||||
// $6D30: walk right, cels $C2/$C3.
|
||||
sim->spr[1].ptr = (uint8_t)(0xC2u + sim->walkParity);
|
||||
sum = (uint16_t)((uint16_t)sim->spr[1].col + 2u);
|
||||
sim->spr[1].col = (uint8_t)sum;
|
||||
sim->spr[1].msb = (uint8_t)(sim->spr[1].msb + (uint8_t)(sum >> 8));
|
||||
sim->spr[1].ptr = (uint8_t)(ST_SPRITE_PASS_WALK_R + sim->walkParity);
|
||||
stSimSpriteAddX(sim, 1u, 2u);
|
||||
return;
|
||||
}
|
||||
// $6D4B: walk left, cels $C4/$C5.
|
||||
sim->spr[1].ptr = (uint8_t)(0xC4u + sim->walkParity);
|
||||
sum = (uint16_t)((uint16_t)sim->spr[1].col + 0xFEu);
|
||||
sim->spr[1].col = (uint8_t)sum;
|
||||
sim->spr[1].msb = (uint8_t)(sim->spr[1].msb + 0xFFu + (uint8_t)(sum >> 8));
|
||||
sim->spr[1].ptr = (uint8_t)(ST_SPRITE_PASS_WALK_L + sim->walkParity);
|
||||
stSimSpriteAddX(sim, 1u, 0xFEu);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -255,7 +237,7 @@ static void walkToTarget(StSimT *sim) {
|
|||
return;
|
||||
}
|
||||
if ((sim->spr[1].col & 0xFEu) == (sim->hoverXCol & 0xFEu)) {
|
||||
sim->spr[1].ptr = 0xC7u;
|
||||
sim->spr[1].ptr = ST_SPRITE_PASS_STAND;
|
||||
sim->stage++;
|
||||
return;
|
||||
}
|
||||
|
|
@ -272,17 +254,14 @@ void stFareBoardingSound(StSimT *sim, const uint8_t *speech) {
|
|||
(void)sim;
|
||||
stAudioSilence();
|
||||
stAudioNoise(false);
|
||||
while (*speech != 0u) {
|
||||
stAudioSpeech(*speech);
|
||||
speech++;
|
||||
}
|
||||
stAudioSpeechPhrase(speech);
|
||||
}
|
||||
|
||||
|
||||
// $6537 -- reserve a free fare pad by RNG (linear probe on collision),
|
||||
// or "UP PLEASE" once every fare pad is taken. Returns the pad number.
|
||||
uint8_t stFareChooseDestination(StSimT *sim) {
|
||||
uint8_t special = sim->level->specialPad;
|
||||
uint8_t special = sim->specialPad;
|
||||
uint8_t x;
|
||||
|
||||
if (sim->fareSlotCount == special) {
|
||||
|
|
@ -349,7 +328,7 @@ void stFarePostTickGate(StSimT *sim) {
|
|||
sim->spr[1].msb = sim->spr[0].msb;
|
||||
sim->spr[1].col = sim->spr[0].col;
|
||||
sim->spr[1].row = sim->spr[0].row;
|
||||
sim->spr[1].ptr = 0xCBu;
|
||||
sim->spr[1].ptr = ST_SPRITE_PASS_BEAM;
|
||||
sim->decayTimer = sim->decayReload;
|
||||
pad = &sim->pads[sim->activeSpriteIdx - 1u];
|
||||
sim->hoverXFrac = pad->passMsb;
|
||||
|
|
@ -374,7 +353,7 @@ void stFareSquashed(StSimT *sim) {
|
|||
sim->spriteSlots[sim->activeSpriteIdx] = 0u;
|
||||
sim->activeSpriteIdx = 0u;
|
||||
sim->fareSlotCount--;
|
||||
stSimDrawText(sim, 14u, 24u, kTextBlank, 1u);
|
||||
stSimClearMessage(sim);
|
||||
}
|
||||
sim->stage = ST_STAGE_LEAVE;
|
||||
stFareBoardingSound(sim, kSpeechHey);
|
||||
|
|
@ -387,14 +366,8 @@ void stFareSquashed(StSimT *sim) {
|
|||
// $43F3 counts down in the input-mask byte and leaves it zero.
|
||||
sim->inputMask = 0u;
|
||||
}
|
||||
sim->spr[1].ptr = 0xC7u;
|
||||
{
|
||||
static const uint8_t kTemplate[7] = { 0x66, 0x66, 0x66, 0x74, 0x77, 0x74, 0x74 };
|
||||
uint8_t k;
|
||||
for (k = 0u; k < ST_NUMBER_CHARS; k++) {
|
||||
stSimPutChar(sim, (uint8_t)(32u + k), 24u, kTemplate[k]);
|
||||
}
|
||||
}
|
||||
sim->spr[1].ptr = ST_SPRITE_PASS_STAND;
|
||||
stSimHudInit(sim);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -442,7 +415,7 @@ void stFareStageDispatch(StSimT *sim) {
|
|||
void stFareUpPlease(StSimT *sim) {
|
||||
uint8_t k;
|
||||
|
||||
sim->activeSpriteIdx = 0x0Bu;
|
||||
sim->activeSpriteIdx = ST_FARE_DEST_UP;
|
||||
stSimDrawText(sim, 14u, 24u, kTextUpPlease, 1u);
|
||||
for (k = 0u; k < 4u; k++) {
|
||||
stSimPutChar(sim, (uint8_t)(18u + k), 0u, ST_CHAR_SPACE);
|
||||
|
|
|
|||
85
stHookTables.h
Normal file
85
stHookTables.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// Space Taxi -- where each level's hook program keeps its tables.
|
||||
//
|
||||
// Every address is a byte in the level's shipped hook blob ($7D98..$7FFF,
|
||||
// StLevelT.hookData), so the same numbers serve the hook programs
|
||||
// (stHooks.c, reading through the live simulation) and the cel manifest
|
||||
// (stLevelCels.c, reading the level file alone -- the offline cel baker
|
||||
// has no simulation). One list, two readers.
|
||||
#ifndef ST_HOOK_TABLES_H
|
||||
#define ST_HOOK_TABLES_H
|
||||
|
||||
// Level indices (0 = A).
|
||||
#define ST_LEVEL_E 4u
|
||||
#define ST_LEVEL_G 6u
|
||||
#define ST_LEVEL_H 7u
|
||||
#define ST_LEVEL_I 8u
|
||||
#define ST_LEVEL_J 9u
|
||||
#define ST_LEVEL_K 10u
|
||||
#define ST_LEVEL_L 11u
|
||||
#define ST_LEVEL_O 14u
|
||||
#define ST_LEVEL_P 15u
|
||||
#define ST_LEVEL_Q 16u
|
||||
#define ST_LEVEL_R 17u
|
||||
#define ST_LEVEL_S 18u
|
||||
#define ST_LEVEL_T 19u
|
||||
#define ST_LEVEL_U 20u
|
||||
#define ST_LEVEL_V 21u
|
||||
#define ST_LEVEL_W 22u
|
||||
#define ST_LEVEL_X 23u
|
||||
|
||||
// Hardware sprites 3..7 are the hook sprites on every level that has any.
|
||||
#define ST_HOOK_FIRST_SPRITE 3u
|
||||
|
||||
// ---- level G "TELEPORTS" ----
|
||||
#define ST_HK_G_CEL 0x7DD4u // 6 cels the orbs cycle through
|
||||
#define ST_HK_G_CEL_PHASES 6u
|
||||
#define ST_HK_G_ORB_COL 0x7DDAu // per sprite: start column, msb, row
|
||||
#define ST_HK_G_ORB_MSB 0x7DE2u
|
||||
#define ST_HK_G_ORB_ROW 0x7DEAu
|
||||
#define ST_HK_G_SPOT_COL 0x7EF3u // 5 landing spots: column, msb, row
|
||||
#define ST_HK_G_SPOT_MSB 0x7EF8u
|
||||
#define ST_HK_G_SPOT_ROW 0x7EFDu
|
||||
#define ST_HK_G_SFX_HOP 0x7F03u
|
||||
#define ST_HK_G_ORB_COLOR 4u
|
||||
|
||||
// ---- level H "PUZZLER" ----
|
||||
#define ST_HK_H_CEL 0x80u // the one sprite cel
|
||||
#define ST_HK_H_COLOR_IDLE 0x01u
|
||||
#define ST_HK_H_COLOR_LIT 0x0Au
|
||||
#define ST_HK_H_COLOR_ACTIVE 0x05u
|
||||
|
||||
// ---- level I "CROSSFIRE" ----
|
||||
#define ST_HK_I_CEL_RISE 0x7DD8u // 5 cels
|
||||
#define ST_HK_I_RISE_PHASES 5u
|
||||
#define ST_HK_I_CEL_BURST 0x7DE5u // 8 cels
|
||||
#define ST_HK_I_BURST_PHASES 8u
|
||||
#define ST_HK_I_COLOR 0x7E7Fu // 3 colours
|
||||
#define ST_HK_I_COLORS 3u
|
||||
#define ST_HK_I_COLOR_IDLE 0x02u
|
||||
|
||||
// ---- levels J "SHOOTING STARS" and P "BLIZZARD" (the falling hazards) ----
|
||||
#define ST_HK_FALL_CEL 0x80u // falling: $80/$81
|
||||
#define ST_HK_FALL_CEL_BURST 0x82u // then the burst run from the table
|
||||
#define ST_HK_J_CEL_BURST 0x7EC9u // phases 1..9
|
||||
#define ST_HK_J_BURST_PHASES 10u
|
||||
#define ST_HK_J_COLOR 7u
|
||||
#define ST_HK_P_CEL_BURST 0x7F09u // phases 1..4
|
||||
#define ST_HK_P_BURST_PHASES 5u
|
||||
#define ST_HK_P_COLOR 3u
|
||||
|
||||
// ---- level L "BLACK HOLE" ----
|
||||
#define ST_HK_L_CEL_FIRST 0x80u // $80..$82 spin
|
||||
#define ST_HK_L_CEL_END 0x83u
|
||||
#define ST_HK_L_COLOR 0u
|
||||
|
||||
// ---- level Q "INTERFERENCE" ----
|
||||
#define ST_HK_Q_CEL 0x7DF2u // 12 cels, multicolour
|
||||
#define ST_HK_Q_CEL_PHASES 12u
|
||||
#define ST_HK_Q_COLOR 6u
|
||||
|
||||
// ---- level U "REBOUND" ----
|
||||
#define ST_HK_U_CEL 0x7F4Bu // 4-entry walk over $80..$82
|
||||
#define ST_HK_U_CEL_PHASES 4u
|
||||
#define ST_HK_U_COLOR 7u
|
||||
|
||||
#endif // ST_HOOK_TABLES_H
|
||||
114
stLevelCels.c
Normal file
114
stLevelCels.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
// Space Taxi -- the cels a level's hook program can put on screen.
|
||||
//
|
||||
// Hook sprites are built from the level's own VIC bitmaps in whatever
|
||||
// colour the hook gives them, and compiling one on the 65816 costs about
|
||||
// half a second -- far too long to do the first time a cel appears mid-
|
||||
// ride. So every level lists its cels up front, from the same hook
|
||||
// tables the hook program reads (stHookTables.h): the offline baker turns
|
||||
// the list into a pre-compiled bank (sprites/levelNN.spc) and the game
|
||||
// compiles whatever the bank does not supply BEFORE the ride starts.
|
||||
//
|
||||
// Only the level file is needed, no simulation, so the baker can link
|
||||
// this on the host without the rest of the game.
|
||||
|
||||
#include "stCels.h"
|
||||
#include "stHookTables.h"
|
||||
|
||||
#define HKL(level, addr) ((level)->hookData[(addr) - ST_HOOK_BASE])
|
||||
|
||||
static void celAdd(StCelDefT *out, uint8_t *count, uint8_t max, uint8_t ptr, uint8_t color, uint8_t multi, uint8_t mc0, uint8_t mc1);
|
||||
|
||||
|
||||
// Append one cel unless the list already has it.
|
||||
static void celAdd(StCelDefT *out, uint8_t *count, uint8_t max, uint8_t ptr, uint8_t color, uint8_t multi, uint8_t mc0, uint8_t mc1) {
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < *count; k++) {
|
||||
if (out[k].ptr == ptr && out[k].color == color && out[k].multi == multi && out[k].mc0 == mc0 && out[k].mc1 == mc1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (*count == max) {
|
||||
return;
|
||||
}
|
||||
out[*count].ptr = ptr;
|
||||
out[*count].color = color;
|
||||
out[*count].multi = multi;
|
||||
out[*count].mc0 = mc0;
|
||||
out[*count].mc1 = mc1;
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
|
||||
uint8_t stLevelCelList(const StLevelT *level, StCelDefT *out, uint8_t max) {
|
||||
uint8_t n = 0u;
|
||||
uint8_t k;
|
||||
uint8_t c;
|
||||
|
||||
switch (level->levelIndex) {
|
||||
case ST_LEVEL_G:
|
||||
for (k = 0u; k < ST_HK_G_CEL_PHASES; k++) {
|
||||
celAdd(out, &n, max, HKL(level, ST_HK_G_CEL + k), ST_HK_G_ORB_COLOR, 0u, 0u, 0u);
|
||||
}
|
||||
break;
|
||||
case ST_LEVEL_H:
|
||||
celAdd(out, &n, max, ST_HK_H_CEL, ST_HK_H_COLOR_IDLE, 0u, 0u, 0u);
|
||||
celAdd(out, &n, max, ST_HK_H_CEL, ST_HK_H_COLOR_LIT, 0u, 0u, 0u);
|
||||
celAdd(out, &n, max, ST_HK_H_CEL, ST_HK_H_COLOR_ACTIVE, 0u, 0u, 0u);
|
||||
break;
|
||||
case ST_LEVEL_I:
|
||||
// Every cel in the idle colour and in each of the three the
|
||||
// launcher picks at random.
|
||||
for (c = 0u; c <= ST_HK_I_COLORS; c++) {
|
||||
uint8_t color = (c == 0u) ? ST_HK_I_COLOR_IDLE : HKL(level, ST_HK_I_COLOR + c - 1u);
|
||||
for (k = 0u; k < ST_HK_I_RISE_PHASES; k++) {
|
||||
celAdd(out, &n, max, HKL(level, ST_HK_I_CEL_RISE + k), color, 0u, 0u, 0u);
|
||||
}
|
||||
for (k = 0u; k < ST_HK_I_BURST_PHASES; k++) {
|
||||
celAdd(out, &n, max, HKL(level, ST_HK_I_CEL_BURST + k), color, 0u, 0u, 0u);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_LEVEL_J:
|
||||
celAdd(out, &n, max, ST_HK_FALL_CEL, ST_HK_J_COLOR, 0u, 0u, 0u);
|
||||
celAdd(out, &n, max, (uint8_t)(ST_HK_FALL_CEL + 1u), ST_HK_J_COLOR, 0u, 0u, 0u);
|
||||
celAdd(out, &n, max, ST_HK_FALL_CEL_BURST, ST_HK_J_COLOR, 0u, 0u, 0u);
|
||||
for (k = 1u; k < ST_HK_J_BURST_PHASES; k++) {
|
||||
celAdd(out, &n, max, HKL(level, ST_HK_J_CEL_BURST + k), ST_HK_J_COLOR, 0u, 0u, 0u);
|
||||
}
|
||||
break;
|
||||
case ST_LEVEL_L:
|
||||
for (k = ST_HK_L_CEL_FIRST; k < ST_HK_L_CEL_END; k++) {
|
||||
celAdd(out, &n, max, k, ST_HK_L_COLOR, 0u, 0u, 0u);
|
||||
}
|
||||
break;
|
||||
case ST_LEVEL_P:
|
||||
celAdd(out, &n, max, ST_HK_FALL_CEL, ST_HK_P_COLOR, 0u, 0u, 0u);
|
||||
celAdd(out, &n, max, (uint8_t)(ST_HK_FALL_CEL + 1u), ST_HK_P_COLOR, 0u, 0u, 0u);
|
||||
celAdd(out, &n, max, ST_HK_FALL_CEL_BURST, ST_HK_P_COLOR, 0u, 0u, 0u);
|
||||
for (k = 1u; k < ST_HK_P_BURST_PHASES; k++) {
|
||||
celAdd(out, &n, max, HKL(level, ST_HK_P_CEL_BURST + k), ST_HK_P_COLOR, 0u, 0u, 0u);
|
||||
}
|
||||
break;
|
||||
case ST_LEVEL_Q:
|
||||
// The hook's cels show HIRES in colour 6 for the whole recorded
|
||||
// ride (tools/stsim STSIM_CELS census, 2026-09-22); the
|
||||
// multicolour variant (the level's own $D025/$D026) stays
|
||||
// listed for the phases the census did not reach.
|
||||
for (k = 0u; k < ST_HK_Q_CEL_PHASES; k++) {
|
||||
celAdd(out, &n, max, HKL(level, ST_HK_Q_CEL + k), ST_HK_Q_COLOR, 0u, 0u, 0u);
|
||||
}
|
||||
for (k = 0u; k < ST_HK_Q_CEL_PHASES; k++) {
|
||||
celAdd(out, &n, max, HKL(level, ST_HK_Q_CEL + k), ST_HK_Q_COLOR, 1u, level->header[5], level->header[6]);
|
||||
}
|
||||
break;
|
||||
case ST_LEVEL_U:
|
||||
for (k = 0u; k < ST_HK_U_CEL_PHASES; k++) {
|
||||
celAdd(out, &n, max, HKL(level, ST_HK_U_CEL + k), ST_HK_U_COLOR, 0u, 0u, 0u);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
354
stMarshalIigs.s
Normal file
354
stMarshalIigs.s
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
; stMarshalIigs.s - Space Taxi's stSimMarshal for the Apple IIgs.
|
||||
;
|
||||
; GAS syntax for the llvm-mos w65816 toolchain (see src/iigs/peislam.s
|
||||
; for the conventions). The C version copies eight sprites' shadow
|
||||
; registers into the displayed frame through far pointers, which the
|
||||
; w65816 backend turns into ~5000 cycles of pointer re-materialisation
|
||||
; per tick (5% of a ride frame). This is the same copy as straight-line
|
||||
; [dp],y moves: ~700 cycles.
|
||||
;
|
||||
; void stSimMarshalIigs(const StMarshalArgsT *args)
|
||||
; args (A = low word, X = bank) points at { spr, frame, multi }:
|
||||
; +0 const StSpriteT *spr (32-bit: low word, bank word)
|
||||
; +4 StFrameT *frame
|
||||
; +8 uint8_t multi
|
||||
; StSpriteT (6 bytes): col, msb, row, enable, ptr, color.
|
||||
; StFrameT: x[8] (u16, +0), y[8] (+16), ptr[8] (+24), color[8] (+32),
|
||||
; enableMask (+40), multiMask (+41).
|
||||
; stSim.c checks these layouts at compile time.
|
||||
;
|
||||
; Every store runs with M=16 and writes two bytes: the byte after each
|
||||
; single-byte field gets a junk high byte that the NEXT store repairs,
|
||||
; so the blocks run in order x, y, ptr, color and finish with the
|
||||
; enable/multi word. The last colour store's junk lands on enableMask,
|
||||
; which the final word overwrites.
|
||||
;
|
||||
; Direct-page $E0-$EF are the compiler's own per-function scratch
|
||||
; (re-set before every use, never live across a call); $C0 is left alone.
|
||||
.section .text.stSimMarshalIigs,"ax"
|
||||
.globl stSimMarshalIigs
|
||||
stSimMarshalIigs:
|
||||
php
|
||||
rep #0x30
|
||||
.a16
|
||||
.i16
|
||||
sta 0xe0 ; args low
|
||||
txa
|
||||
sta 0xe2 ; args bank
|
||||
ldy #0
|
||||
lda [0xe0],y
|
||||
sta 0xe4 ; spr low
|
||||
ldy #2
|
||||
lda [0xe0],y
|
||||
sta 0xe6 ; spr bank
|
||||
ldy #4
|
||||
lda [0xe0],y
|
||||
sta 0xe8 ; frame low
|
||||
ldy #6
|
||||
lda [0xe0],y
|
||||
sta 0xea ; frame bank
|
||||
ldy #8
|
||||
lda [0xe0],y
|
||||
and #0xff
|
||||
sta 0xec ; multi
|
||||
stz 0xee ; enable mask accumulator
|
||||
; sprite 0: x = (msb ? 0x100 : 0) | col; enable bit
|
||||
ldy #0
|
||||
lda [0xe4],y ; col | msb<<8
|
||||
sta 0xf0
|
||||
and #0xff00
|
||||
beq mX0clr
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
ora #0x0100
|
||||
bra mX0st
|
||||
mX0clr:
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
mX0st:
|
||||
ldy #0
|
||||
sta [0xe8],y
|
||||
ldy #3
|
||||
lda [0xe4],y ; enable | ptr<<8
|
||||
and #0xff
|
||||
beq mE0off
|
||||
lda 0xee
|
||||
ora #1
|
||||
sta 0xee
|
||||
mE0off:
|
||||
; sprite 1: x = (msb ? 0x100 : 0) | col; enable bit
|
||||
ldy #6
|
||||
lda [0xe4],y ; col | msb<<8
|
||||
sta 0xf0
|
||||
and #0xff00
|
||||
beq mX1clr
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
ora #0x0100
|
||||
bra mX1st
|
||||
mX1clr:
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
mX1st:
|
||||
ldy #2
|
||||
sta [0xe8],y
|
||||
ldy #9
|
||||
lda [0xe4],y ; enable | ptr<<8
|
||||
and #0xff
|
||||
beq mE1off
|
||||
lda 0xee
|
||||
ora #2
|
||||
sta 0xee
|
||||
mE1off:
|
||||
; sprite 2: x = (msb ? 0x100 : 0) | col; enable bit
|
||||
ldy #12
|
||||
lda [0xe4],y ; col | msb<<8
|
||||
sta 0xf0
|
||||
and #0xff00
|
||||
beq mX2clr
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
ora #0x0100
|
||||
bra mX2st
|
||||
mX2clr:
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
mX2st:
|
||||
ldy #4
|
||||
sta [0xe8],y
|
||||
ldy #15
|
||||
lda [0xe4],y ; enable | ptr<<8
|
||||
and #0xff
|
||||
beq mE2off
|
||||
lda 0xee
|
||||
ora #4
|
||||
sta 0xee
|
||||
mE2off:
|
||||
; sprite 3: x = (msb ? 0x100 : 0) | col; enable bit
|
||||
ldy #18
|
||||
lda [0xe4],y ; col | msb<<8
|
||||
sta 0xf0
|
||||
and #0xff00
|
||||
beq mX3clr
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
ora #0x0100
|
||||
bra mX3st
|
||||
mX3clr:
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
mX3st:
|
||||
ldy #6
|
||||
sta [0xe8],y
|
||||
ldy #21
|
||||
lda [0xe4],y ; enable | ptr<<8
|
||||
and #0xff
|
||||
beq mE3off
|
||||
lda 0xee
|
||||
ora #8
|
||||
sta 0xee
|
||||
mE3off:
|
||||
; sprite 4: x = (msb ? 0x100 : 0) | col; enable bit
|
||||
ldy #24
|
||||
lda [0xe4],y ; col | msb<<8
|
||||
sta 0xf0
|
||||
and #0xff00
|
||||
beq mX4clr
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
ora #0x0100
|
||||
bra mX4st
|
||||
mX4clr:
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
mX4st:
|
||||
ldy #8
|
||||
sta [0xe8],y
|
||||
ldy #27
|
||||
lda [0xe4],y ; enable | ptr<<8
|
||||
and #0xff
|
||||
beq mE4off
|
||||
lda 0xee
|
||||
ora #16
|
||||
sta 0xee
|
||||
mE4off:
|
||||
; sprite 5: x = (msb ? 0x100 : 0) | col; enable bit
|
||||
ldy #30
|
||||
lda [0xe4],y ; col | msb<<8
|
||||
sta 0xf0
|
||||
and #0xff00
|
||||
beq mX5clr
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
ora #0x0100
|
||||
bra mX5st
|
||||
mX5clr:
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
mX5st:
|
||||
ldy #10
|
||||
sta [0xe8],y
|
||||
ldy #33
|
||||
lda [0xe4],y ; enable | ptr<<8
|
||||
and #0xff
|
||||
beq mE5off
|
||||
lda 0xee
|
||||
ora #32
|
||||
sta 0xee
|
||||
mE5off:
|
||||
; sprite 6: x = (msb ? 0x100 : 0) | col; enable bit
|
||||
ldy #36
|
||||
lda [0xe4],y ; col | msb<<8
|
||||
sta 0xf0
|
||||
and #0xff00
|
||||
beq mX6clr
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
ora #0x0100
|
||||
bra mX6st
|
||||
mX6clr:
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
mX6st:
|
||||
ldy #12
|
||||
sta [0xe8],y
|
||||
ldy #39
|
||||
lda [0xe4],y ; enable | ptr<<8
|
||||
and #0xff
|
||||
beq mE6off
|
||||
lda 0xee
|
||||
ora #64
|
||||
sta 0xee
|
||||
mE6off:
|
||||
; sprite 7: x = (msb ? 0x100 : 0) | col; enable bit
|
||||
ldy #42
|
||||
lda [0xe4],y ; col | msb<<8
|
||||
sta 0xf0
|
||||
and #0xff00
|
||||
beq mX7clr
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
ora #0x0100
|
||||
bra mX7st
|
||||
mX7clr:
|
||||
lda 0xf0
|
||||
and #0x00ff
|
||||
mX7st:
|
||||
ldy #14
|
||||
sta [0xe8],y
|
||||
ldy #45
|
||||
lda [0xe4],y ; enable | ptr<<8
|
||||
and #0xff
|
||||
beq mE7off
|
||||
lda 0xee
|
||||
ora #128
|
||||
sta 0xee
|
||||
mE7off:
|
||||
; y[] block (16-bit stores; the junk high byte is repaired by the next store)
|
||||
ldy #2
|
||||
lda [0xe4],y
|
||||
ldy #16
|
||||
sta [0xe8],y
|
||||
ldy #8
|
||||
lda [0xe4],y
|
||||
ldy #17
|
||||
sta [0xe8],y
|
||||
ldy #14
|
||||
lda [0xe4],y
|
||||
ldy #18
|
||||
sta [0xe8],y
|
||||
ldy #20
|
||||
lda [0xe4],y
|
||||
ldy #19
|
||||
sta [0xe8],y
|
||||
ldy #26
|
||||
lda [0xe4],y
|
||||
ldy #20
|
||||
sta [0xe8],y
|
||||
ldy #32
|
||||
lda [0xe4],y
|
||||
ldy #21
|
||||
sta [0xe8],y
|
||||
ldy #38
|
||||
lda [0xe4],y
|
||||
ldy #22
|
||||
sta [0xe8],y
|
||||
ldy #44
|
||||
lda [0xe4],y
|
||||
ldy #23
|
||||
sta [0xe8],y
|
||||
; ptr[] block (16-bit stores; the junk high byte is repaired by the next store)
|
||||
ldy #4
|
||||
lda [0xe4],y
|
||||
ldy #24
|
||||
sta [0xe8],y
|
||||
ldy #10
|
||||
lda [0xe4],y
|
||||
ldy #25
|
||||
sta [0xe8],y
|
||||
ldy #16
|
||||
lda [0xe4],y
|
||||
ldy #26
|
||||
sta [0xe8],y
|
||||
ldy #22
|
||||
lda [0xe4],y
|
||||
ldy #27
|
||||
sta [0xe8],y
|
||||
ldy #28
|
||||
lda [0xe4],y
|
||||
ldy #28
|
||||
sta [0xe8],y
|
||||
ldy #34
|
||||
lda [0xe4],y
|
||||
ldy #29
|
||||
sta [0xe8],y
|
||||
ldy #40
|
||||
lda [0xe4],y
|
||||
ldy #30
|
||||
sta [0xe8],y
|
||||
ldy #46
|
||||
lda [0xe4],y
|
||||
ldy #31
|
||||
sta [0xe8],y
|
||||
; color[] block (16-bit stores; the junk high byte is repaired by the next store)
|
||||
ldy #5
|
||||
lda [0xe4],y
|
||||
ldy #32
|
||||
sta [0xe8],y
|
||||
ldy #11
|
||||
lda [0xe4],y
|
||||
ldy #33
|
||||
sta [0xe8],y
|
||||
ldy #17
|
||||
lda [0xe4],y
|
||||
ldy #34
|
||||
sta [0xe8],y
|
||||
ldy #23
|
||||
lda [0xe4],y
|
||||
ldy #35
|
||||
sta [0xe8],y
|
||||
ldy #29
|
||||
lda [0xe4],y
|
||||
ldy #36
|
||||
sta [0xe8],y
|
||||
ldy #35
|
||||
lda [0xe4],y
|
||||
ldy #37
|
||||
sta [0xe8],y
|
||||
ldy #41
|
||||
lda [0xe4],y
|
||||
ldy #38
|
||||
sta [0xe8],y
|
||||
ldy #47
|
||||
lda [0xe4],y
|
||||
ldy #39
|
||||
sta [0xe8],y
|
||||
; enableMask | multiMask<<8
|
||||
lda 0xec
|
||||
xba
|
||||
and #0xff00
|
||||
ora 0xee
|
||||
ldy #40
|
||||
sta [0xe8],y
|
||||
plp
|
||||
rtl
|
||||
386
stRender.c
386
stRender.c
|
|
@ -40,11 +40,9 @@
|
|||
// cab, exhaust and passenger sets plus the intro star) or a cel change
|
||||
// mid-play rebuilds and recompiles a sprite. Glyphs are direct-mapped
|
||||
// by character, so the count is a power of two.
|
||||
#if defined(__W65816__)
|
||||
#define ST_SPRITE_CACHE 48u
|
||||
#else
|
||||
#define ST_SPRITE_CACHE 72u
|
||||
#endif
|
||||
// Room for the baked cab/passenger/exhaust set (37) plus the largest
|
||||
// level's hook cels (I: 30) at once.
|
||||
#define ST_SPRITE_CACHE 80u
|
||||
#define ST_SPRITE_BACKUP_BYTES JOEY_SPRITE_BACKUP_BYTES(ST_SPRITE_TILES, ST_SPRITE_TILES)
|
||||
#define ST_SPRITE_PX (8 * ST_SPRITE_TILES)
|
||||
// Palette slots the title logo animation owns. The title screen draws
|
||||
|
|
@ -71,7 +69,9 @@ typedef struct {
|
|||
bool used;
|
||||
bool pinned; // prewarmed moving cel: never evicted (its
|
||||
// compiled code is costly to re-emit on the 65816)
|
||||
bool compiled; // jlSpriteCompile succeeded for this cel
|
||||
uint32_t lastUse; // for least-recently-used eviction
|
||||
uint32_t retryAt; // cacheStamp at which a failed compile may retry
|
||||
} StSpriteCacheT;
|
||||
|
||||
|
||||
|
|
@ -91,6 +91,9 @@ typedef struct {
|
|||
// Title logo (stRenderTitleLogo): all four flip-book frames in one
|
||||
// tile, animated by rewriting logoSlotMask[]'s palette slots.
|
||||
bool logoMode;
|
||||
bool starMode; // level intro: cycling the starfield
|
||||
uint8_t starPhase; // which ring the bright band is on
|
||||
uint8_t starTick; // frames until the band steps outward
|
||||
bool logoTileOk; // the live glyph is one of the frames
|
||||
uint8_t logoSlotCount;
|
||||
uint8_t logoSlotMask[ST_LOGO_PAL_SLOTS]; // frames each slot is lit in
|
||||
|
|
@ -100,8 +103,6 @@ typedef struct {
|
|||
jlTileT logoTile;
|
||||
// Cell range (inclusive) each character has been painted in since
|
||||
// the last full repaint: where a changed glyph's cells can be.
|
||||
uint16_t glyphFirst[ST_CHARSET_CHARS];
|
||||
uint16_t glyphLast[ST_CHARSET_CHARS];
|
||||
// Column band of the cells about to be repainted, per character row
|
||||
// (min > max = the row is clean), the same shape as the library's
|
||||
// own per-row dirty bands.
|
||||
|
|
@ -111,7 +112,10 @@ typedef struct {
|
|||
StSpriteCacheT cache[ST_SPRITE_CACHE];
|
||||
StSpriteCacheT *lastHit[ST_HW_SPRITES]; // the entry each hardware sprite used last
|
||||
jlSpriteBackupT backup[ST_HW_SPRITES];
|
||||
uint8_t backupMem[ST_HW_SPRITES][ST_SPRITE_BACKUP_BYTES] __attribute__((aligned(2)));
|
||||
// ST_HW_SPRITES backups of ST_SPRITE_BACKUP_BYTES each, from jlAlloc:
|
||||
// 4.5 KB that as BSS would not fit the IIgs entry bank (text, rodata,
|
||||
// BSS and the C heap share its 64 KB).
|
||||
uint8_t *backupMem;
|
||||
StDrawnT slot[ST_HW_SPRITES];
|
||||
uint8_t lastPresentFrame;
|
||||
} StRenderStateT;
|
||||
|
|
@ -132,9 +136,26 @@ static const uint16_t kC64Palette[16] = {
|
|||
// four of these are used; the rest are headroom if the frames change.
|
||||
static const uint8_t kLogoPalSlot[ST_LOGO_PAL_SLOTS] = { 4u, 8u, 9u, 10u, 13u, 14u, 15u };
|
||||
|
||||
// Level-intro warp: how a star ring looks at each distance BEHIND the
|
||||
// bright band, as C64 colour indices (white, light grey, grey, dark
|
||||
// grey, then black). A ring this far behind the band or further is
|
||||
// unlit, so a lit head with a short fading tail sweeps outward and the
|
||||
// rest of the field stays dark.
|
||||
static const uint8_t kStarRamp[] = { 1u, 15u, 12u, 11u };
|
||||
#define ST_STAR_RAMP_LEN (sizeof(kStarRamp) / sizeof(kStarRamp[0]))
|
||||
// Frames per ring step. The intro runs at the game's 30 Hz tick, so a
|
||||
// step every other frame sweeps the eight rings in about half a second.
|
||||
#define ST_STAR_STEP_FRAMES 2u
|
||||
|
||||
|
||||
static void buildSpriteCel(const uint8_t *bm, uint8_t multi, uint8_t color, uint8_t mc0, uint8_t mc1);
|
||||
static jlSpriteT *cachedSprite(StSimT *sim, uint8_t idx);
|
||||
static void cacheCompile(StSpriteCacheT *e);
|
||||
static StSpriteCacheT *cacheFreeSlot(void);
|
||||
static void levelCelsEvict(void);
|
||||
static const uint8_t *levelSpriteBitmap(const StLevelT *level, uint8_t ptr);
|
||||
static void loadingBar(jlSurfaceT *stage, uint8_t done, uint8_t total);
|
||||
static uint8_t cellCol(uint16_t cell, uint8_t row);
|
||||
static uint8_t cellRow(uint16_t cell);
|
||||
static void collectGlyphs(StSimT *sim);
|
||||
static void dirtyBands(const StSimT *sim);
|
||||
|
|
@ -145,6 +166,7 @@ static bool loadPrecompiledCels(void);
|
|||
static bool logoBuildTile(const StSimT *sim);
|
||||
static uint8_t logoFrameIndex(const StSimT *sim);
|
||||
static void logoPaletteApply(const StSimT *sim, uint8_t frame);
|
||||
static void starPaletteApply(void);
|
||||
static void paintCells(jlSurfaceT *stage, StSimT *sim);
|
||||
static void pasteCell(jlSurfaceT *stage, const StSimT *sim, uint16_t cell, uint8_t bx, uint8_t by);
|
||||
static bool spriteOnScreen(int16_t px, int16_t py);
|
||||
|
|
@ -171,12 +193,27 @@ static void buildSpriteCel(const uint8_t *bm, uint8_t multi, uint8_t color, uint
|
|||
}
|
||||
|
||||
|
||||
// Compile a cached cel if it is not already, backing off after a failure
|
||||
// (arena full) so a cel that cannot fit is not re-staged every frame --
|
||||
// jlSpriteCompile's failure path runs the whole emitter twice.
|
||||
#define ST_COMPILE_RETRY_STAMPS 4096u // ~8 frames' worth of cachedSprite calls per frame -> ~25 s
|
||||
static void cacheCompile(StSpriteCacheT *e) {
|
||||
if (e->compiled || gRender.cacheStamp < e->retryAt) {
|
||||
return;
|
||||
}
|
||||
e->compiled = jlSpriteCompile(e->sprite);
|
||||
if (!e->compiled) {
|
||||
e->retryAt = gRender.cacheStamp + ST_COMPILE_RETRY_STAMPS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The JoeyLib sprite for hardware sprite `idx` of the current frame,
|
||||
// built on first use from its VIC bitmap and colours.
|
||||
static jlSpriteT *cachedSprite(StSimT *sim, uint8_t idx) {
|
||||
uint8_t ptr = sim->frame.ptr[idx];
|
||||
uint8_t color = drawColor(sim, idx);
|
||||
uint8_t multi = (uint8_t)((sim->frame.multiMask >> idx) & 1u);
|
||||
uint8_t multi = (uint8_t)((sim->frame.multiMask & kStBit[idx]) != 0u ? 1u : 0u);
|
||||
uint8_t mc0 = multi ? sim->spriteMc0 : 0u;
|
||||
uint8_t mc1 = multi ? sim->spriteMc1 : 0u;
|
||||
uint8_t level = (ptr < ST_SPRITE_PTR_FIRST && sim->level != 0) ? sim->level->levelIndex : 0xFFu;
|
||||
|
|
@ -213,20 +250,36 @@ static jlSpriteT *cachedSprite(StSimT *sim, uint8_t idx) {
|
|||
// so fail into the interpreter path.
|
||||
return 0;
|
||||
}
|
||||
// No bitmap for this pointer (hooks enable a sprite a tick before
|
||||
// they aim it, leaving it at block 0): nothing to draw, and no cel
|
||||
// to build and evict for.
|
||||
if (stSimSpriteBitmap(sim, ptr) == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (slot->used) {
|
||||
jlSpriteDestroy(slot->sprite);
|
||||
slot->sprite = 0;
|
||||
slot->used = false;
|
||||
slot->sprite = 0;
|
||||
slot->used = false;
|
||||
slot->compiled = false;
|
||||
}
|
||||
buildSpriteCel(stSimSpriteBitmap(sim, ptr), multi, color, mc0, mc1);
|
||||
slot->sprite = jlSpriteCreateFromSurface(gRender.scratch, 0, 0, ST_SPRITE_TILES, ST_SPRITE_TILES);
|
||||
if (slot->sprite == 0) {
|
||||
return 0;
|
||||
}
|
||||
// Only the cab, exhaust and passenger move every tick; the codegen
|
||||
// arena is theirs. Everything else stays interpreted (drawn seldom).
|
||||
if (idx <= 2u) {
|
||||
(void)jlSpriteCompile(slot->sprite);
|
||||
// Nothing compiles mid-ride: a compile is ~0.5 s on the 65816, a
|
||||
// visible hitch. The cab, exhaust and passenger cels come baked
|
||||
// (stRenderPrewarm), a level's hook cels come baked or are compiled
|
||||
// at level entry (stRenderLevelCels), and a cel that still gets
|
||||
// built here draws interpreted -- and is logged, because it means
|
||||
// the level's cel list (stLevelCels.c) missed one.
|
||||
slot->compiled = false;
|
||||
slot->retryAt = 0u;
|
||||
if (idx <= 2u && gPrewarming) {
|
||||
cacheCompile(slot);
|
||||
}
|
||||
if (!gPrewarming) {
|
||||
ST_LOG("spacetaxi: ! cel $%02X colour %u (level %u) built mid-ride -- add it to stLevelCelList", ptr, color, level);
|
||||
}
|
||||
slot->lastUse = gRender.cacheStamp;
|
||||
slot->ptr = ptr;
|
||||
|
|
@ -257,6 +310,19 @@ static const uint8_t kCellRow[125] = {
|
|||
};
|
||||
|
||||
|
||||
// Column of a cell whose row is known: cell - row * 40 through a table,
|
||||
// because the two-shift form of the multiply came back as a __mulhi3
|
||||
// library call on the 65816.
|
||||
static uint8_t cellCol(uint16_t cell, uint8_t row) {
|
||||
static const uint16_t kRowBase[ST_SCREEN_ROWS] = {
|
||||
0, 40, 80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480,
|
||||
520, 560, 600, 640, 680, 720, 760, 800, 840, 880, 920, 960
|
||||
};
|
||||
return (uint8_t)(cell - kRowBase[row]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint8_t cellRow(uint16_t cell) {
|
||||
return kCellRow[cell >> 3];
|
||||
}
|
||||
|
|
@ -271,7 +337,7 @@ static uint8_t cellRow(uint16_t cell) {
|
|||
static void collectGlyphs(StSimT *sim) {
|
||||
uint8_t k;
|
||||
uint16_t cell;
|
||||
uint16_t last;
|
||||
uint16_t next;
|
||||
|
||||
if (sim->charDirtyAll) {
|
||||
sim->charDirtyAll = false;
|
||||
|
|
@ -283,18 +349,33 @@ static void collectGlyphs(StSimT *sim) {
|
|||
if (sim->dirtyAll) {
|
||||
continue;
|
||||
}
|
||||
last = gRender.glyphLast[ch];
|
||||
for (cell = gRender.glyphFirst[ch]; cell <= last; cell++) {
|
||||
if (sim->screen[cell] != ch || sim->cellDirty[cell] != 0u) {
|
||||
continue;
|
||||
}
|
||||
sim->cellDirty[cell] = 1u;
|
||||
if (sim->dirtyCount < (uint16_t)(sizeof(sim->dirtyList) / sizeof(sim->dirtyList[0]))) {
|
||||
sim->dirtyList[sim->dirtyCount++] = cell;
|
||||
} else {
|
||||
sim->dirtyAll = true;
|
||||
break;
|
||||
// Exactly the cells showing `ch`, straight off the reverse index
|
||||
// the sim maintains (StSimT in stSim.h). No scan, no screen[]
|
||||
// test: a cell is in this list if and only if it shows `ch`.
|
||||
//
|
||||
// This replaced a walk of a per-glyph [first, last] span. That
|
||||
// span only ever widened -- pasteCell pushed it out and nothing
|
||||
// pulled it back -- so a glyph that once appeared in transient
|
||||
// text kept a screen-wide span for the rest of the level and was
|
||||
// rescanned on every animation frame, at 24-bit far-pointer cost
|
||||
// per cell. It measured 22% of the whole program on level H.
|
||||
//
|
||||
// `next` is read before the body because the overflow arm below
|
||||
// stops the walk, and because keeping the read up here makes the
|
||||
// loop independent of anything the body does to the cell.
|
||||
cell = sim->glyphHead[ch];
|
||||
while (cell != ST_GLYPH_CELL_NONE) {
|
||||
next = sim->cellNext[cell];
|
||||
if (sim->cellDirty[cell] == 0u) {
|
||||
sim->cellDirty[cell] = 1u;
|
||||
if (sim->dirtyCount < (uint16_t)(sizeof(sim->dirtyList) / sizeof(sim->dirtyList[0]))) {
|
||||
sim->dirtyList[sim->dirtyCount++] = cell;
|
||||
} else {
|
||||
sim->dirtyAll = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cell = next;
|
||||
}
|
||||
}
|
||||
sim->charDirtyCount = 0u;
|
||||
|
|
@ -331,7 +412,7 @@ static void dirtyBands(const StSimT *sim) {
|
|||
for (k = 0u; k < sim->dirtyCount; k++) {
|
||||
uint16_t cell = sim->dirtyList[k];
|
||||
uint8_t r = cellRow(cell);
|
||||
uint8_t col = (uint8_t)(cell - ((uint16_t)r << 5) - ((uint16_t)r << 3));
|
||||
uint8_t col = cellCol(cell, r);
|
||||
if (col < gRender.dirtyColMin[r]) {
|
||||
gRender.dirtyColMin[r] = col;
|
||||
}
|
||||
|
|
@ -422,7 +503,7 @@ static bool logoBuildTile(const StSimT *sim) {
|
|||
uint8_t f;
|
||||
uint8_t slot;
|
||||
for (f = 0u; f < ST_LOGO_FRAMES; f++) {
|
||||
if (((sim->charset[ST_LOGO_FRAME_FIRST + f][row] >> (7u - col)) & 1u) != 0u) {
|
||||
if (((stSimGlyphRow(sim, (uint8_t)(ST_LOGO_FRAME_FIRST + f), row) >> (7u - col)) & 1u) != 0u) {
|
||||
mask |= (uint8_t)(1u << f);
|
||||
}
|
||||
}
|
||||
|
|
@ -454,7 +535,8 @@ static uint8_t logoFrameIndex(const StSimT *sim) {
|
|||
uint8_t f;
|
||||
|
||||
for (f = 0u; f < ST_LOGO_FRAMES; f++) {
|
||||
if (memcmp(sim->charset[ST_LOGO_CHAR], sim->charset[ST_LOGO_FRAME_FIRST + f], 8u) == 0) {
|
||||
if (memcmp(stSimGlyph(sim, ST_LOGO_CHAR),
|
||||
stSimGlyph(sim, (uint8_t)(ST_LOGO_FRAME_FIRST + f)), 8u) == 0) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
|
@ -494,8 +576,6 @@ static void paintCells(jlSurfaceT *stage, StSimT *sim) {
|
|||
uint8_t by;
|
||||
|
||||
if (sim->dirtyAll) {
|
||||
memset(gRender.glyphFirst, 0xFF, sizeof(gRender.glyphFirst));
|
||||
memset(gRender.glyphLast, 0, sizeof(gRender.glyphLast));
|
||||
cell = 0u;
|
||||
for (by = 0u; by < ST_SCREEN_ROWS; by++) {
|
||||
for (bx = 0u; bx < ST_SCREEN_COLS; bx++) {
|
||||
|
|
@ -511,7 +591,7 @@ static void paintCells(jlSurfaceT *stage, StSimT *sim) {
|
|||
for (k = 0u; k < sim->dirtyCount; k++) {
|
||||
cell = sim->dirtyList[k];
|
||||
by = cellRow(cell);
|
||||
bx = (uint8_t)(cell - ((uint16_t)by << 5) - ((uint16_t)by << 3));
|
||||
bx = cellCol(cell, by);
|
||||
pasteCell(stage, sim, cell, bx, by);
|
||||
sim->cellDirty[cell] = 0u;
|
||||
}
|
||||
|
|
@ -525,12 +605,6 @@ static void paintCells(jlSurfaceT *stage, StSimT *sim) {
|
|||
static void pasteCell(jlSurfaceT *stage, const StSimT *sim, uint16_t cell, uint8_t bx, uint8_t by) {
|
||||
uint8_t chr = sim->screen[cell];
|
||||
|
||||
if (cell < gRender.glyphFirst[chr]) {
|
||||
gRender.glyphFirst[chr] = cell;
|
||||
}
|
||||
if (cell > gRender.glyphLast[chr]) {
|
||||
gRender.glyphLast[chr] = cell;
|
||||
}
|
||||
// On the title the logo's cells carry all four flip-book frames at
|
||||
// once; the palette decides which one shows, so they are pasted as
|
||||
// they are and never touched again.
|
||||
|
|
@ -538,7 +612,30 @@ static void pasteCell(jlSurfaceT *stage, const StSimT *sim, uint16_t cell, uint8
|
|||
jlTilePaste(stage, bx, by, &gRender.logoTile);
|
||||
return;
|
||||
}
|
||||
jlTilePasteGlyph(stage, bx, by, sim->charset[chr], sim->color[cell], sim->bgColor);
|
||||
jlTilePasteGlyph(stage, bx, by, stSimGlyph(sim, chr), sim->color[cell], sim->bgColor);
|
||||
}
|
||||
|
||||
|
||||
// Light the starfield's ring colours for the current phase: the ring
|
||||
// the band is on takes kStarRamp[0], the ones just inside it the rest
|
||||
// of the ramp, and everything else the background. One palette write
|
||||
// per step and not a single pixel moves -- that is the whole point of
|
||||
// ST_STAR_RING_FIRST (stSim.h).
|
||||
static void starPaletteApply(void) {
|
||||
uint16_t pal[SURFACE_COLORS_PER_PALETTE];
|
||||
uint16_t color;
|
||||
uint8_t behind;
|
||||
uint8_t ring;
|
||||
|
||||
jlPaletteGet(gRender.stage, 0u, pal);
|
||||
for (ring = 0u; ring < ST_STAR_RING_COUNT; ring++) {
|
||||
// How far this ring sits behind the band, wrapping so the band
|
||||
// re-enters at the centre as it leaves the edge.
|
||||
behind = (uint8_t)((gRender.starPhase - ring) & (ST_STAR_RING_COUNT - 1u));
|
||||
color = (behind < ST_STAR_RAMP_LEN) ? kC64Palette[kStarRamp[behind]] : kC64Palette[0];
|
||||
pal[ST_STAR_RING_FIRST + ring] = color;
|
||||
}
|
||||
jlPaletteSet(gRender.stage, 0u, pal);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -598,15 +695,26 @@ void stRenderFrame(jlSurfaceT *stage, StSimT *sim) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (gRender.starMode) {
|
||||
// The warp is the only thing animating here, and it animates in
|
||||
// the palette: no cells change, no sprite moves for it, so the
|
||||
// present that ends this frame copies no pixels at all.
|
||||
gRender.starTick++;
|
||||
if (gRender.starTick >= ST_STAR_STEP_FRAMES) {
|
||||
gRender.starTick = 0u;
|
||||
gRender.starPhase = (uint8_t)((gRender.starPhase + 1u) & (ST_STAR_RING_COUNT - 1u));
|
||||
starPaletteApply();
|
||||
}
|
||||
}
|
||||
collectGlyphs(sim);
|
||||
dirtyBands(sim);
|
||||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||
uint8_t idx = (uint8_t)(ST_HW_SPRITES - 1u - k);
|
||||
StDrawnT *d = &gRender.slot[k];
|
||||
uint8_t multi = (uint8_t)((sim->frame.multiMask >> idx) & 1u);
|
||||
uint8_t multi = (uint8_t)((sim->frame.multiMask & kStBit[idx]) != 0u ? 1u : 0u);
|
||||
int16_t px = (int16_t)((int16_t)sim->frame.x[idx] - ST_SPRITE_X_ORIGIN);
|
||||
int16_t py = (int16_t)((int16_t)sim->frame.y[idx] - ST_SPRITE_Y_ORIGIN);
|
||||
bool want = (sim->frame.enableMask & (uint8_t)(1u << idx)) != 0u && spriteOnScreen(px, py);
|
||||
bool want = (sim->frame.enableMask & kStBit[idx]) != 0u && spriteOnScreen(px, py);
|
||||
bool same = (want == d->drawn);
|
||||
if (same && want) {
|
||||
same = (d->x == sim->frame.x[idx] && d->y == sim->frame.y[idx] && d->ptr == sim->frame.ptr[idx] && d->color == drawColor(sim, idx) && d->multi == multi);
|
||||
|
|
@ -633,7 +741,7 @@ void stRenderFrame(jlSurfaceT *stage, StSimT *sim) {
|
|||
jlSpriteT *sp;
|
||||
int16_t px;
|
||||
int16_t py;
|
||||
if ((sim->frame.enableMask & (uint8_t)(1u << idx)) == 0u) {
|
||||
if ((sim->frame.enableMask & kStBit[idx]) == 0u) {
|
||||
continue;
|
||||
}
|
||||
px = (int16_t)((int16_t)sim->frame.x[idx] - ST_SPRITE_X_ORIGIN);
|
||||
|
|
@ -651,7 +759,7 @@ void stRenderFrame(jlSurfaceT *stage, StSimT *sim) {
|
|||
d->y = sim->frame.y[idx];
|
||||
d->ptr = sim->frame.ptr[idx];
|
||||
d->color = drawColor(sim, idx);
|
||||
d->multi = (uint8_t)((sim->frame.multiMask >> idx) & 1u);
|
||||
d->multi = (uint8_t)((sim->frame.multiMask & kStBit[idx]) != 0u ? 1u : 0u);
|
||||
}
|
||||
{
|
||||
// Sync to the retrace unless the frame already spans more than
|
||||
|
|
@ -667,13 +775,20 @@ void stRenderFrame(jlSurfaceT *stage, StSimT *sim) {
|
|||
|
||||
|
||||
void stRenderInit(jlSurfaceT *stage) {
|
||||
uint8_t k;
|
||||
uint8_t *backupMem = gRender.backupMem;
|
||||
uint8_t k;
|
||||
|
||||
memset(&gRender, 0, sizeof(gRender));
|
||||
memset(gRender.glyphFirst, 0xFF, sizeof(gRender.glyphFirst));
|
||||
gRender.stage = stage;
|
||||
if (backupMem == 0) {
|
||||
backupMem = (uint8_t *)jlAlloc((uint32_t)ST_HW_SPRITES * ST_SPRITE_BACKUP_BYTES);
|
||||
if (backupMem == 0) {
|
||||
ST_LOG("stRenderInit: no memory for sprite backups");
|
||||
}
|
||||
}
|
||||
gRender.backupMem = backupMem;
|
||||
gRender.stage = stage;
|
||||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||
gRender.backup[k].bytes = gRender.backupMem[k];
|
||||
gRender.backup[k].bytes = (backupMem == 0) ? 0 : backupMem + (uint16_t)k * ST_SPRITE_BACKUP_BYTES;
|
||||
}
|
||||
jlPaletteSet(stage, 0u, kC64Palette);
|
||||
jlScbSetRange(stage, 0u, (uint16_t)(SURFACE_HEIGHT - 1u), 0u);
|
||||
|
|
@ -695,10 +810,145 @@ void stRenderInit(jlSurfaceT *stage) {
|
|||
// cache so no cel is JIT-compiled at boot (each 65816 compile costs
|
||||
// ~0.4 s). Every kStCels entry becomes a pinned cache slot keyed exactly
|
||||
// as the play lookups: system ptr (level 0xFF), the level-wide colours.
|
||||
// The first unused cache slot, or NULL when the cache is full.
|
||||
static StSpriteCacheT *cacheFreeSlot(void) {
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < ST_SPRITE_CACHE; k++) {
|
||||
if (!gRender.cache[k].used) {
|
||||
return &gRender.cache[k];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Drop every cel that belongs to a level (the baked set is level 0xFF and
|
||||
// stays), freeing its arena code, and forget any hardware sprite's last
|
||||
// hit on it.
|
||||
static void levelCelsEvict(void) {
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < ST_SPRITE_CACHE; k++) {
|
||||
StSpriteCacheT *e = &gRender.cache[k];
|
||||
uint8_t h;
|
||||
if (!e->used || e->level == 0xFFu) {
|
||||
continue;
|
||||
}
|
||||
for (h = 0u; h < ST_HW_SPRITES; h++) {
|
||||
if (gRender.lastHit[h] == e) {
|
||||
gRender.lastHit[h] = 0;
|
||||
}
|
||||
}
|
||||
jlSpriteDestroy(e->sprite);
|
||||
e->sprite = 0;
|
||||
e->used = false;
|
||||
e->pinned = false;
|
||||
e->compiled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// A level's own sprite block, or NULL when the level does not ship it.
|
||||
static const uint8_t *levelSpriteBitmap(const StLevelT *level, uint8_t ptr) {
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < level->spriteCount; k++) {
|
||||
if (level->sprites[k].ptr == ptr) {
|
||||
return level->sprites[k].bitmap;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void loadingBar(jlSurfaceT *stage, uint8_t done, uint8_t total) {
|
||||
jlFillRect(stage, 60, 110, (uint16_t)((uint16_t)done * 200u / total), 6u, 1u);
|
||||
jlStagePresent();
|
||||
}
|
||||
|
||||
|
||||
// Ready a level's hook cels BEFORE the ride: the previous level's cels
|
||||
// go, then the level's list (stLevelCelList) is filled from its baked
|
||||
// bank (sprites/levelNN.spc) or, when there is none, built and compiled
|
||||
// here behind the LOADING bar. Either way nothing compiles once the
|
||||
// level is running. Keyed exactly as cachedSprite keys them, so every
|
||||
// lookup during the ride is a hit.
|
||||
void stRenderLevelCels(jlSurfaceT *stage, const StLevelT *level) {
|
||||
static StCelDefT list[ST_LEVEL_CELS_MAX];
|
||||
jlSpriteT *cels[ST_LEVEL_CELS_MAX];
|
||||
char path[24];
|
||||
uint8_t n;
|
||||
uint8_t got;
|
||||
uint8_t k;
|
||||
|
||||
levelCelsEvict();
|
||||
if (level == 0) {
|
||||
return;
|
||||
}
|
||||
n = stLevelCelList(level, list, ST_LEVEL_CELS_MAX);
|
||||
if (n == 0u) {
|
||||
return;
|
||||
}
|
||||
memcpy(path, "sprites/level", 13u);
|
||||
path[13] = (char)('0' + (level->levelIndex + 1u) / 10u);
|
||||
path[14] = (char)('0' + (level->levelIndex + 1u) % 10u);
|
||||
memcpy(path + 15, ".spc", 5u);
|
||||
got = (uint8_t)jlSpriteBankLoadPrecompiled(path, cels, n, 0);
|
||||
if (got == n) {
|
||||
ST_LOG("spacetaxi: level %u cels from %s (%u)", level->levelIndex, path, n);
|
||||
} else {
|
||||
for (k = 0u; k < got; k++) {
|
||||
jlSpriteDestroy(cels[k]);
|
||||
}
|
||||
ST_LOG("spacetaxi: level %u: no usable %s -- compiling %u cels at entry", level->levelIndex, path, n);
|
||||
stRenderLoading(stage);
|
||||
}
|
||||
gPrewarming = true;
|
||||
for (k = 0u; k < n; k++) {
|
||||
StSpriteCacheT *slot = cacheFreeSlot();
|
||||
if (slot == 0) {
|
||||
ST_LOG("spacetaxi: ! sprite cache full at level cel %u", k);
|
||||
break;
|
||||
}
|
||||
if (got == n) {
|
||||
slot->sprite = cels[k];
|
||||
slot->compiled = true;
|
||||
} else {
|
||||
const uint8_t *bm = levelSpriteBitmap(level, list[k].ptr);
|
||||
if (bm == 0) {
|
||||
continue;
|
||||
}
|
||||
buildSpriteCel(bm, list[k].multi, list[k].color, list[k].mc0, list[k].mc1);
|
||||
slot->sprite = jlSpriteCreateFromSurface(gRender.scratch, 0, 0, ST_SPRITE_TILES, ST_SPRITE_TILES);
|
||||
if (slot->sprite == 0) {
|
||||
continue;
|
||||
}
|
||||
slot->compiled = false;
|
||||
slot->retryAt = 0u;
|
||||
cacheCompile(slot);
|
||||
loadingBar(stage, (uint8_t)(k + 1u), n);
|
||||
}
|
||||
slot->ptr = list[k].ptr;
|
||||
slot->color = list[k].color;
|
||||
slot->multi = list[k].multi;
|
||||
slot->mc0 = list[k].mc0;
|
||||
slot->mc1 = list[k].mc1;
|
||||
slot->level = level->levelIndex;
|
||||
slot->used = true;
|
||||
slot->pinned = true;
|
||||
slot->lastUse = gRender.cacheStamp;
|
||||
}
|
||||
gPrewarming = false;
|
||||
if (got != n) {
|
||||
jlFillRect(stage, 60, 110, 200u, 6u, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns false if the .spc is missing or built for another target/shift
|
||||
// count (other ports, or a stale bake), so the caller falls back to the
|
||||
// runtime JIT prewarm below. Its cross-platform contract makes this a
|
||||
// no-op everywhere but the IIgs, where the bake is wired.
|
||||
// count (a stale bake), so the caller falls back to the runtime JIT
|
||||
// prewarm below. Every port stages its own bake (make/<port>.mk).
|
||||
static bool loadPrecompiledCels(void) {
|
||||
jlSpriteT *cels[64];
|
||||
uint16_t n;
|
||||
|
|
@ -761,8 +1011,10 @@ void stRenderPrewarm(jlSurfaceT *stage, StSimT *sim) {
|
|||
// Precompiled bank: instant, no per-cel JIT. Falls through to the
|
||||
// runtime build below on any port without a matching .spc.
|
||||
if (loadPrecompiledCels()) {
|
||||
ST_LOG("spacetaxi: cels from sprites/staxicels.spc");
|
||||
return;
|
||||
}
|
||||
ST_LOG("spacetaxi: ! no usable sprites/staxicels.spc -- JIT prewarm");
|
||||
saved = sim->frame;
|
||||
gPrewarming = true;
|
||||
sim->frame.multiMask = 0x07u;
|
||||
|
|
@ -773,24 +1025,21 @@ void stRenderPrewarm(jlSurfaceT *stage, StSimT *sim) {
|
|||
sim->frame.color[0] = 0x06u;
|
||||
(void)cachedSprite(sim, 0u);
|
||||
done++;
|
||||
jlFillRect(stage, 60, 110, (uint16_t)((uint16_t)done * 200u / total), 6u, 1u);
|
||||
jlStagePresent();
|
||||
loadingBar(stage, done, total);
|
||||
}
|
||||
for (k = 0u; k < sizeof(kPassPtrs); k++) {
|
||||
sim->frame.ptr[1] = kPassPtrs[k];
|
||||
sim->frame.color[1] = 0x06u;
|
||||
(void)cachedSprite(sim, 1u);
|
||||
done++;
|
||||
jlFillRect(stage, 60, 110, (uint16_t)((uint16_t)done * 200u / total), 6u, 1u);
|
||||
jlStagePresent();
|
||||
loadingBar(stage, done, total);
|
||||
}
|
||||
for (k = 0u; k < sizeof(kFlamePtrs); k++) {
|
||||
sim->frame.ptr[2] = kFlamePtrs[k];
|
||||
sim->frame.color[2] = 0x07u;
|
||||
(void)cachedSprite(sim, 2u);
|
||||
done++;
|
||||
jlFillRect(stage, 60, 110, (uint16_t)((uint16_t)done * 200u / total), 6u, 1u);
|
||||
jlStagePresent();
|
||||
loadingBar(stage, done, total);
|
||||
}
|
||||
// The intro star is a hires sprite in colour 7. Build it as a moving
|
||||
// (idx <= 2) cel so it compiles: the level-name intro draws seven of
|
||||
|
|
@ -809,16 +1058,17 @@ void stRenderPrewarm(jlSurfaceT *stage, StSimT *sim) {
|
|||
void stRenderSceneChanged(StSimT *sim) {
|
||||
uint8_t k;
|
||||
|
||||
if (gRender.logoMode) {
|
||||
// The logo's reserved slots go back to being C64 colours.
|
||||
if (gRender.logoMode || gRender.starMode) {
|
||||
// The borrowed slots go back to being C64 colours.
|
||||
gRender.logoMode = false;
|
||||
gRender.logoTileOk = false;
|
||||
gRender.starMode = false;
|
||||
jlPaletteSet(gRender.stage, 0u, kC64Palette);
|
||||
}
|
||||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||
gRender.slot[k].drawn = false;
|
||||
}
|
||||
stSimDirtyAll(sim);
|
||||
stSimDirtyCells(sim);
|
||||
sim->charDirtyAll = true;
|
||||
sim->charDirtyCount = 0u;
|
||||
}
|
||||
|
|
@ -838,7 +1088,19 @@ void stRenderTitleLogo(StSimT *sim) {
|
|||
gRender.logoMode = true;
|
||||
gRender.logoTileOk = (frame < ST_LOGO_FRAMES);
|
||||
logoPaletteApply(sim, gRender.logoTileOk ? frame : 0u);
|
||||
stSimDirtyAll(sim);
|
||||
stSimDirtyCells(sim);
|
||||
}
|
||||
|
||||
|
||||
// Turn on the level intro's palette-cycled starfield. Call it after
|
||||
// stRenderSceneChanged (which turns it back off) on entry to the level
|
||||
// intro. The cells were painted by stIntroEnter; from here the warp is
|
||||
// one palette write every ST_STAR_STEP_FRAMES frames.
|
||||
void stRenderIntroStars(void) {
|
||||
gRender.starMode = true;
|
||||
gRender.starPhase = 0u;
|
||||
gRender.starTick = 0u;
|
||||
starPaletteApply();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -848,4 +1110,6 @@ void stRenderShutdown(void) {
|
|||
jlSurfaceDestroy(gRender.scratch);
|
||||
gRender.scratch = 0;
|
||||
}
|
||||
jlFree(gRender.backupMem);
|
||||
gRender.backupMem = 0;
|
||||
}
|
||||
|
|
|
|||
270
stSim.h
270
stSim.h
|
|
@ -31,6 +31,9 @@
|
|||
#define ST_SCREEN_COLS 40u
|
||||
#define ST_SCREEN_ROWS 25u
|
||||
#define ST_SCREEN_CELLS (ST_SCREEN_COLS * ST_SCREEN_ROWS)
|
||||
// End-of-list / not-linked sentinel for the glyph reverse index below.
|
||||
// ST_SCREEN_CELLS is 1000, so no real cell index can collide with it.
|
||||
#define ST_GLYPH_CELL_NONE 0xFFFFu
|
||||
// row * 40 + col. Written as shifts (40 == 32 + 8) because the 65816 has
|
||||
// no multiply: with a variable row the * form called the compiler's
|
||||
// software multiply helper, and the collision pre-check does that a
|
||||
|
|
@ -43,6 +46,9 @@
|
|||
#define ST_SPRITE_Y_ORIGIN 50
|
||||
#define ST_SPRITE_W 24
|
||||
#define ST_SPRITE_H 21
|
||||
// A sprite row shifted onto the 8-pixel character grid has one of 8
|
||||
// phases (its left edge 0..7 pixels into a cell) -- see rowWindow.
|
||||
#define ST_ROW_PHASES 8
|
||||
#define ST_HW_SPRITES 8u
|
||||
|
||||
// Fixed screen cells the game writes directly (C64 screen addresses).
|
||||
|
|
@ -53,6 +59,8 @@
|
|||
#define ST_CELL_SCREENS ST_CELL(23, 32) // $07B8..$07BC
|
||||
#define ST_CELL_SCORE ST_CELL(24, 2) // $07C2..$07C8, 7 chars
|
||||
#define ST_CELL_MESSAGE ST_CELL(24, 14) // $07CE, 11 chars
|
||||
#define ST_MESSAGE_COL 14u
|
||||
#define ST_MESSAGE_ROW 24u
|
||||
#define ST_CELL_PAD_DIGIT ST_CELL(24, 18) // $07D2
|
||||
#define ST_CELL_FARE ST_CELL(24, 32) // $07E0..$07E6, 7 chars
|
||||
#define ST_NUMBER_CHARS 7u
|
||||
|
|
@ -71,7 +79,57 @@
|
|||
#define ST_CHAR_FUEL_EMPTY 0x7Au
|
||||
#define ST_CHAR_TRANSPORTER 0x67u // animated top-wall hatch
|
||||
#define ST_CHAR_CAB_ICON 0xC8u
|
||||
#define ST_CHAR_MENU_SENTINEL 0x7Bu // $07A6 == $7B: first fuel cell half = out of fuel
|
||||
#define ST_CHAR_ELECTROID 0x6Fu // level O's scrolling barrier glyph
|
||||
#define ST_FARE_DEST_UP 0x0Bu // $7D8E: the fare aboard wants UP
|
||||
|
||||
// ---- level-intro starfield --------------------------------------------
|
||||
//
|
||||
// The C64's level intro streams seven star SPRITES out of the centre of
|
||||
// the screen. That is the most expensive thing this port asks a present
|
||||
// for: eight sprites are save-under drawn and restored every frame, and
|
||||
// because a row's dirty band is one min..max interval, two stars far
|
||||
// apart on the same row widen that row to nearly full width. Radially
|
||||
// spreading stars maximise exactly that, so the warp ends up presenting
|
||||
// close to the whole framebuffer every frame -- which is what makes it
|
||||
// the slowest thing the IIgs does, and wasted work everywhere else.
|
||||
//
|
||||
// So the warp is not animated in pixels at all. The starfield is painted
|
||||
// ONCE into screen RAM and animated by cycling the colours its cells are
|
||||
// drawn in -- the same trick the title logo already uses
|
||||
// (stRenderTitleLogo). A frame costs one palette upload and NO dirty
|
||||
// pixel rows.
|
||||
//
|
||||
// The contract between the two halves is just this colour range:
|
||||
// stTitle.c colours a star's cell ST_STAR_RING_FIRST + ring (ring 0 is
|
||||
// the centre), and the renderer cycles that range. These are C64 colour
|
||||
// indices the intro screen never uses -- it draws in 0, 3 and, in demo
|
||||
// mode, 4 and 5; the cab sprite adds 2, 6 and 7.
|
||||
#define ST_STAR_RING_FIRST 8u
|
||||
#define ST_STAR_RING_COUNT 8u
|
||||
|
||||
// The renderer wraps the sweep's phase with a mask rather than a
|
||||
// modulo, so the ring count has to stay a power of two. Changing it to
|
||||
// something else must fail to compile here instead of quietly making
|
||||
// the warp skip rings.
|
||||
typedef char stStarRingCountIsPow2[((ST_STAR_RING_COUNT & (ST_STAR_RING_COUNT - 1u)) == 0u) ? 1 : -1];
|
||||
// Ring 0 is the centre, which in a warp is the VANISHING POINT: those
|
||||
// stars are the far ones and get the small glyph. The big glyph belongs
|
||||
// to the outer rings, the stars about to rush past the viewer.
|
||||
#define ST_STAR_GLYPH_NEAR 0x2Au // '*', the outer rings
|
||||
#define ST_STAR_GLYPH_FAR 0x2Eu // '.', the inner rings
|
||||
#define ST_STAR_FAR_RINGS 5u // rings 0..4 are still distant
|
||||
|
||||
// VIC sprite block pointers the game selects by name. The cab's bit 0 is
|
||||
// the landing gear, so each facing is a pair.
|
||||
#define ST_SPRITE_CAB_RIGHT 0xC0u // +1 = gear down
|
||||
#define ST_SPRITE_CAB_LEFT 0xDCu // +1 = gear down
|
||||
#define ST_SPRITE_PASS_WALK_R 0xC2u // +walkParity
|
||||
#define ST_SPRITE_PASS_WALK_L 0xC4u // +walkParity
|
||||
#define ST_SPRITE_PASS_STAND 0xC7u
|
||||
#define ST_SPRITE_PASS_BEAM 0xCBu // counts down to PASS_STAND
|
||||
#define ST_SPRITE_PASS_GONE 0xCCu // one past PASS_BEAM: fully shrunk
|
||||
#define ST_SPRITE_WRECK_FIRST 0xCCu // the wreck cel walk, FIRST..LAST-1
|
||||
#define ST_SPRITE_WRECK_LAST 0xD1u
|
||||
|
||||
// Title logo ($4827): the logo is one character repeated over rows
|
||||
// 1..11, and the flip-book animates it by copying one of four frame
|
||||
|
|
@ -88,6 +146,16 @@
|
|||
// Distinct characters whose glyph can change in one frame before the
|
||||
// renderer gives up and repaints everything.
|
||||
#define ST_CHAR_DIRTY_MAX 8u
|
||||
// Characters that may hold an edited glyph at once. The game edits six
|
||||
// across the whole game (the transporter hatch $67, level O's barrier
|
||||
// $6F, the title logo $84 and level W's three laser glyphs $91..$93), so
|
||||
// this is generous; an overflow parks the edit in the spill entry, where
|
||||
// it is simply never displayed rather than corrupting another character.
|
||||
#define ST_GLYPH_OVERRIDES 16u
|
||||
|
||||
typedef struct {
|
||||
uint8_t rows[8];
|
||||
} StGlyphT;
|
||||
|
||||
// Level image as loaded from a .dat (STL4). Kept in the C64's units.
|
||||
#define ST_MAX_PADS 10u
|
||||
|
|
@ -98,6 +166,113 @@
|
|||
#define ST_HOOK_BASE 0x7D98u
|
||||
#define ST_HOOK_BYTES (0x8000u - ST_HOOK_BASE)
|
||||
|
||||
// Per-level hook scratch. The original keeps a hook's running state
|
||||
// inside the level's own data block, at fixed C64 addresses interleaved
|
||||
// with its tables -- and, for some levels, on top of the hook's own 6502
|
||||
// code, which this port never executes. A level reads its TABLES straight
|
||||
// out of the shipped blob (the single source of truth) and keeps only the
|
||||
// bytes it WRITES here. Seeded from
|
||||
// the blob at scene load, so the first tick starts where the original's
|
||||
// did. Every level is converted, so no C64-addressed working copy of the
|
||||
// blob exists any more.
|
||||
#define ST_HOOK_H_SEGS 11u // level H segment ids 0..10
|
||||
#define ST_HOOK_W_LASERS 8u
|
||||
|
||||
typedef struct {
|
||||
uint8_t segFlag[ST_HOOK_H_SEGS]; // $7E15..$7E1F wall segment up/down
|
||||
uint8_t switchId; // $7E4C also read back as a table entry
|
||||
uint8_t tick; // $7E53
|
||||
uint8_t active; // $7E54 switch being animated
|
||||
uint8_t step; // $7E55 0..3 of the animation
|
||||
uint8_t tone; // $7E56 rising chime
|
||||
} StHookHT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t celPhase; // $7DD2 orb cel cycle 0..5
|
||||
uint8_t tick; // $7E00
|
||||
uint8_t lastSpot; // $7DD1 landing spot used last, 1..5
|
||||
uint8_t hop; // $7DD3 ticks left in a teleport
|
||||
uint8_t sweep; // $7F02 the hop's falling tone
|
||||
} StHookGT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state[ST_HW_SPRITES]; // $7DB8 0 idle, 1 rising, 2 burst
|
||||
uint8_t phase[ST_HW_SPRITES]; // $7DC0 cel phase
|
||||
uint8_t dx[ST_HW_SPRITES]; // $7DC8
|
||||
uint8_t dy[ST_HW_SPRITES]; // $7DD0
|
||||
} StHookIT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t parity; // $7DBD magnet pole flip
|
||||
} StHookKT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t tick; // $7DBD mod-8 scroll gate
|
||||
} StHookOT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t phase[ST_HW_SPRITES]; // $7E83 interference cel phase
|
||||
} StHookQT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t gateShut; // $7D9C
|
||||
} StHookTT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t colorPhase; // $7DAB
|
||||
uint8_t state[ST_HOOK_W_LASERS]; // $7DAC 0 idle, 1 extending, 2 fading
|
||||
uint8_t row[ST_HOOK_W_LASERS]; // $7DB5 beam head / fade phase
|
||||
uint8_t started; // $7DE5
|
||||
} StHookWT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t celPhase[ST_HW_SPRITES]; // $7F4F
|
||||
uint8_t state[ST_HW_SPRITES]; // $7F57 0 idle, 1 active
|
||||
uint8_t dir[ST_HW_SPRITES]; // $7F5F entry edge 0..3
|
||||
uint8_t life[ST_HW_SPRITES]; // $7F6E
|
||||
uint8_t cooldown; // $7F6D ticks before the next bounce
|
||||
} StHookUT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t col; // $7D9C
|
||||
uint8_t dir; // $7D9D
|
||||
uint8_t tick; // $7D9E
|
||||
} StHookXT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t row; // $7D98 row the leaves grow along
|
||||
uint8_t seg; // $7D99 leaves grown this cycle 0..4
|
||||
uint8_t tick; // $7D9A ticks toward the next leaf
|
||||
uint8_t padSlot; // $7D9B number of the next pad to hang
|
||||
} StHookET;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state[ST_HW_SPRITES]; // $7EDB 0 idle, 1 falling, 2 bursting
|
||||
uint8_t phase[ST_HW_SPRITES]; // $7ED3 burst cel phase
|
||||
} StHookJT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state[ST_HW_SPRITES]; // $7F16 0 idle, 1 falling, 2 melting
|
||||
uint8_t phase[ST_HW_SPRITES]; // $7F0E melt cel phase
|
||||
uint8_t parity; // $7F1F a melt advances every other count
|
||||
} StHookPT;
|
||||
|
||||
typedef union {
|
||||
StHookET e;
|
||||
StHookGT g;
|
||||
StHookHT h;
|
||||
StHookIT i;
|
||||
StHookJT j;
|
||||
StHookKT k;
|
||||
StHookOT o;
|
||||
StHookPT p;
|
||||
StHookQT q;
|
||||
StHookTT t;
|
||||
StHookUT u;
|
||||
StHookWT w;
|
||||
StHookXT x;
|
||||
} StHookScratchT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t x1Hi; // slot byte 0: landing X lower bound, high byte
|
||||
uint8_t x1Lo; // slot byte 1
|
||||
|
|
@ -128,7 +303,7 @@ typedef struct {
|
|||
StPadT pads[ST_MAX_PADS]; // $7D0A..
|
||||
uint8_t screen[ST_SCREEN_CELLS]; // decompressed screen RAM
|
||||
uint8_t color[ST_SCREEN_CELLS]; // decompressed colour RAM
|
||||
uint8_t levelIndex; // 0..23 = A..X, 24 = title
|
||||
uint8_t levelIndex; // 0..23 = A..X, 24 = Y, 25 = title
|
||||
uint8_t spriteCount;
|
||||
StLevelSpriteT sprites[ST_MAX_LEVEL_SPRITES];
|
||||
uint8_t hookData[ST_HOOK_BYTES]; // $7D98..$7FFF as shipped
|
||||
|
|
@ -200,7 +375,34 @@ typedef struct {
|
|||
uint16_t dirtyList[512]; // cells marked since the last frame
|
||||
uint16_t dirtyCount;
|
||||
bool dirtyAll; // list overflowed / whole screen
|
||||
uint8_t charset[ST_CHARSET_CHARS][8]; // $2800 working copy
|
||||
// Reverse index: for each glyph, the exact set of cells showing it,
|
||||
// as doubly-linked lists threaded through the cell array.
|
||||
//
|
||||
// The renderer has to repaint every cell showing a glyph whose
|
||||
// BITMAP changed -- a chunky framebuffer bakes the pixels in at
|
||||
// paste time, so unlike the C64's character mode there is no free
|
||||
// re-composite. It used to find those cells by scanning a per-glyph
|
||||
// [first, last] span, which PC profiling showed was the single
|
||||
// hottest loop in the program (22% of all samples on level H). This
|
||||
// gives the exact set instead: no scan, cost proportional to the
|
||||
// cells that really show the glyph.
|
||||
//
|
||||
// screen[] is the only truth and these mirror it: setCell keeps them
|
||||
// in step one cell at a time, and a bulk screen write re-derives
|
||||
// them via stSimDirtyAll, which every bulk writer already calls.
|
||||
// They live in the NOT-cleared block for the same reason screen[]
|
||||
// does -- stSimNewGame must leave the live picture alone.
|
||||
uint16_t glyphHead[ST_CHARSET_CHARS]; // ST_GLYPH_CELL_NONE = none
|
||||
uint16_t cellNext[ST_SCREEN_CELLS];
|
||||
uint16_t cellPrev[ST_SCREEN_CELLS];
|
||||
// $2800. The charset is NOT copied: the ROM set is const and only the
|
||||
// handful of glyphs the game rewrites at runtime are stored here, so
|
||||
// this costs ~400 bytes instead of 2 KB and a scene load clears an
|
||||
// index rather than copying 2 KB. Reach glyphs through stSimGlyph /
|
||||
// stSimGlyphRow / stSimGlyphMut, never by indexing directly.
|
||||
uint8_t glyphSlot[ST_CHARSET_CHARS]; // 0 = ROM glyph, else slot + 1
|
||||
StGlyphT glyphOverride[ST_GLYPH_OVERRIDES + 1u]; // last = spill
|
||||
uint8_t glyphOverrideCount;
|
||||
// Characters whose glyph bits the game has edited since the last
|
||||
// frame -- the transporter hatch, the title logo flip, the laser
|
||||
// beams. A short list, not a 256-entry flag array: the renderer had
|
||||
|
|
@ -221,6 +423,8 @@ typedef struct {
|
|||
// ---- level image (mutable copies: hooks edit the pad table) ----
|
||||
const StLevelT *level;
|
||||
StPadT pads[ST_MAX_PADS]; // $7D0A working copy
|
||||
uint8_t padCount; // $7D5A working copy (level E opens pads)
|
||||
uint8_t specialPad; // $7D09 working copy
|
||||
|
||||
// ---- input ----
|
||||
uint8_t inputMask; // $7169 EOR $FF of $DC00: 1 = pressed
|
||||
|
|
@ -255,12 +459,25 @@ typedef struct {
|
|||
uint8_t hitDispatchResult; // $721D
|
||||
uint8_t spriteSpriteColl; // $71CA latched $D01E
|
||||
uint8_t spriteBgColl; // $71CB latched $D01F
|
||||
// Per-sprite 24-bit row masks of the displayed frame, rebuilt only
|
||||
// when the sprite's bitmap or multicolour mode changes (derived
|
||||
// state, not C64 memory).
|
||||
uint32_t collMask[ST_HW_SPRITES][ST_SPRITE_H];
|
||||
// Sprites besides the cab whose $D01F bit a hook reads (levels J
|
||||
// and P watch their hazards hit the scenery); the rest are never
|
||||
// tested (derived state, not C64 memory).
|
||||
uint8_t bgCollSprites;
|
||||
// Per-sprite row masks of the displayed frame (3 bytes per row, the
|
||||
// leftmost pixel is bit 7 of byte 0), rebuilt only when the sprite's
|
||||
// bitmap or multicolour mode changes (derived state, not C64 memory).
|
||||
uint8_t collMask[ST_HW_SPRITES][ST_SPRITE_H][3];
|
||||
const uint8_t *collMaskBm[ST_HW_SPRITES];
|
||||
uint8_t collMaskMulti[ST_HW_SPRITES];
|
||||
// First and last rows of collMask[idx] with any pixel (first ==
|
||||
// ST_SPRITE_H when the mask is empty): the row tests walk only these.
|
||||
uint8_t collRowFirst[ST_HW_SPRITES];
|
||||
uint8_t collRowLast[ST_HW_SPRITES];
|
||||
// The cab's rows pre-shifted to each grid phase (cabWindows), built
|
||||
// per phase on first use; bit s of cabWinValid says cabWin[s]
|
||||
// matches collMask[0].
|
||||
uint8_t cabWin[ST_ROW_PHASES][ST_SPRITE_H][4];
|
||||
uint8_t cabWinValid;
|
||||
|
||||
// ---- fuel ----
|
||||
uint8_t fuelCountdown; // $71C7
|
||||
|
|
@ -300,6 +517,12 @@ typedef struct {
|
|||
uint8_t levelState; // $7215 screens completed
|
||||
uint8_t demoMode; // $721C
|
||||
uint8_t postMortem; // $5E9D
|
||||
// Jingles. The C64 plays its tunes BLOCKING ($44CF spins until the
|
||||
// song ends), so the sim only RAISES a request here and the host
|
||||
// plays it while holding the sim frozen -- tick-exactness survives
|
||||
// because no tick happens while the tune sounds.
|
||||
uint8_t jingleRequest; // song number + 1 to play now; 0 = none
|
||||
uint8_t jingleRotate; // $5E9B: start-of-screen tune = ++this & 3
|
||||
|
||||
// ---- demo playback ($48F2): the $0902 buffer a recording is
|
||||
// loaded into; a shorter recording leaves the previous tail behind
|
||||
|
|
@ -318,8 +541,6 @@ typedef struct {
|
|||
uint8_t logoColorIdx; // $48A4
|
||||
uint8_t logoCycleAux; // $48A5
|
||||
uint8_t logoDiv; // $48A6
|
||||
uint8_t starTimer[7]; // $44F8
|
||||
uint8_t starReload[7]; // $4500
|
||||
uint8_t introLoopCount; // $4508
|
||||
uint8_t introCabDx; // $450A
|
||||
uint8_t introCabDxTimer; // $450B
|
||||
|
|
@ -327,7 +548,7 @@ typedef struct {
|
|||
uint8_t spriteMc1; // $D026
|
||||
|
||||
// ---- per-level hook scratch ($7D9C.. and friends) ----
|
||||
uint8_t hookRam[ST_HOOK_BYTES]; // $7D98..$7FFF working copy
|
||||
StHookScratchT hookScratch; // per-level hook state
|
||||
uint8_t hookLevel; // level index the hook state belongs to
|
||||
uint8_t warpCounter; // $5A66
|
||||
uint8_t warpMask; // $5CE8
|
||||
|
|
@ -357,6 +578,29 @@ bool stSimAdvancePlayer(StSimT *sim);
|
|||
void stSimArchiveHud(StSimT *sim);
|
||||
// Mark every cell dirty (scene change).
|
||||
void stSimDirtyAll(StSimT *sim);
|
||||
void stSimDirtyCells(StSimT *sim); // repaint all, glyph index kept
|
||||
// $43A5 -- blank the fare meter back to its template.
|
||||
void stSimHudInit(StSimT *sim);
|
||||
// $4253 + $4293 -- snapshot the sprite shadows into the displayed frame.
|
||||
void stSimMarshal(StSimT *sim);
|
||||
// $63D0 -- rotate every row of a glyph one pixel right and mark it dirty.
|
||||
void stSimRotateGlyph(StSimT *sim, uint8_t ch);
|
||||
// A character's eight 1bpp rows: the ROM glyph, or the game's edit of it.
|
||||
// kStBit[i] == 1 << i. A variable shift is a library bit loop on the
|
||||
// 65816, so sprite-index bit tests go through this table instead.
|
||||
extern const uint8_t kStBit[ST_HW_SPRITES];
|
||||
|
||||
const uint8_t *stSimGlyph(const StSimT *sim, uint8_t ch);
|
||||
uint8_t stSimGlyphRow(const StSimT *sim, uint8_t ch, uint8_t row);
|
||||
// The same eight rows, writable (copied from ROM on the first edit).
|
||||
uint8_t *stSimGlyphMut(StSimT *sim, uint8_t ch);
|
||||
// Drop every edit: the whole charset is the ROM set again (scene load).
|
||||
void stSimGlyphReset(StSimT *sim);
|
||||
// The 17-bit VIC sprite X (msb:col), read and signed-byte add ($411B).
|
||||
uint16_t stSimSpriteX(const StSimT *sim, uint8_t idx);
|
||||
void stSimSpriteAddX(StSimT *sim, uint8_t idx, uint8_t delta);
|
||||
// $6C38 -- blank the 11-character message row.
|
||||
void stSimClearMessage(StSimT *sim);
|
||||
// A glyph's bits changed: every cell showing it has to be repainted.
|
||||
void stSimMarkChar(StSimT *sim, uint8_t ch);
|
||||
// Text and HUD primitives (screen RAM writes).
|
||||
|
|
@ -404,13 +648,19 @@ void stHookPerTick2(StSimT *sim); // $7D6C
|
|||
void stHookPerTick3(StSimT *sim); // $7D6F
|
||||
uint8_t stHookInput(StSimT *sim, uint8_t input); // $7D72
|
||||
uint8_t stHookHitVerdict(StSimT *sim); // $7D75: 0 = passenger contact is safe
|
||||
// Seed a converted level's scratch from the shipped blob (scene load).
|
||||
void stHookSceneLoad(StSimT *sim);
|
||||
|
||||
// ---- audio sink (host provides; stAudio.c / stsim stub) ----
|
||||
void stAudioSfx(const uint8_t *program9); // $42E9 load
|
||||
void stAudioNoise(bool on); // $D412 = $81 / $80
|
||||
void stAudioThrustSweep(uint8_t value); // $D400/$D401 = value
|
||||
void stAudioSpeech(uint8_t ch); // $9802
|
||||
void stAudioSpeechPhrase(const uint8_t *speech);
|
||||
void stAudioSilence(void); // voices 1+2 gate off
|
||||
void stAudioJingle(uint8_t song); // $44CF: silence, then play song (caller blocks)
|
||||
bool stAudioJingleActive(void); // still sounding?
|
||||
void stAudioMusic(uint8_t song, bool loop); // $CB02: silence, then play song in the background
|
||||
void stAudioVoice2(uint8_t freqLo, uint8_t freqHi, uint8_t ctrl); // level-hook tones
|
||||
void stAudioVoice1Freq(uint8_t value); // $D400/$D401 pokes from the fuel pump
|
||||
|
||||
|
|
|
|||
512
stSongData.h
Normal file
512
stSongData.h
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
// 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>
|
||||
|
||||
static const uint8_t gStSong0[109] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0xFF, 0xFF, 0x81, 0x10, 0x50, 0x01,
|
||||
0x02, 0x11, 0xA8, 0x01, 0x02, 0x83, 0x20, 0x21, 0x85, 0x10, 0x7A, 0x01,
|
||||
0x02, 0x11, 0xA8, 0x01, 0x02, 0x83, 0x20, 0x21, 0x85, 0x10, 0x50, 0x01,
|
||||
0x02, 0x11, 0xA8, 0x01, 0x02, 0x83, 0x20, 0x21, 0x85, 0x10, 0x7A, 0x01,
|
||||
0x02, 0x11, 0xDC, 0x01, 0x02, 0x83, 0x20, 0x21, 0x85, 0x10, 0x3E, 0x01,
|
||||
0x02, 0x11, 0xFC, 0x00, 0x02, 0x83, 0x21, 0x85, 0x11, 0xDC, 0x01, 0x02,
|
||||
0x83, 0x20, 0x21, 0x85, 0x10, 0x1B, 0x01, 0x02, 0x11, 0xFC, 0x00, 0x02,
|
||||
0x83, 0x21, 0x85, 0x11, 0xDC, 0x01, 0x02, 0x83, 0x20, 0x21, 0x85, 0x10,
|
||||
0xFC, 0x00, 0x02, 0x11, 0xFC, 0x00, 0x02, 0x8B, 0x21, 0x88, 0x20, 0x86,
|
||||
0x00,
|
||||
};
|
||||
|
||||
static const uint8_t gStSong1[119] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0xFF, 0xFF, 0x81, 0x10, 0xFC, 0x00,
|
||||
0x07, 0x11, 0x9F, 0x00, 0x07, 0x87, 0x20, 0x21, 0x81, 0x10, 0x1B, 0x01,
|
||||
0x07, 0x11, 0xA8, 0x00, 0x07, 0x87, 0x20, 0x21, 0x81, 0x10, 0xFC, 0x00,
|
||||
0x07, 0x11, 0xBD, 0x00, 0x07, 0x87, 0x20, 0x21, 0x81, 0x10, 0x1B, 0x01,
|
||||
0x07, 0x11, 0xD4, 0x00, 0x07, 0x87, 0x20, 0x21, 0x81, 0x10, 0x3E, 0x01,
|
||||
0x07, 0x11, 0xBD, 0x00, 0x07, 0x87, 0x20, 0x21, 0x81, 0x10, 0x50, 0x01,
|
||||
0x07, 0x11, 0xA8, 0x00, 0x07, 0x87, 0x20, 0x21, 0x81, 0x10, 0x3E, 0x01,
|
||||
0x07, 0x11, 0x9F, 0x00, 0x07, 0x87, 0x20, 0x21, 0x81, 0x10, 0x50, 0x01,
|
||||
0x07, 0x11, 0xA8, 0x00, 0x07, 0x87, 0x20, 0x21, 0x81, 0x10, 0x7A, 0x01,
|
||||
0x07, 0x11, 0xBD, 0x00, 0x07, 0x87, 0x21, 0x90, 0x20, 0x82, 0x00,
|
||||
};
|
||||
|
||||
static const uint8_t gStSong2[128] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0xFF, 0xFF, 0x81, 0x10, 0x7E, 0x00,
|
||||
0x00, 0x11, 0x9F, 0x00, 0x00, 0x85, 0x21, 0x82, 0x20, 0x81, 0x10, 0x7E,
|
||||
0x00, 0x00, 0x11, 0xA8, 0x00, 0x00, 0x85, 0x21, 0x82, 0x20, 0x81, 0x10,
|
||||
0x8D, 0x00, 0x00, 0x11, 0xBD, 0x00, 0x00, 0x85, 0x21, 0x82, 0x20, 0x81,
|
||||
0x10, 0x9F, 0x00, 0x00, 0x11, 0x9F, 0x00, 0x00, 0x85, 0x21, 0x82, 0x20,
|
||||
0x81, 0x10, 0x9F, 0x00, 0x00, 0x11, 0xA8, 0x00, 0x00, 0x85, 0x21, 0x82,
|
||||
0x20, 0x81, 0x10, 0xA8, 0x00, 0x00, 0x11, 0xBD, 0x00, 0x00, 0x85, 0x21,
|
||||
0x82, 0x20, 0x81, 0x10, 0xA8, 0x00, 0x00, 0x11, 0x9F, 0x00, 0x00, 0x85,
|
||||
0x21, 0x82, 0x20, 0x81, 0x10, 0xBD, 0x00, 0x00, 0x11, 0xA8, 0x00, 0x00,
|
||||
0x85, 0x21, 0x82, 0x20, 0x81, 0x11, 0x9F, 0x00, 0x00, 0x85, 0x21, 0x83,
|
||||
0x11, 0x7E, 0x00, 0x00, 0x85, 0x21, 0x84, 0x00,
|
||||
};
|
||||
|
||||
static const uint8_t gStSong3[154] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0xFF, 0xFF, 0x81, 0x10, 0xFC, 0x00,
|
||||
0x00, 0x11, 0x50, 0x01, 0x02, 0x12, 0x50, 0x01, 0x02, 0x83, 0x20, 0x21,
|
||||
0x22, 0x82, 0x10, 0x1B, 0x01, 0x00, 0x83, 0x20, 0x82, 0x10, 0x3E, 0x01,
|
||||
0x00, 0x11, 0x50, 0x01, 0x02, 0x12, 0x50, 0x01, 0x02, 0x83, 0x20, 0x21,
|
||||
0x22, 0x82, 0x10, 0xFC, 0x00, 0x00, 0x83, 0x20, 0x82, 0x10, 0x1B, 0x01,
|
||||
0x00, 0x11, 0x50, 0x01, 0x02, 0x12, 0x50, 0x01, 0x02, 0x83, 0x20, 0x21,
|
||||
0x22, 0x82, 0x10, 0xFC, 0x00, 0x00, 0x83, 0x20, 0x82, 0x10, 0x1B, 0x01,
|
||||
0x00, 0x11, 0x50, 0x01, 0x02, 0x12, 0x50, 0x01, 0x02, 0x83, 0x20, 0x21,
|
||||
0x22, 0x82, 0x10, 0xDC, 0x01, 0x00, 0x83, 0x20, 0x82, 0x11, 0x3E, 0x01,
|
||||
0x02, 0x12, 0x7A, 0x01, 0x02, 0x83, 0x21, 0x22, 0x87, 0x11, 0x50, 0x01,
|
||||
0x02, 0x12, 0x7A, 0x01, 0x02, 0x83, 0x21, 0x22, 0x87, 0x11, 0x1B, 0x01,
|
||||
0x02, 0x12, 0xFC, 0x00, 0x02, 0x83, 0x21, 0x22, 0x87, 0x11, 0xFC, 0x00,
|
||||
0x02, 0x12, 0xDC, 0x01, 0x02, 0x83, 0x21, 0x22, 0x88, 0x00,
|
||||
};
|
||||
|
||||
static const uint8_t gStSong4[92] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0xFF, 0xFF, 0x81, 0x10, 0xF8, 0x01,
|
||||
0x05, 0x11, 0xC1, 0x01, 0x05, 0x87, 0x20, 0x21, 0x89, 0x10, 0xF8, 0x01,
|
||||
0x05, 0x11, 0xC1, 0x01, 0x05, 0x87, 0x20, 0x21, 0x81, 0x10, 0xA1, 0x02,
|
||||
0x05, 0x11, 0xF8, 0x01, 0x05, 0x97, 0x20, 0x21, 0x99, 0x10, 0xF8, 0x01,
|
||||
0x05, 0x11, 0xA8, 0x01, 0x05, 0x87, 0x20, 0x21, 0x89, 0x10, 0xA1, 0x02,
|
||||
0x05, 0x11, 0xF8, 0x01, 0x05, 0x87, 0x20, 0x21, 0x81, 0x10, 0x50, 0x03,
|
||||
0x05, 0x11, 0xA1, 0x02, 0x05, 0x88, 0x11, 0x7B, 0x02, 0x05, 0x88, 0x11,
|
||||
0xA1, 0x02, 0x05, 0x87, 0x20, 0x21, 0x82, 0x00,
|
||||
};
|
||||
|
||||
static const uint8_t gStSong5[890] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0xFF, 0xFF, 0x81, 0x10, 0xF8, 0x01,
|
||||
0x02, 0x11, 0x9F, 0x00, 0x02, 0x12, 0x6A, 0x00, 0x0A, 0x83, 0x21, 0x82,
|
||||
0x12, 0xD4, 0x00, 0x0A, 0x85, 0x11, 0x9F, 0x00, 0x02, 0x12, 0x6A, 0x00,
|
||||
0x0A, 0x83, 0x21, 0x82, 0x12, 0xD4, 0x00, 0x0A, 0x85, 0x11, 0x9F, 0x00,
|
||||
0x02, 0x12, 0x6A, 0x00, 0x0A, 0x83, 0x21, 0x82, 0x12, 0xD4, 0x00, 0x0A,
|
||||
0x85, 0x11, 0x9F, 0x00, 0x02, 0x12, 0x6A, 0x00, 0x0A, 0x83, 0x21, 0x81,
|
||||
0x20, 0x81, 0x12, 0xD4, 0x00, 0x0A, 0x85, 0x10, 0xF8, 0x01, 0x02, 0x11,
|
||||
0x9F, 0x00, 0x02, 0x12, 0x6A, 0x00, 0x0A, 0x83, 0x21, 0x82, 0x12, 0xD4,
|
||||
0x00, 0x0A, 0x85, 0x11, 0x9F, 0x00, 0x02, 0x12, 0x6A, 0x00, 0x0A, 0x83,
|
||||
0x21, 0x82, 0x12, 0xD4, 0x00, 0x0A, 0x85, 0x11, 0x9F, 0x00, 0x02, 0x12,
|
||||
0x6A, 0x00, 0x0A, 0x83, 0x21, 0x82, 0x12, 0xD4, 0x00, 0x0A, 0x85, 0x11,
|
||||
0x9F, 0x00, 0x02, 0x12, 0x6A, 0x00, 0x0A, 0x83, 0x21, 0x81, 0x20, 0x81,
|
||||
0x12, 0xD4, 0x00, 0x0A, 0x85, 0x10, 0xF8, 0x01, 0x02, 0x11, 0x9F, 0x00,
|
||||
0x02, 0x12, 0x6A, 0x00, 0x0A, 0x83, 0x21, 0x82, 0x12, 0xD4, 0x00, 0x0A,
|
||||
0x85, 0x11, 0x9F, 0x00, 0x02, 0x12, 0x6A, 0x00, 0x0A, 0x83, 0x21, 0x82,
|
||||
0x12, 0xD4, 0x00, 0x0A, 0x85, 0x11, 0x9F, 0x00, 0x02, 0x12, 0x6A, 0x00,
|
||||
0x0A, 0x83, 0x21, 0x81, 0x20, 0x81, 0x12, 0xD4, 0x00, 0x0A, 0x83, 0x22,
|
||||
0x82, 0x10, 0x36, 0x02, 0x02, 0x11, 0x8D, 0x00, 0x02, 0x12, 0x64, 0x00,
|
||||
0x0A, 0x83, 0x21, 0x81, 0x20, 0x81, 0x12, 0xC8, 0x00, 0x0A, 0x85, 0x10,
|
||||
0x36, 0x02, 0x02, 0x11, 0x8D, 0x00, 0x02, 0x12, 0x64, 0x00, 0x0A, 0x83,
|
||||
0x21, 0x82, 0x12, 0xC8, 0x00, 0x0A, 0x85, 0x11, 0x8D, 0x00, 0x02, 0x12,
|
||||
0x64, 0x00, 0x0A, 0x83, 0x21, 0x82, 0x12, 0xC8, 0x00, 0x0A, 0x85, 0x11,
|
||||
0x8D, 0x00, 0x02, 0x12, 0x64, 0x00, 0x0A, 0x83, 0x21, 0x82, 0x12, 0xC8,
|
||||
0x00, 0x0A, 0x83, 0x22, 0x82, 0x11, 0x8D, 0x00, 0x02, 0x12, 0x64, 0x00,
|
||||
0x0A, 0x83, 0x21, 0x81, 0x20, 0x81, 0x12, 0xC8, 0x00, 0x0A, 0x85, 0x10,
|
||||
0x7B, 0x02, 0x02, 0x11, 0xF8, 0x01, 0x02, 0x12, 0x5E, 0x00, 0x0A, 0x84,
|
||||
0x20, 0x21, 0x81, 0x12, 0xBD, 0x00, 0x0A, 0x85, 0x12, 0x5E, 0x00, 0x0A,
|
||||
0x85, 0x12, 0xBD, 0x00, 0x0A, 0x85, 0x10, 0xA1, 0x02, 0x02, 0x11, 0x36,
|
||||
0x02, 0x02, 0x12, 0x54, 0x00, 0x0A, 0x84, 0x20, 0x21, 0x81, 0x12, 0xA8,
|
||||
0x00, 0x0A, 0x85, 0x12, 0x54, 0x00, 0x0A, 0x85, 0x12, 0xA8, 0x00, 0x0A,
|
||||
0x85, 0x10, 0xF3, 0x02, 0x02, 0x11, 0x7B, 0x02, 0x02, 0x12, 0x4F, 0x00,
|
||||
0x0A, 0x84, 0x20, 0x21, 0x81, 0x12, 0x9F, 0x00, 0x0A, 0x85, 0x12, 0x4F,
|
||||
0x00, 0x0A, 0x85, 0x12, 0x9F, 0x00, 0x0A, 0x85, 0x10, 0x20, 0x03, 0x02,
|
||||
0x11, 0x7B, 0x02, 0x02, 0x12, 0x47, 0x00, 0x0A, 0x84, 0x20, 0x21, 0x81,
|
||||
0x12, 0x8D, 0x00, 0x0A, 0x85, 0x12, 0x47, 0x00, 0x0A, 0x85, 0x12, 0x8D,
|
||||
0x00, 0x0A, 0x85, 0x10, 0x50, 0x03, 0x02, 0x11, 0x7B, 0x02, 0x02, 0x12,
|
||||
0x43, 0x00, 0x0A, 0x85, 0x12, 0x85, 0x00, 0x0A, 0x85, 0x12, 0x43, 0x00,
|
||||
0x0A, 0x85, 0x12, 0x85, 0x00, 0x0A, 0x85, 0x12, 0x43, 0x00, 0x0A, 0x85,
|
||||
0x12, 0x85, 0x00, 0x0A, 0x85, 0x12, 0x43, 0x00, 0x0A, 0x85, 0x12, 0x85,
|
||||
0x00, 0x0A, 0x85, 0x10, 0xA8, 0x01, 0x02, 0x11, 0x3E, 0x01, 0x02, 0x12,
|
||||
0x43, 0x00, 0x0A, 0x84, 0x20, 0x21, 0x81, 0x12, 0x85, 0x00, 0x0A, 0x85,
|
||||
0x22, 0x9E, 0x10, 0x50, 0x03, 0x02, 0x11, 0x50, 0x01, 0x02, 0x12, 0xFC,
|
||||
0x00, 0x0A, 0xA2, 0x20, 0x21, 0x84, 0x22, 0x82, 0x10, 0x50, 0x03, 0x02,
|
||||
0x11, 0x50, 0x01, 0x02, 0x12, 0xFC, 0x00, 0x0A, 0xA2, 0x20, 0x21, 0x84,
|
||||
0x22, 0x82, 0x10, 0x50, 0x03, 0x02, 0x11, 0x50, 0x01, 0x02, 0x12, 0xFC,
|
||||
0x00, 0x0A, 0x98, 0x20, 0x21, 0x84, 0x22, 0x82, 0x10, 0xF3, 0x02, 0x02,
|
||||
0x11, 0x3E, 0x01, 0x02, 0x12, 0xE1, 0x00, 0x0A, 0x84, 0x20, 0x21, 0x84,
|
||||
0x22, 0x82, 0x10, 0xF3, 0x02, 0x02, 0x11, 0x3E, 0x01, 0x02, 0x12, 0xE1,
|
||||
0x00, 0x0A, 0xA2, 0x20, 0x21, 0x84, 0x22, 0x82, 0x10, 0xA1, 0x02, 0x02,
|
||||
0x11, 0x1B, 0x01, 0x02, 0x12, 0xD4, 0x00, 0x0A, 0xA2, 0x21, 0x84, 0x22,
|
||||
0x82, 0x10, 0x7B, 0x02, 0x02, 0x11, 0xFC, 0x00, 0x02, 0x12, 0xBD, 0x00,
|
||||
0x0A, 0x84, 0x20, 0x21, 0x84, 0x22, 0x8C, 0x10, 0x36, 0x02, 0x02, 0x11,
|
||||
0x1B, 0x01, 0x02, 0x12, 0xA8, 0x00, 0x0A, 0x84, 0x20, 0x21, 0x84, 0x22,
|
||||
0x8C, 0x10, 0xF3, 0x02, 0x02, 0x11, 0x3E, 0x01, 0x02, 0x12, 0x7E, 0x00,
|
||||
0x0A, 0x85, 0x12, 0xBD, 0x00, 0x0A, 0x85, 0x12, 0x7E, 0x00, 0x0A, 0x85,
|
||||
0x12, 0xBD, 0x00, 0x0A, 0x85, 0x12, 0x7E, 0x00, 0x0A, 0x85, 0x12, 0xBD,
|
||||
0x00, 0x0A, 0x85, 0x12, 0x7E, 0x00, 0x0A, 0x85, 0x12, 0xBD, 0x00, 0x0A,
|
||||
0x85, 0x12, 0x7E, 0x00, 0x0A, 0x84, 0x20, 0x81, 0x12, 0xBD, 0x00, 0x0A,
|
||||
0x85, 0x10, 0x7B, 0x02, 0x02, 0x12, 0x7E, 0x00, 0x0A, 0x84, 0x20, 0x81,
|
||||
0x12, 0xBD, 0x00, 0x0A, 0x85, 0x10, 0xF8, 0x01, 0x02, 0x12, 0x7E, 0x00,
|
||||
0x0A, 0x84, 0x20, 0x81, 0x12, 0xBD, 0x00, 0x0A, 0x85, 0x10, 0x7B, 0x02,
|
||||
0x02, 0x12, 0x7E, 0x00, 0x0A, 0x84, 0x20, 0x21, 0x81, 0x12, 0xBD, 0x00,
|
||||
0x0A, 0x83, 0x22, 0x82, 0x10, 0xF3, 0x02, 0x02, 0x11, 0x1B, 0x01, 0x02,
|
||||
0x12, 0x77, 0x00, 0x0A, 0x85, 0x12, 0xBD, 0x00, 0x0A, 0x85, 0x12, 0x77,
|
||||
0x00, 0x0A, 0x84, 0x20, 0x81, 0x12, 0xBD, 0x00, 0x0A, 0x85, 0x10, 0x50,
|
||||
0x03, 0x02, 0x12, 0x77, 0x00, 0x0A, 0x85, 0x12, 0xBD, 0x00, 0x0A, 0x85,
|
||||
0x12, 0x77, 0x00, 0x0A, 0x84, 0x20, 0x81, 0x12, 0xBD, 0x00, 0x0A, 0x85,
|
||||
0x10, 0xF3, 0x02, 0x02, 0x12, 0x77, 0x00, 0x0A, 0x84, 0x20, 0x81, 0x12,
|
||||
0xBD, 0x00, 0x0A, 0x85, 0x10, 0xA1, 0x02, 0x02, 0x12, 0x77, 0x00, 0x0A,
|
||||
0x84, 0x20, 0x81, 0x12, 0xBD, 0x00, 0x0A, 0x85, 0x10, 0x7B, 0x02, 0x02,
|
||||
0x12, 0x77, 0x00, 0x0A, 0x84, 0x20, 0x81, 0x12, 0xBD, 0x00, 0x0A, 0x85,
|
||||
0x10, 0x36, 0x02, 0x02, 0x12, 0x77, 0x00, 0x0A, 0x84, 0x20, 0x21, 0x81,
|
||||
0x12, 0xBD, 0x00, 0x0A, 0x83, 0x22, 0x82, 0x10, 0xF8, 0x01, 0x02, 0x11,
|
||||
0x3E, 0x01, 0x02, 0x12, 0x7E, 0x00, 0x0A, 0x84, 0x20, 0x21, 0x84, 0x22,
|
||||
0x83, 0x00,
|
||||
};
|
||||
|
||||
static const uint8_t gStSong6[611] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0xFF, 0xFF, 0x81, 0x11, 0x7A, 0x01,
|
||||
0x01, 0x12, 0xF8, 0x01, 0x01, 0x88, 0x21, 0x22, 0x90, 0x11, 0x7A, 0x01,
|
||||
0x01, 0x12, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x22, 0x84, 0x11, 0x7A, 0x01,
|
||||
0x01, 0x12, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x22, 0x84, 0x11, 0x7A, 0x01,
|
||||
0x01, 0x12, 0xF8, 0x01, 0x01, 0xA0, 0x21, 0x22, 0x84, 0x10, 0x5E, 0x00,
|
||||
0x00, 0x86, 0x20, 0x86, 0x10, 0x7E, 0x00, 0x00, 0x86, 0x20, 0x86, 0x10,
|
||||
0x9F, 0x00, 0x00, 0x86, 0x20, 0x86, 0x10, 0xBD, 0x00, 0x00, 0x11, 0x50,
|
||||
0x01, 0x01, 0x12, 0xC1, 0x01, 0x01, 0x88, 0x21, 0x22, 0x84, 0x11, 0x2C,
|
||||
0x01, 0x01, 0x12, 0x90, 0x01, 0x01, 0x88, 0x21, 0x22, 0x84, 0x11, 0x50,
|
||||
0x01, 0x01, 0x12, 0xC1, 0x01, 0x01, 0x88, 0x21, 0x22, 0x84, 0x11, 0x7A,
|
||||
0x01, 0x01, 0x12, 0xF8, 0x01, 0x01, 0x88, 0x21, 0x22, 0x90, 0x11, 0x7A,
|
||||
0x01, 0x01, 0x12, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x22, 0x84, 0x20, 0x11,
|
||||
0x7A, 0x01, 0x01, 0x12, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x22, 0x84, 0x11,
|
||||
0x7A, 0x01, 0x01, 0x12, 0xF8, 0x01, 0x01, 0x92, 0x10, 0xD4, 0x00, 0x00,
|
||||
0x83, 0x20, 0x8B, 0x21, 0x22, 0x84, 0x10, 0xBD, 0x00, 0x00, 0x83, 0x20,
|
||||
0x8F, 0x10, 0x9F, 0x00, 0x00, 0x83, 0x20, 0x83, 0x11, 0x7A, 0x01, 0x01,
|
||||
0x12, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x22, 0x84, 0x11, 0x7A, 0x01, 0x01,
|
||||
0x12, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x22, 0x84, 0x10, 0x8D, 0x00, 0x00,
|
||||
0x11, 0xA8, 0x01, 0x01, 0x12, 0x36, 0x02, 0x01, 0x88, 0x21, 0x22, 0x84,
|
||||
0x11, 0x7A, 0x01, 0x01, 0x12, 0xF8, 0x01, 0x01, 0x88, 0x21, 0x22, 0x84,
|
||||
0x11, 0xA8, 0x01, 0x01, 0x12, 0x36, 0x02, 0x01, 0x86, 0x20, 0x82, 0x21,
|
||||
0x22, 0x84, 0x10, 0x77, 0x00, 0x00, 0x11, 0xDC, 0x01, 0x01, 0x12, 0x7B,
|
||||
0x02, 0x01, 0x88, 0x21, 0x22, 0x90, 0x11, 0xDC, 0x01, 0x01, 0x12, 0x7B,
|
||||
0x02, 0x01, 0x82, 0x21, 0x22, 0x84, 0x11, 0xDC, 0x01, 0x01, 0x12, 0x7B,
|
||||
0x02, 0x01, 0x82, 0x21, 0x22, 0x84, 0x11, 0xDC, 0x01, 0x01, 0x12, 0x7B,
|
||||
0x02, 0x01, 0x92, 0x20, 0x8E, 0x21, 0x22, 0x84, 0x10, 0x3B, 0x00, 0x00,
|
||||
0x98, 0x11, 0xDC, 0x01, 0x01, 0x12, 0x7B, 0x02, 0x01, 0x82, 0x21, 0x22,
|
||||
0x84, 0x11, 0xDC, 0x01, 0x01, 0x12, 0x7B, 0x02, 0x01, 0x82, 0x21, 0x22,
|
||||
0x84, 0x11, 0xDC, 0x01, 0x01, 0x12, 0x7B, 0x02, 0x01, 0x88, 0x21, 0x22,
|
||||
0x84, 0x11, 0xA8, 0x01, 0x01, 0x12, 0x36, 0x02, 0x01, 0x86, 0x20, 0x82,
|
||||
0x21, 0x22, 0x84, 0x11, 0xDC, 0x01, 0x01, 0x12, 0x7B, 0x02, 0x01, 0x88,
|
||||
0x21, 0x22, 0x84, 0x10, 0x7E, 0x00, 0x00, 0x11, 0xF8, 0x01, 0x01, 0x12,
|
||||
0xA1, 0x02, 0x01, 0x88, 0x21, 0x22, 0x90, 0x11, 0xF8, 0x01, 0x01, 0x12,
|
||||
0xA1, 0x02, 0x01, 0x82, 0x21, 0x22, 0x84, 0x11, 0xF8, 0x01, 0x01, 0x12,
|
||||
0xA1, 0x02, 0x01, 0x82, 0x21, 0x22, 0x84, 0x11, 0xF8, 0x01, 0x01, 0x12,
|
||||
0xA1, 0x02, 0x01, 0x92, 0x20, 0x8E, 0x21, 0x22, 0x84, 0x10, 0x3F, 0x00,
|
||||
0x00, 0x98, 0x11, 0xF8, 0x01, 0x01, 0x12, 0xA1, 0x02, 0x01, 0x82, 0x21,
|
||||
0x22, 0x84, 0x20, 0x11, 0xF8, 0x01, 0x01, 0x12, 0xA1, 0x02, 0x01, 0x82,
|
||||
0x21, 0x22, 0x84, 0x10, 0x7E, 0x00, 0x00, 0x11, 0x36, 0x02, 0x01, 0x12,
|
||||
0xF3, 0x02, 0x01, 0x88, 0x21, 0x22, 0x84, 0x11, 0xF8, 0x01, 0x01, 0x12,
|
||||
0xA1, 0x02, 0x01, 0x86, 0x20, 0x82, 0x21, 0x22, 0x84, 0x11, 0x36, 0x02,
|
||||
0x01, 0x12, 0xF3, 0x02, 0x01, 0x88, 0x21, 0x22, 0x84, 0x10, 0x8D, 0x00,
|
||||
0x00, 0x11, 0x7B, 0x02, 0x01, 0x12, 0x50, 0x03, 0x01, 0xB2, 0x21, 0x84,
|
||||
0x20, 0x82, 0x22, 0x90, 0x10, 0x47, 0x00, 0x00, 0x98, 0x11, 0x7B, 0x02,
|
||||
0x01, 0x12, 0x50, 0x03, 0x01, 0x82, 0x21, 0x22, 0x84, 0x20, 0x11, 0x7B,
|
||||
0x02, 0x01, 0x12, 0x50, 0x03, 0x01, 0x82, 0x21, 0x22, 0x84, 0x10, 0x8D,
|
||||
0x00, 0x00, 0x11, 0x36, 0x02, 0x01, 0x12, 0x50, 0x03, 0x01, 0x88, 0x21,
|
||||
0x22, 0x84, 0x11, 0x36, 0x02, 0x01, 0x12, 0x50, 0x03, 0x01, 0x88, 0x21,
|
||||
0x22, 0x84, 0x11, 0x36, 0x02, 0x01, 0x12, 0x50, 0x03, 0x01, 0x86, 0x20,
|
||||
0x82, 0x21, 0x22, 0x84, 0x10, 0x9F, 0x00, 0x00, 0x11, 0x16, 0x02, 0x01,
|
||||
0x12, 0x50, 0x03, 0x01, 0xEC, 0x20, 0x22, 0x82, 0x21, 0x85, 0x00,
|
||||
};
|
||||
|
||||
static const uint8_t gStSong7[777] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0xFF, 0xFF, 0x81, 0x10, 0x7A, 0x01,
|
||||
0x00, 0x11, 0xF6, 0x04, 0x05, 0x12, 0x7E, 0x00, 0x07, 0x8A, 0x22, 0x84,
|
||||
0x21, 0x86, 0x11, 0x42, 0x05, 0x05, 0x85, 0x11, 0xF6, 0x04, 0x05, 0x84,
|
||||
0x21, 0x81, 0x11, 0x6C, 0x04, 0x05, 0x12, 0x77, 0x00, 0x07, 0x84, 0x21,
|
||||
0x86, 0x11, 0xF6, 0x04, 0x05, 0x22, 0x84, 0x21, 0x86, 0x11, 0x42, 0x05,
|
||||
0x05, 0x83, 0x20, 0x81, 0x21, 0x86, 0x10, 0xFC, 0x00, 0x00, 0x11, 0xF6,
|
||||
0x04, 0x05, 0x12, 0x6A, 0x00, 0x07, 0x84, 0x21, 0x86, 0x11, 0x42, 0x05,
|
||||
0x05, 0x22, 0x84, 0x21, 0x86, 0x11, 0xE6, 0x05, 0x05, 0x83, 0x20, 0x81,
|
||||
0x21, 0x86, 0x10, 0x1B, 0x01, 0x00, 0x11, 0xF0, 0x03, 0x05, 0x12, 0x5E,
|
||||
0x00, 0x07, 0x8A, 0x10, 0x3E, 0x01, 0x00, 0x22, 0x84, 0x21, 0x86, 0x10,
|
||||
0x50, 0x01, 0x00, 0x85, 0x11, 0xF0, 0x03, 0x05, 0x85, 0x10, 0x7A, 0x01,
|
||||
0x00, 0x12, 0x7E, 0x00, 0x07, 0x8A, 0x22, 0x85, 0x11, 0xB8, 0x03, 0x05,
|
||||
0x85, 0x11, 0x50, 0x03, 0x05, 0x85, 0x11, 0xF3, 0x02, 0x05, 0x85, 0x11,
|
||||
0x6C, 0x04, 0x05, 0x12, 0x77, 0x00, 0x07, 0x84, 0x21, 0x86, 0x11, 0xF6,
|
||||
0x04, 0x05, 0x22, 0x84, 0x21, 0x86, 0x11, 0x42, 0x05, 0x05, 0x84, 0x21,
|
||||
0x86, 0x11, 0xE6, 0x05, 0x05, 0x12, 0x7E, 0x00, 0x07, 0x83, 0x20, 0x81,
|
||||
0x21, 0x86, 0x11, 0xE6, 0x05, 0x05, 0x22, 0x84, 0x21, 0x86, 0x11, 0xE6,
|
||||
0x05, 0x05, 0x84, 0x21, 0x86, 0x10, 0xA8, 0x01, 0x00, 0x11, 0x6C, 0x04,
|
||||
0x05, 0x12, 0x5E, 0x00, 0x07, 0x89, 0x21, 0x81, 0x10, 0x7A, 0x01, 0x00,
|
||||
0x22, 0x8A, 0x10, 0x50, 0x01, 0x00, 0x11, 0x6C, 0x04, 0x05, 0x8A, 0x10,
|
||||
0x7A, 0x01, 0x00, 0x11, 0xF6, 0x04, 0x05, 0x12, 0x7E, 0x00, 0x07, 0x89,
|
||||
0x21, 0x81, 0x22, 0x83, 0x20, 0x91, 0x10, 0x50, 0x01, 0x00, 0x11, 0xB8,
|
||||
0x03, 0x05, 0x12, 0x77, 0x00, 0x07, 0x89, 0x21, 0x81, 0x10, 0x3E, 0x01,
|
||||
0x00, 0x22, 0x8A, 0x10, 0x1B, 0x01, 0x00, 0x11, 0xB8, 0x03, 0x05, 0x8A,
|
||||
0x10, 0x3E, 0x01, 0x00, 0x11, 0xF0, 0x03, 0x05, 0x12, 0x6A, 0x00, 0x07,
|
||||
0x89, 0x21, 0x81, 0x22, 0x83, 0x20, 0x91, 0x10, 0x1B, 0x01, 0x00, 0x11,
|
||||
0xF3, 0x02, 0x05, 0x12, 0x5E, 0x00, 0x07, 0x89, 0x21, 0x81, 0x10, 0xFC,
|
||||
0x00, 0x00, 0x22, 0x8A, 0x10, 0xEE, 0x00, 0x00, 0x11, 0xF3, 0x02, 0x05,
|
||||
0x89, 0x21, 0x81, 0x10, 0xFC, 0x00, 0x00, 0x11, 0xF0, 0x03, 0x05, 0x12,
|
||||
0x7E, 0x00, 0x07, 0x83, 0x20, 0x87, 0x11, 0xB8, 0x03, 0x05, 0x22, 0x8A,
|
||||
0x10, 0x3E, 0x01, 0x00, 0x11, 0xF0, 0x03, 0x05, 0x89, 0x21, 0x81, 0x10,
|
||||
0xBD, 0x00, 0x00, 0x11, 0x6C, 0x04, 0x05, 0x12, 0x77, 0x00, 0x07, 0x8A,
|
||||
0x11, 0xF0, 0x03, 0x05, 0x22, 0x8A, 0x11, 0x6C, 0x04, 0x05, 0x8A, 0x11,
|
||||
0xF6, 0x04, 0x05, 0x12, 0x6A, 0x00, 0x07, 0x8A, 0x11, 0x6C, 0x04, 0x05,
|
||||
0x22, 0x83, 0x20, 0x87, 0x11, 0xF6, 0x04, 0x05, 0x8A, 0x10, 0xEE, 0x00,
|
||||
0x00, 0x11, 0x42, 0x05, 0x05, 0x12, 0x5E, 0x00, 0x07, 0x8A, 0x10, 0xFC,
|
||||
0x00, 0x00, 0x11, 0xF6, 0x04, 0x05, 0x22, 0x8A, 0x10, 0x1B, 0x01, 0x00,
|
||||
0x11, 0x42, 0x05, 0x05, 0x89, 0x21, 0x81, 0x10, 0xFC, 0x00, 0x00, 0x11,
|
||||
0xF6, 0x04, 0x05, 0x12, 0x7E, 0x00, 0x07, 0x83, 0x20, 0x86, 0x21, 0x81,
|
||||
0x22, 0x8A, 0x11, 0xF6, 0x04, 0x05, 0x8A, 0x10, 0xEE, 0x00, 0x00, 0x11,
|
||||
0xE6, 0x05, 0x05, 0x12, 0x77, 0x00, 0x07, 0x8A, 0x10, 0xFC, 0x00, 0x00,
|
||||
0x22, 0x8A, 0x10, 0x1B, 0x01, 0x00, 0x8A, 0x10, 0x3E, 0x01, 0x00, 0x12,
|
||||
0x6A, 0x00, 0x07, 0x83, 0x20, 0x86, 0x21, 0x81, 0x22, 0x94, 0x10, 0x1B,
|
||||
0x01, 0x00, 0x11, 0xE6, 0x05, 0x05, 0x12, 0x5E, 0x00, 0x07, 0x83, 0x20,
|
||||
0x87, 0x22, 0x89, 0x21, 0x81, 0x10, 0x1B, 0x01, 0x00, 0x8A, 0x10, 0x7A,
|
||||
0x01, 0x00, 0x11, 0x6C, 0x04, 0x05, 0x12, 0x8D, 0x00, 0x07, 0x89, 0x21,
|
||||
0x81, 0x22, 0x8A, 0x11, 0xF0, 0x03, 0x05, 0x8A, 0x11, 0xB8, 0x03, 0x05,
|
||||
0x12, 0x77, 0x00, 0x07, 0x8A, 0x11, 0xF0, 0x03, 0x05, 0x22, 0x8A, 0x11,
|
||||
0x6C, 0x04, 0x05, 0x8A, 0x11, 0xF3, 0x02, 0x05, 0x12, 0x6A, 0x00, 0x07,
|
||||
0x83, 0x20, 0x86, 0x21, 0x81, 0x22, 0x8A, 0x10, 0x7A, 0x01, 0x00, 0x11,
|
||||
0x6C, 0x04, 0x05, 0x81, 0x20, 0x84, 0x10, 0x7A, 0x01, 0x00, 0x81, 0x20,
|
||||
0x84, 0x10, 0x7A, 0x01, 0x00, 0x11, 0xAF, 0x04, 0x05, 0x12, 0x5E, 0x00,
|
||||
0x07, 0x83, 0x20, 0x87, 0x10, 0x7A, 0x01, 0x00, 0x22, 0x83, 0x20, 0x86,
|
||||
0x21, 0x81, 0x10, 0x7A, 0x01, 0x00, 0x83, 0x20, 0x87, 0x10, 0x7A, 0x01,
|
||||
0x00, 0x11, 0xF6, 0x04, 0x05, 0x12, 0x7E, 0x00, 0x07, 0x85, 0x11, 0xE6,
|
||||
0x05, 0x05, 0x85, 0x11, 0xF6, 0x04, 0x05, 0x85, 0x11, 0xE6, 0x05, 0x05,
|
||||
0x85, 0x11, 0xF6, 0x04, 0x05, 0x84, 0x12, 0x5E, 0x00, 0x07, 0x81, 0x11,
|
||||
0xE6, 0x05, 0x05, 0x85, 0x11, 0xF6, 0x04, 0x05, 0x85, 0x11, 0xE6, 0x05,
|
||||
0x05, 0x85, 0x11, 0xF6, 0x04, 0x05, 0x85, 0x11, 0xE6, 0x05, 0x05, 0x83,
|
||||
0x12, 0x7E, 0x00, 0x07, 0x82, 0x11, 0xF6, 0x04, 0x05, 0x85, 0x11, 0xE6,
|
||||
0x05, 0x05, 0x85, 0x11, 0xF6, 0x04, 0x05, 0x85, 0x11, 0xE6, 0x05, 0x05,
|
||||
0x85, 0x11, 0xF6, 0x04, 0x05, 0x82, 0x12, 0x5E, 0x00, 0x07, 0x83, 0x11,
|
||||
0xE6, 0x05, 0x05, 0x85, 0x11, 0xF6, 0x04, 0x05, 0x85, 0x11, 0xE6, 0x05,
|
||||
0x05, 0x85, 0x11, 0xF6, 0x04, 0x05, 0x81, 0x22, 0x85, 0x12, 0x7E, 0x00,
|
||||
0x07, 0x88, 0x21, 0x89, 0x20, 0x88, 0x22, 0x86, 0x00,
|
||||
};
|
||||
|
||||
static const uint8_t gStSong8[2338] = {
|
||||
0x4A, 0x59, 0x4D, 0x31, 0x14, 0x00, 0x00, 0x00, 0x81, 0x10, 0x1F, 0x00,
|
||||
0x07, 0x11, 0x7E, 0x00, 0x01, 0x13, 0x1C, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0xB2, 0x00, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0xD4, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xFC, 0x00,
|
||||
0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0x50, 0x01, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x10, 0x21, 0x00, 0x07, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xC1, 0x01,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0xF8, 0x01,
|
||||
0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0x57, 0x02, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xF3, 0x02, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x82, 0x03, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x10, 0x23, 0x00, 0x07, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xF0, 0x03, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0x42, 0x05, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0x31, 0x06, 0x01, 0x13, 0x1D, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0xF6, 0x04,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1C, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xF0, 0x03, 0x01, 0x82, 0x21, 0x82, 0x10, 0x21, 0x00, 0x07,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0x20, 0x03, 0x01, 0x13, 0x1D, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0xA1, 0x02,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x36, 0x02, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x86, 0x11, 0xF8, 0x01, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0xC1, 0x01, 0x01, 0x82, 0x10, 0x1F,
|
||||
0x00, 0x07, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x7A, 0x01, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x86, 0x11, 0x3E, 0x01, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0xFC, 0x00, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xD4, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x10, 0x21, 0x00,
|
||||
0x07, 0x11, 0x9F, 0x00, 0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0x7E, 0x00, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0xB2, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1C, 0x00, 0x0A, 0x86, 0x11, 0xD4, 0x00,
|
||||
0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xFC, 0x00, 0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86,
|
||||
0x10, 0x23, 0x00, 0x07, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0x50, 0x01,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0xC1, 0x01,
|
||||
0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0x57, 0x02, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0xF3, 0x02, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x10, 0x21, 0x00, 0x07, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0x82, 0x03, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xF0, 0x03, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x42, 0x05, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x31, 0x06,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xF6, 0x04, 0x01, 0x82, 0x21, 0x82, 0x10, 0x1F, 0x00, 0x07,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xF0, 0x03, 0x01, 0x13, 0x1D, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1C, 0x00, 0x0A, 0x84, 0x11, 0x20, 0x03,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xA1, 0x02, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x86, 0x11, 0x36, 0x02, 0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0xF8, 0x01, 0x01, 0x82, 0x10, 0x21,
|
||||
0x00, 0x07, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xC1, 0x01, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x86, 0x11, 0x7A, 0x01, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x3E, 0x01, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xFC, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x10, 0x23, 0x00,
|
||||
0x07, 0x11, 0xD4, 0x00, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x9F, 0x00, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0x7E, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xB2, 0x00,
|
||||
0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xD4, 0x00, 0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86,
|
||||
0x10, 0x21, 0x00, 0x07, 0x13, 0x1C, 0x00, 0x0A, 0x82, 0x11, 0xFC, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0x50, 0x01,
|
||||
0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xC1, 0x01, 0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x57, 0x02, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x10, 0x1F, 0x00, 0x07, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xF3, 0x02, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0x82, 0x03, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0xF0, 0x03, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x42, 0x05,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x31, 0x06, 0x01, 0x82, 0x21, 0x82, 0x10, 0x21, 0x00, 0x07,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0xF6, 0x04, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0xF0, 0x03,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x20, 0x03, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x86, 0x11, 0xA1, 0x02, 0x01, 0x13, 0x1C, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0x36, 0x02, 0x01, 0x82, 0x10, 0x23,
|
||||
0x00, 0x07, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x86, 0x11, 0xC1, 0x01, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x7A, 0x01, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0x3E, 0x01,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x10, 0x21, 0x00,
|
||||
0x07, 0x11, 0xFC, 0x00, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0xD4, 0x00, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0x9F, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x7E, 0x00,
|
||||
0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xB2, 0x00, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x10, 0x1F, 0x00, 0x07, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0xD4, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xFC, 0x00,
|
||||
0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x84, 0x11, 0x50, 0x01, 0x01, 0x82, 0x21, 0x13, 0x1C, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0xC1, 0x01, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xF8, 0x01, 0x01, 0x13, 0x1D, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x10, 0x21, 0x00, 0x07, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x84, 0x11, 0x57, 0x02, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xF3, 0x02, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x82, 0x03, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0xF0, 0x03,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x42, 0x05, 0x01, 0x82, 0x21, 0x82, 0x10, 0x23, 0x00, 0x07,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x31, 0x06, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0xF6, 0x04,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xF0, 0x03, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x86, 0x11, 0x20, 0x03, 0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0xA1, 0x02, 0x01, 0x82, 0x10, 0x21,
|
||||
0x00, 0x07, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x36, 0x02, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1C, 0x00, 0x0A,
|
||||
0x86, 0x11, 0xF8, 0x01, 0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0xC1, 0x01, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0x7A, 0x01,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x10, 0x1F, 0x00,
|
||||
0x07, 0x11, 0x3E, 0x01, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0xFC, 0x00, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xD4, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x9F, 0x00,
|
||||
0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0x7E, 0x00, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x10, 0x21, 0x00, 0x07, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xB2, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0xD4, 0x00,
|
||||
0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xFC, 0x00, 0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0x50, 0x01, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xC1, 0x01, 0x01, 0x13, 0x1D, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x10, 0x23, 0x00, 0x07, 0x13, 0x1C, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0x57, 0x02, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xF3, 0x02, 0x01, 0x13, 0x1D, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x82, 0x03,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xF0, 0x03, 0x01, 0x82, 0x21, 0x82, 0x10, 0x21, 0x00, 0x07,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x42, 0x05, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x31, 0x06,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xF6, 0x04, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x86, 0x11, 0xF0, 0x03, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x20, 0x03, 0x01, 0x82, 0x10, 0x1F,
|
||||
0x00, 0x07, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0xA1, 0x02, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x86, 0x11, 0x36, 0x02, 0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1C, 0x00, 0x0A, 0x82, 0x11, 0xC1, 0x01,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x10, 0x21, 0x00,
|
||||
0x07, 0x11, 0x7A, 0x01, 0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0x3E, 0x01, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xFC, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0xD4, 0x00,
|
||||
0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0x9F, 0x00, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x10, 0x23, 0x00, 0x07, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0x7E, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0xB2, 0x00,
|
||||
0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xD4, 0x00, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0xFC, 0x00, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x86, 0x11, 0x50, 0x01, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x10, 0x21, 0x00, 0x07, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xC1, 0x01, 0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0xF8, 0x01, 0x01, 0x82, 0x21, 0x82,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0x57, 0x02, 0x01, 0x13, 0x1C, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0xF3, 0x02,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x82, 0x03, 0x01, 0x82, 0x21, 0x82, 0x10, 0x1F, 0x00, 0x07,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xF0, 0x03, 0x01, 0x13, 0x1E, 0x00,
|
||||
0x0A, 0x82, 0x21, 0x84, 0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x42, 0x05,
|
||||
0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x31, 0x06, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x86, 0x11, 0xF6, 0x04, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0xF0, 0x03, 0x01, 0x82, 0x10, 0x21,
|
||||
0x00, 0x07, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x82, 0x11, 0x20, 0x03, 0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A,
|
||||
0x86, 0x11, 0xA1, 0x02, 0x01, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1E, 0x00, 0x0A, 0x84, 0x11, 0x36, 0x02, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1E, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0xF8, 0x01,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x10, 0x23, 0x00,
|
||||
0x07, 0x11, 0xC1, 0x01, 0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84,
|
||||
0x13, 0x1D, 0x00, 0x0A, 0x84, 0x11, 0x7A, 0x01, 0x01, 0x82, 0x21, 0x13,
|
||||
0x1C, 0x00, 0x0A, 0x86, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x11, 0x3E, 0x01,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1D, 0x00, 0x0A, 0x86, 0x11, 0xFC, 0x00,
|
||||
0x01, 0x13, 0x1D, 0x00, 0x0A, 0x82, 0x21, 0x84, 0x13, 0x1D, 0x00, 0x0A,
|
||||
0x84, 0x11, 0xD4, 0x00, 0x01, 0x82, 0x21, 0x13, 0x1E, 0x00, 0x0A, 0x86,
|
||||
0x10, 0x21, 0x00, 0x07, 0x13, 0x1E, 0x00, 0x0A, 0x82, 0x11, 0x9F, 0x00,
|
||||
0x01, 0x82, 0x21, 0x82, 0x13, 0x1E, 0x00, 0x0A, 0x85, 0x00,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *data;
|
||||
uint16_t length;
|
||||
} StSongT;
|
||||
|
||||
#define ST_SONG_COUNT 9u
|
||||
#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] = {
|
||||
{ gStSong0, (uint16_t)sizeof(gStSong0) },
|
||||
{ gStSong1, (uint16_t)sizeof(gStSong1) },
|
||||
{ gStSong2, (uint16_t)sizeof(gStSong2) },
|
||||
{ gStSong3, (uint16_t)sizeof(gStSong3) },
|
||||
{ gStSong4, (uint16_t)sizeof(gStSong4) },
|
||||
{ gStSong5, (uint16_t)sizeof(gStSong5) },
|
||||
{ gStSong6, (uint16_t)sizeof(gStSong6) },
|
||||
{ gStSong7, (uint16_t)sizeof(gStSong7) },
|
||||
{ gStSong8, (uint16_t)sizeof(gStSong8) },
|
||||
};
|
||||
|
||||
#endif // ST_SONG_DATA_H
|
||||
490
stSpeechData.c
Normal file
490
stSpeechData.c
Normal file
|
|
@ -0,0 +1,490 @@
|
|||
// Generated by assets/extractSpeech.py. Do not hand-edit.
|
||||
|
||||
#include "stSpeechData.h"
|
||||
|
||||
const StSpeechEntryT kStSpeechIndex[ST_SPEECH_COUNT] = {
|
||||
{ 0x50u, 0u, 562u }, // 'P'
|
||||
{ 0x31u, 562u, 420u }, // '1'
|
||||
{ 0x3Fu, 982u, 266u }, // '?'
|
||||
{ 0x32u, 1248u, 480u }, // '2'
|
||||
{ 0x33u, 1728u, 463u }, // '3'
|
||||
{ 0x34u, 2191u, 315u }, // '4'
|
||||
{ 0x35u, 2506u, 550u }, // '5'
|
||||
{ 0x36u, 3056u, 527u }, // '6'
|
||||
{ 0x37u, 3583u, 758u }, // '7'
|
||||
{ 0x38u, 4341u, 385u }, // '8'
|
||||
{ 0x39u, 4726u, 491u }, // '9'
|
||||
{ 0x48u, 5217u, 520u }, // 'H'
|
||||
{ 0x54u, 5737u, 632u }, // 'T'
|
||||
{ 0x21u, 6369u, 708u }, // '!'
|
||||
{ 0x55u, 7077u, 368u }, // 'U'
|
||||
};
|
||||
|
||||
const uint8_t kStSpeechRle[ST_SPEECH_RLE_BYTES] = {
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xF2, 0x42, 0xCD, 0x27, 0x10, 0x09, 0xAB, 0x31, 0xB6, 0x12, 0x37, 0x09, 0x22, 0x04, 0x1C, 0x0D,
|
||||
0x16, 0x0E, 0x2F, 0x0B, 0x19, 0x12, 0x0E, 0x12, 0x19, 0x06, 0x1A, 0x0F, 0x09, 0x19, 0x0D, 0x16,
|
||||
0x13, 0x06, 0x05, 0x03, 0x38, 0x08, 0x0F, 0x17, 0x0E, 0x12, 0x0F, 0x12, 0x16, 0x09, 0x15, 0x15,
|
||||
0x06, 0x13, 0x08, 0x15, 0x0C, 0x13, 0x18, 0x10, 0x15, 0x1C, 0x0C, 0x0C, 0x09, 0x02, 0x0C, 0x14,
|
||||
0x15, 0x14, 0x1D, 0x11, 0x11, 0x0B, 0x0A, 0x02, 0x0A, 0x15, 0x15, 0x0B, 0x15, 0x05, 0x06, 0x07,
|
||||
0x07, 0x07, 0x15, 0x08, 0x04, 0x08, 0x0B, 0x07, 0x03, 0x08, 0x0B, 0x04, 0x05, 0x0D, 0x13, 0x08,
|
||||
0x04, 0x06, 0x24, 0x08, 0x04, 0x03, 0x02, 0x03, 0x09, 0x07, 0x05, 0x07, 0x0B, 0x05, 0x05, 0x0A,
|
||||
0x14, 0x08, 0x06, 0x06, 0x18, 0x06, 0x06, 0x09, 0x17, 0x07, 0x05, 0x08, 0x0B, 0x04, 0x05, 0x0A,
|
||||
0x14, 0x09, 0x04, 0x07, 0x09, 0x06, 0x06, 0x09, 0x07, 0x08, 0x05, 0x03, 0x0E, 0x07, 0x04, 0x09,
|
||||
0x0B, 0x04, 0x06, 0x09, 0x15, 0x08, 0x04, 0x06, 0x17, 0x09, 0x07, 0x0C, 0x15, 0x0A, 0x01, 0x09,
|
||||
0x16, 0x09, 0x15, 0x09, 0x06, 0x03, 0x0C, 0x05, 0x05, 0x0A, 0x09, 0x08, 0x07, 0x04, 0x0B, 0x07,
|
||||
0x05, 0x08, 0x15, 0x0A, 0x14, 0x08, 0x05, 0x05, 0x0B, 0x04, 0x07, 0x0F, 0x04, 0x0A, 0x05, 0x08,
|
||||
0x09, 0x07, 0x03, 0x09, 0x15, 0x0A, 0x14, 0x09, 0x04, 0x05, 0x18, 0x0A, 0x0A, 0x0A, 0x06, 0x03,
|
||||
0x0C, 0x14, 0x15, 0x0A, 0x14, 0x14, 0x0A, 0x06, 0x05, 0x0E, 0x08, 0x09, 0x16, 0x08, 0x03, 0x08,
|
||||
0x16, 0x09, 0x15, 0x13, 0x16, 0x0F, 0x08, 0x09, 0x05, 0x06, 0x0A, 0x08, 0x04, 0x07, 0x16, 0x0A,
|
||||
0x06, 0x02, 0x0B, 0x13, 0x17, 0x09, 0x0F, 0x09, 0x07, 0x02, 0x0C, 0x08, 0x03, 0x08, 0x15, 0x0B,
|
||||
0x13, 0x14, 0x0A, 0x14, 0x13, 0x0A, 0x15, 0x13, 0x12, 0x0F, 0x14, 0x0F, 0x10, 0x11, 0x10, 0x10,
|
||||
0x15, 0x0A, 0x06, 0x02, 0x0D, 0x13, 0x14, 0x0B, 0x12, 0x11, 0x0E, 0x16, 0x15, 0x0A, 0x17, 0x07,
|
||||
0x04, 0x05, 0x19, 0x06, 0x14, 0x0B, 0x14, 0x18, 0x07, 0x04, 0x0C, 0x07, 0x05, 0x05, 0x10, 0x02,
|
||||
0x05, 0x07, 0x08, 0x02, 0x0C, 0x07, 0x06, 0x07, 0x08, 0x38, 0x16, 0x09, 0x05, 0x05, 0x0C, 0x06,
|
||||
0x05, 0x07, 0x16, 0x08, 0x07, 0x03, 0x0A, 0x13, 0x0B, 0x1C, 0x08, 0x0B, 0x04, 0x07, 0x06, 0x04,
|
||||
0x0D, 0x05, 0x06, 0x06, 0x0B, 0x02, 0x08, 0x07, 0x08, 0x05, 0x08, 0x08, 0x1F, 0x0A, 0x05, 0x08,
|
||||
0x06, 0x04, 0x0C, 0x07, 0x05, 0x05, 0x18, 0x0A, 0x07, 0x02, 0x09, 0x08, 0x06, 0x07, 0x05, 0x09,
|
||||
0x17, 0x10, 0x09, 0x07, 0x06, 0x06, 0x0C, 0x05, 0x05, 0x07, 0x17, 0x09, 0x07, 0x05, 0x0C, 0x13,
|
||||
0x06, 0x06, 0x08, 0x06, 0x06, 0x0B, 0x05, 0x02, 0x0D, 0x07, 0x06, 0x03, 0x0F, 0x05, 0x05, 0x07,
|
||||
0x17, 0x17, 0x07, 0x17, 0x24, 0x11, 0x11, 0x09, 0x17, 0x08, 0x03, 0x08, 0x16, 0x0B, 0x14, 0x13,
|
||||
0x18, 0x06, 0x16, 0x0C, 0x0E, 0x0A, 0x04, 0x03, 0x10, 0x12, 0x16, 0x12, 0x0D, 0x14, 0x15, 0x0B,
|
||||
0x16, 0x0C, 0x10, 0x0F, 0x15, 0x0A, 0x02, 0x05, 0x18, 0x0C, 0x13, 0x09, 0x05, 0x07, 0x30, 0x09,
|
||||
0x11, 0x1B, 0x1A, 0x05, 0x05, 0x06, 0x1A, 0x15, 0x14, 0x0C, 0x20, 0x14, 0x18, 0x16, 0x03, 0x09,
|
||||
0x05, 0x03, 0x0F, 0x05, 0x05, 0x09, 0x15, 0x16, 0x15, 0x13, 0x17, 0x09, 0x1E, 0x14, 0x0D, 0x0B,
|
||||
0x19, 0x05, 0x03, 0x0B, 0x14, 0x16, 0x15, 0x14, 0x18, 0x08, 0x26, 0x12, 0x11, 0x0B, 0x16, 0x14,
|
||||
0x15, 0x15, 0x16, 0x16, 0x0A, 0x23, 0x42, 0x0A, 0x18, 0x05, 0x05, 0x09, 0x24, 0x08, 0x18, 0x16,
|
||||
0x13, 0x17, 0x15, 0x18, 0x1A, 0x0A, 0x23, 0x09, 0x25, 0x15, 0x17, 0x18, 0x11, 0x14, 0x3C, 0x10,
|
||||
0x57, 0x0F, 0x16, 0x15, 0x18, 0x13, 0x48, 0x1A, 0x16, 0x13, 0x4E, 0x1C, 0x6B, 0x18, 0xFE, 0xFE,
|
||||
0xFE, 0xFF, 0xFE, 0x63, 0x1D, 0xC8, 0x29, 0xBE, 0x1B, 0x59, 0x14, 0x48, 0x19, 0x1A, 0x0E, 0x1E,
|
||||
0x1F, 0x20, 0x11, 0x0E, 0x23, 0x19, 0x10, 0x19, 0x22, 0x18, 0x12, 0x15, 0x20, 0x17, 0x13, 0x18,
|
||||
0x1E, 0x17, 0x13, 0x17, 0x1D, 0x16, 0x14, 0x1A, 0x1A, 0x16, 0x12, 0x17, 0x1E, 0x16, 0x13, 0x17,
|
||||
0x1D, 0x12, 0x15, 0x17, 0x1F, 0x16, 0x12, 0x17, 0x1C, 0x14, 0x14, 0x18, 0x1E, 0x15, 0x0F, 0x1A,
|
||||
0x19, 0x13, 0x10, 0x1E, 0x1D, 0x12, 0x11, 0x1C, 0x17, 0x11, 0x1A, 0x1A, 0x1A, 0x11, 0x11, 0x1D,
|
||||
0x14, 0x10, 0x11, 0x25, 0x19, 0x10, 0x12, 0x1C, 0x13, 0x10, 0x10, 0x0B, 0x09, 0x13, 0x18, 0x12,
|
||||
0x11, 0x17, 0x16, 0x10, 0x0E, 0x0D, 0x0F, 0x0E, 0x19, 0x11, 0x10, 0x17, 0x16, 0x10, 0x0D, 0x0E,
|
||||
0x10, 0x0D, 0x18, 0x10, 0x11, 0x18, 0x12, 0x14, 0x0D, 0x0F, 0x0C, 0x0F, 0x19, 0x10, 0x10, 0x19,
|
||||
0x15, 0x11, 0x0D, 0x0C, 0x12, 0x0E, 0x17, 0x0F, 0x11, 0x1A, 0x11, 0x0C, 0x14, 0x0C, 0x17, 0x0B,
|
||||
0x13, 0x01, 0x04, 0x0D, 0x10, 0x1B, 0x10, 0x0C, 0x0C, 0x0E, 0x0A, 0x0B, 0x0B, 0x0A, 0x14, 0x13,
|
||||
0x0C, 0x1F, 0x0D, 0x0F, 0x0B, 0x0E, 0x1A, 0x0D, 0x20, 0x0C, 0x0B, 0x24, 0x09, 0x0E, 0x0C, 0x0C,
|
||||
0x0B, 0x0A, 0x05, 0x0E, 0x22, 0x06, 0x01, 0x04, 0x0A, 0x0E, 0x03, 0x10, 0x0B, 0x0F, 0x0D, 0x0C,
|
||||
0x0B, 0x06, 0x0A, 0x0B, 0x16, 0x04, 0x0E, 0x0C, 0x09, 0x0F, 0x02, 0x10, 0x0A, 0x0C, 0x0C, 0x0C,
|
||||
0x1D, 0x0B, 0x09, 0x08, 0x09, 0x04, 0x0D, 0x0C, 0x0A, 0x0E, 0x02, 0x10, 0x0C, 0x0A, 0x0B, 0x02,
|
||||
0x07, 0x0D, 0x0E, 0x18, 0x13, 0x07, 0x0D, 0x0C, 0x08, 0x09, 0x0A, 0x0D, 0x0D, 0x07, 0x08, 0x09,
|
||||
0x0B, 0x09, 0x0B, 0x0B, 0x01, 0x0F, 0x0B, 0x10, 0x0F, 0x07, 0x0D, 0x07, 0x0A, 0x0D, 0x09, 0x0E,
|
||||
0x05, 0x05, 0x0F, 0x0D, 0x10, 0x26, 0x18, 0x03, 0x02, 0x05, 0x0A, 0x0B, 0x05, 0x0D, 0x08, 0x0A,
|
||||
0x09, 0x0A, 0x1B, 0x17, 0x08, 0x0D, 0x07, 0x0B, 0x04, 0x0A, 0x08, 0x03, 0x02, 0x05, 0x08, 0x0B,
|
||||
0x07, 0x0C, 0x04, 0x09, 0x0B, 0x0D, 0x06, 0x05, 0x0D, 0x19, 0x06, 0x1A, 0x05, 0x0D, 0x04, 0x07,
|
||||
0x08, 0x04, 0x02, 0x04, 0x05, 0x09, 0x0B, 0x0F, 0x01, 0x09, 0x0A, 0x09, 0x06, 0x08, 0x0A, 0x0A,
|
||||
0x07, 0x0C, 0x04, 0x1A, 0x06, 0x0E, 0x0B, 0x05, 0x0C, 0x0C, 0x04, 0x09, 0x0A, 0x1A, 0x06, 0x0A,
|
||||
0x07, 0x08, 0x09, 0x08, 0x0A, 0x2B, 0x04, 0x0B, 0x27, 0x03, 0x03, 0x05, 0x02, 0x0B, 0x0B, 0x05,
|
||||
0x02, 0x11, 0x05, 0x02, 0x0D, 0x0A, 0x14, 0x0A, 0x07, 0x1A, 0x09, 0x06, 0x03, 0x12, 0x1F, 0x04,
|
||||
0x02, 0x04, 0x03, 0x0B, 0x0A, 0x04, 0x08, 0x0D, 0x04, 0x05, 0x19, 0x0B, 0x1B, 0x18, 0x0F, 0x1E,
|
||||
0x12, 0x04, 0x0E, 0x04, 0x04, 0x19, 0x06, 0x18, 0x0B, 0x58, 0x14, 0x14, 0x0B, 0x0D, 0x19, 0x1B,
|
||||
0x04, 0x56, 0x16, 0x40, 0x29, 0x04, 0x15, 0x3A, 0x07, 0x37, 0x14, 0x55, 0x19, 0xFE, 0x80, 0x5B,
|
||||
0xFE, 0x3C, 0x80, 0xFE, 0xFE, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xA2, 0x40, 0x48, 0x1D, 0x3C,
|
||||
0x0B, 0xFE, 0xFE, 0xBB, 0x51, 0xFE, 0xFE, 0xFE, 0x0D, 0x13, 0x92, 0x24, 0x36, 0x30, 0x67, 0x23,
|
||||
0x37, 0x25, 0x6D, 0x23, 0x36, 0x2B, 0x67, 0x21, 0x35, 0x46, 0x29, 0x20, 0x0A, 0x1F, 0x2F, 0x97,
|
||||
0x11, 0x1A, 0x2E, 0x1C, 0x62, 0x44, 0x2D, 0x1E, 0x23, 0x15, 0x2B, 0x0F, 0x14, 0x1E, 0x2F, 0x20,
|
||||
0x19, 0x16, 0x25, 0x1E, 0x0E, 0x1E, 0x2D, 0x20, 0x15, 0x18, 0x22, 0x4F, 0x30, 0x19, 0x21, 0x12,
|
||||
0x27, 0x4B, 0x2F, 0x21, 0x15, 0x10, 0x30, 0x47, 0x2E, 0x16, 0x6D, 0x39, 0x2E, 0x2D, 0x48, 0x48,
|
||||
0x2D, 0x24, 0x55, 0x3C, 0x30, 0x2D, 0x3C, 0x4C, 0x31, 0x29, 0x34, 0x57, 0x2E, 0x29, 0x2E, 0x34,
|
||||
0x03, 0x24, 0x32, 0x26, 0x38, 0x29, 0x04, 0x23, 0x37, 0x24, 0x38, 0x50, 0x31, 0x21, 0x3B, 0x4F,
|
||||
0x3C, 0x13, 0x43, 0x42, 0x31, 0x2A, 0x46, 0x3F, 0x2F, 0x2C, 0x3D, 0x3F, 0x33, 0x28, 0x3E, 0x48,
|
||||
0x2F, 0x31, 0x41, 0x38, 0x31, 0x2A, 0x4E, 0x30, 0x2E, 0x2A, 0x46, 0x37, 0x2F, 0x2A, 0x46, 0x33,
|
||||
0x31, 0x29, 0x49, 0x37, 0x2E, 0x2A, 0x35, 0x47, 0x2F, 0x26, 0x41, 0x42, 0x30, 0x25, 0x50, 0x2C,
|
||||
0x32, 0x24, 0x38, 0x43, 0x31, 0x29, 0x35, 0x49, 0x32, 0x1D, 0x37, 0x4C, 0x32, 0x1E, 0x48, 0x32,
|
||||
0xFE, 0xD3, 0x48, 0x74, 0x24, 0xAE, 0x2C, 0x45, 0x03, 0x50, 0x02, 0x1D, 0x26, 0x12, 0x02, 0x21,
|
||||
0x02, 0x03, 0x02, 0x48, 0x02, 0x1F, 0x1B, 0x46, 0x2E, 0x13, 0x01, 0x2D, 0x02, 0x03, 0x03, 0x01,
|
||||
0x03, 0x01, 0x03, 0xCC, 0x1B, 0x4B, 0x03, 0x03, 0x02, 0x01, 0x09, 0x74, 0x08, 0x02, 0x00, 0x02,
|
||||
0x1F, 0x79, 0x0E, 0x03, 0x01, 0x03, 0x02, 0x03, 0x02, 0x04, 0x01, 0x24, 0x01, 0x36, 0x02, 0x03,
|
||||
0x3C, 0x04, 0x01, 0x1D, 0x1F, 0xCF, 0x03, 0x01, 0x38, 0x90, 0x39, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x5C, 0x06, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03,
|
||||
0x3F, 0x0E, 0x13, 0x08, 0x9B, 0x23, 0x2B, 0x36, 0x25, 0x02, 0x25, 0x01, 0x23, 0x03, 0x02, 0x02,
|
||||
0x15, 0x02, 0x1B, 0x0A, 0x23, 0x02, 0x25, 0x02, 0x3E, 0x01, 0x05, 0x02, 0x14, 0x0F, 0x25, 0x18,
|
||||
0x3E, 0x13, 0x6B, 0x05, 0x0B, 0x0A, 0x72, 0x21, 0x09, 0x16, 0xBA, 0x24, 0x45, 0x03, 0x05, 0x1A,
|
||||
0x04, 0x09, 0x02, 0x0F, 0x12, 0x02, 0x1B, 0x04, 0x08, 0x03, 0x0F, 0x04, 0x04, 0x08, 0x04, 0x32,
|
||||
0x42, 0x03, 0x07, 0x1A, 0x03, 0x08, 0x03, 0x23, 0x48, 0x0E, 0x05, 0x04, 0x05, 0x25, 0x18, 0x05,
|
||||
0x06, 0x06, 0x23, 0x19, 0x05, 0x0B, 0x02, 0x09, 0x03, 0x0A, 0x17, 0x06, 0x07, 0x09, 0x09, 0x02,
|
||||
0x19, 0x06, 0x05, 0x07, 0x06, 0x0A, 0x03, 0x09, 0x03, 0x0A, 0x0B, 0x03, 0x07, 0x05, 0x09, 0x08,
|
||||
0x08, 0x03, 0x19, 0x07, 0x04, 0x07, 0x07, 0x16, 0x02, 0x0B, 0x0C, 0x02, 0x07, 0x07, 0x06, 0x0A,
|
||||
0x08, 0x03, 0x09, 0x03, 0x0B, 0x07, 0x05, 0x06, 0x07, 0x0B, 0x02, 0x08, 0x03, 0x0A, 0x0C, 0x03,
|
||||
0x07, 0x07, 0x07, 0x09, 0x08, 0x03, 0x18, 0x06, 0x07, 0x05, 0x0A, 0x09, 0x02, 0x08, 0x03, 0x0A,
|
||||
0x0B, 0x04, 0x07, 0x06, 0x08, 0x09, 0x07, 0x04, 0x19, 0x05, 0x07, 0x05, 0x09, 0x08, 0x05, 0x08,
|
||||
0x03, 0x0A, 0x0A, 0x05, 0x06, 0x07, 0x07, 0x09, 0x08, 0x04, 0x0B, 0x02, 0x0A, 0x07, 0x05, 0x06,
|
||||
0x0B, 0x05, 0x06, 0x09, 0x04, 0x0A, 0x0B, 0x03, 0x07, 0x06, 0x08, 0x07, 0x0A, 0x04, 0x08, 0x05,
|
||||
0x06, 0x0B, 0x07, 0x04, 0x1B, 0x09, 0x03, 0x0B, 0x0D, 0x01, 0x07, 0x05, 0x0A, 0x0A, 0x06, 0x04,
|
||||
0x09, 0x03, 0x0A, 0x08, 0x05, 0x06, 0x07, 0x05, 0x06, 0x13, 0x02, 0x0F, 0x13, 0x04, 0x0A, 0x09,
|
||||
0x08, 0x03, 0x19, 0x05, 0x07, 0x05, 0x06, 0x03, 0x17, 0x08, 0x03, 0x0D, 0x0A, 0x03, 0x07, 0x05,
|
||||
0x0A, 0x0B, 0x04, 0x06, 0x09, 0x03, 0x0E, 0x04, 0x07, 0x04, 0x1B, 0x0F, 0x03, 0x0D, 0x0A, 0x02,
|
||||
0x08, 0x04, 0x0B, 0x0B, 0x04, 0x06, 0x28, 0x03, 0x1A, 0x22, 0x16, 0x04, 0x0A, 0x0C, 0x04, 0x05,
|
||||
0x1B, 0x04, 0x08, 0x04, 0x1A, 0x06, 0x04, 0x1A, 0x17, 0x08, 0x05, 0x0B, 0x05, 0x05, 0x1B, 0x05,
|
||||
0x08, 0x09, 0x15, 0x25, 0x18, 0x08, 0x04, 0x0C, 0x26, 0x16, 0x17, 0x26, 0x0C, 0x03, 0x08, 0x19,
|
||||
0x1A, 0x06, 0x06, 0x08, 0x1B, 0x04, 0x07, 0x19, 0x05, 0x09, 0x0C, 0x04, 0x07, 0x09, 0x09, 0x06,
|
||||
0x08, 0x07, 0x09, 0x08, 0x06, 0x08, 0x19, 0x2B, 0x03, 0x0A, 0x0D, 0x02, 0x09, 0x06, 0x08, 0x0A,
|
||||
0x08, 0x05, 0x0A, 0x0B, 0x05, 0x07, 0x18, 0x09, 0x06, 0x23, 0x03, 0x0C, 0x2C, 0x04, 0x1B, 0x19,
|
||||
0x08, 0x06, 0x1A, 0x07, 0x07, 0x09, 0x04, 0x09, 0x04, 0x0B, 0x2B, 0x06, 0x1C, 0x07, 0x07, 0x0E,
|
||||
0x03, 0x0A, 0x19, 0x05, 0x0A, 0x0A, 0x05, 0x08, 0x08, 0x06, 0x0D, 0x04, 0x0A, 0x0B, 0x07, 0x05,
|
||||
0x09, 0x0E, 0x03, 0x1D, 0x2A, 0x1A, 0x0F, 0x1C, 0x28, 0x1C, 0x09, 0x04, 0x0A, 0x18, 0x2F, 0x06,
|
||||
0x19, 0x1C, 0x1F, 0x05, 0x05, 0x1B, 0x1E, 0x14, 0x23, 0x1C, 0x19, 0x1D, 0x21, 0x07, 0x04, 0x0D,
|
||||
0x36, 0x13, 0x1F, 0x17, 0x1C, 0x24, 0x36, 0x15, 0x26, 0x1C, 0x5D, 0x20, 0x63, 0x2B, 0x53, 0x2A,
|
||||
0x7C, 0x28, 0x61, 0x2D, 0xFE, 0x23, 0x22, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x5C, 0xFE, 0xFE, 0xFE, 0xFE, 0x76, 0x23, 0x6F,
|
||||
0x28, 0x84, 0x32, 0x22, 0x05, 0x08, 0x04, 0x1C, 0x16, 0x1B, 0x2E, 0x52, 0x0B, 0x26, 0x2C, 0x54,
|
||||
0x08, 0x1D, 0x34, 0x54, 0x0B, 0x1B, 0x32, 0x24, 0x05, 0x2C, 0x0A, 0x1B, 0x25, 0x03, 0x08, 0x25,
|
||||
0x05, 0x2C, 0x09, 0x0C, 0x04, 0x0A, 0x2F, 0x24, 0x09, 0x2A, 0x0A, 0x1B, 0x20, 0x02, 0x09, 0x25,
|
||||
0x08, 0x4F, 0x1C, 0x04, 0x09, 0x26, 0x07, 0x4F, 0x1B, 0x05, 0x09, 0x24, 0x08, 0x20, 0x08, 0x26,
|
||||
0x1B, 0x04, 0x08, 0x0E, 0x05, 0x09, 0x10, 0x52, 0x18, 0x04, 0x08, 0x0E, 0x06, 0x06, 0x13, 0x1E,
|
||||
0x18, 0x1B, 0x17, 0x05, 0x07, 0x10, 0x02, 0x09, 0x14, 0x1D, 0x0F, 0x25, 0x16, 0x05, 0x08, 0x0B,
|
||||
0x08, 0x07, 0x12, 0x1B, 0x09, 0x05, 0x09, 0x20, 0x18, 0x06, 0x07, 0x0C, 0x08, 0x05, 0x14, 0x19,
|
||||
0x17, 0x20, 0x1A, 0x07, 0x07, 0x0B, 0x08, 0x06, 0x0F, 0x1D, 0x08, 0x06, 0x08, 0x21, 0x1B, 0x07,
|
||||
0x07, 0x0A, 0x09, 0x06, 0x0B, 0x1E, 0x08, 0x06, 0x08, 0x22, 0x1C, 0x08, 0x06, 0x0B, 0x07, 0x07,
|
||||
0x0A, 0x1E, 0x0A, 0x04, 0x09, 0x1A, 0x27, 0x07, 0x07, 0x0A, 0x07, 0x07, 0x09, 0x1E, 0x09, 0x06,
|
||||
0x08, 0x1A, 0x2B, 0x07, 0x06, 0x0A, 0x07, 0x07, 0x09, 0x1D, 0x07, 0x07, 0x08, 0x19, 0x06, 0x05,
|
||||
0x24, 0x07, 0x07, 0x09, 0x07, 0x07, 0x09, 0x1D, 0x06, 0x07, 0x08, 0x08, 0x05, 0x0A, 0x06, 0x07,
|
||||
0x09, 0x07, 0x09, 0x03, 0x0B, 0x06, 0x07, 0x0A, 0x06, 0x08, 0x09, 0x08, 0x06, 0x0C, 0x06, 0x07,
|
||||
0x09, 0x08, 0x04, 0x0B, 0x05, 0x07, 0x09, 0x06, 0x08, 0x07, 0x0A, 0x08, 0x06, 0x09, 0x06, 0x08,
|
||||
0x09, 0x07, 0x07, 0x0B, 0x06, 0x07, 0x0A, 0x06, 0x05, 0x19, 0x2D, 0x05, 0x09, 0x09, 0x05, 0x09,
|
||||
0x07, 0x09, 0x04, 0x1B, 0x07, 0x05, 0x08, 0x18, 0x18, 0x07, 0x08, 0x05, 0x09, 0x05, 0x08, 0x09,
|
||||
0x04, 0x0A, 0x07, 0x09, 0x06, 0x09, 0x06, 0x08, 0x17, 0x1F, 0x17, 0x09, 0x05, 0x02, 0x07, 0x04,
|
||||
0x0A, 0x1A, 0x04, 0x0A, 0x04, 0x0C, 0x02, 0x09, 0x08, 0x05, 0x09, 0x06, 0x05, 0x07, 0x07, 0x06,
|
||||
0x08, 0x07, 0x06, 0x0B, 0x07, 0x05, 0x08, 0x05, 0x08, 0x19, 0x06, 0x07, 0x07, 0x08, 0x03, 0x0A,
|
||||
0x07, 0x05, 0x16, 0x09, 0x04, 0x09, 0x03, 0x0A, 0x05, 0x0A, 0x07, 0x0A, 0x09, 0x04, 0x08, 0x0A,
|
||||
0x02, 0x0B, 0x06, 0x07, 0x07, 0x08, 0x05, 0x08, 0x25, 0x15, 0x04, 0x0B, 0x02, 0x1A, 0x04, 0x06,
|
||||
0x07, 0x05, 0x08, 0x18, 0x06, 0x06, 0x08, 0x06, 0x05, 0x0A, 0x04, 0x08, 0x09, 0x04, 0x08, 0x55,
|
||||
0x08, 0x04, 0x09, 0x06, 0x05, 0x0C, 0x04, 0x08, 0x07, 0x05, 0x0B, 0x15, 0x1D, 0x52, 0x0A, 0x02,
|
||||
0x0B, 0x04, 0x04, 0x1B, 0x04, 0x06, 0x06, 0x24, 0x18, 0x26, 0x1C, 0x14, 0x0A, 0x02, 0x0B, 0x24,
|
||||
0x1F, 0x15, 0x1B, 0x24, 0x1A, 0x19, 0x0E, 0x02, 0x07, 0x27, 0x06, 0x05, 0x0C, 0x1B, 0x16, 0x6C,
|
||||
0x0B, 0x03, 0x06, 0x09, 0x03, 0x25, 0x16, 0x13, 0x05, 0x8A, 0x06, 0x03, 0x0C, 0x03, 0x03, 0x6E,
|
||||
0x1D, 0x56, 0x22, 0x2C, 0x16, 0x26, 0x1B, 0x5F, 0x24, 0x8C, 0x11, 0x5A, 0x20, 0x62, 0x44, 0x5B,
|
||||
0x23, 0x80, 0x1E, 0x70, 0x20, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xBF, 0x04, 0xFE, 0xCF, 0x1A, 0x51, 0x0F, 0x23,
|
||||
0x23, 0x36, 0x08, 0x18, 0x0E, 0x1C, 0x26, 0x56, 0x12, 0x16, 0x27, 0x1C, 0x16, 0x26, 0x10, 0x16,
|
||||
0x26, 0x1C, 0x14, 0x27, 0x12, 0x15, 0x25, 0x1C, 0x17, 0x24, 0x10, 0x1A, 0x22, 0x1D, 0x1A, 0x20,
|
||||
0x11, 0x19, 0x23, 0x1C, 0x19, 0x22, 0x11, 0x1B, 0x22, 0x1A, 0x19, 0x23, 0x13, 0x18, 0x24, 0x1B,
|
||||
0x17, 0x25, 0x11, 0x19, 0x23, 0x1B, 0x17, 0x24, 0x12, 0x18, 0x24, 0x1B, 0x16, 0x25, 0x11, 0x19,
|
||||
0x24, 0x1B, 0x17, 0x25, 0x10, 0x1A, 0x24, 0x19, 0x18, 0x24, 0x11, 0x19, 0x25, 0x1B, 0x15, 0x26,
|
||||
0x11, 0x1A, 0x25, 0x19, 0x15, 0x27, 0x12, 0x19, 0x27, 0x18, 0x14, 0x28, 0x12, 0x18, 0x2A, 0x18,
|
||||
0x13, 0x2B, 0x10, 0x18, 0x2B, 0x16, 0x14, 0x2E, 0x0B, 0x19, 0x2D, 0x15, 0x14, 0x2D, 0x0D, 0x19,
|
||||
0x2F, 0x15, 0x12, 0x2E, 0x10, 0x16, 0x1A, 0x02, 0x15, 0x14, 0x11, 0x2E, 0x11, 0x16, 0x18, 0x06,
|
||||
0x14, 0x15, 0x10, 0x2D, 0x10, 0x16, 0x37, 0x15, 0x0D, 0x2B, 0x11, 0x19, 0x1B, 0x0D, 0x15, 0x2B,
|
||||
0x0A, 0x13, 0x11, 0x22, 0x14, 0x11, 0x18, 0x1A, 0x12, 0x1B, 0x1A, 0x15, 0x16, 0x0F, 0x1E, 0x47,
|
||||
0x15, 0x17, 0x18, 0x1C, 0x17, 0x22, 0x10, 0x15, 0x18, 0x14, 0x12, 0x16, 0x26, 0x15, 0x1B, 0x16,
|
||||
0x1E, 0x12, 0x12, 0x21, 0x21, 0x1B, 0x13, 0x13, 0x24, 0x0F, 0x0F, 0x1E, 0x10, 0x10, 0x0F, 0x10,
|
||||
0x0A, 0x08, 0x0C, 0x0F, 0x11, 0x07, 0x0D, 0x11, 0x0E, 0x1D, 0x0E, 0x13, 0x16, 0x21, 0x0E, 0x16,
|
||||
0x1A, 0x0F, 0x15, 0x18, 0x0F, 0x1F, 0x17, 0x1E, 0x0F, 0x14, 0x1D, 0x14, 0x12, 0x1A, 0x11, 0x16,
|
||||
0x24, 0x15, 0x16, 0x15, 0x1B, 0x16, 0x15, 0x15, 0x13, 0x15, 0x2F, 0x15, 0x16, 0x1F, 0x11, 0x1E,
|
||||
0x10, 0x11, 0x1B, 0x13, 0x21, 0x05, 0x0F, 0x22, 0x0A, 0x20, 0x0E, 0x17, 0x16, 0x1C, 0x10, 0x1B,
|
||||
0x0F, 0x0C, 0x08, 0x09, 0x0E, 0x21, 0x0C, 0x20, 0x0E, 0x1F, 0x26, 0x0C, 0x19, 0x15, 0x17, 0x12,
|
||||
0x21, 0x13, 0x0F, 0x1C, 0x0B, 0x1F, 0x0E, 0x18, 0x0D, 0x4D, 0x3A, 0x40, 0x47, 0xB0, 0x18, 0x72,
|
||||
0x30, 0xC7, 0x11, 0x1D, 0x1E, 0x78, 0x0E, 0x4C, 0x70, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xC4, 0x0E, 0x4A, 0x1A, 0x1D, 0x0F, 0x19, 0x14, 0x19, 0x11, 0x18, 0x1B, 0x11,
|
||||
0x19, 0x13, 0x1A, 0x11, 0x1B, 0x14, 0x1A, 0x0E, 0x1C, 0x10, 0x11, 0x18, 0x0D, 0x0D, 0x09, 0x0B,
|
||||
0x0A, 0x07, 0x0D, 0x0E, 0x1B, 0x0F, 0x10, 0x17, 0x0F, 0x0C, 0x11, 0x15, 0x10, 0x0D, 0x1A, 0x0F,
|
||||
0x0F, 0x17, 0x0D, 0x0E, 0x0E, 0x0D, 0x1A, 0x0E, 0x0E, 0x1A, 0x0E, 0x10, 0x15, 0x0D, 0x0F, 0x0D,
|
||||
0x19, 0x0E, 0x0E, 0x1B, 0x0D, 0x0D, 0x19, 0x0C, 0x0E, 0x0D, 0x1B, 0x0D, 0x0D, 0x1D, 0x0C, 0x0C,
|
||||
0x0D, 0x1A, 0x0D, 0x0D, 0x1D, 0x0C, 0x0E, 0x0C, 0x03, 0x0D, 0x0B, 0x0C, 0x0D, 0x1B, 0x0C, 0x0E,
|
||||
0x1E, 0x0B, 0x0E, 0x1D, 0x0C, 0x0C, 0x0B, 0x1D, 0x0D, 0x0B, 0x20, 0x0C, 0x0D, 0x0C, 0x05, 0x0C,
|
||||
0x0B, 0x0C, 0x0C, 0x0A, 0x07, 0x0A, 0x0E, 0x0D, 0x0F, 0x02, 0x0C, 0x0C, 0x0D, 0x0C, 0x05, 0x0C,
|
||||
0x0A, 0x0C, 0x0C, 0x20, 0x0B, 0x09, 0x21, 0x0C, 0x0D, 0x1D, 0x0B, 0x0B, 0x0C, 0x22, 0x09, 0x0D,
|
||||
0x04, 0x0A, 0x0D, 0x0C, 0x0E, 0x1C, 0x0B, 0x0B, 0x0D, 0x0C, 0x20, 0x15, 0x15, 0x0C, 0x0D, 0x1D,
|
||||
0x0A, 0x0C, 0x0B, 0x0D, 0x0C, 0x09, 0x0A, 0x16, 0x15, 0x0C, 0x0D, 0x0C, 0x05, 0x0B, 0x09, 0x0B,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0A, 0x16, 0x13, 0x0B, 0x0D, 0x0D, 0x06, 0x0B, 0x08, 0x0C, 0x0B, 0x0C,
|
||||
0x0C, 0x0C, 0x0E, 0x11, 0x13, 0x0B, 0x0E, 0x10, 0x02, 0x0A, 0x09, 0x0C, 0x0B, 0x0C, 0x0C, 0x0C,
|
||||
0x0D, 0x12, 0x14, 0x0B, 0x0D, 0x0E, 0x05, 0x0A, 0x09, 0x0C, 0x0B, 0x0A, 0x0C, 0x0E, 0x0C, 0x15,
|
||||
0x12, 0x0C, 0x0E, 0x0E, 0x04, 0x0B, 0x09, 0x0B, 0x0C, 0x0A, 0x0B, 0x0D, 0x0F, 0x14, 0x16, 0x0B,
|
||||
0x0D, 0x0B, 0x06, 0x0B, 0x09, 0x0B, 0x0C, 0x0C, 0x09, 0x0C, 0x30, 0x05, 0x09, 0x0B, 0x0C, 0x0C,
|
||||
0x06, 0x0B, 0x09, 0x0B, 0x0B, 0x0B, 0x0A, 0x0B, 0x17, 0x0D, 0x0C, 0x07, 0x0A, 0x0A, 0x0B, 0x0B,
|
||||
0x07, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x08, 0x0A, 0x0D, 0x18, 0x0D, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B,
|
||||
0x06, 0x0B, 0x0A, 0x0B, 0x0C, 0x0B, 0x06, 0x09, 0x0E, 0x26, 0x02, 0x09, 0x0B, 0x0A, 0x0C, 0x09,
|
||||
0x08, 0x09, 0x0B, 0x0B, 0x0E, 0x15, 0x0A, 0x12, 0x08, 0x0C, 0x0B, 0x09, 0x08, 0x0C, 0x0B, 0x0A,
|
||||
0x09, 0x0A, 0x09, 0x0B, 0x0B, 0x09, 0x03, 0x09, 0x0C, 0x0E, 0x0F, 0x09, 0x0B, 0x0B, 0x0B, 0x09,
|
||||
0x0B, 0x0A, 0x07, 0x0B, 0x0B, 0x0B, 0x16, 0x0A, 0x0C, 0x19, 0x03, 0x0D, 0x06, 0x0E, 0x09, 0x0B,
|
||||
0x0C, 0x0A, 0x09, 0x0B, 0x0A, 0x0C, 0x16, 0x0A, 0x0B, 0x18, 0x04, 0x0B, 0x08, 0x0D, 0x0A, 0x0C,
|
||||
0x0C, 0x09, 0x05, 0x0C, 0x0C, 0x0B, 0x0F, 0x12, 0x0B, 0x18, 0x06, 0x0B, 0x09, 0x0C, 0x0D, 0x0C,
|
||||
0x0E, 0x19, 0x0A, 0x0C, 0x0A, 0x09, 0x08, 0x0A, 0x10, 0x0F, 0x04, 0x0B, 0x0A, 0x0A, 0x12, 0x0B,
|
||||
0x0C, 0x09, 0x08, 0x0C, 0x0B, 0x0D, 0x05, 0x07, 0x0B, 0x0F, 0x0A, 0x44, 0x0A, 0x0C, 0x0C, 0x09,
|
||||
0x04, 0x0B, 0x0C, 0x0A, 0x09, 0x07, 0x0B, 0x0B, 0x09, 0x25, 0x0E, 0x18, 0x0C, 0x0B, 0x0C, 0x08,
|
||||
0x04, 0x0C, 0x0C, 0x17, 0x0D, 0x0A, 0x18, 0x1D, 0x07, 0x15, 0x0A, 0x04, 0x09, 0x0B, 0x0B, 0x1B,
|
||||
0x0B, 0x17, 0x0B, 0x10, 0x13, 0x1A, 0x0A, 0x13, 0x0E, 0x08, 0x08, 0x0C, 0x08, 0x0A, 0x06, 0x0D,
|
||||
0x0A, 0x18, 0x0C, 0x13, 0x0A, 0x4E, 0x13, 0x0B, 0x1A, 0x0A, 0x0C, 0x19, 0x08, 0x17, 0x08, 0x19,
|
||||
0x09, 0x18, 0x0A, 0x14, 0x0E, 0x0F, 0x14, 0x1C, 0x09, 0x0A, 0x0B, 0x19, 0x0B, 0x0F, 0x11, 0x2E,
|
||||
0x06, 0x08, 0x0E, 0x19, 0x08, 0x19, 0x0B, 0x1A, 0x08, 0x0F, 0x14, 0x0E, 0x11, 0x19, 0x08, 0x19,
|
||||
0x0C, 0x12, 0x13, 0x81, 0x07, 0x17, 0x09, 0x2F, 0x1A, 0x83, 0x0B, 0x12, 0x2D, 0x1E, 0x09, 0x54,
|
||||
0x0B, 0x37, 0x2C, 0xFE, 0x30, 0x36, 0x59, 0x54, 0xFE, 0xFE, 0x09, 0x44, 0xC5, 0x1A, 0xFE, 0xFF,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0x02, 0x03, 0x02, 0x4C, 0x03, 0x03, 0x02, 0x5B, 0x03, 0x03, 0x02, 0x35,
|
||||
0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x04, 0x01, 0x11,
|
||||
0x01, 0x55, 0x0F, 0x01, 0x03, 0x03, 0x02, 0x6B, 0x15, 0x03, 0x02, 0x15, 0x03, 0x02, 0x03, 0x04,
|
||||
0x01, 0x20, 0x02, 0x01, 0x04, 0x02, 0x03, 0x03, 0x02, 0x04, 0x02, 0x21, 0x03, 0x2B, 0x03, 0x02,
|
||||
0x03, 0x01, 0x04, 0x09, 0x02, 0x03, 0x02, 0x38, 0x03, 0x79, 0x19, 0x02, 0x03, 0x57, 0x03, 0x02,
|
||||
0x02, 0x2C, 0x21, 0x01, 0x03, 0x10, 0x02, 0x2C, 0x02, 0x02, 0x03, 0x02, 0x03, 0x1A, 0x02, 0x0A,
|
||||
0x07, 0x02, 0x03, 0x02, 0x03, 0x23, 0x03, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x11, 0x02, 0x02,
|
||||
0x03, 0x03, 0x02, 0x3B, 0x01, 0x11, 0x02, 0x04, 0x01, 0x03, 0x02, 0x1B, 0x07, 0x1C, 0x03, 0x02,
|
||||
0x04, 0x01, 0x0A, 0x01, 0x03, 0x1E, 0x02, 0x04, 0x01, 0x19, 0x01, 0x09, 0x04, 0x01, 0x03, 0x03,
|
||||
0x02, 0x04, 0x02, 0x22, 0x0A, 0x02, 0x02, 0x11, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03,
|
||||
0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x0F, 0x16, 0x02, 0x02, 0x03, 0x03, 0x01, 0x10, 0x02, 0x02,
|
||||
0x03, 0x02, 0x03, 0x02, 0x02, 0x0A, 0x03, 0x02, 0x03, 0x1E, 0x03, 0x01, 0x09, 0x10, 0x03, 0x01,
|
||||
0x09, 0x02, 0x03, 0x0E, 0x03, 0x01, 0x04, 0x02, 0x02, 0x03, 0x01, 0x11, 0x02, 0x39, 0x0C, 0x02,
|
||||
0x03, 0x29, 0x01, 0x02, 0x09, 0x01, 0x03, 0x03, 0x03, 0x03, 0x02, 0x22, 0x03, 0x1C, 0x14, 0x1A,
|
||||
0x03, 0x02, 0x03, 0x03, 0x03, 0xFE, 0x5B, 0x1A, 0x1C, 0x05, 0x05, 0x0C, 0x25, 0x08, 0x23, 0x1E,
|
||||
0x09, 0x03, 0x0E, 0x07, 0x05, 0x0A, 0x1A, 0x08, 0x05, 0x06, 0x1B, 0x2B, 0x0B, 0x02, 0x0D, 0x08,
|
||||
0x06, 0x04, 0x1A, 0x17, 0x18, 0x20, 0x02, 0x0B, 0x0A, 0x03, 0x0C, 0x08, 0x06, 0x04, 0x1A, 0x0B,
|
||||
0x23, 0x22, 0x01, 0x05, 0x02, 0x03, 0x0B, 0x03, 0x0C, 0x09, 0x06, 0x03, 0x19, 0x14, 0x19, 0x18,
|
||||
0x02, 0x09, 0x03, 0x04, 0x02, 0x04, 0x0A, 0x04, 0x07, 0x0B, 0x25, 0x12, 0x1B, 0x16, 0x06, 0x08,
|
||||
0x03, 0x06, 0x01, 0x03, 0x0B, 0x04, 0x06, 0x0B, 0x1A, 0x14, 0x23, 0x16, 0x07, 0x0B, 0x03, 0x0A,
|
||||
0x0B, 0x04, 0x06, 0x0B, 0x18, 0x16, 0x19, 0x1F, 0x0D, 0x0C, 0x02, 0x05, 0x03, 0x02, 0x0B, 0x04,
|
||||
0x04, 0x0C, 0x19, 0x15, 0x1B, 0x18, 0x13, 0x0F, 0x01, 0x05, 0x04, 0x01, 0x0B, 0x05, 0x03, 0x0C,
|
||||
0x1A, 0x14, 0x18, 0x15, 0x15, 0x13, 0x04, 0x03, 0x04, 0x01, 0x0B, 0x05, 0x04, 0x0B, 0x18, 0x16,
|
||||
0x17, 0x16, 0x15, 0x17, 0x05, 0x03, 0x11, 0x06, 0x04, 0x09, 0x18, 0x16, 0x17, 0x15, 0x16, 0x1A,
|
||||
0x05, 0x03, 0x11, 0x05, 0x06, 0x07, 0x1A, 0x17, 0x1A, 0x10, 0x19, 0x1A, 0x1A, 0x05, 0x29, 0x16,
|
||||
0x17, 0x14, 0x19, 0x16, 0x04, 0x07, 0x1A, 0x05, 0x06, 0x08, 0x1A, 0x17, 0x0C, 0x16, 0x41, 0x08,
|
||||
0x0B, 0x02, 0x0C, 0x07, 0x06, 0x07, 0x19, 0x16, 0x0E, 0x1A, 0x4E, 0x0B, 0x0A, 0x03, 0x0A, 0x16,
|
||||
0x19, 0x17, 0x18, 0x17, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xEE, 0x02, 0x03, 0x03, 0xFE, 0x3D, 0x08, 0x01, 0x03, 0x02, 0x03, 0x03,
|
||||
0x02, 0x03, 0x02, 0x65, 0x1A, 0xCF, 0x02, 0x3E, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03,
|
||||
0x03, 0x3E, 0x03, 0x02, 0x02, 0x03, 0x02, 0x04, 0x02, 0x1B, 0x02, 0x16, 0x02, 0x03, 0x02, 0x5F,
|
||||
0x08, 0x01, 0x03, 0x03, 0x02, 0x04, 0x02, 0xED, 0x02, 0x03, 0x02, 0x16, 0x02, 0xFE, 0x4A, 0x40,
|
||||
0xE7, 0x14, 0x6F, 0x02, 0x03, 0x02, 0x80, 0x02, 0x03, 0x02, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFE,
|
||||
0x7C, 0x24, 0x9B, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x0E, 0x08, 0x01, 0x03, 0x52, 0x02,
|
||||
0x03, 0x09, 0x01, 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, 0x01, 0x0A, 0x01, 0x03, 0x02, 0x1F, 0x02,
|
||||
0x02, 0x03, 0x03, 0x07, 0x14, 0x02, 0x03, 0x02, 0x03, 0x03, 0x3A, 0x03, 0x02, 0x09, 0x02, 0x02,
|
||||
0x3B, 0x01, 0x16, 0x01, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x23, 0x03, 0x02, 0x03, 0x02, 0x03,
|
||||
0x03, 0x04, 0x02, 0x02, 0x1E, 0x08, 0x0E, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x02, 0x41, 0x01,
|
||||
0x03, 0x02, 0x11, 0x1A, 0x02, 0x17, 0x02, 0x03, 0x03, 0x02, 0x0D, 0x03, 0x01, 0x03, 0x02, 0x03,
|
||||
0x02, 0x04, 0x01, 0x03, 0x10, 0x01, 0x03, 0x01, 0x34, 0x02, 0x03, 0x02, 0x04, 0x19, 0x01, 0x03,
|
||||
0x01, 0x0F, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x10, 0x01, 0x03, 0x02, 0x03, 0x02,
|
||||
0x16, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x0E, 0x02, 0x02, 0x02, 0x03, 0x01, 0x0B, 0x02,
|
||||
0x02, 0x02, 0x03, 0x02, 0x03, 0x01, 0x0A, 0x03, 0x01, 0x03, 0x03, 0x02, 0x18, 0x02, 0x03, 0x02,
|
||||
0x1D, 0x02, 0x04, 0x01, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03,
|
||||
0x02, 0x03, 0x15, 0x02, 0x03, 0x02, 0x04, 0x01, 0x0C, 0x02, 0x10, 0x02, 0x03, 0x02, 0x1A, 0x02,
|
||||
0x0F, 0x02, 0x02, 0x03, 0x01, 0x04, 0x02, 0x02, 0x14, 0x03, 0x02, 0x03, 0x02, 0x03, 0x04, 0x01,
|
||||
0x0B, 0x01, 0x03, 0x02, 0x03, 0x02, 0x15, 0x02, 0x02, 0x03, 0x03, 0x02, 0x05, 0x02, 0x02, 0x03,
|
||||
0x02, 0x03, 0x02, 0x03, 0x12, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x01, 0x04, 0x01, 0x03, 0x01,
|
||||
0x16, 0x02, 0x28, 0x02, 0x02, 0x0E, 0x02, 0x03, 0x19, 0x03, 0x02, 0x03, 0x02, 0x02, 0x11, 0x01,
|
||||
0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x18, 0x02,
|
||||
0x04, 0x02, 0x03, 0x02, 0x04, 0x01, 0x0A, 0x01, 0x0C, 0x02, 0x01, 0x0B, 0x02, 0x03, 0x02, 0x04,
|
||||
0x01, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x26, 0x02, 0x10, 0x02,
|
||||
0x0F, 0x03, 0x01, 0x04, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x0B, 0x03, 0x02, 0x03,
|
||||
0x19, 0x02, 0x03, 0x02, 0x2A, 0x03, 0x01, 0x04, 0x01, 0x03, 0x03, 0x03, 0x34, 0x02, 0x02, 0x02,
|
||||
0x03, 0x02, 0x08, 0x02, 0x03, 0x03, 0x03, 0x02, 0x0C, 0x03, 0x01, 0x03, 0x02, 0x02, 0x14, 0x02,
|
||||
0x03, 0x02, 0x03, 0x01, 0x04, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x01, 0x0C, 0x02, 0x02, 0x03,
|
||||
0x03, 0x01, 0x3E, 0x03, 0x01, 0x11, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x01, 0x03,
|
||||
0x02, 0x03, 0x03, 0x02, 0x2D, 0x02, 0x35, 0x37, 0x5D, 0x22, 0x1C, 0x15, 0x1D, 0x15, 0x1A, 0x28,
|
||||
0x13, 0x01, 0x05, 0x09, 0x0C, 0x02, 0x0C, 0x02, 0x0B, 0x0A, 0x22, 0x21, 0x03, 0x05, 0x0B, 0x0A,
|
||||
0x05, 0x08, 0x0C, 0x02, 0x0A, 0x0E, 0x02, 0x05, 0x18, 0x1A, 0x06, 0x10, 0x01, 0x05, 0x0B, 0x03,
|
||||
0x0C, 0x08, 0x0C, 0x03, 0x0A, 0x0B, 0x04, 0x05, 0x0A, 0x04, 0x0B, 0x05, 0x13, 0x03, 0x03, 0x11,
|
||||
0x02, 0x04, 0x0B, 0x0C, 0x03, 0x08, 0x19, 0x0D, 0x14, 0x15, 0x13, 0x14, 0x02, 0x02, 0x04, 0x03,
|
||||
0x0B, 0x16, 0x11, 0x02, 0x04, 0x0B, 0x17, 0x13, 0x0D, 0x1C, 0x0B, 0x03, 0x0A, 0x16, 0x11, 0x12,
|
||||
0x17, 0x09, 0x18, 0x1E, 0x0A, 0x05, 0x08, 0x0E, 0x05, 0x02, 0x11, 0x13, 0x18, 0x07, 0x17, 0x14,
|
||||
0x02, 0x09, 0x03, 0x03, 0x03, 0x04, 0x0A, 0x15, 0x10, 0x14, 0x0F, 0x01, 0x06, 0x08, 0x17, 0x14,
|
||||
0x02, 0x0B, 0x0A, 0x03, 0x09, 0x13, 0x12, 0x14, 0x0E, 0x02, 0x06, 0x08, 0x17, 0x0A, 0x06, 0x02,
|
||||
0x05, 0x0D, 0x08, 0x03, 0x09, 0x0F, 0x14, 0x15, 0x0F, 0x12, 0x16, 0x09, 0x0E, 0x0F, 0x14, 0x0F,
|
||||
0x14, 0x16, 0x0D, 0x12, 0x17, 0x0A, 0x0F, 0x0E, 0x09, 0x02, 0x09, 0x0D, 0x15, 0x0E, 0x03, 0x05,
|
||||
0x0B, 0x14, 0x0C, 0x13, 0x0A, 0x15, 0x0B, 0x03, 0x08, 0x0C, 0x16, 0x0C, 0x07, 0x03, 0x0B, 0x0A,
|
||||
0x15, 0x14, 0x0C, 0x14, 0x0C, 0x04, 0x07, 0x0B, 0x17, 0x0B, 0x08, 0x05, 0x0A, 0x08, 0x08, 0x05,
|
||||
0x08, 0x09, 0x07, 0x05, 0x09, 0x16, 0x0A, 0x06, 0x08, 0x0B, 0x18, 0x0B, 0x05, 0x06, 0x0C, 0x07,
|
||||
0x06, 0x08, 0x18, 0x06, 0x0A, 0x08, 0x03, 0x0A, 0x0B, 0x05, 0x08, 0x0C, 0x17, 0x0C, 0x04, 0x07,
|
||||
0x0A, 0x09, 0x05, 0x08, 0x09, 0x08, 0x06, 0x08, 0x08, 0x09, 0x04, 0x09, 0x0B, 0x05, 0x08, 0x0B,
|
||||
0x18, 0x0C, 0x04, 0x07, 0x0C, 0x05, 0x08, 0x09, 0x07, 0x07, 0x0A, 0x09, 0x05, 0x09, 0x06, 0x09,
|
||||
0x0A, 0x06, 0x09, 0x0B, 0x0B, 0x02, 0x0C, 0x0A, 0x03, 0x09, 0x0B, 0x04, 0x08, 0x0C, 0x04, 0x07,
|
||||
0x0B, 0x05, 0x08, 0x0B, 0x05, 0x08, 0x0B, 0x07, 0x08, 0x0B, 0x09, 0x05, 0x0E, 0x06, 0x07, 0x0D,
|
||||
0x15, 0x17, 0x17, 0x0C, 0x08, 0x08, 0x0B, 0x06, 0x0C, 0x0A, 0x0A, 0x04, 0x1B, 0x0D, 0x16, 0x19,
|
||||
0x1D, 0x05, 0x0E, 0x08, 0x0A, 0x05, 0x3F, 0x31, 0x43, 0x20, 0xB4, 0x23, 0xBE, 0x39, 0x80, 0x16,
|
||||
0x10, 0x24, 0xFE, 0xBF, 0x81, 0x75, 0x19, 0x73, 0x11, 0x5C, 0x1C, 0xE7, 0x1B, 0xA1, 0x15, 0x38,
|
||||
0x1C, 0x83, 0x2E, 0x42, 0x1A, 0x8B, 0x16, 0x5B, 0x3B, 0xEC, 0x31, 0xFE, 0x47, 0x75, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFE, 0xFE, 0x20, 0x03, 0x04, 0x05, 0x17, 0x1A, 0x22, 0x0A, 0x1F,
|
||||
0x1B, 0x3E, 0x1C, 0x18, 0x12, 0x20, 0x10, 0x1F, 0x0A, 0x17, 0x18, 0x05, 0x02, 0x19, 0x13, 0x17,
|
||||
0x17, 0x3A, 0x1B, 0x19, 0x12, 0x16, 0x09, 0x02, 0x09, 0x1E, 0x1B, 0x03, 0x0F, 0x02, 0x06, 0x19,
|
||||
0x04, 0x22, 0x05, 0x04, 0x0D, 0x26, 0x18, 0x01, 0x06, 0x03, 0x05, 0x03, 0x02, 0x13, 0x04, 0x05,
|
||||
0x05, 0x18, 0x04, 0x03, 0x15, 0x1F, 0x23, 0x02, 0x06, 0x02, 0x03, 0x06, 0x01, 0x0A, 0x04, 0x05,
|
||||
0x05, 0x18, 0x03, 0x07, 0x09, 0x03, 0x06, 0x1E, 0x19, 0x01, 0x07, 0x03, 0x05, 0x18, 0x05, 0x04,
|
||||
0x07, 0x16, 0x02, 0x07, 0x09, 0x05, 0x04, 0x20, 0x1F, 0x03, 0x05, 0x19, 0x04, 0x05, 0x07, 0x16,
|
||||
0x02, 0x0F, 0x02, 0x05, 0x05, 0x1D, 0x1D, 0x03, 0x05, 0x04, 0x02, 0x12, 0x05, 0x03, 0x13, 0x1B,
|
||||
0x0D, 0x20, 0x1A, 0x03, 0x04, 0x05, 0x01, 0x14, 0x03, 0x04, 0x05, 0x21, 0x03, 0x03, 0x11, 0x1B,
|
||||
0x1A, 0x02, 0x05, 0x04, 0x02, 0x1B, 0x15, 0x24, 0x09, 0x1F, 0x0F, 0x02, 0x06, 0x03, 0x02, 0x1B,
|
||||
0x19, 0x24, 0x09, 0x20, 0x0A, 0x02, 0x06, 0x03, 0x03, 0x1A, 0x04, 0x05, 0x16, 0x3D, 0x04, 0x03,
|
||||
0x0B, 0x03, 0x05, 0x03, 0x04, 0x1B, 0x02, 0x09, 0x15, 0x04, 0x03, 0x23, 0x25, 0x03, 0x05, 0x03,
|
||||
0x04, 0x2F, 0x13, 0x05, 0x02, 0x22, 0x03, 0x04, 0x04, 0x04, 0x12, 0x02, 0x06, 0x03, 0x04, 0x1C,
|
||||
0x01, 0x07, 0x03, 0x07, 0x11, 0x4A, 0x08, 0x02, 0x06, 0x03, 0x04, 0x25, 0x1D, 0x24, 0x0B, 0x03,
|
||||
0x03, 0x13, 0x0B, 0x03, 0x05, 0x03, 0x05, 0x23, 0x12, 0x27, 0x06, 0x03, 0x06, 0x17, 0x03, 0x03,
|
||||
0x10, 0x03, 0x05, 0x03, 0x04, 0x24, 0x04, 0x06, 0x04, 0x13, 0x03, 0x0A, 0x02, 0x04, 0x10, 0x24,
|
||||
0x11, 0x02, 0x05, 0x04, 0x04, 0x25, 0x03, 0x22, 0x04, 0x3F, 0x16, 0x03, 0x05, 0x03, 0x04, 0x47,
|
||||
0x10, 0x06, 0x03, 0x08, 0x44, 0x03, 0x04, 0x04, 0x04, 0x47, 0x05, 0x06, 0x04, 0x04, 0x04, 0x06,
|
||||
0x05, 0x39, 0x11, 0x02, 0x06, 0x02, 0x05, 0x2E, 0x05, 0x04, 0x13, 0x10, 0x1D, 0x3D, 0x07, 0x03,
|
||||
0x05, 0x03, 0x04, 0x39, 0x38, 0x50, 0x04, 0x03, 0x05, 0x03, 0x04, 0x04, 0x02, 0x1D, 0x02, 0x05,
|
||||
0x2C, 0x11, 0x03, 0x09, 0x02, 0x06, 0x01, 0x2D, 0x1E, 0x02, 0x05, 0x03, 0x05, 0x03, 0x02, 0x04,
|
||||
0x02, 0x1E, 0x09, 0x03, 0x03, 0x04, 0x03, 0x25, 0x03, 0x0B, 0x01, 0x05, 0x10, 0x1E, 0x03, 0x06,
|
||||
0x34, 0x32, 0x1E, 0x80, 0x04, 0x03, 0x05, 0x03, 0x05, 0xD7, 0x19, 0x03, 0x18, 0xF5, 0x1B, 0xFE,
|
||||
0xFE, 0x0D, 0x8F, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFE, 0xFE, 0x0A, 0x1A, 0xB8, 0x1B, 0xB9, 0x0D, 0x5F, 0x2F,
|
||||
0x33, 0x0D, 0x1A, 0x08, 0x1C, 0x09, 0x18, 0x0C, 0x55, 0x09, 0x0C, 0x07, 0x0A, 0x07, 0x11, 0x03,
|
||||
0x0A, 0x0A, 0x0E, 0x15, 0x0B, 0x0A, 0x1B, 0x13, 0x0E, 0x0A, 0x0B, 0x09, 0x0A, 0x07, 0x0E, 0x06,
|
||||
0x0A, 0x09, 0x0B, 0x0B, 0x05, 0x07, 0x0A, 0x09, 0x1C, 0x14, 0x09, 0x0E, 0x0B, 0x0B, 0x09, 0x06,
|
||||
0x0E, 0x07, 0x0A, 0x09, 0x0A, 0x18, 0x09, 0x0A, 0x1D, 0x0F, 0x0B, 0x0D, 0x0C, 0x0A, 0x09, 0x08,
|
||||
0x0B, 0x0B, 0x07, 0x0A, 0x0A, 0x0C, 0x56, 0x0D, 0x0C, 0x0A, 0x09, 0x08, 0x0C, 0x0A, 0x0A, 0x07,
|
||||
0x0B, 0x0C, 0x0F, 0x07, 0x2B, 0x0B, 0x07, 0x0B, 0x09, 0x0B, 0x0A, 0x09, 0x0C, 0x08, 0x0B, 0x09,
|
||||
0x0A, 0x0B, 0x0B, 0x08, 0x3E, 0x0A, 0x0A, 0x0B, 0x0C, 0x09, 0x0C, 0x08, 0x0B, 0x0A, 0x09, 0x0A,
|
||||
0x09, 0x0A, 0x0D, 0x09, 0x23, 0x0B, 0x0A, 0x0C, 0x0B, 0x07, 0x0D, 0x08, 0x0C, 0x09, 0x09, 0x0A,
|
||||
0x0B, 0x0B, 0x3B, 0x0B, 0x08, 0x0C, 0x0A, 0x09, 0x0C, 0x0A, 0x0B, 0x08, 0x0A, 0x0A, 0x0A, 0x0B,
|
||||
0x22, 0x09, 0x0D, 0x0D, 0x06, 0x0C, 0x0B, 0x09, 0x0C, 0x09, 0x0B, 0x09, 0x0A, 0x09, 0x0B, 0x0A,
|
||||
0x24, 0x08, 0x0D, 0x09, 0x0A, 0x0C, 0x0C, 0x08, 0x0B, 0x0A, 0x0B, 0x0A, 0x09, 0x0A, 0x09, 0x0B,
|
||||
0x10, 0x06, 0x0D, 0x08, 0x0F, 0x08, 0x0B, 0x0B, 0x0D, 0x08, 0x0B, 0x0A, 0x0B, 0x09, 0x09, 0x0A,
|
||||
0x0A, 0x0B, 0x0F, 0x07, 0x0C, 0x0A, 0x0C, 0x09, 0x0B, 0x0C, 0x0D, 0x07, 0x0C, 0x0A, 0x0A, 0x0A,
|
||||
0x0A, 0x09, 0x0A, 0x0A, 0x0F, 0x09, 0x0B, 0x0A, 0x0F, 0x0C, 0x06, 0x0C, 0x0C, 0x08, 0x0C, 0x0A,
|
||||
0x0A, 0x0A, 0x09, 0x0B, 0x09, 0x0B, 0x0C, 0x09, 0x0D, 0x0A, 0x0E, 0x0F, 0x07, 0x0C, 0x0B, 0x09,
|
||||
0x0B, 0x0A, 0x0B, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0C, 0x0A, 0x0D, 0x09, 0x15, 0x0C, 0x05, 0x04,
|
||||
0x02, 0x05, 0x0E, 0x06, 0x0C, 0x0A, 0x0B, 0x09, 0x09, 0x0B, 0x0A, 0x0A, 0x0C, 0x08, 0x0E, 0x08,
|
||||
0x0F, 0x05, 0x04, 0x0C, 0x0A, 0x09, 0x0B, 0x08, 0x0B, 0x0A, 0x0B, 0x09, 0x09, 0x0A, 0x0A, 0x0B,
|
||||
0x44, 0x0D, 0x06, 0x0C, 0x0D, 0x06, 0x0C, 0x0A, 0x0B, 0x09, 0x09, 0x0B, 0x0B, 0x0B, 0x45, 0x0C,
|
||||
0x0B, 0x0A, 0x0B, 0x07, 0x0C, 0x09, 0x0B, 0x08, 0x0A, 0x0A, 0x0C, 0x0B, 0x22, 0x09, 0x0D, 0x19,
|
||||
0x08, 0x0B, 0x11, 0x02, 0x0C, 0x0A, 0x0B, 0x08, 0x08, 0x0B, 0x0C, 0x0B, 0x3B, 0x1A, 0x06, 0x0C,
|
||||
0x21, 0x0A, 0x0B, 0x1C, 0x0D, 0x0C, 0x3A, 0x1B, 0x07, 0x0B, 0x0D, 0x07, 0x0C, 0x09, 0x0E, 0x09,
|
||||
0x4D, 0x09, 0x0D, 0x0F, 0x04, 0x0B, 0x08, 0x0A, 0x0D, 0x07, 0x0C, 0x0A, 0x0B, 0x0A, 0x0A, 0x0C,
|
||||
0x64, 0x0B, 0x09, 0x0A, 0x0B, 0x09, 0x0B, 0x09, 0x0C, 0x09, 0x0A, 0x08, 0x0B, 0x0B, 0x57, 0x0C,
|
||||
0x06, 0x0B, 0x0B, 0x09, 0x0C, 0x06, 0x0C, 0x09, 0x0A, 0x0A, 0x0A, 0x08, 0x0A, 0x09, 0x45, 0x0D,
|
||||
0x0B, 0x0B, 0x0A, 0x09, 0x0A, 0x09, 0x0A, 0x0A, 0x09, 0x09, 0x0C, 0x09, 0x65, 0x08, 0x0A, 0x0B,
|
||||
0x0B, 0x05, 0x0D, 0x08, 0xA4, 0x08, 0x0B, 0x0A, 0x0B, 0x05, 0x0E, 0x05, 0x0D, 0x05, 0x98, 0x08,
|
||||
0x0B, 0x0B, 0x0A, 0x04, 0x99, 0x1A, 0x08, 0x0E, 0x0B, 0x06, 0x10, 0x03, 0x1B, 0x0A, 0x2C, 0x09,
|
||||
0x5E, 0x12, 0x0C, 0x06, 0xD9, 0x09, 0x1A, 0x08, 0x3C, 0x07, 0x87, 0x07, 0x0E, 0x02, 0x09, 0x09,
|
||||
0x59, 0x07, 0x6A, 0x07, 0x1A, 0x16, 0xC4, 0x07, 0xFA, 0x07, 0xFE, 0x03, 0x17, 0xFE, 0xFE, 0xFE,
|
||||
0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x9C, 0x6F, 0xFE, 0x97, 0x39, 0x70,
|
||||
0x18, 0x16, 0x0D, 0x17, 0x18, 0x1B, 0x12, 0x17, 0x15, 0x17, 0x0E, 0x18, 0x12, 0x20, 0x16, 0x0A,
|
||||
0x0B, 0x02, 0x06, 0x10, 0x04, 0x03, 0x0D, 0x15, 0x14, 0x14, 0x15, 0x0A, 0x05, 0x05, 0x0D, 0x04,
|
||||
0x03, 0x10, 0x06, 0x03, 0x0B, 0x16, 0x13, 0x14, 0x0C, 0x16, 0x18, 0x04, 0x03, 0x0F, 0x07, 0x04,
|
||||
0x0A, 0x15, 0x14, 0x14, 0x13, 0x0F, 0x1A, 0x16, 0x09, 0x03, 0x09, 0x15, 0x14, 0x15, 0x0A, 0x16,
|
||||
0x1A, 0x16, 0x08, 0x04, 0x09, 0x15, 0x14, 0x16, 0x08, 0x16, 0x17, 0x05, 0x02, 0x05, 0x01, 0x08,
|
||||
0x08, 0x03, 0x09, 0x15, 0x15, 0x15, 0x0A, 0x15, 0x17, 0x06, 0x02, 0x0D, 0x09, 0x03, 0x09, 0x15,
|
||||
0x0E, 0x1C, 0x09, 0x15, 0x07, 0x03, 0x0A, 0x04, 0x03, 0x03, 0x02, 0x08, 0x08, 0x03, 0x0A, 0x14,
|
||||
0x15, 0x0E, 0x0F, 0x15, 0x06, 0x04, 0x09, 0x06, 0x07, 0x09, 0x08, 0x03, 0x09, 0x15, 0x13, 0x15,
|
||||
0x09, 0x07, 0x02, 0x0C, 0x04, 0x04, 0x0A, 0x05, 0x07, 0x0A, 0x06, 0x04, 0x0A, 0x13, 0x14, 0x15,
|
||||
0x09, 0x07, 0x04, 0x09, 0x12, 0x06, 0x01, 0x04, 0x01, 0x09, 0x07, 0x04, 0x09, 0x14, 0x14, 0x15,
|
||||
0x0A, 0x1D, 0x08, 0x04, 0x03, 0x03, 0x02, 0x09, 0x06, 0x04, 0x0A, 0x13, 0x15, 0x15, 0x14, 0x12,
|
||||
0x08, 0x04, 0x03, 0x03, 0x02, 0x09, 0x07, 0x03, 0x0A, 0x14, 0x15, 0x15, 0x0B, 0x04, 0x06, 0x0F,
|
||||
0x08, 0x04, 0x04, 0x0E, 0x06, 0x04, 0x09, 0x14, 0x15, 0x16, 0x14, 0x0F, 0x08, 0x04, 0x09, 0x08,
|
||||
0x07, 0x04, 0x0A, 0x13, 0x15, 0x15, 0x07, 0x1F, 0x07, 0x03, 0x05, 0x03, 0x01, 0x09, 0x06, 0x04,
|
||||
0x09, 0x14, 0x14, 0x17, 0x06, 0x06, 0x06, 0x12, 0x08, 0x03, 0x09, 0x09, 0x06, 0x04, 0x0A, 0x13,
|
||||
0x15, 0x16, 0x07, 0x06, 0x05, 0x13, 0x07, 0x04, 0x09, 0x09, 0x05, 0x05, 0x0A, 0x13, 0x15, 0x16,
|
||||
0x06, 0x08, 0x03, 0x14, 0x08, 0x03, 0x09, 0x09, 0x06, 0x04, 0x0A, 0x14, 0x14, 0x15, 0x15, 0x13,
|
||||
0x09, 0x03, 0x05, 0x0E, 0x04, 0x05, 0x09, 0x14, 0x14, 0x16, 0x14, 0x15, 0x09, 0x03, 0x05, 0x0F,
|
||||
0x04, 0x05, 0x0B, 0x12, 0x14, 0x17, 0x13, 0x15, 0x0B, 0x03, 0x05, 0x0E, 0x04, 0x05, 0x0A, 0x14,
|
||||
0x14, 0x16, 0x13, 0x18, 0x0B, 0x03, 0x04, 0x10, 0x05, 0x03, 0x0B, 0x14, 0x13, 0x18, 0x0E, 0x16,
|
||||
0x11, 0x04, 0x04, 0x0F, 0x05, 0x03, 0x0A, 0x14, 0x15, 0x16, 0x11, 0x18, 0x10, 0x03, 0x04, 0x0F,
|
||||
0x05, 0x04, 0x07, 0x17, 0x05, 0x02, 0x0F, 0x16, 0x14, 0x17, 0x06, 0x01, 0x08, 0x03, 0x04, 0x10,
|
||||
0x04, 0x04, 0x0C, 0x13, 0x03, 0x04, 0x12, 0x13, 0x10, 0x17, 0x16, 0x04, 0x03, 0x10, 0x04, 0x05,
|
||||
0x0B, 0x13, 0x03, 0x04, 0x10, 0x14, 0x03, 0x04, 0x0C, 0x1F, 0x11, 0x03, 0x04, 0x10, 0x04, 0x04,
|
||||
0x0C, 0x13, 0x04, 0x02, 0x11, 0x18, 0x16, 0x16, 0x19, 0x02, 0x04, 0x1A, 0x06, 0x20, 0x17, 0x16,
|
||||
0x16, 0x16, 0x19, 0x04, 0x03, 0x11, 0x03, 0x05, 0x06, 0x18, 0x03, 0x0A, 0x12, 0x17, 0x19, 0x12,
|
||||
0x21, 0x04, 0x04, 0x1A, 0x04, 0x28, 0x11, 0x18, 0x16, 0x16, 0x14, 0x0C, 0x07, 0x02, 0x05, 0x19,
|
||||
0x05, 0x22, 0x17, 0x05, 0x02, 0x0D, 0x1A, 0x1E, 0x0B, 0x15, 0x05, 0x03, 0x05, 0x1A, 0x03, 0x05,
|
||||
0x0B, 0x09, 0x02, 0x0B, 0x1F, 0x40, 0x11, 0x13, 0x07, 0x02, 0x05, 0x04, 0x02, 0x12, 0x15, 0x20,
|
||||
0x11, 0x19, 0x10, 0x22, 0x2D, 0x03, 0x05, 0x19, 0x05, 0x03, 0x0C, 0x1F, 0x17, 0x4A, 0x2E, 0x03,
|
||||
0x05, 0x19, 0x03, 0x3E, 0x11, 0x22, 0x0B, 0x44, 0x18, 0x1B, 0x17, 0x1B, 0x19, 0x19, 0x12, 0x4B,
|
||||
0x1D, 0xE1, 0x27, 0xF4, 0x1E, 0x3C, 0x49, 0xFE, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xAA, 0x1C, 0xD0, 0x2F, 0x09, 0x03, 0x0F, 0x03, 0x04, 0x01, 0x0A, 0x03, 0x42, 0x17, 0x23, 0x16,
|
||||
0x1C, 0x0E, 0x10, 0x10, 0x32, 0x09, 0x12, 0x0F, 0x03, 0x02, 0x26, 0x02, 0x22, 0x13, 0x81, 0x08,
|
||||
0x20, 0x2B, 0x11, 0x0F, 0x16, 0x03, 0x2C, 0x04, 0x21, 0x03, 0x09, 0x08, 0x08, 0x04, 0x10, 0x0D,
|
||||
0x06, 0x06, 0x04, 0x03, 0x3A, 0x03, 0x09, 0x06, 0x06, 0x09, 0x02, 0x15, 0x11, 0x18, 0x4F, 0x02,
|
||||
0x1A, 0x1A, 0x09, 0x14, 0x18, 0x06, 0x04, 0x05, 0x1A, 0x05, 0x05, 0x3E, 0x0B, 0x10, 0x19, 0x07,
|
||||
0x24, 0x06, 0x0A, 0x04, 0x04, 0x0B, 0x02, 0x1B, 0x10, 0x11, 0x18, 0x08, 0x18, 0x04, 0x08, 0x05,
|
||||
0x0A, 0x18, 0x01, 0x1A, 0x09, 0x09, 0x03, 0x06, 0x17, 0x07, 0x19, 0x05, 0x08, 0x05, 0x11, 0x1E,
|
||||
0x02, 0x0C, 0x08, 0x09, 0x02, 0x08, 0x0D, 0x03, 0x05, 0x07, 0x18, 0x04, 0x0A, 0x04, 0x17, 0x1C,
|
||||
0x01, 0x0C, 0x08, 0x0A, 0x01, 0x09, 0x0C, 0x04, 0x05, 0x06, 0x17, 0x05, 0x0B, 0x03, 0x0B, 0x04,
|
||||
0x0A, 0x06, 0x05, 0x12, 0x01, 0x06, 0x03, 0x01, 0x07, 0x15, 0x0E, 0x03, 0x03, 0x08, 0x16, 0x08,
|
||||
0x16, 0x06, 0x07, 0x06, 0x0A, 0x12, 0x02, 0x05, 0x03, 0x02, 0x05, 0x15, 0x0E, 0x10, 0x17, 0x06,
|
||||
0x17, 0x08, 0x07, 0x03, 0x0B, 0x13, 0x03, 0x04, 0x03, 0x03, 0x03, 0x15, 0x0D, 0x12, 0x18, 0x04,
|
||||
0x17, 0x08, 0x16, 0x15, 0x02, 0x06, 0x02, 0x04, 0x03, 0x0E, 0x01, 0x04, 0x0E, 0x0B, 0x02, 0x03,
|
||||
0x1A, 0x04, 0x17, 0x08, 0x15, 0x14, 0x03, 0x04, 0x03, 0x04, 0x02, 0x0F, 0x01, 0x03, 0x0E, 0x10,
|
||||
0x17, 0x07, 0x17, 0x09, 0x0F, 0x1A, 0x02, 0x06, 0x03, 0x03, 0x03, 0x0D, 0x04, 0x01, 0x11, 0x07,
|
||||
0x23, 0x03, 0x16, 0x09, 0x07, 0x04, 0x05, 0x19, 0x02, 0x06, 0x02, 0x03, 0x04, 0x0C, 0x04, 0x02,
|
||||
0x0F, 0x09, 0x05, 0x03, 0x14, 0x09, 0x14, 0x08, 0x07, 0x07, 0x06, 0x15, 0x03, 0x04, 0x03, 0x02,
|
||||
0x05, 0x0C, 0x05, 0x02, 0x0F, 0x08, 0x04, 0x04, 0x14, 0x09, 0x15, 0x08, 0x06, 0x07, 0x09, 0x13,
|
||||
0x05, 0x03, 0x0C, 0x0A, 0x05, 0x04, 0x0D, 0x09, 0x02, 0x05, 0x13, 0x0B, 0x14, 0x0B, 0x02, 0x07,
|
||||
0x09, 0x16, 0x06, 0x02, 0x0B, 0x0B, 0x06, 0x03, 0x0C, 0x08, 0x05, 0x06, 0x09, 0x03, 0x07, 0x07,
|
||||
0x15, 0x09, 0x09, 0x03, 0x0A, 0x0A, 0x02, 0x0A, 0x06, 0x06, 0x07, 0x0A, 0x06, 0x04, 0x0A, 0x06,
|
||||
0x07, 0x06, 0x08, 0x06, 0x08, 0x06, 0x09, 0x05, 0x06, 0x0E, 0x13, 0x05, 0x09, 0x0A, 0x04, 0x08,
|
||||
0x06, 0x05, 0x09, 0x05, 0x18, 0x07, 0x06, 0x07, 0x08, 0x08, 0x06, 0x09, 0x05, 0x18, 0x11, 0x08,
|
||||
0x05, 0x07, 0x05, 0x07, 0x07, 0x08, 0x05, 0x08, 0x08, 0x04, 0x08, 0x07, 0x07, 0x05, 0x08, 0x08,
|
||||
0x15, 0x17, 0x14, 0x0B, 0x11, 0x07, 0x07, 0x05, 0x15, 0x07, 0x08, 0x02, 0x0C, 0x04, 0x07, 0x07,
|
||||
0x09, 0x05, 0x05, 0x1B, 0x08, 0x12, 0x3E, 0x09, 0x58, 0x09, 0x15, 0x0C, 0x13, 0x04, 0x3C, 0x09,
|
||||
0x20, 0x07, 0x7B, 0x16, 0x05, 0x26, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x40, 0x04, 0x3B, 0x07, 0xCB,
|
||||
0x03, 0x07, 0x08, 0x72, 0x08, 0x19, 0x07, 0x04, 0x08, 0x03, 0x03, 0x0F, 0x03, 0x01, 0x03, 0x03,
|
||||
0x02, 0x02, 0x03, 0x02, 0x02, 0x2A, 0x02, 0x18, 0x02, 0x03, 0x02, 0x5D, 0x09, 0x01, 0x03, 0x03,
|
||||
0x02, 0x11, 0x1A, 0x20, 0x01, 0x1D, 0x03, 0x03, 0x01, 0x32, 0x38, 0x03, 0x02, 0x21, 0x02, 0x51,
|
||||
0x01, 0x0A, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, 0x02, 0x02, 0x08, 0x03, 0x02, 0x0E, 0x03, 0x01,
|
||||
0x02, 0x03, 0x02, 0x44, 0x03, 0x02, 0x03, 0x03, 0x01, 0x2F, 0x02, 0x29, 0x08, 0x2A, 0x07, 0x02,
|
||||
0x04, 0x01, 0x0A, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x6C, 0x15, 0x02, 0x02, 0x02, 0x03, 0x10,
|
||||
0x01, 0x17, 0x02, 0x03, 0x01, 0x11, 0x02, 0x02, 0x03, 0x50, 0x02, 0x02, 0x02, 0x38, 0x03, 0x1A,
|
||||
0x29, 0x02, 0x03, 0x03, 0x02, 0x04, 0x01, 0x67, 0x01, 0x03, 0x02, 0x03, 0x01, 0x1A, 0x02, 0x04,
|
||||
0x01, 0x0A, 0x01, 0x04, 0x01, 0x04, 0x02, 0x1A, 0x01, 0x02, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03,
|
||||
0x02, 0x27, 0x01, 0x02, 0x03, 0x03, 0x01, 0x22, 0x02, 0x03, 0x03, 0x03, 0x02, 0x39, 0x0F, 0x02,
|
||||
0x03, 0x0E, 0x03, 0x2A, 0x02, 0x03, 0x02, 0xFE, 0xFE, 0x34, 0x1B, 0xED, 0x20, 0xE7, 0x21, 0x40,
|
||||
0x59, 0x57, 0x2E, 0xE9, 0x23, 0xFE, 0x01, 0x27, 0x40, 0x5B, 0xFE, 0xFE, 0x16, 0x71, 0xFE, 0xFE,
|
||||
0xFF, 0x0F, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0x4D, 0x20, 0x22, 0x19, 0x1A, 0x16, 0x1B, 0x19, 0x1B, 0x19, 0x1C, 0x13, 0x1C, 0x1D, 0x19, 0x10,
|
||||
0x2E, 0x08, 0x14, 0x2B, 0x17, 0x0E, 0x4B, 0x12, 0x09, 0x13, 0x13, 0x10, 0x0E, 0x0C, 0x14, 0x09,
|
||||
0x12, 0x10, 0x0B, 0x12, 0x13, 0x10, 0x0F, 0x0A, 0x16, 0x04, 0x16, 0x0E, 0x0D, 0x12, 0x13, 0x11,
|
||||
0x0E, 0x0E, 0x12, 0x04, 0x17, 0x0E, 0x0D, 0x11, 0x13, 0x12, 0x0F, 0x08, 0x15, 0x08, 0x15, 0x0D,
|
||||
0x0B, 0x13, 0x13, 0x12, 0x0C, 0x07, 0x17, 0x04, 0x17, 0x2C, 0x22, 0x16, 0x18, 0x05, 0x17, 0x08,
|
||||
0x04, 0x07, 0x04, 0x14, 0x31, 0x06, 0x17, 0x06, 0x17, 0x28, 0x10, 0x0B, 0x13, 0x0B, 0x18, 0x05,
|
||||
0x17, 0x26, 0x12, 0x0B, 0x16, 0x06, 0x37, 0x05, 0x06, 0x18, 0x12, 0x0C, 0x12, 0x07, 0x18, 0x04,
|
||||
0x19, 0x07, 0x07, 0x04, 0x03, 0x0F, 0x12, 0x09, 0x0A, 0x03, 0x06, 0x07, 0x15, 0x0A, 0x16, 0x13,
|
||||
0x05, 0x0E, 0x12, 0x09, 0x0A, 0x03, 0x06, 0x07, 0x16, 0x09, 0x17, 0x10, 0x06, 0x0E, 0x12, 0x09,
|
||||
0x13, 0x09, 0x15, 0x0A, 0x18, 0x10, 0x04, 0x0D, 0x12, 0x0A, 0x0A, 0x03, 0x04, 0x09, 0x15, 0x0A,
|
||||
0x15, 0x08, 0x08, 0x01, 0x05, 0x0E, 0x12, 0x0A, 0x0A, 0x02, 0x05, 0x09, 0x15, 0x07, 0x17, 0x09,
|
||||
0x10, 0x0E, 0x11, 0x0A, 0x13, 0x09, 0x14, 0x09, 0x15, 0x13, 0x07, 0x0F, 0x10, 0x0A, 0x13, 0x09,
|
||||
0x14, 0x08, 0x17, 0x12, 0x08, 0x13, 0x0C, 0x0A, 0x13, 0x09, 0x15, 0x08, 0x16, 0x14, 0x06, 0x0E,
|
||||
0x12, 0x09, 0x13, 0x09, 0x15, 0x13, 0x0B, 0x13, 0x08, 0x0D, 0x13, 0x08, 0x16, 0x07, 0x16, 0x08,
|
||||
0x16, 0x12, 0x08, 0x15, 0x0B, 0x09, 0x15, 0x08, 0x15, 0x08, 0x06, 0x03, 0x0C, 0x13, 0x09, 0x15,
|
||||
0x0C, 0x08, 0x03, 0x06, 0x0A, 0x09, 0x05, 0x04, 0x0A, 0x13, 0x15, 0x09, 0x0B, 0x14, 0x17, 0x09,
|
||||
0x18, 0x04, 0x0C, 0x03, 0x06, 0x06, 0x15, 0x08, 0x10, 0x12, 0x13, 0x0E, 0x17, 0x05, 0x12, 0x08,
|
||||
0x14, 0x08, 0x04, 0x04, 0x09, 0x12, 0x0F, 0x12, 0x0F, 0x0D, 0x13, 0x07, 0x14, 0x11, 0x0A, 0x13,
|
||||
0x10, 0x10, 0x15, 0x09, 0x2F, 0x0D, 0x10, 0x13, 0x0F, 0x10, 0x16, 0x09, 0x2D, 0x0F, 0x10, 0x14,
|
||||
0x0F, 0x0F, 0x16, 0x08, 0x17, 0x04, 0x14, 0x0D, 0x11, 0x15, 0x11, 0x0E, 0x12, 0x0C, 0x26, 0x14,
|
||||
0x0F, 0x1E, 0x19, 0x06, 0x18, 0x06, 0x07, 0x02, 0x18, 0x06, 0x08, 0x05, 0x09, 0x13, 0x04, 0x08,
|
||||
0x03, 0x06, 0x17, 0x08, 0x05, 0x03, 0x0F, 0x03, 0x31, 0x05, 0x07, 0x14, 0x0B, 0x13, 0x16, 0x11,
|
||||
0x14, 0x0B, 0x2E, 0x08, 0x15, 0x12, 0x02, 0x05, 0x17, 0x0A, 0x05, 0x01, 0x19, 0x07, 0x3C, 0x13,
|
||||
0x04, 0x16, 0x16, 0x08, 0x1B, 0x12, 0x21, 0x11, 0x14, 0x16, 0x02, 0x0E, 0x2F, 0x04, 0x06, 0x0A,
|
||||
0x10, 0x14, 0x18, 0x07, 0x09, 0x14, 0x0B, 0x05, 0x02, 0x06, 0x26, 0x02, 0x2E, 0x12, 0x2B, 0x11,
|
||||
0x14, 0x07, 0x03, 0x05, 0x30, 0x02, 0x06, 0x04, 0x18, 0x1F, 0x58, 0x06, 0x02, 0x05, 0x2F, 0x04,
|
||||
0x04, 0x06, 0x09, 0x02, 0x04, 0x31, 0x22, 0x3A, 0xC5, 0x16, 0x3F, 0x03, 0x0A, 0x02, 0x51, 0x12,
|
||||
0x12, 0x10, 0xFE, 0xD0, 0x35, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0x63, 0x02, 0x04, 0x02, 0x03, 0x03, 0x81, 0x02, 0x03, 0x02, 0x47, 0x09, 0x0A, 0x02,
|
||||
0x02, 0x03, 0x03, 0x02, 0x2B, 0x01, 0x04, 0x02, 0x04, 0x02, 0x04, 0x01, 0x38, 0x02, 0x80, 0x03,
|
||||
0x03, 0x02, 0x63, 0x01, 0x03, 0x02, 0x03, 0x02, 0x56, 0x02, 0x03, 0x02, 0x03, 0x03, 0x19, 0x02,
|
||||
0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x01, 0x60, 0x2C, 0x01, 0x03, 0x3E, 0x01,
|
||||
0x04, 0x01, 0x32, 0x02, 0x02, 0x03, 0x02, 0x17, 0x01, 0x03, 0x3D, 0x02, 0x03, 0x03, 0x03, 0x02,
|
||||
0x0A, 0x02, 0x5B, 0x02, 0x1F, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x04, 0x01,
|
||||
0x09, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04, 0x01, 0x03, 0x02, 0x03, 0x02, 0x04, 0x01,
|
||||
0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x2C, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03,
|
||||
0x04, 0x01, 0x23, 0x02, 0x03, 0x02, 0x25, 0x03, 0x02, 0x02, 0x03, 0x02, 0x1B, 0x02, 0x03, 0x02,
|
||||
0x04, 0x01, 0x37, 0x02, 0x04, 0x02, 0x12, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
|
||||
0x10, 0x02, 0x04, 0x01, 0x0D, 0x01, 0x04, 0x01, 0x04, 0x01, 0x25, 0x02, 0x03, 0x02, 0x03, 0x02,
|
||||
0x04, 0x02, 0x0A, 0x02, 0x0B, 0x02, 0x04, 0x02, 0x04, 0x03, 0x02, 0x03, 0x03, 0x0E, 0x3E, 0x02,
|
||||
0x04, 0x18, 0x01, 0x03, 0x03, 0x02, 0x04, 0x0A, 0x87, 0x11, 0x03, 0x02, 0x03, 0x02, 0x52, 0x02,
|
||||
0x04, 0x02, 0x12, 0x02, 0x30, 0x02, 0x03, 0x02, 0x04, 0x02, 0x04, 0x01, 0x04, 0x02, 0x02, 0x03,
|
||||
0x02, 0x02, 0x02, 0x03, 0x03, 0x01, 0x27, 0x02, 0xA4, 0x02, 0x03, 0x02, 0x18, 0x02, 0x03, 0x02,
|
||||
0x24, 0x16, 0x01, 0x1B, 0xFF, 0x01, 0x0F, 0x1A, 0x0D, 0x0B, 0x20, 0x0E, 0x07, 0x0C, 0x0A, 0x0B,
|
||||
0x22, 0x0A, 0x0D, 0x09, 0x0A, 0x0B, 0x1E, 0x10, 0x04, 0x0D, 0x10, 0x0C, 0x1E, 0x0A, 0x0B, 0x08,
|
||||
0x0C, 0x0A, 0x10, 0x07, 0x09, 0x0C, 0x04, 0x0E, 0x0C, 0x0C, 0x1F, 0x0E, 0x1D, 0x08, 0x11, 0x1A,
|
||||
0x03, 0x0D, 0x0C, 0x0B, 0x21, 0x0C, 0x10, 0x13, 0x14, 0x12, 0x0A, 0x0D, 0x0B, 0x0B, 0x0E, 0x03,
|
||||
0x10, 0x0C, 0x1E, 0x09, 0x11, 0x13, 0x08, 0x0B, 0x0C, 0x0C, 0x0C, 0x04, 0x10, 0x0E, 0x3E, 0x1F,
|
||||
0x0A, 0x0D, 0x0F, 0x02, 0x0B, 0x0F, 0x0E, 0x0C, 0x20, 0x04, 0x03, 0x1E, 0x0B, 0x0D, 0x1C, 0x0E,
|
||||
0x0E, 0x0C, 0x1E, 0x17, 0x02, 0x0C, 0x0B, 0x0D, 0x1B, 0x11, 0x1D, 0x06, 0x20, 0x0F, 0x02, 0x0B,
|
||||
0x0B, 0x0E, 0x0C, 0x04, 0x0F, 0x0B, 0x10, 0x12, 0x1E, 0x20, 0x0B, 0x0B, 0x0E, 0x04, 0x09, 0x03,
|
||||
0x02, 0x0A, 0x0B, 0x0D, 0x04, 0x08, 0x1D, 0x10, 0x05, 0x0D, 0x0B, 0x0C, 0x0D, 0x04, 0x0F, 0x0B,
|
||||
0x0D, 0x0A, 0x0B, 0x08, 0x0D, 0x0E, 0x11, 0x12, 0x0B, 0x0B, 0x0E, 0x03, 0x0A, 0x0E, 0x0C, 0x0C,
|
||||
0x0B, 0x0A, 0x09, 0x0B, 0x0D, 0x1D, 0x0B, 0x0C, 0x0E, 0x04, 0x0A, 0x0D, 0x0C, 0x0D, 0x0B, 0x09,
|
||||
0x0B, 0x07, 0x0E, 0x0E, 0x03, 0x0B, 0x03, 0x02, 0x06, 0x01, 0x02, 0x0B, 0x0F, 0x03, 0x0B, 0x0B,
|
||||
0x0D, 0x0E, 0x0C, 0x07, 0x09, 0x0A, 0x0C, 0x0A, 0x0B, 0x0C, 0x04, 0x01, 0x05, 0x10, 0x10, 0x02,
|
||||
0x0B, 0x03, 0x02, 0x04, 0x0F, 0x09, 0x11, 0x09, 0x03, 0x0D, 0x0B, 0x0C, 0x0A, 0x12, 0x01, 0x03,
|
||||
0x0B, 0x0B, 0x1D, 0x02, 0x02, 0x09, 0x0F, 0x0C, 0x13, 0x12, 0x0F, 0x0F, 0x0E, 0x0D, 0x0B, 0x03,
|
||||
0x02, 0x05, 0x22, 0x09, 0x10, 0x0A, 0x02, 0x04, 0x10, 0x0E, 0x0D, 0x1B, 0x0A, 0x0C, 0x0C, 0x0B,
|
||||
0x0E, 0x03, 0x0F, 0x0C, 0x0D, 0x0B, 0x05, 0x0B, 0x0A, 0x0C, 0x0D, 0x0F, 0x09, 0x03, 0x0B, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x04, 0x0F, 0x0C, 0x0C, 0x0D, 0x06, 0x0C, 0x0D, 0x0A, 0x0B, 0x08, 0x0E, 0x09,
|
||||
0x0D, 0x0D, 0x0B, 0x0E, 0x1E, 0x0C, 0x0E, 0x1B, 0x0D, 0x0C, 0x0C, 0x0E, 0x1D, 0x09, 0x0B, 0x0A,
|
||||
0x0C, 0x0C, 0x0A, 0x0A, 0x0E, 0x0B, 0x0B, 0x09, 0x0C, 0x0A, 0x0E, 0x0F, 0x07, 0x0C, 0x2F, 0x0A,
|
||||
0x10, 0x09, 0x15, 0x0B, 0x19, 0x0E, 0x13, 0x10, 0x11, 0x11, 0x11, 0x14, 0x31, 0x1F, 0x54, 0x11,
|
||||
0x5B, 0x0F, 0x2F, 0x0A, 0x12, 0x34, 0x9E, 0x0C, 0x12, 0x18, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFF,
|
||||
};
|
||||
26
stSpeechData.h
Normal file
26
stSpeechData.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Generated by assets/extractSpeech.py. Do not hand-edit.
|
||||
//
|
||||
// Space Taxi's digitised speech as the C64 stores it: 1-bit
|
||||
// run-length streams. Each byte is one half-cycle length; the
|
||||
// player toggles its output after each. $FE is a raster sync
|
||||
// and $FF ends an utterance. stAudio.c expands these to PCM
|
||||
// through the jlAudioPlaySfxStream fill callback.
|
||||
|
||||
#ifndef ST_SPEECH_DATA_H
|
||||
#define ST_SPEECH_DATA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t code; // PETSCII: 'H' 'T' '!' 'P' '1'..'9' '?' 'U'
|
||||
uint16_t offset; // into kStSpeechRle
|
||||
uint16_t length;
|
||||
} StSpeechEntryT;
|
||||
|
||||
#define ST_SPEECH_COUNT 15u
|
||||
#define ST_SPEECH_RLE_BYTES 7445u
|
||||
|
||||
extern const StSpeechEntryT kStSpeechIndex[ST_SPEECH_COUNT];
|
||||
extern const uint8_t kStSpeechRle[ST_SPEECH_RLE_BYTES];
|
||||
|
||||
#endif
|
||||
133
stTitle.c
133
stTitle.c
|
|
@ -11,6 +11,11 @@
|
|||
// Level intro ($4523..$4727): a black screen with the level name, the
|
||||
// cab rising from the bottom and seven star sprites streaming out of
|
||||
// the centre, until the cab reaches mid-screen.
|
||||
//
|
||||
// The seven star sprites are replaced by a static starfield whose
|
||||
// colours are cycled -- see ST_STAR_RING_FIRST in stSim.h for why and
|
||||
// how. The cab still flies, and it is still what ends the intro, so the
|
||||
// sequence keeps its length and its cue; only the warp changes.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -28,24 +33,49 @@ static const uint8_t kLogoColor[8] = { 0x02, 0x08, 0x07, 0x05, 0x06, 0x0E, 0x03
|
|||
// Intro cab drift per loop count ($470D).
|
||||
static const int8_t kIntroCabDy[4] = { -2, 1, -1, 1 };
|
||||
// Intro texts ($4624 / $463F).
|
||||
static const uint8_t kTextDemoExit[] = { 0x44, 0x45, 0x4D, 0x4F, 0x2C, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4A, 0x4F, 0x59, 0x53, 0x54, 0x49, 0x43, 0x4B, 0x20, 0x54, 0x4F, 0x20, 0x45, 0x58, 0x49, 0x54, 0 };
|
||||
static const uint8_t kTextScreens[] = { 0x54, 0x48, 0x49, 0x53, 0x20, 0x49, 0x53, 0x20, 0x31, 0x20, 0x4F, 0x46, 0x20, 0x32, 0x35, 0x20, 0x44, 0x49, 0x46, 0x46, 0x45, 0x52, 0x45, 0x4E, 0x54, 0x20, 0x53, 0x43, 0x52, 0x45, 0x45, 0x4E, 0x53, 0x21, 0 };
|
||||
static const uint8_t kTextDemoExit[] = "DEMO, USE JOYSTICK TO EXIT";
|
||||
static const uint8_t kTextScreens[] = "THIS IS 1 OF 25 DIFFERENT SCREENS!";
|
||||
|
||||
#define ST_TITLE_CAB_LIFT_ROW 0x14u
|
||||
#define ST_TITLE_SPARKLE_TICKS 0x5Au
|
||||
#define ST_TITLE_HOVER_COL 0x28u
|
||||
#define ST_INTRO_STAR_PTR 0xDAu
|
||||
#define ST_INTRO_STAR_RELOAD 0x20u
|
||||
#define ST_INTRO_CAB_END_ROW 0x94u
|
||||
#define ST_INTRO_CAB_DX_RELOAD 0x28u
|
||||
|
||||
// The palette-cycled starfield. Seven stars per ring so the bright band
|
||||
// stays the same weight all the way out, placed at fixed pseudo-random
|
||||
// angles and clear of the three lines the intro screen writes (the level
|
||||
// name on row 12, and the demo hints on rows 3 and 24).
|
||||
typedef struct {
|
||||
uint8_t col;
|
||||
uint8_t row;
|
||||
uint8_t ring;
|
||||
} StStarT;
|
||||
|
||||
static const StStarT kIntroStar[] = {
|
||||
{ 18u, 10u, 0u }, { 19u, 10u, 0u }, { 17u, 11u, 0u }, { 18u, 13u, 0u },
|
||||
{ 21u, 13u, 0u }, { 22u, 14u, 0u }, { 18u, 15u, 0u }, { 18u, 8u, 1u },
|
||||
{ 19u, 8u, 1u }, { 14u, 10u, 1u }, { 25u, 14u, 1u }, { 21u, 15u, 1u },
|
||||
{ 25u, 15u, 1u }, { 20u, 17u, 1u }, { 26u, 7u, 2u }, { 12u, 10u, 2u },
|
||||
{ 29u, 11u, 2u }, { 11u, 13u, 2u }, { 29u, 14u, 2u }, { 21u, 17u, 2u },
|
||||
{ 23u, 18u, 2u }, { 21u, 4u, 3u }, { 24u, 4u, 3u }, { 11u, 8u, 3u },
|
||||
{ 12u, 8u, 3u }, { 10u, 10u, 3u }, { 30u, 16u, 3u }, { 14u, 17u, 3u },
|
||||
{ 15u, 2u, 4u }, { 8u, 8u, 4u }, { 32u, 9u, 4u }, { 9u, 17u, 4u },
|
||||
{ 32u, 17u, 4u }, { 32u, 18u, 4u }, { 24u, 22u, 4u }, { 16u, 1u, 5u },
|
||||
{ 28u, 1u, 5u }, { 31u, 2u, 5u }, { 36u, 13u, 5u }, { 6u, 15u, 5u },
|
||||
{ 4u, 16u, 5u }, { 5u, 19u, 5u }, { 8u, 0u, 6u }, { 30u, 0u, 6u },
|
||||
{ 1u, 8u, 6u }, { 2u, 12u, 6u }, { 37u, 16u, 6u }, { 7u, 21u, 6u },
|
||||
{ 32u, 22u, 6u }, { 0u, 4u, 7u }, { 39u, 7u, 7u }, { 0u, 10u, 7u },
|
||||
{ 38u, 20u, 7u }, { 38u, 21u, 7u }, { 4u, 22u, 7u }, { 35u, 22u, 7u },
|
||||
};
|
||||
#define ST_INTRO_STAR_COUNT (sizeof(kIntroStar) / sizeof(kIntroStar[0]))
|
||||
|
||||
|
||||
static void addToRow(StSimT *sim, uint8_t idx, uint8_t delta);
|
||||
static void addToSpriteX(StSimT *sim, uint8_t idx, uint8_t delta);
|
||||
static void logoColorCycle(StSimT *sim);
|
||||
static void logoFlip(StSimT *sim);
|
||||
static void marshalFrame(StSimT *sim);
|
||||
static void starRespawn(StSimT *sim, uint8_t idx);
|
||||
static void paintStarfield(StSimT *sim);
|
||||
|
||||
|
||||
// $4113
|
||||
|
|
@ -54,16 +84,6 @@ static void addToRow(StSimT *sim, uint8_t idx, uint8_t delta) {
|
|||
}
|
||||
|
||||
|
||||
// $411B
|
||||
static void addToSpriteX(StSimT *sim, uint8_t idx, uint8_t delta) {
|
||||
uint16_t x = (uint16_t)(((uint16_t)sim->spr[idx].msb << 8) | sim->spr[idx].col);
|
||||
|
||||
x = (uint16_t)(x + (uint16_t)(int16_t)(int8_t)delta);
|
||||
sim->spr[idx].col = (uint8_t)x;
|
||||
sim->spr[idx].msb = (uint8_t)(x >> 8);
|
||||
}
|
||||
|
||||
|
||||
// $4861 -- the next logo colour, onto sprites 3..7 and onto the logo
|
||||
// itself. The C64 writes the colour into all 407 cells of rows 1..11,
|
||||
// columns 1..37; only the cells showing the logo character take any
|
||||
|
|
@ -90,7 +110,8 @@ static void logoFlip(StSimT *sim) {
|
|||
if (sim->logoDiv != 0u) {
|
||||
return;
|
||||
}
|
||||
memcpy(sim->charset[ST_LOGO_CHAR], sim->charset[ST_LOGO_CHAR + kLogoFlip[sim->logoCycleAux]], 8u);
|
||||
memcpy(stSimGlyphMut(sim, ST_LOGO_CHAR),
|
||||
stSimGlyph(sim, (uint8_t)(ST_LOGO_CHAR + kLogoFlip[sim->logoCycleAux])), 8u);
|
||||
stSimMarkChar(sim, ST_LOGO_CHAR);
|
||||
sim->logoCycleAux++;
|
||||
if (sim->logoCycleAux == 6u) {
|
||||
|
|
@ -103,32 +124,21 @@ static void logoFlip(StSimT *sim) {
|
|||
}
|
||||
|
||||
|
||||
// $4253 + $4293 as the title and intro loops call them.
|
||||
static void marshalFrame(StSimT *sim) {
|
||||
uint8_t i;
|
||||
uint8_t enable = 0u;
|
||||
// Paint the level-intro starfield into screen RAM, once. A star's cell
|
||||
// is coloured ST_STAR_RING_FIRST + its ring and never touched again --
|
||||
// the renderer animates the warp by cycling those colours, which costs
|
||||
// no dirty rows at all. See ST_STAR_RING_FIRST in stSim.h.
|
||||
static void paintStarfield(StSimT *sim) {
|
||||
const StStarT *star;
|
||||
uint8_t one[2];
|
||||
uint8_t k;
|
||||
|
||||
for (i = 0u; i < ST_HW_SPRITES; i++) {
|
||||
sim->frame.x[i] = (uint16_t)(((uint16_t)(sim->spr[i].msb != 0u ? 1u : 0u) << 8) | sim->spr[i].col);
|
||||
sim->frame.y[i] = sim->spr[i].row;
|
||||
sim->frame.ptr[i] = sim->spr[i].ptr;
|
||||
sim->frame.color[i] = sim->spr[i].color;
|
||||
if (sim->spr[i].enable != 0u) {
|
||||
enable |= (uint8_t)(1u << i);
|
||||
}
|
||||
one[1] = 0u; // stSimDrawText stops below screen code 6
|
||||
for (k = 0u; k < (uint8_t)ST_INTRO_STAR_COUNT; k++) {
|
||||
star = &kIntroStar[k];
|
||||
one[0] = (star->ring < ST_STAR_FAR_RINGS) ? ST_STAR_GLYPH_FAR : ST_STAR_GLYPH_NEAR;
|
||||
stSimDrawText(sim, star->col, star->row, one, (uint8_t)(ST_STAR_RING_FIRST + star->ring));
|
||||
}
|
||||
sim->frame.enableMask = enable;
|
||||
sim->frame.multiMask = sim->multiColorMask;
|
||||
}
|
||||
|
||||
|
||||
// $4675 -- a star reappears near the centre, seeded by star 0's row.
|
||||
static void starRespawn(StSimT *sim, uint8_t idx) {
|
||||
sim->spr[idx].enable = 1u;
|
||||
sim->spr[idx].msb = 0u;
|
||||
sim->spr[idx].col = (uint8_t)((sim->spr[0].row & 7u) + 0xA6u);
|
||||
sim->spr[idx].row = (uint8_t)(((sim->spr[0].row & 0x30u) >> 4) + 0x89u);
|
||||
sim->starReload[idx] = ST_INTRO_STAR_RELOAD;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -159,21 +169,26 @@ void stIntroEnter(StSimT *sim, const StLevelT *level) {
|
|||
sim->spr[idx].color = 0x07u;
|
||||
sim->spr[idx].ptr = ST_INTRO_STAR_PTR;
|
||||
sim->spr[idx].enable = 0u;
|
||||
sim->starTimer[idx] = stSimRng(sim, 0x20u);
|
||||
sim->starReload[idx] = 0u;
|
||||
// $44F8/$4500 held each star's spawn timer and reload. Nothing
|
||||
// reads them now that the warp is painted rather than flown, but
|
||||
// the seven RNG draws MUST stay: they advance the shared RNG and
|
||||
// the level that follows draws from it, so dropping them would
|
||||
// change the game that comes after the intro.
|
||||
(void)stSimRng(sim, 0x20u);
|
||||
}
|
||||
sim->borderColor = 0u;
|
||||
sim->bgColor = 0u;
|
||||
sim->multiColorMask = 0x80u;
|
||||
marshalFrame(sim);
|
||||
stSimMarshal(sim);
|
||||
// $40CA: blank screen.
|
||||
memset(sim->screen, ST_CHAR_SPACE, ST_SCREEN_CELLS);
|
||||
memset(sim->color, 0, ST_SCREEN_CELLS);
|
||||
stSimDirtyAll(sim);
|
||||
memcpy(sim->charset, stC64Charset(), sizeof(sim->charset));
|
||||
stSimGlyphReset(sim);
|
||||
sim->charDirtyAll = true;
|
||||
sim->charDirtyCount = 0u;
|
||||
stSimDrawText(sim, 10u, 12u, level->name, 3u);
|
||||
paintStarfield(sim);
|
||||
if (sim->demoMode != 0u && sim->postMortem == 0u) {
|
||||
stSimDrawText(sim, 7u, 3u, kTextDemoExit, 5u);
|
||||
stSimDrawText(sim, 3u, 24u, kTextScreens, 4u);
|
||||
|
|
@ -187,27 +202,11 @@ void stIntroEnter(StSimT *sim, const StLevelT *level) {
|
|||
bool stIntroStep(StSimT *sim) {
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < 7u; k++) {
|
||||
uint8_t idx = (uint8_t)(6u - k);
|
||||
if (sim->starTimer[idx] == 0u) {
|
||||
addToSpriteX(sim, idx, (uint8_t)stC64IntroStarDx(idx));
|
||||
addToRow(sim, idx, (uint8_t)stC64IntroStarDy(idx));
|
||||
sim->starReload[idx]--;
|
||||
if (sim->starReload[idx] == 0u) {
|
||||
starRespawn(sim, idx);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
sim->starTimer[idx]--;
|
||||
if (sim->starTimer[idx] == 0u) {
|
||||
starRespawn(sim, idx);
|
||||
}
|
||||
}
|
||||
marshalFrame(sim);
|
||||
stSimMarshal(sim);
|
||||
sim->introLoopCount = (uint8_t)((sim->introLoopCount + 1u) & 3u);
|
||||
addToRow(sim, 7u, (uint8_t)kIntroCabDy[sim->introLoopCount]);
|
||||
if ((sim->introLoopCount & 1u) == 0u) {
|
||||
addToSpriteX(sim, 7u, sim->introCabDx);
|
||||
stSimSpriteAddX(sim, 7u, sim->introCabDx);
|
||||
sim->introCabDxTimer--;
|
||||
if (sim->introCabDxTimer == 0u) {
|
||||
sim->introCabDxTimer = ST_INTRO_CAB_DX_RELOAD;
|
||||
|
|
@ -222,7 +221,7 @@ bool stIntroStep(StSimT *sim) {
|
|||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||
sim->spr[k].enable = 0u;
|
||||
}
|
||||
marshalFrame(sim);
|
||||
stSimMarshal(sim);
|
||||
sim->rngT1 = 0x06u;
|
||||
sim->rngT2 = 0x17u;
|
||||
return true;
|
||||
|
|
@ -237,7 +236,7 @@ void stTitleEnter(StSimT *sim, const StLevelT *title) {
|
|||
memcpy(sim->screen, title->screen, ST_SCREEN_CELLS);
|
||||
memcpy(sim->color, title->color, ST_SCREEN_CELLS);
|
||||
stSimDirtyAll(sim);
|
||||
memcpy(sim->charset, stC64Charset(), sizeof(sim->charset));
|
||||
stSimGlyphReset(sim);
|
||||
sim->charDirtyAll = true;
|
||||
sim->charDirtyCount = 0u;
|
||||
logoColorCycle(sim);
|
||||
|
|
@ -260,7 +259,7 @@ void stTitleEnter(StSimT *sim, const StLevelT *title) {
|
|||
sim->multiColorMask = 0x07u;
|
||||
sim->spriteMc1 = 0x07u;
|
||||
sim->spriteMc0 = 0x02u;
|
||||
marshalFrame(sim);
|
||||
stSimMarshal(sim);
|
||||
sim->stage = ST_STAGE_WAIT;
|
||||
sim->introFrameCount = ST_TITLE_SPARKLE_TICKS;
|
||||
sim->hoverXFrac = 0u;
|
||||
|
|
@ -313,7 +312,7 @@ bool stTitleTick(StSimT *sim) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
marshalFrame(sim);
|
||||
stSimMarshal(sim);
|
||||
logoFlip(sim);
|
||||
return sim->stage == ST_STAGE_DROP_IN;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,12 @@
|
|||
// boot with jlSpriteBankLoadPrecompiled, so no cel is JIT-compiled on
|
||||
// the 65816 (which costs ~0.4 s each).
|
||||
//
|
||||
// Usage: staxibake OUTPUT.spr
|
||||
// Usage: staxibake OUTPUT.spr the cab/passenger/exhaust bank
|
||||
// staxibake --level LEVEL.dat OUTPUT.spr one level's hook-sprite cels
|
||||
//
|
||||
// The per-level bank holds the cels stLevelCelList names for that level
|
||||
// (its own VIC bitmaps in the colours its hook program uses), in list
|
||||
// order -- the game rebuilds the same list at level entry to key them.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -26,39 +31,87 @@
|
|||
#define SPR_OFF_HEIGHT 7u
|
||||
#define SPR_OFF_CELLS 8u
|
||||
|
||||
static const uint8_t *levelBitmap(const StLevelT *level, uint8_t ptr);
|
||||
static bool writeHeader(FILE *out, uint16_t count);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
uint8_t header[SPR_HEADER_BYTES];
|
||||
FILE *out;
|
||||
uint16_t i;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: staxibake OUTPUT.spr\n");
|
||||
return 2;
|
||||
}
|
||||
out = fopen(argv[1], "wb");
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "staxibake: cannot write %s\n", argv[1]);
|
||||
return 1;
|
||||
// A level's own sprite block, or NULL when the level does not ship it.
|
||||
static const uint8_t *levelBitmap(const StLevelT *level, uint8_t ptr) {
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < level->spriteCount; k++) {
|
||||
if (level->sprites[k].ptr == ptr) {
|
||||
return level->sprites[k].bitmap;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool writeHeader(FILE *out, uint16_t count) {
|
||||
uint8_t header[SPR_HEADER_BYTES];
|
||||
|
||||
memset(header, 0, sizeof(header));
|
||||
memcpy(header, "JSP1", 4);
|
||||
header[SPR_OFF_TARGET] = 0u; // cross-platform chunky
|
||||
header[SPR_OFF_HAS_PAL] = 0u; // the game owns its palette
|
||||
header[SPR_OFF_WIDTH] = (uint8_t)ST_CEL_TILES;
|
||||
header[SPR_OFF_HEIGHT] = (uint8_t)ST_CEL_TILES;
|
||||
header[SPR_OFF_CELLS] = (uint8_t)(kStCelCount & 0xFFu);
|
||||
header[SPR_OFF_CELLS + 1u] = (uint8_t)(kStCelCount >> 8);
|
||||
if (fwrite(header, 1, SPR_HEADER_BYTES, out) != SPR_HEADER_BYTES) {
|
||||
header[SPR_OFF_TARGET] = 0u; // cross-platform chunky
|
||||
header[SPR_OFF_HAS_PAL] = 0u; // the game owns its palette
|
||||
header[SPR_OFF_WIDTH] = (uint8_t)ST_CEL_TILES;
|
||||
header[SPR_OFF_HEIGHT] = (uint8_t)ST_CEL_TILES;
|
||||
header[SPR_OFF_CELLS] = (uint8_t)(count & 0xFFu);
|
||||
header[SPR_OFF_CELLS + 1u] = (uint8_t)(count >> 8);
|
||||
return fwrite(header, 1, SPR_HEADER_BYTES, out) == SPR_HEADER_BYTES;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
static StLevelT level;
|
||||
static StCelDefT levelCels[ST_LEVEL_CELS_MAX];
|
||||
const StCelDefT *cels = kStCels;
|
||||
uint16_t count = kStCelCount;
|
||||
const char *outPath;
|
||||
FILE *out;
|
||||
uint16_t i;
|
||||
|
||||
if (argc == 4 && strcmp(argv[1], "--level") == 0) {
|
||||
FILE *fp = fopen(argv[2], "rb");
|
||||
if (fp == NULL || !stLevelParse(&level, fp)) {
|
||||
fprintf(stderr, "staxibake: cannot load level %s\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
fclose(fp);
|
||||
cels = levelCels;
|
||||
count = stLevelCelList(&level, levelCels, ST_LEVEL_CELS_MAX);
|
||||
outPath = argv[3];
|
||||
} else if (argc == 2) {
|
||||
outPath = argv[1];
|
||||
} else {
|
||||
fprintf(stderr, "usage: staxibake OUTPUT.spr\n staxibake --level LEVEL.dat OUTPUT.spr\n");
|
||||
return 2;
|
||||
}
|
||||
out = fopen(outPath, "wb");
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "staxibake: cannot write %s\n", outPath);
|
||||
return 1;
|
||||
}
|
||||
if (!writeHeader(out, count)) {
|
||||
fprintf(stderr, "staxibake: header write failed\n");
|
||||
fclose(out);
|
||||
return 1;
|
||||
}
|
||||
for (i = 0u; i < kStCelCount; i++) {
|
||||
for (i = 0u; i < count; i++) {
|
||||
uint8_t blob[ST_CEL_BYTES];
|
||||
const uint8_t *bm = stC64SpriteBitmap((uint8_t)(kStCels[i].ptr - ST_SPRITE_PTR_FIRST));
|
||||
|
||||
stCelBlob(bm, kStCels[i].multi, kStCels[i].color, kStCels[i].mc0, kStCels[i].mc1, blob);
|
||||
const uint8_t *bm;
|
||||
if (cels == levelCels) {
|
||||
bm = levelBitmap(&level, cels[i].ptr);
|
||||
if (bm == NULL) {
|
||||
fprintf(stderr, "staxibake: level %s has no sprite block $%02X\n", argv[2], (unsigned)cels[i].ptr);
|
||||
fclose(out);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
bm = stC64SpriteBitmap((uint8_t)(cels[i].ptr - ST_SPRITE_PTR_FIRST));
|
||||
}
|
||||
stCelBlob(bm, cels[i].multi, cels[i].color, cels[i].mc0, cels[i].mc1, blob);
|
||||
if (fwrite(blob, 1, ST_CEL_BYTES, out) != ST_CEL_BYTES) {
|
||||
fprintf(stderr, "staxibake: cel %u write failed\n", (unsigned)i);
|
||||
fclose(out);
|
||||
|
|
@ -66,6 +119,6 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
fclose(out);
|
||||
fprintf(stderr, "staxibake: wrote %u cels (%ux%u tiles) -> %s\n", (unsigned)kStCelCount, (unsigned)ST_CEL_TILES, (unsigned)ST_CEL_TILES, argv[1]);
|
||||
fprintf(stderr, "staxibake: wrote %u cels (%ux%u tiles) -> %s\n", (unsigned)count, (unsigned)ST_CEL_TILES, (unsigned)ST_CEL_TILES, outPath);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
36
tools/staxiharness/Makefile
Normal file
36
tools/staxiharness/Makefile
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Host-side checks of Space Taxi's front-end screens (the parts tools/stsim
|
||||
# cannot reach: they live in spacetaxi.c, above the simulation). Builds the
|
||||
# game on the BLANK port with spacetaxi.c INCLUDED into the harness so its
|
||||
# statics are reachable, and wraps the keyboard queue and the save file
|
||||
# with scripted stand-ins.
|
||||
#
|
||||
# make -C tools/staxiharness build + run
|
||||
|
||||
REPO := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/../..)
|
||||
ST := $(REPO)/examples/spacetaxi
|
||||
OUT := $(REPO)/build/tools/staxiharness
|
||||
SRCS := $(filter-out $(ST)/spacetaxi.c,$(wildcard $(ST)/*.c)) \
|
||||
$(wildcard $(REPO)/src/core/*.c) $(wildcard $(REPO)/src/generic/*.c) \
|
||||
$(REPO)/src/blank/blank.c
|
||||
CFLAGS := -O0 -g -w -DJOEYLIB_PLATFORM_BLANK -I$(REPO)/include -I$(REPO)/src/core \
|
||||
-I$(REPO)/src/codegen -I$(ST)
|
||||
WRAPS := -Wl,--wrap=jlInputGetChar -Wl,--wrap=jlSaveWrite -Wl,--wrap=jlSaveRead
|
||||
|
||||
.PHONY: all run clean
|
||||
|
||||
all: run
|
||||
|
||||
$(OUT)/harness: harness.c $(ST)/spacetaxi.c $(SRCS)
|
||||
@mkdir -p $(OUT)
|
||||
$(CC) $(CFLAGS) harness.c $(SRCS) $(WRAPS) -o $@
|
||||
|
||||
# The title screen's level file is read through DATA/levels (the DOS bake
|
||||
# is the cross-platform STL4 form), so run from a directory that has one.
|
||||
run: $(OUT)/harness
|
||||
@mkdir -p $(OUT)/DATA
|
||||
@ln -sfn $(ST)/generated/dos/levels $(OUT)/DATA/levels
|
||||
@ln -sfn $(ST)/generated/dos/speech.bin $(OUT)/DATA/speech.bin
|
||||
cd $(OUT) && ./harness
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
183
tools/staxiharness/harness.c
Normal file
183
tools/staxiharness/harness.c
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
// Space Taxi front-end harness: the immortal-cabbies table and the name
|
||||
// entry screen, driven with scripted keys on the host (BLANK port).
|
||||
//
|
||||
// spacetaxi.c is INCLUDED so its static state and routines are visible;
|
||||
// its main() is renamed away. jlInputGetChar, jlSaveWrite and jlSaveRead
|
||||
// are replaced through the linker's --wrap with a key script and an
|
||||
// in-memory save image (see the Makefile).
|
||||
#define main staxiMain
|
||||
#include "spacetaxi.c"
|
||||
#undef main
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define SAVE_IMAGE_MAX 512u
|
||||
|
||||
bool __wrap_jlSaveWrite(const char *name, const void *buf, uint32_t len);
|
||||
uint32_t __wrap_jlSaveRead(const char *name, void *buf, uint32_t max);
|
||||
int __wrap_jlInputGetChar(void);
|
||||
|
||||
static void check(bool ok, const char *what);
|
||||
static void rowText(uint8_t row, uint8_t col, uint8_t n, char *out);
|
||||
static void setScore(uint8_t player, const uint8_t *digits);
|
||||
|
||||
static const char *gKeys = "";
|
||||
static uint8_t gSaveImage[SAVE_IMAGE_MAX];
|
||||
static uint32_t gSaveLen = 0u;
|
||||
static int gFails = 0;
|
||||
|
||||
|
||||
int __wrap_jlInputGetChar(void) {
|
||||
if (*gKeys == 0) {
|
||||
return -1;
|
||||
}
|
||||
return (unsigned char)*gKeys++;
|
||||
}
|
||||
|
||||
|
||||
uint32_t __wrap_jlSaveRead(const char *name, void *buf, uint32_t max) {
|
||||
(void)name;
|
||||
if (gSaveLen == 0u || gSaveLen > max) {
|
||||
return 0u;
|
||||
}
|
||||
memcpy(buf, gSaveImage, gSaveLen);
|
||||
return gSaveLen;
|
||||
}
|
||||
|
||||
|
||||
bool __wrap_jlSaveWrite(const char *name, const void *buf, uint32_t len) {
|
||||
(void)name;
|
||||
if (len > sizeof(gSaveImage)) {
|
||||
return false;
|
||||
}
|
||||
memcpy(gSaveImage, buf, len);
|
||||
gSaveLen = len;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void check(bool ok, const char *what) {
|
||||
printf("%s %s\n", ok ? "ok " : "FAIL", what);
|
||||
if (!ok) {
|
||||
gFails++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// `n` screen cells of one row as a C string.
|
||||
static void rowText(uint8_t row, uint8_t col, uint8_t n, char *out) {
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < n; k++) {
|
||||
out[k] = (char)gSim.screen[ST_CELL(row, col + k)];
|
||||
}
|
||||
out[n] = 0;
|
||||
}
|
||||
|
||||
|
||||
// A player's score as the sim keeps it: seven screen-code digits with
|
||||
// the point at ST_HS_POINT_AT.
|
||||
static void setScore(uint8_t player, const uint8_t *digits) {
|
||||
uint8_t k;
|
||||
|
||||
for (k = 0u; k < ST_NUMBER_CHARS; k++) {
|
||||
gSim.scoreBackup[player][k] = (uint8_t)(ST_CHAR_DIGIT_BASE + digits[k]);
|
||||
}
|
||||
gSim.scoreBackup[player][ST_HS_POINT_AT] = ST_CHAR_POINT;
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
static const uint8_t kDigits[ST_NUMBER_CHARS] = { 1u, 2u, 3u, 4u, 0u, 5u, 6u };
|
||||
jlConfigT config;
|
||||
jlSurfaceT *stage;
|
||||
char buf[48];
|
||||
uint8_t k;
|
||||
|
||||
config.codegenBytes = 160UL * 1024;
|
||||
config.audioBytes = 32UL * 1024;
|
||||
if (!jlInit(&config)) {
|
||||
printf("jlInit failed\n");
|
||||
return 1;
|
||||
}
|
||||
stage = jlStageGet();
|
||||
memset(&gGame, 0, sizeof(gGame));
|
||||
memset(&gSim, 0, sizeof(gSim));
|
||||
stRenderInit(stage);
|
||||
stAudioInit();
|
||||
stSimNewGame(&gSim, 2u, false);
|
||||
|
||||
// ---- ranking ($4D92) ----
|
||||
check(highScoreInsert((const uint8_t *)" 49.99") == ST_HS_ENTRIES, "49.99 is below the $50 floor");
|
||||
check(highScoreInsert((const uint8_t *)" 50.00") == ST_HS_ENTRIES, "50.00 passes the floor but beats nobody");
|
||||
check(highScoreInsert((const uint8_t *)" 500.00") == 8u, "500.00 lands in slot 8 (under 504.97, above 498.77)");
|
||||
check(memcmp(gHighScores[9].score, " 498.77", 7) == 0 && memcmp(gHighScores[7].score, " 504.97", 7) == 0, "older entries shifted down, the last one dropped");
|
||||
check(highScoreInsert((const uint8_t *)"3877.56") == 0u, "a tie goes above the older entry");
|
||||
check(memcmp(gHighScores[1].score, "3877.56", 7) == 0 && memcmp(gHighScores[1].name, "MICHAEL PLATE ", 15) == 0, "the tied old entry is now second");
|
||||
|
||||
// ---- the entry screen for cabbie 2 with $1234.56 on shift 3 ($4D52 / $4E35) ----
|
||||
gSim.player = 1u;
|
||||
gGame.variation = 3u;
|
||||
setScore(1u, kDigits);
|
||||
gKeys = "zz"; // typed before the screen: flushed like $0277
|
||||
check(nameEntryStart(), "1234.56 ranks");
|
||||
check(gGame.state == ST_STATE_NAME_ENTRY && gGame.hsSlot == 3u, "slot 3 (under the two 3877.56 and 1809.51)");
|
||||
check(gSim.borderColor == 2u && gSim.bgColor == 15u, "red border, grey field");
|
||||
rowText(3u, 7u, 25u, buf);
|
||||
check(strcmp(buf, "CONGRATULATIONS CABBIE 2,") == 0, buf);
|
||||
rowText(0u, 15u, 8u, buf);
|
||||
check(strcmp(buf, "$1234.56") == 0, buf);
|
||||
rowText(9u, 9u, 21u, buf);
|
||||
check(strcmp(buf, "ENTER YOUR NAME BELOW") == 0, buf);
|
||||
check(*gKeys == 0, "earlier keystrokes discarded");
|
||||
|
||||
// ---- typing ($4ED8): s c o 9 t t <backspace> T ----
|
||||
gKeys = "sco9tt\bT";
|
||||
runNameEntry(1u);
|
||||
rowText(ST_HS_NAME_ROW, ST_HS_NAME_COL, 5u, buf);
|
||||
check(strcmp(buf, "SCOTT") == 0, buf);
|
||||
check(gGame.hsLen == 5u, "five characters kept ('9' ignored, one deleted, one retyped)");
|
||||
check(gGame.state == ST_STATE_NAME_ENTRY, "still entering");
|
||||
for (k = 0u; k < 2u; k++) {
|
||||
runNameEntry(1u);
|
||||
}
|
||||
check(gSim.screen[ST_CELL(ST_HS_NAME_ROW, ST_HS_NAME_COL + 5u)] == ' ', "first flip blanks the cursor ($4F4D)");
|
||||
for (k = 0u; k < 3u; k++) {
|
||||
runNameEntry(1u);
|
||||
}
|
||||
check(gSim.screen[ST_CELL(ST_HS_NAME_ROW, ST_HS_NAME_COL + 5u)] == '%', "second flip shows it");
|
||||
gKeys = "\r";
|
||||
runNameEntry(1u);
|
||||
check(gGame.state != ST_STATE_NAME_ENTRY, "RETURN leaves the screen");
|
||||
check(memcmp(gHighScores[3].name, "SCOTT ", 15) == 0 && gHighScores[3].shift == 3u, "name and shift stored");
|
||||
check(gSaveLen == 240u && gSaveImage[3 * 24 + 7] == 0 && memcmp(&gSaveImage[3 * 24 + 8], "SCOTT ", 6) == 0 && gSaveImage[3 * 24 + 23] == 3u, "saved in the C64 image layout");
|
||||
check(gSim.playersDone == 1u, "game-over bookkeeping continued");
|
||||
|
||||
// ---- reload from the image ($23E5) ----
|
||||
memset(gHighScores, 0, sizeof(gHighScores));
|
||||
highScoreLoad();
|
||||
check(memcmp(gHighScores[3].name, "SCOTT ", 15) == 0 && memcmp(gHighScores[0].score, "3877.56", 7) == 0, "table restored from the save");
|
||||
|
||||
// ---- an empty name becomes "*" ----
|
||||
gSim.player = 0u;
|
||||
setScore(0u, kDigits);
|
||||
check(nameEntryStart() && gGame.hsSlot == 3u, "second entry, a tie goes above");
|
||||
gKeys = "\r";
|
||||
runNameEntry(1u);
|
||||
check(gHighScores[3].name[0] == '*' && memcmp(gHighScores[4].name, "SCOTT", 5) == 0, "an empty name is stored as *");
|
||||
|
||||
// ---- the table screen ($4C1F) ----
|
||||
highScoreDraw();
|
||||
rowText(1u, 9u, 20u, buf);
|
||||
check(strcmp(buf, "THE IMMORTAL CABBIES") == 0, buf);
|
||||
rowText(12u, 4u, 26u, buf);
|
||||
check(strcmp(buf, "$1234.56 SCOTT ") == 0, buf);
|
||||
check(gSim.screen[ST_CELL(12, 34)] == '3' && gSim.screen[ST_CELL(10, 15)] == '*', "shift digit in the SHIFT column, * name above");
|
||||
rowText(24u, 3u, 34u, buf);
|
||||
check(strcmp(buf, "PRESS FIRE TO RETURN TO TITLE PAGE") == 0, buf);
|
||||
check(jlMusicIsPlaying(), "song 7 under the table");
|
||||
|
||||
printf("%s (%d failures)\n", gFails ? "staxiharness: FAIL" : "staxiharness: PASS", gFails);
|
||||
jlShutdown();
|
||||
return gFails ? 1 : 0;
|
||||
}
|
||||
|
|
@ -2,10 +2,16 @@
|
|||
ST := ../../examples/spacetaxi
|
||||
CC ?= gcc
|
||||
CFLAGS := -O1 -g -Wall -Wextra -std=c99 -I$(ST)
|
||||
SRCS := stsim.c $(ST)/stSim.c $(ST)/stFare.c $(ST)/stHooks.c $(ST)/stLevelFile.c $(ST)/stTitle.c $(ST)/stC64Data.c
|
||||
SRCS := stsim.c $(ST)/stSim.c $(ST)/stFare.c $(ST)/stHooks.c $(ST)/stLevelFile.c $(ST)/stTitle.c $(ST)/stC64Data.c $(ST)/stLevelCels.c
|
||||
|
||||
stsim: $(SRCS) $(ST)/stSim.h $(ST)/stC64Data.h $(ST)/stDemoStreams.h
|
||||
stsim: $(SRCS) $(ST)/stSim.h $(ST)/stC64Data.h $(ST)/stDemoStreams.h gateStreams.h
|
||||
$(CC) $(CFLAGS) $(SRCS) -o $@
|
||||
|
||||
# The fixture generator for gateStreams.h. Not built by default: it runs
|
||||
# a long search and is only needed when a level's stream is (re)made.
|
||||
recorder: recorder.c $(SRCS:stsim.c=) $(ST)/stSim.h
|
||||
$(CC) $(CFLAGS) recorder.c $(ST)/stSim.c $(ST)/stFare.c $(ST)/stHooks.c \
|
||||
$(ST)/stLevelFile.c $(ST)/stTitle.c $(ST)/stC64Data.c -o $@
|
||||
|
||||
clean:
|
||||
rm -f stsim
|
||||
rm -f stsim recorder
|
||||
|
|
|
|||
34
tools/stsim/celGate.sh
Executable file
34
tools/stsim/celGate.sh
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env bash
|
||||
# Cel gate for Space Taxi: every level cel a recorded ride DISPLAYS must be
|
||||
# in the level's baked manifest (stLevelCelList in stLevelCels.c), or the
|
||||
# real ports build it mid-ride and draw it interpreted -- the "compiling
|
||||
# sprites on the fly" hitch. Runs the same rides gate.sh does with the
|
||||
# stsim census (STSIM_CELS=1) and fails on any MISSING line.
|
||||
#
|
||||
# celGate.sh check every hook level
|
||||
set -u
|
||||
|
||||
here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
repo=$(cd "$here/../.." && pwd)
|
||||
levels=$repo/examples/spacetaxi/generated/iigs/levels
|
||||
ticks=4000
|
||||
pairs="H:08 T:20 W:23 X:24 G:07 I:09 K:11 O:15 Q:17 R:18 U:21 V:22 E:05 J:10 L:12 P:16 S:19"
|
||||
|
||||
make -C "$here" >/dev/null || { echo "celGate: build failed" >&2; exit 2; }
|
||||
|
||||
fail=0
|
||||
for p in $pairs; do
|
||||
l=${p%%:*}; n=${p##*:}
|
||||
out=$(STSIM_CELS=1 "$here/stsim" "$levels/level$n.dat" "$l" "$ticks" 2>&1 >/dev/null | grep -E '^(CEL|CENSUS)')
|
||||
missing=$(echo "$out" | grep -c '^CEL MISSING')
|
||||
census=$(echo "$out" | grep '^CENSUS' | sed 's/^CENSUS //')
|
||||
if [ "$missing" -ne 0 ]; then
|
||||
printf ' %s: *** %s cel(s) shown but not baked *** (%s)\n' "$l" "$missing" "$census"
|
||||
echo "$out" | grep '^CEL MISSING' | sed 's/^/ /'
|
||||
fail=1
|
||||
else
|
||||
printf ' %s: ok (%s)\n' "$l" "$census"
|
||||
fi
|
||||
done
|
||||
[ $fail -eq 0 ] && echo "celGate: PASS" || echo "celGate: FAIL"
|
||||
exit $fail
|
||||
75
tools/stsim/gate.sh
Executable file
75
tools/stsim/gate.sh
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env bash
|
||||
# Behaviour gate for the Space Taxi simulation.
|
||||
#
|
||||
# Runs every hook level through stsim and compares the per-tick trace
|
||||
# against a golden capture. A refactor that changes nothing observable
|
||||
# leaves all seventeen traces byte-identical; anything else is a regression.
|
||||
#
|
||||
# H, W, T and X ride the C64's own attract recordings (the ones checked
|
||||
# against VICE traces). The other thirteen ride synthesised fixtures from
|
||||
# gateStreams.h -- a regression gate only, not evidence of C64 fidelity.
|
||||
#
|
||||
# gate.sh capture [dir] record goldens from the CURRENT tree
|
||||
# gate.sh check [dir] compare the current tree against them
|
||||
# gate.sh hashes print one md5 per level (compact reference)
|
||||
#
|
||||
# Capture from a tree you trust, refactor, then check.
|
||||
set -u
|
||||
|
||||
here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
repo=$(cd "$here/../.." && pwd)
|
||||
levels=$repo/examples/spacetaxi/generated/iigs/levels
|
||||
mode=${1:-check}
|
||||
dir=${2:-$here/golden}
|
||||
ticks=4000
|
||||
|
||||
# level letter -> level file number
|
||||
pairs="H:08 T:20 W:23 X:24 G:07 I:09 K:11 O:15 Q:17 R:18 U:21 V:22 E:05 J:10 L:12 P:16 S:19"
|
||||
|
||||
make -C "$here" >/dev/null || { echo "gate: build failed" >&2; exit 2; }
|
||||
|
||||
case "$mode" in
|
||||
capture)
|
||||
mkdir -p "$dir"
|
||||
for p in $pairs; do
|
||||
l=${p%%:*}; n=${p##*:}
|
||||
"$here/stsim" "$levels/level$n.dat" "$l" "$ticks" > "$dir/demo$l.jsonl" 2>/dev/null
|
||||
printf ' %s: %s ticks\n' "$l" "$(wc -l < "$dir/demo$l.jsonl")"
|
||||
done
|
||||
echo "gate: captured to $dir"
|
||||
;;
|
||||
check)
|
||||
fail=0
|
||||
for p in $pairs; do
|
||||
l=${p%%:*}; n=${p##*:}
|
||||
got=$(mktemp)
|
||||
"$here/stsim" "$levels/level$n.dat" "$l" "$ticks" > "$got" 2>/dev/null
|
||||
if [ ! -f "$dir/demo$l.jsonl" ]; then
|
||||
echo " $l: no golden (run: gate.sh capture)"
|
||||
elif cmp -s "$dir/demo$l.jsonl" "$got"; then
|
||||
printf ' %s: IDENTICAL (%s ticks)\n' "$l" "$(wc -l < "$got")"
|
||||
else
|
||||
echo " $l: *** DIFFERS ***"
|
||||
diff "$dir/demo$l.jsonl" "$got" | head -3
|
||||
fail=1
|
||||
fi
|
||||
rm -f "$got"
|
||||
done
|
||||
[ $fail -eq 0 ] && echo "gate: PASS" || echo "gate: FAIL"
|
||||
# The cel census rides the same recordings: a cel a ride displays that
|
||||
# its manifest does not bake is a mid-ride interpreted sprite.
|
||||
"$here/celGate.sh" || fail=1
|
||||
exit $fail
|
||||
;;
|
||||
hashes)
|
||||
for p in $pairs; do
|
||||
l=${p%%:*}; n=${p##*:}
|
||||
h=$("$here/stsim" "$levels/level$n.dat" "$l" "$ticks" 2>/dev/null | md5sum | cut -d' ' -f1)
|
||||
printf '%s %s\n' "$l" "$h"
|
||||
done
|
||||
;;
|
||||
*)
|
||||
sed -n '2,20p' "$0"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
21
tools/stsim/gateHashes.txt
Normal file
21
tools/stsim/gateHashes.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Space Taxi behaviour gate -- md5 of each level's 4000-tick trace.
|
||||
# Regenerate with: tools/stsim/gate.sh hashes
|
||||
# H/W/T/X ride the C64's attract recordings; the rest ride
|
||||
# synthesised fixtures from gateStreams.h (regression gate only).
|
||||
H 760501b0e48f3922bfb0f23fd2831935
|
||||
T c0b3f9e9a74e0d526703cf9b1875557b
|
||||
W 92226455989e8326577a6ea20df8c8ea
|
||||
X 87251d616a1be6e0c9c9317987b0fe20
|
||||
G 73530651372c60042f1f46b5c0cbada0
|
||||
I 7fe4415429d2b72a50884424269cb685
|
||||
K 567be2ed37219356a055866459971345
|
||||
O 02455280933e915e57803a4059aaefd9
|
||||
Q a7732866d54ed06d52e5dc7406b5b229
|
||||
R 066a9be80107446893b4571d247ee5cc
|
||||
U 02dd2f26245442ab016ef02e10fde611
|
||||
V cc2cb13c5e393d07fbece9c0c465e387
|
||||
E 21ff29d69d8318bcb2e870b9602e910e
|
||||
J 4c22a7515949b1701ed4fedabb7823dd
|
||||
L a0383cbde2800bb09353df15214934ef
|
||||
P f345d0adc9e011662d582c4277ee663e
|
||||
S daa3cd12320e32d3e9b6b97b19b0a6d0
|
||||
460
tools/stsim/gateStreams.h
Normal file
460
tools/stsim/gateStreams.h
Normal file
|
|
@ -0,0 +1,460 @@
|
|||
// Synthesised demo input streams -- a TEST FIXTURE, not game content.
|
||||
//
|
||||
// The C64 ships attract recordings for four screens only (H, W, T and X);
|
||||
// those live in examples/spacetaxi/stDemoStreams.h and are the streams
|
||||
// checked against VICE traces. The thirteen streams below were searched for
|
||||
// by tools/stsim's recorder against this port's own simulation, scored on
|
||||
// how long the cab survives and how much of the level's hook state, fare
|
||||
// machine and screen animation the ride reaches.
|
||||
//
|
||||
// So they prove one thing and not another: they are a REGRESSION gate --
|
||||
// refactor the hooks and the tick-by-tick trace must not move -- but they
|
||||
// are NOT evidence that a hook matches the original, because no C64 trace
|
||||
// exists for these screens. Treat a change to these bytes as invalidating
|
||||
// the goldens, and never put them in the attract rotation.
|
||||
|
||||
#ifndef ST_GATE_STREAMS_H
|
||||
#define ST_GATE_STREAMS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// level G -- 1400 ticks, 5 hook bytes, 10 fare stages, 256 pictures, 13 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat G 20260921
|
||||
static const uint8_t kGateStreamG[320] = {
|
||||
0x88, 0x05, 0x81, 0x09, 0x81, 0x05, 0x81, 0x04, 0x81, 0x06, 0x84, 0x0C,
|
||||
0x81, 0x01, 0x89, 0x02, 0x81, 0x09, 0x82, 0x0D, 0x88, 0x05, 0x81, 0x03,
|
||||
0x80, 0x09, 0x81, 0x01, 0x90, 0x02, 0x81, 0x04, 0x90, 0x08, 0x81, 0x03,
|
||||
0x90, 0x0A, 0x88, 0x0E, 0x88, 0x0C, 0x90, 0x0C, 0x81, 0x04, 0x81, 0x0D,
|
||||
0x90, 0x0A, 0x81, 0x0D, 0x84, 0x0E, 0x81, 0x09, 0x81, 0x08, 0x81, 0x0C,
|
||||
0x82, 0x04, 0x81, 0x02, 0x81, 0x0E, 0x81, 0x02, 0x84, 0x01, 0x88, 0x0A,
|
||||
0x88, 0x05, 0x90, 0x09, 0x81, 0x02, 0x84, 0x09, 0x84, 0x05, 0x81, 0x0D,
|
||||
0x84, 0x09, 0x88, 0x03, 0x84, 0x06, 0x84, 0x0D, 0x81, 0x05, 0x84, 0x0C,
|
||||
0x88, 0x0C, 0x88, 0x0C, 0x88, 0x03, 0x88, 0x09, 0x81, 0x0A, 0x81, 0x09,
|
||||
0x81, 0x06, 0x81, 0x07, 0x81, 0x05, 0x88, 0x09, 0x88, 0x02, 0x81, 0x0B,
|
||||
0x84, 0x0A, 0x84, 0x05, 0x88, 0x03, 0x81, 0x05, 0x81, 0x0B, 0x81, 0x05,
|
||||
0x90, 0x05, 0x84, 0x09, 0x81, 0x06, 0x81, 0x07, 0x90, 0x0D, 0x81, 0x04,
|
||||
0x81, 0x0E, 0x88, 0x0D, 0x88, 0x0D, 0x88, 0x06, 0x82, 0x02, 0x88, 0x0D,
|
||||
0x90, 0x0E, 0x81, 0x04, 0x81, 0x0B, 0x84, 0x0B, 0x81, 0x05, 0x84, 0x07,
|
||||
0x88, 0x0A, 0x80, 0x04, 0x84, 0x07, 0x84, 0x0B, 0x88, 0x0D, 0x90, 0x0E,
|
||||
0x90, 0x06, 0x88, 0x08, 0x82, 0x0C, 0x81, 0x02, 0x81, 0x0E, 0x88, 0x0A,
|
||||
0x90, 0x0B, 0x81, 0x04, 0x88, 0x08, 0x90, 0x07, 0x84, 0x03, 0x82, 0x08,
|
||||
0x81, 0x05, 0x81, 0x03, 0x81, 0x03, 0x81, 0x06, 0x90, 0x0B, 0x84, 0x0E,
|
||||
0x82, 0x0E, 0x88, 0x08, 0x88, 0x04, 0x81, 0x0D, 0x88, 0x04, 0x81, 0x08,
|
||||
0x88, 0x0C, 0x81, 0x06, 0x81, 0x04, 0x90, 0x0B, 0x81, 0x08, 0x84, 0x04,
|
||||
0x90, 0x08, 0x84, 0x09, 0x88, 0x09, 0x81, 0x0B, 0x81, 0x07, 0x84, 0x0D,
|
||||
0x88, 0x0A, 0x88, 0x09, 0x90, 0x0B, 0x90, 0x02, 0x84, 0x0D, 0x81, 0x0E,
|
||||
0x90, 0x0D, 0x84, 0x07, 0x82, 0x0C, 0x81, 0x0E, 0x81, 0x06, 0x88, 0x09,
|
||||
0x90, 0x02, 0x90, 0x04, 0x81, 0x09, 0x84, 0x0A, 0x90, 0x06, 0x81, 0x04,
|
||||
0x90, 0x03, 0x90, 0x08, 0x84, 0x0B, 0x81, 0x02, 0x90, 0x04, 0x84, 0x03,
|
||||
0x81, 0x03, 0x84, 0x05, 0x90, 0x0C, 0x81, 0x01, 0x90, 0x0D, 0x81, 0x02,
|
||||
0x90, 0x05, 0x90, 0x0E, 0x81, 0x03, 0x90, 0x0A,
|
||||
};
|
||||
|
||||
// level I -- 1400 ticks, 20 hook bytes, 10 fare stages, 256 pictures, 22 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat I 20260918
|
||||
static const uint8_t kGateStreamI[320] = {
|
||||
0x84, 0x0E, 0x81, 0x06, 0x84, 0x0E, 0x88, 0x0B, 0x88, 0x05, 0x81, 0x03,
|
||||
0x82, 0x07, 0x90, 0x0A, 0x81, 0x08, 0x88, 0x0E, 0x88, 0x0E, 0x90, 0x0B,
|
||||
0x82, 0x0D, 0x81, 0x01, 0x81, 0x0A, 0x90, 0x0A, 0x82, 0x03, 0x81, 0x07,
|
||||
0x82, 0x05, 0x81, 0x0B, 0x81, 0x05, 0x82, 0x05, 0x82, 0x0C, 0x81, 0x08,
|
||||
0x88, 0x0C, 0x90, 0x04, 0x81, 0x02, 0x88, 0x08, 0x81, 0x03, 0x81, 0x05,
|
||||
0x81, 0x0A, 0x88, 0x0E, 0x81, 0x06, 0x84, 0x0E, 0x82, 0x07, 0x82, 0x01,
|
||||
0x81, 0x04, 0x82, 0x08, 0x90, 0x0C, 0x90, 0x05, 0x81, 0x08, 0x82, 0x0D,
|
||||
0x90, 0x06, 0x81, 0x0A, 0x84, 0x0B, 0x84, 0x0C, 0x84, 0x0C, 0x88, 0x09,
|
||||
0x81, 0x06, 0x81, 0x0C, 0x81, 0x04, 0x82, 0x09, 0x88, 0x05, 0x82, 0x0E,
|
||||
0x81, 0x0C, 0x81, 0x07, 0x88, 0x01, 0x90, 0x0E, 0x81, 0x02, 0x90, 0x0E,
|
||||
0x81, 0x02, 0x90, 0x07, 0x84, 0x05, 0x84, 0x06, 0x88, 0x06, 0x88, 0x0C,
|
||||
0x81, 0x0C, 0x84, 0x0B, 0x82, 0x09, 0x81, 0x05, 0x81, 0x0B, 0x82, 0x09,
|
||||
0x90, 0x0E, 0x90, 0x06, 0x88, 0x0D, 0x84, 0x03, 0x82, 0x0B, 0x84, 0x0D,
|
||||
0x90, 0x0B, 0x90, 0x04, 0x81, 0x0B, 0x81, 0x08, 0x88, 0x08, 0x90, 0x0A,
|
||||
0x81, 0x03, 0x81, 0x01, 0x81, 0x0E, 0x81, 0x04, 0x88, 0x02, 0x90, 0x05,
|
||||
0x81, 0x07, 0x81, 0x01, 0x82, 0x09, 0x90, 0x06, 0x81, 0x09, 0x90, 0x0E,
|
||||
0x88, 0x05, 0x82, 0x0D, 0x88, 0x03, 0x81, 0x06, 0x84, 0x0C, 0x82, 0x01,
|
||||
0x81, 0x09, 0x82, 0x0E, 0x90, 0x01, 0x81, 0x01, 0x84, 0x05, 0x82, 0x06,
|
||||
0x88, 0x0A, 0x81, 0x05, 0x82, 0x03, 0x90, 0x07, 0x90, 0x08, 0x81, 0x02,
|
||||
0x90, 0x0D, 0x88, 0x0D, 0x81, 0x08, 0x90, 0x0E, 0x82, 0x0D, 0x88, 0x04,
|
||||
0x81, 0x0C, 0x82, 0x09, 0x90, 0x04, 0x81, 0x0C, 0x82, 0x06, 0x90, 0x0E,
|
||||
0x90, 0x0D, 0x90, 0x07, 0x90, 0x03, 0x82, 0x03, 0x88, 0x06, 0x81, 0x07,
|
||||
0x90, 0x08, 0x81, 0x02, 0x90, 0x09, 0x81, 0x04, 0x90, 0x06, 0x82, 0x0A,
|
||||
0x90, 0x05, 0x88, 0x05, 0x88, 0x06, 0x90, 0x0B, 0x81, 0x03, 0x82, 0x02,
|
||||
0x90, 0x0B, 0x81, 0x02, 0x90, 0x0C, 0x90, 0x07, 0x81, 0x01, 0x84, 0x08,
|
||||
0x90, 0x0C, 0x81, 0x0E, 0x88, 0x08, 0x88, 0x0C, 0x81, 0x0C, 0x90, 0x04,
|
||||
0x84, 0x0D, 0x81, 0x01, 0x88, 0x08, 0x88, 0x09,
|
||||
};
|
||||
|
||||
// level K -- 1400 ticks, 1 hook bytes, 10 fare stages, 256 pictures, 16 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat K 11
|
||||
static const uint8_t kGateStreamK[320] = {
|
||||
0x84, 0x06, 0x82, 0x0B, 0x90, 0x0C, 0x82, 0x0E, 0x90, 0x05, 0x88, 0x03,
|
||||
0x88, 0x02, 0x82, 0x0E, 0x88, 0x07, 0x84, 0x02, 0x84, 0x0B, 0x84, 0x08,
|
||||
0x90, 0x0A, 0x88, 0x07, 0x84, 0x07, 0x81, 0x03, 0x84, 0x08, 0x82, 0x0E,
|
||||
0x82, 0x0D, 0x84, 0x01, 0x81, 0x09, 0x81, 0x0E, 0x81, 0x0C, 0x81, 0x0B,
|
||||
0x82, 0x0C, 0x82, 0x06, 0x81, 0x01, 0x84, 0x01, 0x90, 0x06, 0x82, 0x0D,
|
||||
0x84, 0x0B, 0x82, 0x09, 0x88, 0x09, 0x88, 0x05, 0x82, 0x02, 0x84, 0x04,
|
||||
0x84, 0x09, 0x88, 0x08, 0x90, 0x09, 0x82, 0x08, 0x81, 0x01, 0x88, 0x01,
|
||||
0x81, 0x06, 0x90, 0x04, 0x82, 0x0A, 0x82, 0x09, 0x82, 0x09, 0x84, 0x0C,
|
||||
0x82, 0x07, 0x90, 0x0E, 0x90, 0x0E, 0x90, 0x07, 0x82, 0x0D, 0x90, 0x02,
|
||||
0x84, 0x04, 0x84, 0x09, 0x88, 0x05, 0x88, 0x03, 0x81, 0x05, 0x82, 0x0E,
|
||||
0x90, 0x04, 0x90, 0x08, 0x88, 0x0C, 0x90, 0x08, 0x81, 0x05, 0x82, 0x0B,
|
||||
0x90, 0x0B, 0x84, 0x05, 0x82, 0x0D, 0x82, 0x08, 0x84, 0x0D, 0x81, 0x01,
|
||||
0x90, 0x08, 0x82, 0x0C, 0x81, 0x09, 0x82, 0x05, 0x84, 0x01, 0x82, 0x0A,
|
||||
0x82, 0x0E, 0x88, 0x0A, 0x84, 0x04, 0x90, 0x01, 0x90, 0x0D, 0x82, 0x08,
|
||||
0x90, 0x0B, 0x84, 0x03, 0x81, 0x01, 0x90, 0x0D, 0x82, 0x0C, 0x82, 0x05,
|
||||
0x81, 0x02, 0x81, 0x06, 0x84, 0x08, 0x81, 0x01, 0x82, 0x06, 0x88, 0x0E,
|
||||
0x88, 0x02, 0x82, 0x0A, 0x90, 0x0E, 0x82, 0x0B, 0x81, 0x0E, 0x81, 0x0A,
|
||||
0x82, 0x08, 0x90, 0x01, 0x81, 0x04, 0x81, 0x0D, 0x90, 0x0C, 0x88, 0x0D,
|
||||
0x88, 0x07, 0x81, 0x05, 0x90, 0x02, 0x82, 0x07, 0x88, 0x02, 0x84, 0x0E,
|
||||
0x82, 0x0D, 0x90, 0x02, 0x88, 0x04, 0x90, 0x0D, 0x82, 0x0A, 0x82, 0x0D,
|
||||
0x88, 0x09, 0x81, 0x04, 0x84, 0x08, 0x90, 0x0B, 0x81, 0x01, 0x90, 0x0C,
|
||||
0x82, 0x0E, 0x84, 0x04, 0x82, 0x06, 0x90, 0x09, 0x84, 0x03, 0x90, 0x01,
|
||||
0x82, 0x0C, 0x81, 0x03, 0x82, 0x05, 0x90, 0x0E, 0x82, 0x0E, 0x84, 0x07,
|
||||
0x90, 0x06, 0x81, 0x02, 0x90, 0x03, 0x82, 0x09, 0x82, 0x0A, 0x81, 0x05,
|
||||
0x82, 0x0D, 0x84, 0x01, 0x90, 0x0A, 0x82, 0x09, 0x81, 0x04, 0x82, 0x02,
|
||||
0x82, 0x08, 0x90, 0x06, 0x90, 0x03, 0x84, 0x09, 0x82, 0x01, 0x82, 0x08,
|
||||
0x82, 0x09, 0x90, 0x01, 0x88, 0x07, 0x88, 0x08,
|
||||
};
|
||||
|
||||
// level O -- 1400 ticks, 1 hook bytes, 3 fare stages, 256 pictures, 0 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat O 20260918
|
||||
static const uint8_t kGateStreamO[320] = {
|
||||
0x84, 0x0E, 0x90, 0x08, 0x82, 0x07, 0x81, 0x0B, 0x84, 0x02, 0x81, 0x09,
|
||||
0x82, 0x06, 0x90, 0x0C, 0x81, 0x08, 0x88, 0x01, 0x88, 0x02, 0x90, 0x04,
|
||||
0x88, 0x06, 0x81, 0x04, 0x82, 0x0A, 0x81, 0x06, 0x81, 0x0E, 0x82, 0x08,
|
||||
0x88, 0x06, 0x82, 0x03, 0x81, 0x06, 0x81, 0x02, 0x88, 0x0D, 0x82, 0x04,
|
||||
0x84, 0x0B, 0x84, 0x03, 0x81, 0x04, 0x84, 0x06, 0x81, 0x04, 0x81, 0x02,
|
||||
0x84, 0x07, 0x82, 0x06, 0x81, 0x06, 0x90, 0x05, 0x88, 0x09, 0x81, 0x0A,
|
||||
0x81, 0x0C, 0x81, 0x02, 0x82, 0x09, 0x82, 0x0D, 0x81, 0x04, 0x81, 0x0B,
|
||||
0x84, 0x03, 0x88, 0x0A, 0x90, 0x0A, 0x81, 0x08, 0x82, 0x08, 0x81, 0x06,
|
||||
0x81, 0x03, 0x82, 0x0A, 0x81, 0x0C, 0x82, 0x08, 0x81, 0x0C, 0x82, 0x0E,
|
||||
0x81, 0x06, 0x81, 0x04, 0x81, 0x0A, 0x84, 0x05, 0x90, 0x0E, 0x84, 0x06,
|
||||
0x82, 0x0B, 0x81, 0x0E, 0x81, 0x03, 0x81, 0x05, 0x90, 0x08, 0x81, 0x01,
|
||||
0x90, 0x0E, 0x84, 0x0D, 0x88, 0x01, 0x90, 0x05, 0x84, 0x0B, 0x81, 0x04,
|
||||
0x81, 0x04, 0x82, 0x01, 0x90, 0x04, 0x82, 0x0D, 0x88, 0x07, 0x81, 0x0B,
|
||||
0x81, 0x07, 0x82, 0x01, 0x88, 0x0A, 0x81, 0x06, 0x90, 0x02, 0x82, 0x08,
|
||||
0x81, 0x01, 0x81, 0x0A, 0x88, 0x0E, 0x88, 0x0D, 0x81, 0x03, 0x88, 0x0D,
|
||||
0x81, 0x02, 0x88, 0x04, 0x84, 0x0E, 0x90, 0x01, 0x82, 0x0C, 0x81, 0x0B,
|
||||
0x81, 0x04, 0x88, 0x03, 0x81, 0x03, 0x88, 0x09, 0x84, 0x0E, 0x81, 0x02,
|
||||
0x81, 0x02, 0x81, 0x08, 0x84, 0x07, 0x84, 0x02, 0x88, 0x0C, 0x84, 0x08,
|
||||
0x90, 0x09, 0x90, 0x0D, 0x81, 0x02, 0x88, 0x0D, 0x84, 0x0C, 0x84, 0x0D,
|
||||
0x84, 0x01, 0x81, 0x07, 0x81, 0x0A, 0x81, 0x01, 0x84, 0x01, 0x84, 0x0D,
|
||||
0x82, 0x0E, 0x81, 0x02, 0x81, 0x06, 0x81, 0x09, 0x88, 0x0D, 0x88, 0x09,
|
||||
0x82, 0x0B, 0x81, 0x0B, 0x88, 0x02, 0x88, 0x0C, 0x81, 0x04, 0x84, 0x0B,
|
||||
0x81, 0x06, 0x88, 0x09, 0x84, 0x0C, 0x81, 0x03, 0x84, 0x0D, 0x84, 0x0D,
|
||||
0x88, 0x0E, 0x84, 0x04, 0x90, 0x0E, 0x81, 0x02, 0x88, 0x01, 0x88, 0x06,
|
||||
0x81, 0x0E, 0x82, 0x08, 0x81, 0x0D, 0x90, 0x0D, 0x88, 0x0E, 0x81, 0x03,
|
||||
0x8A, 0x09, 0x90, 0x0B, 0x84, 0x07, 0x88, 0x03, 0x81, 0x0C, 0x82, 0x07,
|
||||
0x81, 0x0E, 0x81, 0x08, 0x90, 0x0D, 0x84, 0x0D,
|
||||
};
|
||||
|
||||
// level Q -- 1400 ticks, 5 hook bytes, 10 fare stages, 256 pictures, 10 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat Q 20260918
|
||||
static const uint8_t kGateStreamQ[320] = {
|
||||
0x84, 0x0E, 0x81, 0x04, 0x81, 0x03, 0x84, 0x09, 0x88, 0x0A, 0x81, 0x09,
|
||||
0x82, 0x06, 0x88, 0x0C, 0x81, 0x08, 0x82, 0x06, 0x88, 0x0E, 0x84, 0x0B,
|
||||
0x88, 0x08, 0x81, 0x09, 0x81, 0x0A, 0x84, 0x05, 0x84, 0x01, 0x88, 0x01,
|
||||
0x81, 0x08, 0x84, 0x0B, 0x81, 0x05, 0x82, 0x05, 0x80, 0x0D, 0x81, 0x08,
|
||||
0x88, 0x0A, 0x88, 0x04, 0x84, 0x08, 0x81, 0x06, 0x81, 0x0C, 0x81, 0x01,
|
||||
0x90, 0x0A, 0x84, 0x08, 0x81, 0x0A, 0x81, 0x0A, 0x82, 0x08, 0x81, 0x06,
|
||||
0x81, 0x09, 0x90, 0x06, 0x81, 0x09, 0x90, 0x0D, 0x88, 0x04, 0x82, 0x05,
|
||||
0x81, 0x0B, 0x84, 0x08, 0x81, 0x08, 0x81, 0x03, 0x82, 0x0D, 0x82, 0x0A,
|
||||
0x84, 0x0E, 0x81, 0x05, 0x81, 0x0E, 0x81, 0x08, 0x84, 0x0A, 0x82, 0x0C,
|
||||
0x84, 0x09, 0x84, 0x01, 0x82, 0x06, 0x88, 0x0E, 0x81, 0x09, 0x90, 0x07,
|
||||
0x81, 0x09, 0x81, 0x07, 0x84, 0x03, 0x81, 0x0B, 0x84, 0x01, 0x90, 0x08,
|
||||
0x90, 0x06, 0x82, 0x03, 0x88, 0x06, 0x88, 0x0C, 0x84, 0x0A, 0x81, 0x03,
|
||||
0x82, 0x0E, 0x81, 0x07, 0x81, 0x04, 0x81, 0x0D, 0x84, 0x02, 0x81, 0x09,
|
||||
0x82, 0x08, 0x88, 0x04, 0x81, 0x09, 0x84, 0x0C, 0x81, 0x0B, 0x84, 0x0D,
|
||||
0x81, 0x02, 0x82, 0x03, 0x81, 0x05, 0x88, 0x0E, 0x84, 0x0D, 0x81, 0x0B,
|
||||
0x88, 0x08, 0x84, 0x0C, 0x90, 0x07, 0x82, 0x0B, 0x81, 0x03, 0x90, 0x05,
|
||||
0x84, 0x05, 0x84, 0x09, 0x81, 0x04, 0x81, 0x0B, 0x81, 0x08, 0x82, 0x0E,
|
||||
0x81, 0x0A, 0x81, 0x03, 0x81, 0x06, 0x88, 0x09, 0x84, 0x0A, 0x88, 0x0B,
|
||||
0x81, 0x05, 0x81, 0x0D, 0x88, 0x03, 0x88, 0x0D, 0x81, 0x01, 0x90, 0x06,
|
||||
0x88, 0x07, 0x82, 0x02, 0x81, 0x04, 0x84, 0x09, 0x81, 0x07, 0x90, 0x06,
|
||||
0x82, 0x03, 0x84, 0x07, 0x81, 0x05, 0x90, 0x0B, 0x81, 0x0B, 0x88, 0x05,
|
||||
0x81, 0x0D, 0x81, 0x0B, 0x92, 0x0E, 0x90, 0x05, 0x82, 0x02, 0x88, 0x0C,
|
||||
0x84, 0x08, 0x81, 0x0A, 0x81, 0x0D, 0x81, 0x05, 0x81, 0x07, 0x81, 0x01,
|
||||
0x81, 0x04, 0x88, 0x01, 0x81, 0x0E, 0x84, 0x04, 0x90, 0x03, 0x81, 0x0D,
|
||||
0x90, 0x09, 0x81, 0x02, 0x81, 0x08, 0x90, 0x07, 0x82, 0x0B, 0x90, 0x08,
|
||||
0x81, 0x03, 0x90, 0x0C, 0x81, 0x0B, 0x88, 0x08, 0x90, 0x04, 0x81, 0x02,
|
||||
0x90, 0x0C, 0x88, 0x05, 0x81, 0x01, 0x90, 0x03,
|
||||
};
|
||||
|
||||
// level R -- 1400 ticks, 0 hook bytes, 3 fare stages, 256 pictures, 0 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat R 20260918
|
||||
static const uint8_t kGateStreamR[320] = {
|
||||
0x90, 0x0E, 0x81, 0x02, 0x82, 0x07, 0x81, 0x05, 0x88, 0x0B, 0x88, 0x09,
|
||||
0x90, 0x0D, 0x90, 0x06, 0x81, 0x08, 0x81, 0x01, 0x90, 0x02, 0x88, 0x04,
|
||||
0x82, 0x07, 0x90, 0x06, 0x88, 0x07, 0x81, 0x06, 0x81, 0x06, 0x82, 0x05,
|
||||
0x84, 0x07, 0x82, 0x05, 0x81, 0x03, 0x84, 0x0E, 0x88, 0x05, 0x88, 0x09,
|
||||
0x88, 0x04, 0x81, 0x09, 0x81, 0x02, 0x82, 0x04, 0x84, 0x0B, 0x81, 0x04,
|
||||
0x82, 0x0C, 0x81, 0x03, 0x88, 0x06, 0x84, 0x08, 0x81, 0x0D, 0x88, 0x09,
|
||||
0x90, 0x0E, 0x82, 0x07, 0x82, 0x02, 0x84, 0x0D, 0x88, 0x0B, 0x81, 0x0B,
|
||||
0x81, 0x03, 0x82, 0x02, 0x90, 0x0B, 0x84, 0x03, 0x88, 0x02, 0x88, 0x09,
|
||||
0x81, 0x02, 0x82, 0x0A, 0x81, 0x06, 0x81, 0x02, 0x90, 0x0A, 0x82, 0x0E,
|
||||
0x81, 0x09, 0x88, 0x03, 0x81, 0x07, 0x84, 0x0D, 0x84, 0x0A, 0x81, 0x03,
|
||||
0x82, 0x07, 0x84, 0x0D, 0x81, 0x03, 0x81, 0x08, 0x84, 0x0E, 0x81, 0x02,
|
||||
0x82, 0x0E, 0x88, 0x03, 0x81, 0x01, 0x81, 0x05, 0x81, 0x06, 0x90, 0x0A,
|
||||
0x84, 0x0A, 0x81, 0x02, 0x82, 0x05, 0x81, 0x03, 0x88, 0x07, 0x84, 0x0C,
|
||||
0x81, 0x04, 0x88, 0x09, 0x90, 0x0E, 0x82, 0x0A, 0x88, 0x09, 0x82, 0x01,
|
||||
0x81, 0x06, 0x81, 0x0D, 0x84, 0x0A, 0x82, 0x0D, 0x88, 0x0A, 0x84, 0x0A,
|
||||
0x90, 0x02, 0x84, 0x02, 0x81, 0x09, 0x82, 0x0A, 0x81, 0x0B, 0x81, 0x0D,
|
||||
0x82, 0x05, 0x84, 0x09, 0x84, 0x04, 0x88, 0x06, 0x84, 0x04, 0x88, 0x0D,
|
||||
0x81, 0x02, 0x82, 0x0B, 0x81, 0x0E, 0x82, 0x0D, 0x82, 0x0A, 0x81, 0x02,
|
||||
0x81, 0x09, 0x81, 0x0D, 0x84, 0x04, 0x82, 0x09, 0x88, 0x04, 0x81, 0x07,
|
||||
0x90, 0x0A, 0x90, 0x0B, 0x81, 0x07, 0x84, 0x0D, 0x82, 0x0A, 0x81, 0x0C,
|
||||
0x88, 0x07, 0x84, 0x09, 0x82, 0x08, 0x90, 0x0A, 0x84, 0x06, 0x82, 0x0D,
|
||||
0x88, 0x05, 0x81, 0x06, 0x81, 0x05, 0x90, 0x0D, 0x90, 0x0B, 0x81, 0x0C,
|
||||
0x81, 0x04, 0x84, 0x06, 0x90, 0x08, 0x90, 0x08, 0x90, 0x08, 0x84, 0x0E,
|
||||
0x88, 0x0E, 0x81, 0x0E, 0x82, 0x0A, 0x90, 0x04, 0x81, 0x06, 0x82, 0x09,
|
||||
0x84, 0x08, 0x90, 0x07, 0x84, 0x0C, 0x90, 0x05, 0x88, 0x0C, 0x84, 0x06,
|
||||
0x84, 0x0A, 0x81, 0x08, 0x81, 0x01, 0x81, 0x01, 0x82, 0x08, 0x88, 0x0A,
|
||||
0x90, 0x0A, 0x90, 0x01, 0x84, 0x0A, 0x81, 0x0B,
|
||||
};
|
||||
|
||||
// level U -- 896 ticks, 21 hook bytes, 3 fare stages, 256 pictures, 0 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat U 44
|
||||
static const uint8_t kGateStreamU[320] = {
|
||||
0x90, 0x01, 0x90, 0x0B, 0x88, 0x08, 0x90, 0x07, 0x88, 0x0D, 0x82, 0x0A,
|
||||
0x82, 0x06, 0x88, 0x0C, 0x90, 0x03, 0x81, 0x04, 0x84, 0x0B, 0x81, 0x0C,
|
||||
0x88, 0x02, 0x84, 0x08, 0x84, 0x01, 0x81, 0x04, 0x90, 0x05, 0x84, 0x06,
|
||||
0x84, 0x08, 0x84, 0x05, 0x81, 0x03, 0x81, 0x09, 0x81, 0x08, 0x88, 0x07,
|
||||
0x81, 0x08, 0x84, 0x06, 0x81, 0x0B, 0x88, 0x0D, 0x90, 0x08, 0x81, 0x01,
|
||||
0x82, 0x01, 0x88, 0x03, 0x81, 0x0E, 0x82, 0x01, 0x81, 0x0D, 0x81, 0x07,
|
||||
0x88, 0x05, 0x88, 0x07, 0x88, 0x0E, 0x84, 0x07, 0x81, 0x03, 0x81, 0x01,
|
||||
0x84, 0x03, 0x81, 0x04, 0x81, 0x08, 0x90, 0x06, 0x81, 0x0C, 0x82, 0x05,
|
||||
0x81, 0x08, 0x82, 0x09, 0x84, 0x06, 0x81, 0x06, 0x90, 0x0C, 0x84, 0x0E,
|
||||
0x82, 0x0C, 0x81, 0x03, 0x81, 0x06, 0x84, 0x0D, 0x88, 0x03, 0x84, 0x0C,
|
||||
0x81, 0x02, 0x81, 0x09, 0x81, 0x0E, 0x88, 0x01, 0x90, 0x06, 0x88, 0x08,
|
||||
0x81, 0x08, 0x81, 0x0C, 0x81, 0x0C, 0x82, 0x06, 0x82, 0x08, 0x88, 0x01,
|
||||
0x81, 0x07, 0x88, 0x0D, 0x84, 0x03, 0x81, 0x02, 0x82, 0x06, 0x81, 0x05,
|
||||
0x81, 0x0E, 0x81, 0x04, 0x90, 0x01, 0x81, 0x02, 0x90, 0x03, 0x81, 0x0A,
|
||||
0x81, 0x04, 0x84, 0x02, 0x81, 0x06, 0x81, 0x0E, 0x81, 0x06, 0x84, 0x07,
|
||||
0x84, 0x04, 0x81, 0x07, 0x81, 0x0E, 0x81, 0x0D, 0x90, 0x0D, 0x90, 0x05,
|
||||
0x88, 0x0C, 0x88, 0x02, 0x81, 0x0B, 0x90, 0x07, 0x88, 0x06, 0x82, 0x0D,
|
||||
0x84, 0x08, 0x84, 0x08, 0x81, 0x01, 0x81, 0x06, 0x82, 0x05, 0x84, 0x06,
|
||||
0x81, 0x06, 0x84, 0x0D, 0x81, 0x04, 0x90, 0x07, 0x88, 0x0D, 0x81, 0x09,
|
||||
0x88, 0x0D, 0x81, 0x0E, 0x81, 0x03, 0x84, 0x0E, 0x81, 0x03, 0x81, 0x0C,
|
||||
0x84, 0x0A, 0x81, 0x06, 0x90, 0x02, 0x81, 0x01, 0x88, 0x02, 0x90, 0x02,
|
||||
0x81, 0x08, 0x84, 0x01, 0x88, 0x0B, 0x88, 0x0B, 0x81, 0x04, 0x81, 0x0C,
|
||||
0x81, 0x07, 0x82, 0x06, 0x88, 0x0C, 0x81, 0x03, 0x90, 0x02, 0x88, 0x0A,
|
||||
0x84, 0x08, 0x81, 0x0E, 0x81, 0x05, 0x88, 0x0C, 0x81, 0x0D, 0x81, 0x05,
|
||||
0x81, 0x04, 0x90, 0x0D, 0x88, 0x03, 0x88, 0x06, 0x81, 0x0B, 0x81, 0x0D,
|
||||
0x84, 0x0D, 0x81, 0x01, 0x81, 0x0D, 0x81, 0x01, 0x82, 0x07, 0x88, 0x02,
|
||||
0x81, 0x09, 0x90, 0x0B, 0x88, 0x0D, 0x82, 0x02,
|
||||
};
|
||||
|
||||
// level V -- 1400 ticks, 0 hook bytes, 6 fare stages, 256 pictures, 23 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat V 20260918
|
||||
static const uint8_t kGateStreamV[320] = {
|
||||
0x84, 0x0E, 0x81, 0x04, 0x81, 0x05, 0x88, 0x0B, 0x84, 0x01, 0x81, 0x03,
|
||||
0x82, 0x06, 0x84, 0x0C, 0x81, 0x08, 0x84, 0x07, 0x82, 0x03, 0x88, 0x0A,
|
||||
0x90, 0x03, 0x81, 0x0D, 0x81, 0x0D, 0x82, 0x05, 0x81, 0x02, 0x81, 0x0E,
|
||||
0x90, 0x06, 0x81, 0x05, 0x90, 0x05, 0x81, 0x0E, 0x82, 0x0D, 0x90, 0x0E,
|
||||
0x88, 0x0E, 0x81, 0x03, 0x90, 0x07, 0x84, 0x0A, 0x81, 0x02, 0x90, 0x07,
|
||||
0x82, 0x07, 0x81, 0x02, 0x81, 0x06, 0x82, 0x08, 0x81, 0x04, 0x88, 0x0C,
|
||||
0x81, 0x06, 0x88, 0x0D, 0x90, 0x0D, 0x81, 0x05, 0x90, 0x03, 0x84, 0x0D,
|
||||
0x84, 0x0A, 0x88, 0x0A, 0x88, 0x0D, 0x81, 0x08, 0x90, 0x08, 0x90, 0x01,
|
||||
0x84, 0x06, 0x82, 0x0B, 0x81, 0x0D, 0x82, 0x07, 0x82, 0x0C, 0x81, 0x01,
|
||||
0x90, 0x08, 0x81, 0x02, 0x81, 0x04, 0x90, 0x0C, 0x84, 0x04, 0x88, 0x04,
|
||||
0x82, 0x03, 0x88, 0x07, 0x81, 0x03, 0x90, 0x05, 0x81, 0x02, 0x81, 0x03,
|
||||
0x88, 0x01, 0x90, 0x05, 0x81, 0x08, 0x81, 0x06, 0x81, 0x07, 0x81, 0x08,
|
||||
0x81, 0x06, 0x81, 0x02, 0x84, 0x0B, 0x88, 0x0D, 0x81, 0x06, 0x90, 0x02,
|
||||
0x81, 0x07, 0x82, 0x0B, 0x88, 0x04, 0x84, 0x04, 0x84, 0x05, 0x81, 0x05,
|
||||
0x81, 0x02, 0x82, 0x09, 0x81, 0x03, 0x90, 0x0C, 0x88, 0x0B, 0x82, 0x01,
|
||||
0x88, 0x0D, 0x88, 0x05, 0x81, 0x02, 0x90, 0x0B, 0x81, 0x02, 0x90, 0x0A,
|
||||
0x88, 0x0C, 0x81, 0x01, 0x90, 0x0A, 0x88, 0x0E, 0x90, 0x0A, 0x84, 0x0B,
|
||||
0x81, 0x03, 0x90, 0x08, 0x88, 0x03, 0x82, 0x0E, 0x84, 0x06, 0x90, 0x0E,
|
||||
0x81, 0x03, 0x88, 0x0A, 0x90, 0x0A, 0x82, 0x09, 0x81, 0x04, 0x88, 0x0C,
|
||||
0x84, 0x04, 0x81, 0x07, 0x90, 0x03, 0x81, 0x01, 0x81, 0x01, 0x81, 0x01,
|
||||
0x82, 0x0E, 0x81, 0x05, 0x81, 0x06, 0x81, 0x08, 0x84, 0x08, 0x88, 0x0C,
|
||||
0x82, 0x09, 0x88, 0x05, 0x81, 0x02, 0x88, 0x04, 0x81, 0x04, 0x88, 0x0C,
|
||||
0x90, 0x07, 0x88, 0x0E, 0x81, 0x03, 0x81, 0x0A, 0x82, 0x0B, 0x81, 0x02,
|
||||
0x88, 0x02, 0x90, 0x0E, 0x88, 0x0D, 0x81, 0x03, 0x88, 0x09, 0x90, 0x04,
|
||||
0x84, 0x01, 0x88, 0x04, 0x90, 0x04, 0x84, 0x04, 0x81, 0x03, 0x90, 0x0C,
|
||||
0x88, 0x07, 0x84, 0x05, 0x81, 0x02, 0x90, 0x0B, 0x90, 0x04, 0x90, 0x09,
|
||||
0x81, 0x02, 0x81, 0x01, 0x90, 0x0B, 0x88, 0x04,
|
||||
};
|
||||
|
||||
// level E -- 1400 ticks, 4 hook bytes, 8 fare stages, 256 pictures, 11 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat E 20260921
|
||||
static const uint8_t kGateStreamE[320] = {
|
||||
0x84, 0x05, 0x82, 0x03, 0x82, 0x05, 0x81, 0x0B, 0x81, 0x07, 0x81, 0x02,
|
||||
0x81, 0x01, 0x89, 0x02, 0x90, 0x03, 0x81, 0x0A, 0x81, 0x05, 0x84, 0x0C,
|
||||
0x81, 0x02, 0x88, 0x07, 0x81, 0x0B, 0x90, 0x08, 0x90, 0x0A, 0x88, 0x02,
|
||||
0x81, 0x05, 0x84, 0x08, 0x81, 0x05, 0x90, 0x03, 0x84, 0x01, 0x84, 0x08,
|
||||
0x88, 0x0A, 0x84, 0x07, 0x81, 0x04, 0x84, 0x07, 0x90, 0x0C, 0x80, 0x08,
|
||||
0x90, 0x07, 0x88, 0x03, 0x90, 0x0B, 0x88, 0x01, 0x90, 0x07, 0x88, 0x04,
|
||||
0x81, 0x02, 0x88, 0x08, 0x84, 0x05, 0x81, 0x05, 0x81, 0x02, 0x81, 0x09,
|
||||
0x88, 0x05, 0x90, 0x0E, 0x81, 0x05, 0x81, 0x01, 0x90, 0x04, 0x90, 0x08,
|
||||
0x81, 0x06, 0x84, 0x0E, 0x81, 0x09, 0x81, 0x01, 0x84, 0x05, 0x81, 0x01,
|
||||
0x81, 0x02, 0x88, 0x0B, 0x90, 0x08, 0x88, 0x0C, 0x88, 0x05, 0x88, 0x08,
|
||||
0x84, 0x09, 0x88, 0x05, 0x90, 0x05, 0x82, 0x0A, 0x81, 0x07, 0x90, 0x0A,
|
||||
0x81, 0x07, 0x81, 0x03, 0x84, 0x0B, 0x84, 0x0E, 0x88, 0x09, 0x90, 0x02,
|
||||
0x81, 0x0E, 0x81, 0x06, 0x90, 0x0E, 0x81, 0x02, 0x90, 0x08, 0x84, 0x08,
|
||||
0x81, 0x0B, 0x88, 0x0D, 0x84, 0x0C, 0x81, 0x09, 0x90, 0x08, 0x82, 0x0B,
|
||||
0x88, 0x08, 0x81, 0x07, 0x82, 0x02, 0x84, 0x0B, 0x88, 0x0B, 0x81, 0x0D,
|
||||
0x84, 0x0E, 0x82, 0x01, 0x81, 0x03, 0x90, 0x0C, 0x81, 0x05, 0x90, 0x04,
|
||||
0x82, 0x0C, 0x81, 0x06, 0x90, 0x0E, 0x88, 0x0B, 0x88, 0x09, 0x81, 0x0E,
|
||||
0x82, 0x0E, 0x90, 0x0C, 0x81, 0x06, 0x81, 0x05, 0x84, 0x0E, 0x81, 0x0C,
|
||||
0x88, 0x0B, 0x90, 0x06, 0x82, 0x05, 0x81, 0x06, 0x88, 0x0D, 0x88, 0x07,
|
||||
0x81, 0x07, 0x84, 0x07, 0x88, 0x08, 0x81, 0x07, 0x90, 0x0C, 0x84, 0x04,
|
||||
0x84, 0x0A, 0x88, 0x0B, 0x80, 0x0A, 0x81, 0x0C, 0x81, 0x07, 0x88, 0x06,
|
||||
0x88, 0x09, 0x88, 0x09, 0x81, 0x0C, 0x80, 0x06, 0x81, 0x06, 0x81, 0x07,
|
||||
0x84, 0x08, 0x82, 0x09, 0x84, 0x0C, 0x90, 0x09, 0x90, 0x03, 0x90, 0x0D,
|
||||
0x81, 0x08, 0x84, 0x05, 0x84, 0x09, 0x88, 0x0B, 0x81, 0x01, 0x81, 0x0A,
|
||||
0x90, 0x0D, 0x88, 0x0E, 0x88, 0x0D, 0x88, 0x05, 0x84, 0x06, 0x81, 0x0E,
|
||||
0x81, 0x0A, 0x81, 0x08, 0x84, 0x0C, 0x88, 0x05, 0x81, 0x02, 0x90, 0x0E,
|
||||
0x84, 0x0D, 0x84, 0x0A, 0x81, 0x05, 0x90, 0x09,
|
||||
};
|
||||
|
||||
// level J -- 1400 ticks, 10 hook bytes, 10 fare stages, 256 pictures, 8 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat J 20260921
|
||||
static const uint8_t kGateStreamJ[320] = {
|
||||
0x88, 0x05, 0x82, 0x09, 0x81, 0x01, 0x81, 0x04, 0x90, 0x06, 0x81, 0x05,
|
||||
0x81, 0x01, 0x90, 0x09, 0x88, 0x05, 0x82, 0x08, 0x81, 0x0A, 0x81, 0x03,
|
||||
0x84, 0x07, 0x88, 0x0D, 0x81, 0x06, 0x81, 0x0A, 0x84, 0x05, 0x90, 0x08,
|
||||
0x81, 0x0B, 0x90, 0x0E, 0x84, 0x0E, 0x81, 0x03, 0x90, 0x09, 0x81, 0x02,
|
||||
0x88, 0x04, 0x88, 0x08, 0x84, 0x0E, 0x81, 0x04, 0x88, 0x0D, 0x90, 0x0E,
|
||||
0x84, 0x09, 0x90, 0x05, 0x81, 0x01, 0x81, 0x03, 0x88, 0x03, 0x88, 0x07,
|
||||
0x81, 0x0B, 0x90, 0x0B, 0x88, 0x08, 0x82, 0x03, 0x90, 0x09, 0x88, 0x03,
|
||||
0x84, 0x06, 0x88, 0x0A, 0x88, 0x0B, 0x84, 0x04, 0x81, 0x05, 0x88, 0x0E,
|
||||
0x81, 0x0A, 0x90, 0x0C, 0x85, 0x04, 0x81, 0x0E, 0x90, 0x02, 0x82, 0x0D,
|
||||
0x84, 0x01, 0x81, 0x02, 0x88, 0x09, 0x81, 0x0B, 0x81, 0x02, 0x82, 0x0C,
|
||||
0x84, 0x04, 0x81, 0x05, 0x81, 0x04, 0x81, 0x04, 0x81, 0x05, 0x90, 0x05,
|
||||
0x88, 0x09, 0x81, 0x02, 0x88, 0x01, 0x81, 0x05, 0x90, 0x04, 0x81, 0x0B,
|
||||
0x81, 0x05, 0x82, 0x0D, 0x88, 0x06, 0x88, 0x07, 0x88, 0x02, 0x84, 0x02,
|
||||
0x90, 0x07, 0x88, 0x09, 0x84, 0x0C, 0x81, 0x01, 0x88, 0x0B, 0x81, 0x0C,
|
||||
0x82, 0x0A, 0x81, 0x08, 0x82, 0x01, 0x88, 0x09, 0x84, 0x05, 0x81, 0x08,
|
||||
0x84, 0x0A, 0x84, 0x09, 0x88, 0x0E, 0x81, 0x01, 0x84, 0x03, 0x82, 0x0C,
|
||||
0x81, 0x0E, 0x84, 0x0A, 0x88, 0x02, 0x84, 0x0D, 0x81, 0x0A, 0x90, 0x0E,
|
||||
0x88, 0x09, 0x90, 0x09, 0x81, 0x05, 0x90, 0x03, 0x88, 0x09, 0x84, 0x06,
|
||||
0x81, 0x01, 0x88, 0x06, 0x81, 0x05, 0x81, 0x09, 0x81, 0x06, 0x90, 0x04,
|
||||
0x82, 0x0A, 0x90, 0x07, 0x81, 0x07, 0x81, 0x0A, 0x84, 0x0E, 0x84, 0x07,
|
||||
0x81, 0x0A, 0x90, 0x0C, 0x81, 0x01, 0x90, 0x01, 0x88, 0x0D, 0x81, 0x03,
|
||||
0x88, 0x05, 0x81, 0x03, 0x88, 0x01, 0x81, 0x01, 0x82, 0x02, 0x88, 0x07,
|
||||
0x83, 0x02, 0x90, 0x07, 0x81, 0x05, 0x81, 0x04, 0x81, 0x0E, 0x88, 0x09,
|
||||
0x81, 0x07, 0x90, 0x03, 0x82, 0x0B, 0x82, 0x0B, 0x90, 0x04, 0x81, 0x05,
|
||||
0x81, 0x03, 0x90, 0x0C, 0x82, 0x07, 0x88, 0x0E, 0x90, 0x04, 0x81, 0x0A,
|
||||
0x88, 0x02, 0x88, 0x0D, 0x82, 0x07, 0x90, 0x01, 0x81, 0x02, 0x81, 0x01,
|
||||
0x82, 0x07, 0x81, 0x08, 0x84, 0x0E, 0x81, 0x03,
|
||||
};
|
||||
|
||||
// level L -- 1400 ticks, 0 hook bytes, 10 fare stages, 256 pictures, 8 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat L 20260921
|
||||
static const uint8_t kGateStreamL[320] = {
|
||||
0x84, 0x05, 0x84, 0x09, 0x81, 0x06, 0x81, 0x04, 0x81, 0x08, 0x81, 0x05,
|
||||
0x81, 0x01, 0x84, 0x09, 0x90, 0x09, 0x82, 0x0D, 0x88, 0x07, 0x81, 0x06,
|
||||
0x81, 0x09, 0x82, 0x01, 0x81, 0x08, 0x88, 0x0B, 0x84, 0x0E, 0x81, 0x03,
|
||||
0x82, 0x02, 0x82, 0x06, 0x82, 0x03, 0x88, 0x0E, 0x84, 0x0C, 0x81, 0x06,
|
||||
0x88, 0x02, 0x81, 0x04, 0x88, 0x0E, 0x81, 0x04, 0x90, 0x0B, 0x81, 0x08,
|
||||
0x84, 0x09, 0x82, 0x09, 0x81, 0x01, 0x90, 0x03, 0x81, 0x05, 0x84, 0x07,
|
||||
0x81, 0x07, 0x90, 0x0B, 0x81, 0x07, 0x88, 0x09, 0x81, 0x0E, 0x88, 0x03,
|
||||
0x81, 0x01, 0x88, 0x09, 0x81, 0x07, 0x81, 0x0C, 0x88, 0x0C, 0x90, 0x0E,
|
||||
0x81, 0x0E, 0x90, 0x05, 0x84, 0x0E, 0x82, 0x0E, 0x82, 0x01, 0x84, 0x0A,
|
||||
0x88, 0x03, 0x90, 0x09, 0x82, 0x05, 0x81, 0x0E, 0x81, 0x05, 0x81, 0x07,
|
||||
0x81, 0x0D, 0x81, 0x0E, 0x90, 0x04, 0x90, 0x04, 0x81, 0x06, 0x81, 0x01,
|
||||
0x88, 0x0B, 0x81, 0x01, 0x90, 0x0B, 0x81, 0x05, 0x84, 0x0D, 0x81, 0x01,
|
||||
0x81, 0x0A, 0x84, 0x0D, 0x82, 0x09, 0x88, 0x06, 0x88, 0x04, 0x84, 0x0C,
|
||||
0x88, 0x0C, 0x84, 0x02, 0x81, 0x07, 0x82, 0x07, 0x84, 0x08, 0x88, 0x09,
|
||||
0x81, 0x01, 0x88, 0x01, 0x81, 0x0C, 0x81, 0x04, 0x84, 0x06, 0x82, 0x06,
|
||||
0x90, 0x0D, 0x81, 0x06, 0x81, 0x0D, 0x82, 0x0D, 0x82, 0x08, 0x81, 0x0C,
|
||||
0x84, 0x05, 0x82, 0x09, 0x81, 0x05, 0x84, 0x07, 0x82, 0x02, 0x84, 0x01,
|
||||
0x81, 0x02, 0x90, 0x02, 0x82, 0x06, 0x88, 0x03, 0x84, 0x0B, 0x81, 0x0E,
|
||||
0x88, 0x0E, 0x90, 0x07, 0x82, 0x08, 0x82, 0x02, 0x90, 0x02, 0x82, 0x03,
|
||||
0x84, 0x07, 0x82, 0x05, 0x84, 0x07, 0x81, 0x0B, 0x82, 0x0E, 0x90, 0x05,
|
||||
0x88, 0x04, 0x90, 0x05, 0x84, 0x0A, 0x82, 0x0A, 0x88, 0x0C, 0x81, 0x08,
|
||||
0x82, 0x0C, 0x81, 0x06, 0x84, 0x09, 0x81, 0x04, 0x84, 0x0B, 0x88, 0x0B,
|
||||
0x81, 0x0C, 0x81, 0x0C, 0x82, 0x0E, 0x81, 0x03, 0x82, 0x09, 0x88, 0x04,
|
||||
0x81, 0x05, 0x88, 0x04, 0x80, 0x0B, 0x84, 0x06, 0x81, 0x0E, 0x84, 0x0B,
|
||||
0x90, 0x0B, 0x90, 0x07, 0x82, 0x0D, 0x84, 0x0D, 0x81, 0x08, 0x81, 0x09,
|
||||
0x84, 0x0E, 0x81, 0x0B, 0x90, 0x04, 0x84, 0x0B, 0x84, 0x03, 0x81, 0x03,
|
||||
0x88, 0x0A, 0x81, 0x07, 0x84, 0x0B, 0x90, 0x0E,
|
||||
};
|
||||
|
||||
// level P -- 1400 ticks, 11 hook bytes, 10 fare stages, 256 pictures, 4 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat P 20260921
|
||||
static const uint8_t kGateStreamP[320] = {
|
||||
0x88, 0x05, 0x82, 0x09, 0x81, 0x0B, 0x81, 0x04, 0x81, 0x04, 0x84, 0x05,
|
||||
0x82, 0x01, 0x90, 0x0C, 0x81, 0x03, 0x81, 0x0D, 0x81, 0x01, 0x84, 0x0C,
|
||||
0x84, 0x0E, 0x88, 0x07, 0x81, 0x0B, 0x88, 0x0D, 0x90, 0x0A, 0x88, 0x02,
|
||||
0x81, 0x05, 0x84, 0x08, 0x81, 0x05, 0x90, 0x0C, 0x84, 0x01, 0x88, 0x08,
|
||||
0x88, 0x0A, 0x84, 0x0C, 0x81, 0x04, 0x84, 0x07, 0x90, 0x0C, 0x80, 0x09,
|
||||
0x90, 0x06, 0x81, 0x03, 0x81, 0x0C, 0x88, 0x01, 0x82, 0x03, 0x81, 0x04,
|
||||
0x84, 0x0D, 0x88, 0x09, 0x84, 0x05, 0x81, 0x05, 0x81, 0x02, 0x81, 0x09,
|
||||
0x81, 0x02, 0x90, 0x0E, 0x81, 0x05, 0x81, 0x01, 0x81, 0x03, 0x88, 0x0A,
|
||||
0x81, 0x06, 0x88, 0x05, 0x90, 0x0C, 0x90, 0x01, 0x84, 0x0E, 0x88, 0x01,
|
||||
0x81, 0x02, 0x82, 0x05, 0x90, 0x08, 0x88, 0x0A, 0x84, 0x0C, 0x90, 0x08,
|
||||
0x84, 0x0C, 0x81, 0x06, 0x81, 0x03, 0x88, 0x0A, 0x84, 0x08, 0x90, 0x0E,
|
||||
0x81, 0x02, 0x88, 0x0C, 0x81, 0x06, 0x84, 0x0C, 0x81, 0x09, 0x80, 0x07,
|
||||
0x88, 0x04, 0x81, 0x07, 0x81, 0x03, 0x81, 0x09, 0x81, 0x05, 0x86, 0x05,
|
||||
0x90, 0x09, 0x84, 0x06, 0x81, 0x03, 0x84, 0x09, 0x81, 0x0E, 0x88, 0x0B,
|
||||
0x90, 0x08, 0x88, 0x0A, 0x81, 0x04, 0x90, 0x0D, 0x88, 0x0E, 0x88, 0x09,
|
||||
0x81, 0x0B, 0x90, 0x0C, 0x84, 0x05, 0x81, 0x08, 0x84, 0x01, 0x82, 0x02,
|
||||
0x81, 0x03, 0x82, 0x0E, 0x88, 0x02, 0x88, 0x05, 0x81, 0x01, 0x81, 0x08,
|
||||
0x82, 0x03, 0x84, 0x0E, 0x81, 0x01, 0x81, 0x08, 0x84, 0x03, 0x82, 0x03,
|
||||
0x82, 0x05, 0x81, 0x0A, 0x81, 0x02, 0x90, 0x01, 0x81, 0x0E, 0x81, 0x0C,
|
||||
0x90, 0x0C, 0x88, 0x0A, 0x84, 0x03, 0x81, 0x03, 0x84, 0x0A, 0x84, 0x05,
|
||||
0x82, 0x09, 0x88, 0x0A, 0x81, 0x06, 0x84, 0x07, 0x84, 0x0C, 0x81, 0x0C,
|
||||
0x82, 0x07, 0x81, 0x06, 0x81, 0x03, 0x88, 0x09, 0x90, 0x01, 0x84, 0x0E,
|
||||
0x81, 0x01, 0x88, 0x06, 0x81, 0x0E, 0x81, 0x0A, 0x88, 0x0A, 0x81, 0x08,
|
||||
0x84, 0x08, 0x88, 0x0E, 0x81, 0x02, 0x84, 0x0E, 0x82, 0x05, 0x81, 0x06,
|
||||
0x88, 0x0C, 0x81, 0x0B, 0x81, 0x0D, 0x84, 0x02, 0x90, 0x0E, 0x84, 0x0E,
|
||||
0x81, 0x02, 0x90, 0x07, 0x88, 0x0C, 0x90, 0x0A, 0x81, 0x0E, 0x81, 0x0A,
|
||||
0x81, 0x0D, 0x81, 0x0B, 0x81, 0x08, 0x81, 0x03,
|
||||
};
|
||||
|
||||
// level S -- 1400 ticks, 0 hook bytes, 10 fare stages, 256 pictures, 23 landings
|
||||
// regenerate: tools/stsim/recorder levels/level??.dat S 20260921
|
||||
static const uint8_t kGateStreamS[320] = {
|
||||
0x90, 0x04, 0x90, 0x0E, 0x88, 0x08, 0x82, 0x0D, 0x88, 0x0C, 0x81, 0x03,
|
||||
0x81, 0x0A, 0x81, 0x0D, 0x88, 0x09, 0x88, 0x0C, 0x82, 0x0E, 0x81, 0x07,
|
||||
0x81, 0x0D, 0x81, 0x0A, 0x90, 0x0D, 0x84, 0x01, 0x90, 0x05, 0x88, 0x0E,
|
||||
0x81, 0x0A, 0x81, 0x0A, 0x90, 0x06, 0x88, 0x03, 0x82, 0x0B, 0x82, 0x0B,
|
||||
0x88, 0x03, 0x88, 0x0A, 0x90, 0x0C, 0x81, 0x0E, 0x81, 0x0E, 0x90, 0x06,
|
||||
0x88, 0x02, 0x82, 0x08, 0x81, 0x0A, 0x90, 0x0D, 0x90, 0x05, 0x81, 0x05,
|
||||
0x88, 0x0B, 0x81, 0x05, 0x90, 0x0B, 0x88, 0x0E, 0x82, 0x09, 0x90, 0x07,
|
||||
0x81, 0x03, 0x81, 0x0D, 0x88, 0x09, 0x88, 0x0E, 0x84, 0x0A, 0x88, 0x0A,
|
||||
0x82, 0x01, 0x90, 0x0C, 0x82, 0x01, 0x90, 0x0A, 0x82, 0x0A, 0x84, 0x03,
|
||||
0x81, 0x02, 0x90, 0x04, 0x84, 0x0E, 0x90, 0x09, 0x81, 0x0D, 0x90, 0x06,
|
||||
0x81, 0x02, 0x90, 0x0E, 0x90, 0x07, 0x82, 0x05, 0x81, 0x06, 0x90, 0x07,
|
||||
0x82, 0x03, 0x90, 0x07, 0x90, 0x0B, 0x82, 0x06, 0x88, 0x0E, 0x90, 0x08,
|
||||
0x84, 0x0A, 0x82, 0x07, 0x81, 0x04, 0x81, 0x03, 0x84, 0x05, 0x90, 0x08,
|
||||
0x81, 0x0C, 0x82, 0x01, 0x90, 0x0B, 0x81, 0x0A, 0x84, 0x05, 0x81, 0x02,
|
||||
0x82, 0x09, 0x90, 0x0E, 0x81, 0x02, 0x84, 0x03, 0x81, 0x0C, 0x81, 0x0C,
|
||||
0x81, 0x0D, 0x82, 0x08, 0x81, 0x03, 0x81, 0x0D, 0x81, 0x0A, 0x81, 0x0A,
|
||||
0x81, 0x0C, 0x82, 0x06, 0x90, 0x0D, 0x88, 0x0C, 0x84, 0x04, 0x81, 0x01,
|
||||
0x81, 0x0A, 0x81, 0x03, 0x90, 0x06, 0x88, 0x07, 0x88, 0x0E, 0x84, 0x0E,
|
||||
0x81, 0x0E, 0x82, 0x03, 0x90, 0x0E, 0x82, 0x05, 0x90, 0x02, 0x88, 0x03,
|
||||
0x81, 0x07, 0x81, 0x0A, 0x81, 0x0B, 0x81, 0x05, 0x84, 0x0D, 0x81, 0x01,
|
||||
0x82, 0x02, 0x90, 0x0C, 0x82, 0x03, 0x90, 0x08, 0x81, 0x05, 0x84, 0x08,
|
||||
0x84, 0x06, 0x88, 0x08, 0x81, 0x0E, 0x82, 0x01, 0x81, 0x01, 0x90, 0x08,
|
||||
0x82, 0x03, 0x90, 0x0C, 0x84, 0x02, 0x81, 0x09, 0x82, 0x04, 0x88, 0x0D,
|
||||
0x90, 0x07, 0x88, 0x0E, 0x82, 0x05, 0x81, 0x0C, 0x90, 0x0A, 0x81, 0x04,
|
||||
0x84, 0x06, 0x82, 0x02, 0x81, 0x09, 0x90, 0x0D, 0x82, 0x06, 0x82, 0x01,
|
||||
0x90, 0x09, 0x81, 0x0B, 0x84, 0x04, 0x88, 0x07, 0x81, 0x0B, 0x81, 0x05,
|
||||
0x82, 0x03, 0x81, 0x07, 0x90, 0x06, 0x82, 0x07,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t level; // level letter the ride was searched for
|
||||
const uint8_t *stream;
|
||||
uint16_t length;
|
||||
} StGateStreamT;
|
||||
|
||||
static const StGateStreamT kGateStreams[] = {
|
||||
{ 'G', kGateStreamG, (uint16_t)sizeof(kGateStreamG) },
|
||||
{ 'I', kGateStreamI, (uint16_t)sizeof(kGateStreamI) },
|
||||
{ 'K', kGateStreamK, (uint16_t)sizeof(kGateStreamK) },
|
||||
{ 'O', kGateStreamO, (uint16_t)sizeof(kGateStreamO) },
|
||||
{ 'Q', kGateStreamQ, (uint16_t)sizeof(kGateStreamQ) },
|
||||
{ 'R', kGateStreamR, (uint16_t)sizeof(kGateStreamR) },
|
||||
{ 'U', kGateStreamU, (uint16_t)sizeof(kGateStreamU) },
|
||||
{ 'V', kGateStreamV, (uint16_t)sizeof(kGateStreamV) },
|
||||
{ 'E', kGateStreamE, (uint16_t)sizeof(kGateStreamE) },
|
||||
{ 'J', kGateStreamJ, (uint16_t)sizeof(kGateStreamJ) },
|
||||
{ 'L', kGateStreamL, (uint16_t)sizeof(kGateStreamL) },
|
||||
{ 'P', kGateStreamP, (uint16_t)sizeof(kGateStreamP) },
|
||||
{ 'S', kGateStreamS, (uint16_t)sizeof(kGateStreamS) },
|
||||
};
|
||||
#define ST_GATE_STREAMS (sizeof(kGateStreams) / sizeof(kGateStreams[0]))
|
||||
|
||||
#endif
|
||||
195
tools/stsim/recorder.c
Normal file
195
tools/stsim/recorder.c
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
// recorder -- search for a demo input stream that exercises a level.
|
||||
//
|
||||
// The C64 ships attract recordings for four screens (H, W, T, X). The
|
||||
// other levels have none, so a refactor of their hooks had nothing to be
|
||||
// checked against. This searches for a synthetic ride instead: random
|
||||
// restarts plus hill climbing over (joystick mask, duration) pairs,
|
||||
// scored on how long the cab survives and how much of the level it
|
||||
// reaches -- hook state bytes written, fare-machine stages entered,
|
||||
// distinct pictures drawn, pads landed on.
|
||||
//
|
||||
// The result is a REGRESSION fixture, not a recording: it pins current
|
||||
// behaviour so a refactor that changes nothing observable leaves the
|
||||
// trace identical. It says nothing about matching the real C64.
|
||||
//
|
||||
// Usage: recorder <level.dat> <letter> <seed> > stream.h
|
||||
// Then assemble the per-level outputs into gateStreams.h.
|
||||
//
|
||||
// Determinism: a candidate is only useful if it replays identically from
|
||||
// a cold start, so every evaluation clears the whole StSimT (see the note
|
||||
// in evaluate) -- stSimNewGame deliberately preserves some cross-screen
|
||||
// state, which would otherwise leak between candidates.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "stSim.h"
|
||||
#include "stDemoStreams.h"
|
||||
|
||||
static StLevelT gLevel;
|
||||
static StSimT gSim;
|
||||
|
||||
void stAudioSfx(const uint8_t *p){(void)p;}
|
||||
void stAudioNoise(bool o){(void)o;}
|
||||
void stAudioThrustSweep(uint8_t v){(void)v;}
|
||||
void stAudioSpeech(uint8_t c){(void)c;}
|
||||
void stAudioSpeechPhrase(const uint8_t *s){(void)s;}
|
||||
void stAudioSilence(void){}
|
||||
void stAudioVoice2(uint8_t a,uint8_t b,uint8_t c){(void)a;(void)b;(void)c;}
|
||||
void stAudioVoice1Freq(uint8_t v){(void)v;}
|
||||
|
||||
#define PAIRS 160
|
||||
#define STREAMLEN (PAIRS * 2)
|
||||
#define MAXTICKS 1400
|
||||
|
||||
typedef struct { uint32_t score; uint32_t ticks; uint32_t cover; uint32_t lands; uint32_t stages; uint32_t scr; uint32_t near; } ResT;
|
||||
|
||||
static uint32_t rs = 1;
|
||||
static uint32_t rnd(void){ rs = rs*1664525u + 1013904223u; return rs>>8; }
|
||||
|
||||
static ResT evaluate(const uint8_t *stream, uint8_t *touchOut)
|
||||
{
|
||||
uint8_t touched[sizeof(StHookScratchT)];
|
||||
uint8_t base[sizeof(StHookScratchT)];
|
||||
uint8_t stageSeen[16];
|
||||
uint32_t t, cover = 0, lands = 0, stages = 0, scrSeen = 0;
|
||||
uint32_t nearest = 255u;
|
||||
uint32_t scrHash[256];
|
||||
uint8_t lastPad = 0;
|
||||
ResT r;
|
||||
|
||||
memset(stageSeen, 0, sizeof(stageSeen));
|
||||
memset(touched, 0, sizeof(touched));
|
||||
// stSimNewGame deliberately PRESERVES flameParity, waveIdx and
|
||||
// walkParity (the C64 carries them from screen to screen), so a
|
||||
// search that reuses one StSimT would score each candidate against
|
||||
// whatever the previous ride left behind -- and the winning stream
|
||||
// would then not reproduce from a cold start. Clear the whole struct
|
||||
// so every evaluation begins exactly where the gate will.
|
||||
memset(&gSim, 0, sizeof(gSim));
|
||||
stSimNewGame(&gSim, 1u, true);
|
||||
stSimSeedDemoBuffer(&gSim, kDemoBufferInit, ST_DEMO_BUFFER_BYTES);
|
||||
stSimEnterLevel(&gSim, &gLevel);
|
||||
stSimSetDemoStream(&gSim, stream, STREAMLEN);
|
||||
memcpy(base, &gSim.hookScratch, sizeof(base));
|
||||
for (t = 0; t < MAXTICKS; t++) {
|
||||
uint16_t k;
|
||||
if (stSimTick(&gSim) != ST_TICK_CONTINUE) { break; }
|
||||
{ const uint8_t *cur = (const uint8_t *)&gSim.hookScratch;
|
||||
for (k = 0; k < (uint16_t)sizeof(base); k++) {
|
||||
if (cur[k] != base[k]) { touched[k] = 1; } } }
|
||||
if (gSim.activePad != 0u && lastPad == 0u) { lands++; }
|
||||
lastPad = gSim.activePad;
|
||||
if (gSim.stage < 16u) { stageSeen[gSim.stage] = 1u; }
|
||||
/* Shaping: how close the ride came to an actual touchdown. Some
|
||||
levels (R) only run their hook once a passenger has boarded,
|
||||
which needs a landing, and a landing is far too precise for a
|
||||
blind search to stumble on -- so reward getting near one. */
|
||||
if (gSim.activePad == 0u && (gSim.spr[0].ptr & 1u) != 0u) {
|
||||
int16_t tx = (int16_t)(((uint16_t)gSim.posXmsb << 8) | gSim.posXcol);
|
||||
uint8_t pi;
|
||||
for (pi = 0u; pi < gLevel.padCount && pi < ST_MAX_PADS; pi++) {
|
||||
int16_t x1 = (int16_t)(((uint16_t)gSim.pads[pi].x1Hi << 8) | gSim.pads[pi].x1Lo);
|
||||
int16_t x2 = (int16_t)(((uint16_t)gSim.pads[pi].x2Hi << 8) | gSim.pads[pi].x2Lo);
|
||||
int16_t dr = (int16_t)((int16_t)gSim.spr[0].row - (int16_t)gSim.pads[pi].row);
|
||||
uint32_t ar = (uint32_t)(dr < 0 ? -dr : dr);
|
||||
uint32_t ax = 0u;
|
||||
uint32_t d;
|
||||
if (tx < x1) { ax = (uint32_t)(x1 - tx); }
|
||||
else if (tx > x2) { ax = (uint32_t)(tx - x2); }
|
||||
/* Both axes matter: the row alone is easy to hit while
|
||||
the cab sits at the far side of the screen. */
|
||||
d = ar * 4u + ax;
|
||||
if (d < nearest) { nearest = d; }
|
||||
}
|
||||
}
|
||||
/* distinct pictures the hook has produced (screen + colour) */
|
||||
{ uint32_t h = 2166136261u; uint16_t c; uint32_t i2; int dup = 0;
|
||||
for (c = 0; c < ST_SCREEN_CELLS; c++) { h = (h ^ gSim.screen[c]) * 16777619u; }
|
||||
for (c = 0; c < ST_SCREEN_CELLS; c++) { h = (h ^ gSim.color[c]) * 16777619u; }
|
||||
for (i2 = 0; i2 < scrSeen; i2++) { if (scrHash[i2] == h) { dup = 1; break; } }
|
||||
if (!dup && scrSeen < 256u) { scrHash[scrSeen++] = h; } }
|
||||
}
|
||||
{ uint16_t k; for (k = 0; k < (uint16_t)sizeof(touched); k++) { if (touched[k]) { cover++; } } }
|
||||
{ int k; for (k = 0; k < 16; k++) { if (stageSeen[k]) { stages++; } } }
|
||||
if (touchOut) { memcpy(touchOut, touched, sizeof(touched)); }
|
||||
r.ticks = t; r.cover = cover; r.lands = lands; r.stages = stages; r.scr = scrSeen;
|
||||
r.near = nearest;
|
||||
r.score = cover * 30000u + stages * 30000u + lands * 4000u + t * 100u + scrSeen * 200u
|
||||
+ (255u - nearest) * 60u;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void randomise(uint8_t *s, int from)
|
||||
{
|
||||
int i;
|
||||
for (i = from; i < PAIRS; i++) {
|
||||
uint32_t d = rnd() % 100u;
|
||||
uint8_t m = 0x80u;
|
||||
if (d < 45u) { m |= 0x01u; } /* thrust up a lot */
|
||||
else if (d < 60u) { m |= 0x04u; }
|
||||
else if (d < 75u) { m |= 0x08u; }
|
||||
else if (d < 82u) { m |= 0x02u; }
|
||||
else if (d < 88u) { m |= 0x10u; }
|
||||
if (rnd() % 5u == 0u) { m |= (uint8_t)(1u << (rnd() % 4u)); }
|
||||
s[i*2] = m;
|
||||
s[i*2 + 1] = (uint8_t)(1u + rnd() % 14u);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t best[STREAMLEN], cur[STREAMLEN], touched[ST_HOOK_BYTES];
|
||||
ResT bestR, curR;
|
||||
FILE *fp;
|
||||
int restart, iter;
|
||||
|
||||
if (argc < 4) { fprintf(stderr, "usage: recorder <level.dat> <name> <seed>\n"); return 2; }
|
||||
fp = fopen(argv[1], "rb");
|
||||
if (!fp || !stLevelParse(&gLevel, fp)) { fprintf(stderr, "cannot load %s\n", argv[1]); return 1; }
|
||||
fclose(fp);
|
||||
rs = (uint32_t)strtoul(argv[3], NULL, 0);
|
||||
|
||||
randomise(best, 0);
|
||||
bestR = evaluate(best, NULL);
|
||||
for (restart = 0; restart < 120; restart++) {
|
||||
memcpy(cur, best, STREAMLEN);
|
||||
if (restart > 0) { randomise(cur, (int)(rnd() % PAIRS)); }
|
||||
curR = evaluate(cur, NULL);
|
||||
for (iter = 0; iter < 3000; iter++) {
|
||||
uint8_t trial[STREAMLEN];
|
||||
ResT tr;
|
||||
int j, nmut = 1 + (int)(rnd() % 3u);
|
||||
memcpy(trial, cur, STREAMLEN);
|
||||
for (j = 0; j < nmut; j++) {
|
||||
int i = (int)(rnd() % PAIRS);
|
||||
if (rnd() % 2u) {
|
||||
uint8_t m = 0x80u;
|
||||
uint32_t d = rnd() % 100u;
|
||||
if (d < 45u) { m |= 0x01u; }
|
||||
else if (d < 62u) { m |= 0x04u; }
|
||||
else if (d < 79u) { m |= 0x08u; }
|
||||
else if (d < 88u) { m |= 0x02u; }
|
||||
else { m |= 0x10u; }
|
||||
trial[i*2] = m;
|
||||
} else {
|
||||
trial[i*2 + 1] = (uint8_t)(1u + rnd() % 14u);
|
||||
}
|
||||
}
|
||||
tr = evaluate(trial, NULL);
|
||||
if (tr.score >= curR.score) { memcpy(cur, trial, STREAMLEN); curR = tr; }
|
||||
}
|
||||
if (curR.score > bestR.score) { memcpy(best, cur, STREAMLEN); bestR = curR; }
|
||||
}
|
||||
bestR = evaluate(best, touched);
|
||||
fprintf(stderr, "%s: ticks=%u hookBytes=%u stages=%u pictures=%u lands=%u nearPad=%u\n",
|
||||
argv[2], bestR.ticks, bestR.cover, bestR.stages, bestR.scr, bestR.lands, bestR.near);
|
||||
printf("// %s: %u ticks, %u hook bytes, %u fare stages, %u pictures, %u landings\n",
|
||||
argv[2], bestR.ticks, bestR.cover, bestR.stages, bestR.scr, bestR.lands);
|
||||
printf("static const uint8_t kGateStream%s[%d] = {", argv[2], STREAMLEN);
|
||||
{ int i; for (i = 0; i < STREAMLEN; i++) {
|
||||
if (i % 12 == 0) { printf("\n "); }
|
||||
printf("0x%02X,%s", best[i], (i % 12 == 11) ? "" : " "); } }
|
||||
printf("\n};\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -5,14 +5,19 @@
|
|||
// the VICE tracer records (see stuff/spacetaxi and the compare script),
|
||||
// so the port's engine can be diffed against the real machine.
|
||||
//
|
||||
// stsim <level.dat> <H|W|T|X> <ticks>
|
||||
// stsim <level.dat> <level letter> <ticks>
|
||||
//
|
||||
// H, W, T and X use the C64's own attract recordings; every other
|
||||
// letter uses a synthesised gate fixture from gateStreams.h.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../examples/spacetaxi/stSim.h"
|
||||
#include "../../examples/spacetaxi/stCels.h"
|
||||
#include "../../examples/spacetaxi/stDemoStreams.h"
|
||||
#include "gateStreams.h"
|
||||
|
||||
|
||||
static StLevelT gLevel;
|
||||
|
|
@ -23,11 +28,105 @@ void stAudioSfx(const uint8_t *program9) { (void)program9; }
|
|||
void stAudioNoise(bool on) { (void)on; }
|
||||
void stAudioThrustSweep(uint8_t value) { (void)value; }
|
||||
void stAudioSpeech(uint8_t ch) { (void)ch; }
|
||||
void stAudioSpeechPhrase(const uint8_t *speech) { (void)speech; }
|
||||
void stAudioSilence(void) { }
|
||||
void stAudioVoice2(uint8_t freqLo, uint8_t freqHi, uint8_t ctrl) { (void)freqLo; (void)freqHi; (void)ctrl; }
|
||||
void stAudioVoice1Freq(uint8_t value) { (void)value; }
|
||||
|
||||
|
||||
// FNV-1a over a byte span: the picture the player actually sees. The
|
||||
// hooks that animate the screen (O, R, V, W, X) change screen, colour or
|
||||
// charset bytes and nothing else this line used to capture.
|
||||
static uint32_t hashBytes(const uint8_t *p, size_t n) {
|
||||
uint32_t h = 2166136261u;
|
||||
size_t i;
|
||||
|
||||
for (i = 0u; i < n; i++) {
|
||||
h = (h ^ p[i]) * 16777619u;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// The charset the game would be showing. The sim no longer holds a
|
||||
// contiguous 2 KB copy -- edited glyphs live in an override table -- so
|
||||
// rebuild the effective image here. Hashing this keeps the trace value
|
||||
// identical to the pre-override captures, which is what lets the goldens
|
||||
// prove the change is behaviour-preserving.
|
||||
static uint32_t charsetHash(const StSimT *sim) {
|
||||
uint8_t image[ST_CHARSET_CHARS * 8u];
|
||||
uint16_t ch;
|
||||
|
||||
for (ch = 0u; ch < ST_CHARSET_CHARS; ch++) {
|
||||
memcpy(&image[ch * 8u], stSimGlyph(sim, (uint8_t)ch), 8u);
|
||||
}
|
||||
return hashBytes(image, sizeof(image));
|
||||
}
|
||||
|
||||
|
||||
// STSIM_CELS=1: every level cel (ptr below the baked set) a ride
|
||||
// displays, as (ptr, colour, multi, mc0, mc1), against what
|
||||
// stLevelCelList bakes for the level -- a cel shown but not listed is
|
||||
// built and drawn interpreted mid-ride on the real ports.
|
||||
#define CENSUS_MAX 64u
|
||||
static StCelDefT gCensus[CENSUS_MAX];
|
||||
static uint8_t gCensusCount;
|
||||
|
||||
|
||||
static void celCensusTick(const StSimT *sim) {
|
||||
uint8_t i;
|
||||
|
||||
for (i = 1u; i < ST_HW_SPRITES; i++) {
|
||||
StCelDefT d;
|
||||
uint8_t k;
|
||||
|
||||
if ((sim->frame.enableMask & kStBit[i]) == 0u || sim->frame.ptr[i] >= ST_SPRITE_PTR_FIRST) {
|
||||
continue;
|
||||
}
|
||||
// A pointer with no bitmap (a hook enables a sprite a tick before
|
||||
// aiming it) draws nothing on every port -- not a cel.
|
||||
if (stSimSpriteBitmap(sim, sim->frame.ptr[i]) == 0) {
|
||||
continue;
|
||||
}
|
||||
d.ptr = sim->frame.ptr[i];
|
||||
d.color = sim->frame.color[i];
|
||||
d.multi = (sim->frame.multiMask & kStBit[i]) != 0u ? 1u : 0u;
|
||||
d.mc0 = d.multi ? sim->spriteMc0 : 0u;
|
||||
d.mc1 = d.multi ? sim->spriteMc1 : 0u;
|
||||
for (k = 0u; k < gCensusCount; k++) {
|
||||
if (memcmp(&gCensus[k], &d, sizeof(d)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == gCensusCount && gCensusCount < CENSUS_MAX) {
|
||||
gCensus[gCensusCount++] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void celCensusReport(const StLevelT *level) {
|
||||
StCelDefT listed[ST_LEVEL_CELS_MAX];
|
||||
uint8_t n = stLevelCelList(level, listed, ST_LEVEL_CELS_MAX);
|
||||
uint8_t k;
|
||||
uint8_t j;
|
||||
|
||||
for (k = 0u; k < gCensusCount; k++) {
|
||||
for (j = 0u; j < n; j++) {
|
||||
if (memcmp(&listed[j], &gCensus[k], sizeof(StCelDefT)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "CEL %s ptr=%02X color=%u multi=%u mc=%u/%u\n", (j < n) ? "listed " : "MISSING", gCensus[k].ptr, gCensus[k].color, gCensus[k].multi, gCensus[k].mc0, gCensus[k].mc1);
|
||||
}
|
||||
fprintf(stderr, "CENSUS shown=%u listed=%u\n", gCensusCount, n);
|
||||
}
|
||||
|
||||
|
||||
static void celCensusReport(const StLevelT *level);
|
||||
static void celCensusTick(const StSimT *sim);
|
||||
|
||||
|
||||
static void printState(const StSimT *sim, uint32_t tick) {
|
||||
uint8_t k;
|
||||
|
||||
|
|
@ -55,7 +154,11 @@ static void printState(const StSimT *sim, uint32_t tick) {
|
|||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||
printf("%03X%02X", sim->frame.x[k], sim->frame.y[k]);
|
||||
}
|
||||
printf("\"}\n");
|
||||
printf("\",\"scr\":\"%08X\",\"col\":\"%08X\",\"chr\":\"%08X\",\"bd\":\"%02X\",\"bg\":\"%02X\"}\n",
|
||||
hashBytes(sim->screen, ST_SCREEN_CELLS),
|
||||
hashBytes(sim->color, ST_SCREEN_CELLS),
|
||||
charsetHash(sim),
|
||||
sim->borderColor, sim->bgColor);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -63,11 +166,12 @@ int main(int argc, char **argv) {
|
|||
FILE *fp;
|
||||
const uint8_t *stream = kDemoStreamH;
|
||||
uint16_t len = (uint16_t)sizeof(kDemoStreamH);
|
||||
uint8_t want;
|
||||
uint32_t ticks;
|
||||
uint32_t t;
|
||||
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "usage: stsim <level.dat> <H|W|T|X> <ticks>\n");
|
||||
fprintf(stderr, "usage: stsim <level.dat> <level letter> <ticks>\n");
|
||||
return 2;
|
||||
}
|
||||
fp = fopen(argv[1], "rb");
|
||||
|
|
@ -76,11 +180,29 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
fclose(fp);
|
||||
switch (argv[2][0]) {
|
||||
want = (uint8_t)argv[2][0];
|
||||
switch (want) {
|
||||
case 'W': stream = kDemoStreamW; len = (uint16_t)sizeof(kDemoStreamW); break;
|
||||
case 'T': stream = kDemoStreamT; len = (uint16_t)sizeof(kDemoStreamT); break;
|
||||
case 'X': stream = kDemoStreamX; len = (uint16_t)sizeof(kDemoStreamX); break;
|
||||
default: break;
|
||||
case 'H': break;
|
||||
default: {
|
||||
// A synthesised gate fixture for a level the C64 has no
|
||||
// attract recording of (see gateStreams.h).
|
||||
uint8_t g;
|
||||
for (g = 0u; g < ST_GATE_STREAMS; g++) {
|
||||
if (kGateStreams[g].level == want) {
|
||||
stream = kGateStreams[g].stream;
|
||||
len = kGateStreams[g].length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (g == ST_GATE_STREAMS) {
|
||||
fprintf(stderr, "stsim: no stream for '%c'\n", (char)want);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ticks = (uint32_t)strtoul(argv[3], NULL, 0);
|
||||
stSimNewGame(&gSim, 1u, true);
|
||||
|
|
@ -101,10 +223,16 @@ int main(int argc, char **argv) {
|
|||
StTickResultE r;
|
||||
printState(&gSim, t);
|
||||
r = stSimTick(&gSim);
|
||||
if (getenv("STSIM_CELS") != NULL) {
|
||||
celCensusTick(&gSim);
|
||||
}
|
||||
if (r != ST_TICK_CONTINUE) {
|
||||
printf("{\"tick\":%u,\"end\":%d}\n", t, (int)r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (getenv("STSIM_CELS") != NULL) {
|
||||
celCensusReport(&gLevel);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue