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)
|
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():
|
def main():
|
||||||
raw = load_raw()
|
raw = load_raw()
|
||||||
sprite_count = SPRITE_PTR_LAST - SPRITE_PTR_FIRST + 1
|
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("// 8=RIGHT); 0 = no cel for that combination.")
|
||||||
h.append("extern const uint8_t kStFlameCelByDirMask[16];")
|
h.append("extern const uint8_t kStFlameCelByDirMask[16];")
|
||||||
h.append("")
|
h.append("")
|
||||||
h.append("// Level-intro star velocities per sprite 0..6 ($450C / $4513).")
|
h.append("// Cross-segment-safe accessors (see stC64Data.c): reach the tables above")
|
||||||
h.append("extern const int8_t kStIntroStarDx[7];")
|
h.append("// by an inter-segment call on the IIgs, where a direct 2-byte data")
|
||||||
h.append("extern const int8_t kStIntroStarDy[7];")
|
h.append("// reference from another bank is not relocatable.")
|
||||||
|
for decl in ACCESSORS:
|
||||||
|
h.append(decl[0])
|
||||||
h.append("")
|
h.append("")
|
||||||
h.append("#endif")
|
h.append("#endif")
|
||||||
|
|
||||||
|
|
@ -143,11 +160,25 @@ def main():
|
||||||
c.append(c_bytes(flame))
|
c.append(c_bytes(flame))
|
||||||
c.append("};")
|
c.append("};")
|
||||||
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("// ---------------------------------------------------------------------------")
|
||||||
|
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:
|
with open(OUT_H, "w", encoding="ascii") as fp:
|
||||||
fp.write("\n".join(h) + "\n")
|
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 <string.h>
|
||||||
|
|
||||||
#include "spacetaxi.h"
|
#include <joey/file.h>
|
||||||
#include "stDemoStreams.h"
|
|
||||||
|
|
||||||
// Diagnostics. The logger drags in vsnprintf (with newlib that pulls the
|
#include "spacetaxi.h"
|
||||||
// whole formatted-output and float-conversion family, ~45 KB) plus a
|
#include "stSongData.h"
|
||||||
// multi-KB ring buffer, and the game has no need of either. That is
|
#include "stDemoStreams.h"
|
||||||
// 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
|
|
||||||
|
|
||||||
#define ST_TICK_HZ 30u
|
#define ST_TICK_HZ 30u
|
||||||
#define ST_MAX_CATCHUP_TICKS 4u
|
#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
|
// "GET READY" shows over the old screen while the C64 cycles the
|
||||||
// leaving-passenger sprites (three busy waits, about half a second).
|
// leaving-passenger sprites (three busy waits, about half a second).
|
||||||
#define ST_GET_READY_TICKS 15u
|
#define ST_GET_READY_TICKS 15u
|
||||||
|
|
@ -48,6 +41,18 @@
|
||||||
// Menu joystick repeat delay ($4101 with X = $82).
|
// Menu joystick repeat delay ($4101 with X = $82).
|
||||||
#define ST_MENU_REPEAT_TICKS 8u
|
#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 {
|
typedef enum {
|
||||||
ST_STATE_TITLE = 0,
|
ST_STATE_TITLE = 0,
|
||||||
ST_STATE_HIGHSCORES,
|
ST_STATE_HIGHSCORES,
|
||||||
|
|
@ -57,7 +62,9 @@ typedef enum {
|
||||||
ST_STATE_GET_READY,
|
ST_STATE_GET_READY,
|
||||||
ST_STATE_INTRO,
|
ST_STATE_INTRO,
|
||||||
ST_STATE_PLAYING,
|
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;
|
} StStateE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -73,8 +80,39 @@ typedef struct {
|
||||||
bool fireArmed; // $445D: FIRE must be released first
|
bool fireArmed; // $445D: FIRE must be released first
|
||||||
uint8_t lastFrame;
|
uint8_t lastFrame;
|
||||||
uint16_t paceAcc;
|
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;
|
} 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.
|
// Menu texts ($5347..$545D) in screen codes.
|
||||||
static const uint8_t kTextGameVariations[] = "GAME VARIATIONS";
|
static const uint8_t kTextGameVariations[] = "GAME VARIATIONS";
|
||||||
static const uint8_t kTextCabbies[] = "SELECT NUMBER OF CABBIES:";
|
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 kTextOnTheTaxi[] = " ON THE SPACE TAXI! ";
|
||||||
static const uint8_t kTextGameOver[] = " GAME OVER! ";
|
static const uint8_t kTextGameOver[] = " GAME OVER! ";
|
||||||
static const uint8_t kTextBlank12[] = " ";
|
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 kTextImmortal[] = "THE IMMORTAL CABBIES";
|
||||||
static const uint8_t *kHighScores[8] = {
|
static const uint8_t kTextShift[] = "SHIFT";
|
||||||
(const uint8_t *)"3877.56 MICHAEL PLATE",
|
static const uint8_t kTextReturnTitle[] = "PRESS FIRE TO RETURN TO TITLE PAGE";
|
||||||
(const uint8_t *)"1809.51 MICHAEL PLATE",
|
static const uint8_t kTextCongrats[] = "CONGRATULATIONS CABBIE ,";
|
||||||
(const uint8_t *)"1179.87 ANDREAS PLATE",
|
static const uint8_t kTextRanks[] = "YOUR SCORE RANKS YOU AS ONE OF";
|
||||||
(const uint8_t *)" 892.65 MICHAEL PLATE",
|
static const uint8_t kTextTopTen[] = "THE TOP TEN CABBIES OF ALL TIME";
|
||||||
(const uint8_t *)" 685.37 ANDREAS PLATE",
|
static const uint8_t kTextEnterName[] = "ENTER YOUR NAME BELOW";
|
||||||
(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 *kAboutLines[7] = {
|
static const uint8_t *kAboutLines[7] = {
|
||||||
(const uint8_t *)"THIS PROGRAM DEVELOPED AND WRITTEN BY",
|
(const uint8_t *)"THIS PROGRAM DEVELOPED AND WRITTEN BY",
|
||||||
(const uint8_t *)"JOHN F. KUTCHER",
|
(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 const uint8_t kTextReturn[] = "PRESS FIRE TO RETURN";
|
||||||
|
|
||||||
static StGameT gGame;
|
static StGameT gGame;
|
||||||
static StSimT gSim;
|
static StSimT gSim;
|
||||||
|
static jlSurfaceT *gStage;
|
||||||
// One level buffer serves both gameplay and the title screen: the title
|
// 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 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
|
// is loaded into gLevel on each return to the title. (Keeping a second
|
||||||
|
|
@ -126,17 +161,25 @@ static StSimT gSim;
|
||||||
static StLevelT gLevel;
|
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 enterTitle(void);
|
||||||
static void gameOverEnter(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 bool joyFire(void);
|
||||||
static uint8_t joyMask(void);
|
static uint8_t joyMask(void);
|
||||||
static bool loadLevel(uint8_t index);
|
static bool loadLevel(uint8_t index);
|
||||||
static uint8_t nextLevelForShift(void);
|
static uint8_t nextLevelForShift(void);
|
||||||
static uint8_t paceTicks(void);
|
static uint8_t paceTicks(void);
|
||||||
|
static bool serviceJingle(void);
|
||||||
static void runCabbiesMenu(uint8_t ticks);
|
static void runCabbiesMenu(uint8_t ticks);
|
||||||
static void runDemoEnd(void);
|
static void runDemoEnd(void);
|
||||||
static void runIntro(uint8_t ticks);
|
static void runIntro(uint8_t ticks);
|
||||||
|
static void runNameEntry(uint8_t ticks);
|
||||||
|
static bool nameEntryStart(void);
|
||||||
static void runPlaying(uint8_t ticks);
|
static void runPlaying(uint8_t ticks);
|
||||||
static void runShiftMenu(uint8_t ticks);
|
static void runShiftMenu(uint8_t ticks);
|
||||||
static void runTitle(uint8_t ticks);
|
static void runTitle(uint8_t ticks);
|
||||||
|
|
@ -149,12 +192,12 @@ static void startNewScreen(void);
|
||||||
|
|
||||||
|
|
||||||
// $40CA -- spaces everywhere, black.
|
// $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->screen, ST_CHAR_SPACE, ST_SCREEN_CELLS);
|
||||||
memset(sim->color, 0, ST_SCREEN_CELLS);
|
memset(sim->color, 0, ST_SCREEN_CELLS);
|
||||||
stSimDirtyAll(sim);
|
stSimDirtyAll(sim);
|
||||||
sim->bgColor = 0u;
|
sim->bgColor = bg;
|
||||||
sim->borderColor = 0u;
|
sim->borderColor = border;
|
||||||
sim->frame.enableMask = 0u;
|
sim->frame.enableMask = 0u;
|
||||||
stRenderSceneChanged(sim);
|
stRenderSceneChanged(sim);
|
||||||
}
|
}
|
||||||
|
|
@ -166,16 +209,239 @@ static void enterTitle(void) {
|
||||||
if (!stLevelLoad(&gLevel, "levels/title.dat")) {
|
if (!stLevelLoad(&gLevel, "levels/title.dat")) {
|
||||||
ST_LOG("spacetaxi: ! title load FAILED");
|
ST_LOG("spacetaxi: ! title load FAILED");
|
||||||
}
|
}
|
||||||
|
stRenderLevelCels(gStage, 0); // the last level's cels go
|
||||||
stTitleEnter(&gSim, &gLevel);
|
stTitleEnter(&gSim, &gLevel);
|
||||||
stRenderSceneChanged(&gSim);
|
stRenderSceneChanged(&gSim);
|
||||||
stRenderTitleLogo(&gSim);
|
stRenderTitleLogo(&gSim);
|
||||||
stAudioNoise(false);
|
stAudioNoise(false);
|
||||||
stAudioSilence();
|
stAudioSilence();
|
||||||
|
jlMusicStop();
|
||||||
gGame.state = ST_STATE_TITLE;
|
gGame.state = ST_STATE_TITLE;
|
||||||
gGame.fireArmed = false;
|
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.
|
// $5FBB -- "GAME OVER!" over the play field, sprites hidden.
|
||||||
static void gameOverEnter(void) {
|
static void gameOverEnter(void) {
|
||||||
stSimDrawText(&gSim, 14u, 10u, kTextBlank12, 1u);
|
stSimDrawText(&gSim, 14u, 10u, kTextBlank12, 1u);
|
||||||
|
|
@ -184,8 +450,9 @@ static void gameOverEnter(void) {
|
||||||
gSim.frame.enableMask = 0u;
|
gSim.frame.enableMask = 0u;
|
||||||
stAudioNoise(false);
|
stAudioNoise(false);
|
||||||
stAudioSilence();
|
stAudioSilence();
|
||||||
gGame.waitTicks = ST_GAME_OVER_TICKS;
|
gGame.waitTicks = ST_GAME_OVER_TICKS;
|
||||||
gGame.state = ST_STATE_GAME_OVER;
|
gGame.gameOverTune = false;
|
||||||
|
gGame.state = ST_STATE_GAME_OVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -222,7 +489,7 @@ static uint8_t joyMask(void) {
|
||||||
static bool loadLevel(uint8_t index) {
|
static bool loadLevel(uint8_t index) {
|
||||||
char path[32];
|
char path[32];
|
||||||
|
|
||||||
if (index >= ST_LEVEL_COUNT) {
|
if (index >= ST_LEVEL_FILES) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Hand-rolled "levels/levelNN.dat" (NN = index+1, 01..24) so the
|
// 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);
|
ST_LOG("spacetaxi: ! cannot load %s", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
stRenderLevelCels(gStage, &gLevel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,7 +522,13 @@ static uint8_t nextLevelForShift(void) {
|
||||||
}
|
}
|
||||||
return (uint8_t)((gGame.variation - 1u) * 8u + sim->levelState);
|
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;
|
return 0xFFu;
|
||||||
}
|
}
|
||||||
if (gGame.variation == 4u) {
|
if (gGame.variation == 4u) {
|
||||||
|
|
@ -355,6 +629,7 @@ static void runIntro(uint8_t ticks) {
|
||||||
}
|
}
|
||||||
for (k = 0u; k < (uint8_t)(ticks * 2u); k++) {
|
for (k = 0u; k < (uint8_t)(ticks * 2u); k++) {
|
||||||
if (stIntroStep(&gSim)) {
|
if (stIntroStep(&gSim)) {
|
||||||
|
jlMusicStop(); // $4709
|
||||||
stSimEnterLevel(&gSim, &gLevel);
|
stSimEnterLevel(&gSim, &gLevel);
|
||||||
stRenderSceneChanged(&gSim);
|
stRenderSceneChanged(&gSim);
|
||||||
if (gGame.demo) {
|
if (gGame.demo) {
|
||||||
|
|
@ -362,6 +637,7 @@ static void runIntro(uint8_t ticks) {
|
||||||
stSimSetDemoStream(&gSim, e->stream, e->length);
|
stSimSetDemoStream(&gSim, e->stream, e->length);
|
||||||
}
|
}
|
||||||
gGame.state = ST_STATE_PLAYING;
|
gGame.state = ST_STATE_PLAYING;
|
||||||
|
serviceJingle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -377,6 +653,9 @@ static void runPlaying(uint8_t ticks) {
|
||||||
StTickResultE r = stSimTick(&gSim);
|
StTickResultE r = stSimTick(&gSim);
|
||||||
stAudioTick();
|
stAudioTick();
|
||||||
if (r == ST_TICK_CONTINUE) {
|
if (r == ST_TICK_CONTINUE) {
|
||||||
|
if (serviceJingle()) {
|
||||||
|
return; // $70D4 bonus cab: the tune blocks
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (gGame.demo) {
|
if (gGame.demo) {
|
||||||
|
|
@ -390,6 +669,9 @@ static void runPlaying(uint8_t ticks) {
|
||||||
case ST_TICK_LIFE_LOST:
|
case ST_TICK_LIFE_LOST:
|
||||||
stSimRespawn(&gSim);
|
stSimRespawn(&gSim);
|
||||||
stRenderSceneChanged(&gSim);
|
stRenderSceneChanged(&gSim);
|
||||||
|
if (serviceJingle()) {
|
||||||
|
return; // $6906 on the new cab
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ST_TICK_PLAYER_OUT:
|
case ST_TICK_PLAYER_OUT:
|
||||||
gameOverEnter();
|
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.
|
// $54F8 -- UP/DOWN pick the shift, FIRE confirms and starts the game.
|
||||||
static void runShiftMenu(uint8_t ticks) {
|
static void runShiftMenu(uint8_t ticks) {
|
||||||
uint8_t mask = joyMask();
|
uint8_t mask = joyMask();
|
||||||
|
|
@ -462,13 +765,7 @@ static void runTitle(uint8_t ticks) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((mask & 0x01u) != 0u) {
|
if ((mask & 0x01u) != 0u) {
|
||||||
uint8_t i;
|
highScoreDraw();
|
||||||
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);
|
|
||||||
gGame.state = ST_STATE_HIGHSCORES;
|
gGame.state = ST_STATE_HIGHSCORES;
|
||||||
gGame.fireArmed = false;
|
gGame.fireArmed = false;
|
||||||
return;
|
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 kAboutCols[7] = { 1u, 12u, 15u, 4u, 5u, 6u, 1u };
|
||||||
static const uint8_t kAboutRows[7] = { 3u, 5u, 7u, 10u, 12u, 14u, 18u };
|
static const uint8_t kAboutRows[7] = { 3u, 5u, 7u, 10u, 12u, 14u, 18u };
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
blankScreen(&gSim);
|
blankScreen(&gSim, 12u, 15u); // $558E: grey border, light-grey field
|
||||||
for (i = 0u; i < 7u; i++) {
|
for (i = 0u; i < 7u; i++) {
|
||||||
stSimDrawText(&gSim, kAboutCols[i], kAboutRows[i], kAboutLines[i], 1u);
|
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.
|
// $5295 -- GAME VARIATIONS page 1.
|
||||||
static void showCabbiesMenu(void) {
|
static void showCabbiesMenu(void) {
|
||||||
blankScreen(&gSim);
|
blankScreen(&gSim, 0u, 0u);
|
||||||
stSimDrawText(&gSim, 13u, 0u, kTextGameVariations, 5u);
|
stSimDrawText(&gSim, 13u, 0u, kTextGameVariations, 5u);
|
||||||
stSimDrawText(&gSim, 1u, 2u, kTextCabbies, 7u);
|
stSimDrawText(&gSim, 1u, 2u, kTextCabbies, 7u);
|
||||||
stSimDrawText(&gSim, 5u, 4u, kTextLeftRight, 11u);
|
stSimDrawText(&gSim, 5u, 4u, kTextLeftRight, 11u);
|
||||||
|
|
@ -518,7 +815,7 @@ static void showCabbiesMenu(void) {
|
||||||
static void showShiftMenu(void) {
|
static void showShiftMenu(void) {
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
|
||||||
blankScreen(&gSim);
|
blankScreen(&gSim, 0u, 0u);
|
||||||
stSimDrawText(&gSim, 1u, 8u, kTextSelectShift, 7u);
|
stSimDrawText(&gSim, 1u, 8u, kTextSelectShift, 7u);
|
||||||
for (i = 0u; i < 5u; i++) {
|
for (i = 0u; i < 5u; i++) {
|
||||||
stSimDrawText(&gSim, 2u, (uint8_t)(10u + i * 2u), kTextShifts[i], 6u);
|
stSimDrawText(&gSim, 2u, (uint8_t)(10u + i * 2u), kTextShifts[i], 6u);
|
||||||
|
|
@ -560,6 +857,11 @@ static void startDemoScreen(void) {
|
||||||
static void startIntro(void) {
|
static void startIntro(void) {
|
||||||
stIntroEnter(&gSim, &gLevel);
|
stIntroEnter(&gSim, &gLevel);
|
||||||
stRenderSceneChanged(&gSim);
|
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;
|
gGame.state = ST_STATE_INTRO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -601,9 +903,15 @@ int main(void) {
|
||||||
jlConfigT config;
|
jlConfigT config;
|
||||||
jlSurfaceT *stage;
|
jlSurfaceT *stage;
|
||||||
|
|
||||||
#if defined(JOEYLIB_PLATFORM_IIGS)
|
// The codegen arena holds every compiled cel, the baked ones too: the
|
||||||
// One 64 KB bank: enough for the cab, exhaust and passenger cels.
|
// 37 cab/exhaust/passenger cels plus a level's hook cels (level I has
|
||||||
config.codegenBytes = 60UL * 1024;
|
// 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
|
#else
|
||||||
config.codegenBytes = 160UL * 1024;
|
config.codegenBytes = 160UL * 1024;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -618,6 +926,7 @@ int main(void) {
|
||||||
jlShutdown();
|
jlShutdown();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
gStage = stage;
|
||||||
memset(&gGame, 0, sizeof(gGame));
|
memset(&gGame, 0, sizeof(gGame));
|
||||||
memset(&gSim, 0, sizeof(gSim));
|
memset(&gSim, 0, sizeof(gSim));
|
||||||
stRenderInit(stage);
|
stRenderInit(stage);
|
||||||
|
|
@ -630,6 +939,7 @@ int main(void) {
|
||||||
stSimSeedDemoBuffer(&gSim, kDemoBufferInit, ST_DEMO_BUFFER_BYTES);
|
stSimSeedDemoBuffer(&gSim, kDemoBufferInit, ST_DEMO_BUFFER_BYTES);
|
||||||
gSim.waveIdx = 3u;
|
gSim.waveIdx = 3u;
|
||||||
stRenderPrewarm(stage, &gSim);
|
stRenderPrewarm(stage, &gSim);
|
||||||
|
highScoreLoad(); // $23E5
|
||||||
enterTitle();
|
enterTitle();
|
||||||
gGame.lastFrame = (uint8_t)jlFrameCount();
|
gGame.lastFrame = (uint8_t)jlFrameCount();
|
||||||
|
|
||||||
|
|
@ -637,8 +947,39 @@ int main(void) {
|
||||||
uint8_t ticks;
|
uint8_t ticks;
|
||||||
|
|
||||||
jlInputPoll();
|
jlInputPoll();
|
||||||
if (jlKeyPressed(KEY_ESCAPE)) {
|
// $4FCB runStopWatcher, on the game tick, the intro and the menus:
|
||||||
break;
|
// 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();
|
ticks = paceTicks();
|
||||||
switch (gGame.state) {
|
switch (gGame.state) {
|
||||||
|
|
@ -677,19 +1018,33 @@ int main(void) {
|
||||||
case ST_STATE_PLAYING:
|
case ST_STATE_PLAYING:
|
||||||
runPlaying(ticks);
|
runPlaying(ticks);
|
||||||
break;
|
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:
|
case ST_STATE_GAME_OVER:
|
||||||
if (gGame.waitTicks > ticks) {
|
if (gGame.waitTicks > ticks) {
|
||||||
gGame.waitTicks = (uint16_t)(gGame.waitTicks - ticks);
|
gGame.waitTicks = (uint16_t)(gGame.waitTicks - ticks);
|
||||||
} else {
|
} else if (!gGame.gameOverTune) {
|
||||||
// $6BD0: one more player done; everybody done -> title.
|
// $5C24: after the GAME OVER! wait, song 5 plays out.
|
||||||
gSim.playersDone++;
|
gGame.gameOverTune = true;
|
||||||
if (gSim.playersDone == gSim.playerCount) {
|
stAudioJingle(ST_SONG_GAME_OVER);
|
||||||
enterTitle();
|
} else if (stAudioJingleActive()) {
|
||||||
} else {
|
// still sounding
|
||||||
startNewScreen();
|
} else if (!nameEntryStart()) {
|
||||||
}
|
gameOverFinish();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ST_STATE_NAME_ENTRY:
|
||||||
|
runNameEntry(ticks);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
enterTitle();
|
enterTitle();
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
21
spacetaxi.h
21
spacetaxi.h
|
|
@ -15,6 +15,21 @@
|
||||||
|
|
||||||
#include "stSim.h"
|
#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/...).
|
// Level loading through the JoeyLib data path (DATA/levels/...).
|
||||||
bool stLevelLoad(StLevelT *out, const char *path);
|
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.
|
// cycle are palette writes instead of repainting 103 (and 407) cells.
|
||||||
// Call after stRenderSceneChanged, which turns it back off.
|
// Call after stRenderSceneChanged, which turns it back off.
|
||||||
void stRenderTitleLogo(StSimT *sim);
|
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);
|
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).
|
// Audio sink setup and the per-tick release timers ($4320).
|
||||||
void stAudioInit(void);
|
void stAudioInit(void);
|
||||||
|
|
|
||||||
421
stAudio.c
421
stAudio.c
|
|
@ -8,8 +8,18 @@
|
||||||
// time; envelopes and waveforms are approximated with an attenuation
|
// time; envelopes and waveforms are approximated with an attenuation
|
||||||
// ramp. The speech samples of the original are not extracted; each
|
// ramp. The speech samples of the original are not extracted; each
|
||||||
// spoken character becomes a short chirp so the cues still land.
|
// 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 "spacetaxi.h"
|
||||||
|
#include <joey/file.h>
|
||||||
|
#include "stSongData.h"
|
||||||
|
|
||||||
|
|
||||||
// SID voice index in a program's byte 8 -> JoeyLib voice slot.
|
// 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_NUM 1022727UL
|
||||||
#define ST_SID_HZ_DEN 16777216UL
|
#define ST_SID_HZ_DEN 16777216UL
|
||||||
|
|
||||||
// Speech chirp: one short tone per character, pitched by the character.
|
// ---- speech ----
|
||||||
#define ST_SPEECH_TICKS 3u
|
//
|
||||||
#define ST_SPEECH_BASE_HZ 300u
|
// The C64 player ($9802) busy-waits a delay loop per stream byte and then
|
||||||
#define ST_SPEECH_STEP_HZ 9u
|
// 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
|
// Thrust sweep register value -> Hz: the C64 writes the same byte to
|
||||||
// both frequency bytes, so the word is value * 257.
|
// 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 gSfx; // SID voice 1 (programs + sweep)
|
||||||
static StSfxSlotT gTone; // SID voice 2
|
static StSfxSlotT gTone; // SID voice 2
|
||||||
static bool gNoiseOn;
|
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 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);
|
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) {
|
static void voiceOff(StSfxSlotT *slot) {
|
||||||
if (slot->ticksLeft != 0u) {
|
if (slot->ticksLeft != 0u) {
|
||||||
jlAudioVoice(slot->voice, 0u, ST_ATTEN_OFF);
|
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).
|
// Once per game tick: run the release timers ($4320 sfxEnvelopeTick).
|
||||||
void stAudioTick(void) {
|
void stAudioTick(void) {
|
||||||
|
if (gSpeechActive) {
|
||||||
|
speechPumpSlice(ST_SPEECH_TICK_SLICE);
|
||||||
|
}
|
||||||
if (gSfx.ticksLeft != 0u) {
|
if (gSfx.ticksLeft != 0u) {
|
||||||
gSfx.ticksLeft--;
|
gSfx.ticksLeft--;
|
||||||
if (gSfx.ticksLeft == 0u) {
|
if (gSfx.ticksLeft == 0u) {
|
||||||
|
|
@ -83,23 +368,23 @@ void stAudioTick(void) {
|
||||||
jlAudioVoice(gTone.voice, 0u, ST_ATTEN_OFF);
|
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 stAudioInit(void) {
|
||||||
(void)jlAudioInit();
|
(void)jlAudioInit();
|
||||||
|
gSpeechStage = (uint8_t *)jlAlloc(ST_SPEECH_STAGE_BYTES);
|
||||||
|
speechLoad();
|
||||||
gSfx.voice = ST_VOICE_SFX;
|
gSfx.voice = ST_VOICE_SFX;
|
||||||
gSfx.ticksLeft = 0u;
|
gSfx.ticksLeft = 0u;
|
||||||
gTone.voice = ST_VOICE_TONE;
|
gTone.voice = ST_VOICE_TONE;
|
||||||
gTone.ticksLeft = 0u;
|
gTone.ticksLeft = 0u;
|
||||||
gNoiseOn = false;
|
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);
|
voiceOff(&gTone);
|
||||||
jlAudioNoise(0u, ST_ATTEN_OFF);
|
jlAudioNoise(0u, ST_ATTEN_OFF);
|
||||||
jlAudioShutdown();
|
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) {
|
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);
|
if (speechQueue(ch)) {
|
||||||
gSpeechTicks = ST_SPEECH_TICKS;
|
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,
|
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
|
// 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) {
|
uint8_t stC64FlameCel(uint8_t dirMask) {
|
||||||
return kStFlameCelByDirMask[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.
|
// 8=RIGHT); 0 = no cel for that combination.
|
||||||
extern const uint8_t kStFlameCelByDirMask[16];
|
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
|
// 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
|
// by an inter-segment call on the IIgs, where a direct 2-byte data
|
||||||
// reference from another bank is not relocatable.
|
// reference from another bank is not relocatable.
|
||||||
|
|
@ -56,7 +52,5 @@ const uint8_t *stC64SpriteBitmap(uint8_t idx);
|
||||||
uint8_t stC64RngByte(uint8_t idx);
|
uint8_t stC64RngByte(uint8_t idx);
|
||||||
const uint8_t *stC64SfxProgram(uint8_t idx);
|
const uint8_t *stC64SfxProgram(uint8_t idx);
|
||||||
uint8_t stC64FlameCel(uint8_t dirMask);
|
uint8_t stC64FlameCel(uint8_t dirMask);
|
||||||
int8_t stC64IntroStarDx(uint8_t idx);
|
|
||||||
int8_t stC64IntroStarDy(uint8_t idx);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
7
stCels.h
7
stCels.h
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "stSim.h"
|
||||||
|
|
||||||
// 3x3 tiles = 24x24 px; 32 bytes per 8x8 tile, tile-major (matches
|
// 3x3 tiles = 24x24 px; 32 bytes per 8x8 tile, tile-major (matches
|
||||||
// jlSpriteCreateFromSurface / the .spr cel layout).
|
// jlSpriteCreateFromSurface / the .spr cel layout).
|
||||||
#define ST_CEL_TILES 3u
|
#define ST_CEL_TILES 3u
|
||||||
|
|
@ -29,6 +31,11 @@ typedef struct {
|
||||||
extern const StCelDefT kStCels[];
|
extern const StCelDefT kStCels[];
|
||||||
extern const uint16_t kStCelCount;
|
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
|
// 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
|
// tile-major 4bpp-packed cel blob. Colours as in the C64 multicolour
|
||||||
// rules; hires uses `color` for a set bit.
|
// rules; hires uses `color` for a set bit.
|
||||||
|
|
|
||||||
95
stFare.c
95
stFare.c
|
|
@ -11,17 +11,16 @@
|
||||||
#include "stSim.h"
|
#include "stSim.h"
|
||||||
|
|
||||||
// Screen-code strings ($6C1E..$6C7D). All ASCII-compatible glyphs.
|
// 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 kTextPadPlease[] = "PAD PLEASE"; // $6C1E
|
||||||
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 kTextUpPlease[] = " UP PLEASE! "; // $6C2B
|
||||||
static const uint8_t kTextBlank[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0 }; // $6C38
|
static const uint8_t kTextHeyTaxi[] = " HEY, TAXI! "; // $6C45
|
||||||
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[] = " THANKS "; // $6C5F
|
||||||
static const uint8_t kTextThanks[] = { 0x20, 0x20, 0x20, 0x54, 0x48, 0x41, 0x4E, 0x4B, 0x53, 0x20, 0x20, 0x20, 0 }; // $6C5F " THANKS "
|
|
||||||
// Speech cue strings fed to the sample player one character at a time.
|
// 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 kSpeechHeyTaxi[] = "HT"; // $6C6C
|
||||||
static const uint8_t kSpeechUp[] = { 0x55, 0x3F, 0 }; // $6C6F "U?"
|
static const uint8_t kSpeechUp[] = "U?"; // $6C6F
|
||||||
static const uint8_t kSpeechPad[] = { 0x50, 0x58, 0x3F, 0 }; // $6C72 "PX?" (X = digit)
|
static const uint8_t kSpeechPad[] = "PX?"; // $6C72 (X = digit)
|
||||||
static const uint8_t kSpeechThanks[] = { 0x21, 0 }; // $6C76 "!"
|
static const uint8_t kSpeechThanks[] = "!"; // $6C76
|
||||||
static const uint8_t kSpeechHey[] = { 0x48, 0 }; // $6C78 "H"
|
static const uint8_t kSpeechHey[] = "H"; // $6C78
|
||||||
// Waiting wave cycle ($66D6) and the base-fare blob ($43B9 = +5.00).
|
// 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 kWaveCels[4] = { 0xC6, 0xC7, 0xD9, 0xC7 };
|
||||||
static const uint8_t kFareBlob[7] = { 0x66, 0x66, 0x66, 0x6F, 0x77, 0x74, 0x74 };
|
static const uint8_t kFareBlob[7] = { 0x66, 0x66, 0x66, 0x6F, 0x77, 0x74, 0x74 };
|
||||||
|
|
@ -45,12 +44,12 @@ static void beamIn(StSimT *sim) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim->spr[1].ptr--;
|
sim->spr[1].ptr--;
|
||||||
if (sim->spr[1].ptr != 0xC7u) {
|
if (sim->spr[1].ptr != ST_SPRITE_PASS_STAND) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sim->collisionPhase != 0u) {
|
if (sim->collisionPhase != 0u) {
|
||||||
sim->stage = ST_STAGE_LEAVE;
|
sim->stage = ST_STAGE_LEAVE;
|
||||||
sim->spr[1].ptr = 0xC7u;
|
sim->spr[1].ptr = ST_SPRITE_PASS_STAND;
|
||||||
sim->spriteSlots[sim->activeSpriteIdx] = 0u;
|
sim->spriteSlots[sim->activeSpriteIdx] = 0u;
|
||||||
sim->activeSpriteIdx = 0u;
|
sim->activeSpriteIdx = 0u;
|
||||||
sim->fareSlotCount--;
|
sim->fareSlotCount--;
|
||||||
|
|
@ -60,15 +59,9 @@ static void beamIn(StSimT *sim) {
|
||||||
stSimDrawText(sim, 14u, 24u, kTextHeyTaxi, 1u);
|
stSimDrawText(sim, 14u, 24u, kTextHeyTaxi, 1u);
|
||||||
stFareBoardingSound(sim, kSpeechHeyTaxi);
|
stFareBoardingSound(sim, kSpeechHeyTaxi);
|
||||||
// $43D1: the meter starts at $10.00..$19.00.
|
// $43D1: the meter starts at $10.00..$19.00.
|
||||||
{
|
stSimHudInit(sim);
|
||||||
uint8_t k;
|
stSimPutChar(sim, 35u, 24u, (uint8_t)(ST_CHAR_DIGIT_BASE + stSimRng(sim, 10u)));
|
||||||
static const uint8_t kTemplate[7] = { 0x66, 0x66, 0x66, 0x74, 0x77, 0x74, 0x74 };
|
stSimPutChar(sim, 34u, 24u, (uint8_t)(ST_CHAR_DIGIT_BASE + 1u));
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -125,7 +118,7 @@ static void newFare(StSimT *sim) {
|
||||||
sim->spr[1].enable = 1u;
|
sim->spr[1].enable = 1u;
|
||||||
sim->stage = ST_STAGE_BEAM_IN;
|
sim->stage = ST_STAGE_BEAM_IN;
|
||||||
sim->decayTimer = sim->decayReload;
|
sim->decayTimer = sim->decayReload;
|
||||||
sim->spr[1].ptr = 0xCBu;
|
sim->spr[1].ptr = ST_SPRITE_PASS_BEAM;
|
||||||
stAudioSpeech((uint8_t)(stSimRng(sim, 3u) + 2u));
|
stAudioSpeech((uint8_t)(stSimRng(sim, 3u) + 2u));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,14 +129,14 @@ static void stageBoard(StSimT *sim) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim->spr[1].ptr++;
|
sim->spr[1].ptr++;
|
||||||
if (sim->spr[1].ptr != 0xCCu) {
|
if (sim->spr[1].ptr != ST_SPRITE_PASS_GONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim->spr[1].enable = 0u;
|
sim->spr[1].enable = 0u;
|
||||||
sim->stage++;
|
sim->stage++;
|
||||||
sim->activeDyingSlot = sim->activePad;
|
sim->activeDyingSlot = sim->activePad;
|
||||||
(void)stFareChooseDestination(sim);
|
(void)stFareChooseDestination(sim);
|
||||||
if (sim->activeSpriteIdx == 0x0Bu) {
|
if (sim->activeSpriteIdx == ST_FARE_DEST_UP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stSimDrawText(sim, 14u, 24u, kTextPadPlease, 1u);
|
stSimDrawText(sim, 14u, 24u, kTextPadPlease, 1u);
|
||||||
|
|
@ -164,7 +157,7 @@ static void stageCleanup(StSimT *sim) {
|
||||||
sim->deathInProgress = 0u;
|
sim->deathInProgress = 0u;
|
||||||
sim->stage = ST_STAGE_IDLE;
|
sim->stage = ST_STAGE_IDLE;
|
||||||
stSimPadLight(sim, false);
|
stSimPadLight(sim, false);
|
||||||
stSimDrawText(sim, 14u, 24u, kTextBlank, 1u);
|
stSimClearMessage(sim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -176,7 +169,7 @@ static void stageDropIn(StSimT *sim) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim->spr[1].ptr--;
|
sim->spr[1].ptr--;
|
||||||
if (sim->spr[1].ptr != 0xC7u) {
|
if (sim->spr[1].ptr != ST_SPRITE_PASS_STAND) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim->stage++;
|
sim->stage++;
|
||||||
|
|
@ -184,13 +177,7 @@ static void stageDropIn(StSimT *sim) {
|
||||||
stFareBoardingSound(sim, kSpeechThanks);
|
stFareBoardingSound(sim, kSpeechThanks);
|
||||||
stSimBcdAdd(sim, ST_CELL_SCORE, kFareBlob);
|
stSimBcdAdd(sim, ST_CELL_SCORE, kFareBlob);
|
||||||
stSimBcdAdd(sim, ST_CELL_SCORE, &sim->screen[ST_CELL_FARE]);
|
stSimBcdAdd(sim, ST_CELL_SCORE, &sim->screen[ST_CELL_FARE]);
|
||||||
{
|
stSimHudInit(sim);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sim->fareSlotCount != 0u) {
|
if (sim->fareSlotCount != 0u) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +191,7 @@ void stFareLeaveStep(StSimT *sim) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim->spr[1].ptr++;
|
sim->spr[1].ptr++;
|
||||||
if (sim->spr[1].ptr != 0xCCu) {
|
if (sim->spr[1].ptr != ST_SPRITE_PASS_GONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim->spr[1].enable = 0u;
|
sim->spr[1].enable = 0u;
|
||||||
|
|
@ -227,24 +214,19 @@ void stFareWaveStep(StSimT *sim) {
|
||||||
void stFareWalkStep(StSimT *sim) {
|
void stFareWalkStep(StSimT *sim) {
|
||||||
int16_t passX;
|
int16_t passX;
|
||||||
int16_t targetX;
|
int16_t targetX;
|
||||||
uint16_t sum;
|
|
||||||
|
|
||||||
sim->walkParity ^= 1u;
|
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);
|
targetX = (int16_t)(((int16_t)sim->hoverXFrac << 8) | sim->hoverXCol);
|
||||||
if ((int16_t)(passX - targetX) < 0) {
|
if ((int16_t)(passX - targetX) < 0) {
|
||||||
// $6D30: walk right, cels $C2/$C3.
|
// $6D30: walk right, cels $C2/$C3.
|
||||||
sim->spr[1].ptr = (uint8_t)(0xC2u + sim->walkParity);
|
sim->spr[1].ptr = (uint8_t)(ST_SPRITE_PASS_WALK_R + sim->walkParity);
|
||||||
sum = (uint16_t)((uint16_t)sim->spr[1].col + 2u);
|
stSimSpriteAddX(sim, 1u, 2u);
|
||||||
sim->spr[1].col = (uint8_t)sum;
|
|
||||||
sim->spr[1].msb = (uint8_t)(sim->spr[1].msb + (uint8_t)(sum >> 8));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// $6D4B: walk left, cels $C4/$C5.
|
// $6D4B: walk left, cels $C4/$C5.
|
||||||
sim->spr[1].ptr = (uint8_t)(0xC4u + sim->walkParity);
|
sim->spr[1].ptr = (uint8_t)(ST_SPRITE_PASS_WALK_L + sim->walkParity);
|
||||||
sum = (uint16_t)((uint16_t)sim->spr[1].col + 0xFEu);
|
stSimSpriteAddX(sim, 1u, 0xFEu);
|
||||||
sim->spr[1].col = (uint8_t)sum;
|
|
||||||
sim->spr[1].msb = (uint8_t)(sim->spr[1].msb + 0xFFu + (uint8_t)(sum >> 8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -255,7 +237,7 @@ static void walkToTarget(StSimT *sim) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((sim->spr[1].col & 0xFEu) == (sim->hoverXCol & 0xFEu)) {
|
if ((sim->spr[1].col & 0xFEu) == (sim->hoverXCol & 0xFEu)) {
|
||||||
sim->spr[1].ptr = 0xC7u;
|
sim->spr[1].ptr = ST_SPRITE_PASS_STAND;
|
||||||
sim->stage++;
|
sim->stage++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -272,17 +254,14 @@ void stFareBoardingSound(StSimT *sim, const uint8_t *speech) {
|
||||||
(void)sim;
|
(void)sim;
|
||||||
stAudioSilence();
|
stAudioSilence();
|
||||||
stAudioNoise(false);
|
stAudioNoise(false);
|
||||||
while (*speech != 0u) {
|
stAudioSpeechPhrase(speech);
|
||||||
stAudioSpeech(*speech);
|
|
||||||
speech++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// $6537 -- reserve a free fare pad by RNG (linear probe on collision),
|
// $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.
|
// or "UP PLEASE" once every fare pad is taken. Returns the pad number.
|
||||||
uint8_t stFareChooseDestination(StSimT *sim) {
|
uint8_t stFareChooseDestination(StSimT *sim) {
|
||||||
uint8_t special = sim->level->specialPad;
|
uint8_t special = sim->specialPad;
|
||||||
uint8_t x;
|
uint8_t x;
|
||||||
|
|
||||||
if (sim->fareSlotCount == special) {
|
if (sim->fareSlotCount == special) {
|
||||||
|
|
@ -349,7 +328,7 @@ void stFarePostTickGate(StSimT *sim) {
|
||||||
sim->spr[1].msb = sim->spr[0].msb;
|
sim->spr[1].msb = sim->spr[0].msb;
|
||||||
sim->spr[1].col = sim->spr[0].col;
|
sim->spr[1].col = sim->spr[0].col;
|
||||||
sim->spr[1].row = sim->spr[0].row;
|
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;
|
sim->decayTimer = sim->decayReload;
|
||||||
pad = &sim->pads[sim->activeSpriteIdx - 1u];
|
pad = &sim->pads[sim->activeSpriteIdx - 1u];
|
||||||
sim->hoverXFrac = pad->passMsb;
|
sim->hoverXFrac = pad->passMsb;
|
||||||
|
|
@ -374,7 +353,7 @@ void stFareSquashed(StSimT *sim) {
|
||||||
sim->spriteSlots[sim->activeSpriteIdx] = 0u;
|
sim->spriteSlots[sim->activeSpriteIdx] = 0u;
|
||||||
sim->activeSpriteIdx = 0u;
|
sim->activeSpriteIdx = 0u;
|
||||||
sim->fareSlotCount--;
|
sim->fareSlotCount--;
|
||||||
stSimDrawText(sim, 14u, 24u, kTextBlank, 1u);
|
stSimClearMessage(sim);
|
||||||
}
|
}
|
||||||
sim->stage = ST_STAGE_LEAVE;
|
sim->stage = ST_STAGE_LEAVE;
|
||||||
stFareBoardingSound(sim, kSpeechHey);
|
stFareBoardingSound(sim, kSpeechHey);
|
||||||
|
|
@ -387,14 +366,8 @@ void stFareSquashed(StSimT *sim) {
|
||||||
// $43F3 counts down in the input-mask byte and leaves it zero.
|
// $43F3 counts down in the input-mask byte and leaves it zero.
|
||||||
sim->inputMask = 0u;
|
sim->inputMask = 0u;
|
||||||
}
|
}
|
||||||
sim->spr[1].ptr = 0xC7u;
|
sim->spr[1].ptr = ST_SPRITE_PASS_STAND;
|
||||||
{
|
stSimHudInit(sim);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -442,7 +415,7 @@ void stFareStageDispatch(StSimT *sim) {
|
||||||
void stFareUpPlease(StSimT *sim) {
|
void stFareUpPlease(StSimT *sim) {
|
||||||
uint8_t k;
|
uint8_t k;
|
||||||
|
|
||||||
sim->activeSpriteIdx = 0x0Bu;
|
sim->activeSpriteIdx = ST_FARE_DEST_UP;
|
||||||
stSimDrawText(sim, 14u, 24u, kTextUpPlease, 1u);
|
stSimDrawText(sim, 14u, 24u, kTextUpPlease, 1u);
|
||||||
for (k = 0u; k < 4u; k++) {
|
for (k = 0u; k < 4u; k++) {
|
||||||
stSimPutChar(sim, (uint8_t)(18u + k), 0u, ST_CHAR_SPACE);
|
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
|
// cab, exhaust and passenger sets plus the intro star) or a cel change
|
||||||
// mid-play rebuilds and recompiles a sprite. Glyphs are direct-mapped
|
// mid-play rebuilds and recompiles a sprite. Glyphs are direct-mapped
|
||||||
// by character, so the count is a power of two.
|
// by character, so the count is a power of two.
|
||||||
#if defined(__W65816__)
|
// Room for the baked cab/passenger/exhaust set (37) plus the largest
|
||||||
#define ST_SPRITE_CACHE 48u
|
// level's hook cels (I: 30) at once.
|
||||||
#else
|
#define ST_SPRITE_CACHE 80u
|
||||||
#define ST_SPRITE_CACHE 72u
|
|
||||||
#endif
|
|
||||||
#define ST_SPRITE_BACKUP_BYTES JOEY_SPRITE_BACKUP_BYTES(ST_SPRITE_TILES, ST_SPRITE_TILES)
|
#define ST_SPRITE_BACKUP_BYTES JOEY_SPRITE_BACKUP_BYTES(ST_SPRITE_TILES, ST_SPRITE_TILES)
|
||||||
#define ST_SPRITE_PX (8 * ST_SPRITE_TILES)
|
#define ST_SPRITE_PX (8 * ST_SPRITE_TILES)
|
||||||
// Palette slots the title logo animation owns. The title screen draws
|
// Palette slots the title logo animation owns. The title screen draws
|
||||||
|
|
@ -71,7 +69,9 @@ typedef struct {
|
||||||
bool used;
|
bool used;
|
||||||
bool pinned; // prewarmed moving cel: never evicted (its
|
bool pinned; // prewarmed moving cel: never evicted (its
|
||||||
// compiled code is costly to re-emit on the 65816)
|
// 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 lastUse; // for least-recently-used eviction
|
||||||
|
uint32_t retryAt; // cacheStamp at which a failed compile may retry
|
||||||
} StSpriteCacheT;
|
} StSpriteCacheT;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -91,6 +91,9 @@ typedef struct {
|
||||||
// Title logo (stRenderTitleLogo): all four flip-book frames in one
|
// Title logo (stRenderTitleLogo): all four flip-book frames in one
|
||||||
// tile, animated by rewriting logoSlotMask[]'s palette slots.
|
// tile, animated by rewriting logoSlotMask[]'s palette slots.
|
||||||
bool logoMode;
|
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
|
bool logoTileOk; // the live glyph is one of the frames
|
||||||
uint8_t logoSlotCount;
|
uint8_t logoSlotCount;
|
||||||
uint8_t logoSlotMask[ST_LOGO_PAL_SLOTS]; // frames each slot is lit in
|
uint8_t logoSlotMask[ST_LOGO_PAL_SLOTS]; // frames each slot is lit in
|
||||||
|
|
@ -100,8 +103,6 @@ typedef struct {
|
||||||
jlTileT logoTile;
|
jlTileT logoTile;
|
||||||
// Cell range (inclusive) each character has been painted in since
|
// Cell range (inclusive) each character has been painted in since
|
||||||
// the last full repaint: where a changed glyph's cells can be.
|
// 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
|
// 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
|
// (min > max = the row is clean), the same shape as the library's
|
||||||
// own per-row dirty bands.
|
// own per-row dirty bands.
|
||||||
|
|
@ -111,7 +112,10 @@ typedef struct {
|
||||||
StSpriteCacheT cache[ST_SPRITE_CACHE];
|
StSpriteCacheT cache[ST_SPRITE_CACHE];
|
||||||
StSpriteCacheT *lastHit[ST_HW_SPRITES]; // the entry each hardware sprite used last
|
StSpriteCacheT *lastHit[ST_HW_SPRITES]; // the entry each hardware sprite used last
|
||||||
jlSpriteBackupT backup[ST_HW_SPRITES];
|
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];
|
StDrawnT slot[ST_HW_SPRITES];
|
||||||
uint8_t lastPresentFrame;
|
uint8_t lastPresentFrame;
|
||||||
} StRenderStateT;
|
} StRenderStateT;
|
||||||
|
|
@ -132,9 +136,26 @@ static const uint16_t kC64Palette[16] = {
|
||||||
// four of these are used; the rest are headroom if the frames change.
|
// 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 };
|
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 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 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 uint8_t cellRow(uint16_t cell);
|
||||||
static void collectGlyphs(StSimT *sim);
|
static void collectGlyphs(StSimT *sim);
|
||||||
static void dirtyBands(const StSimT *sim);
|
static void dirtyBands(const StSimT *sim);
|
||||||
|
|
@ -145,6 +166,7 @@ static bool loadPrecompiledCels(void);
|
||||||
static bool logoBuildTile(const StSimT *sim);
|
static bool logoBuildTile(const StSimT *sim);
|
||||||
static uint8_t logoFrameIndex(const StSimT *sim);
|
static uint8_t logoFrameIndex(const StSimT *sim);
|
||||||
static void logoPaletteApply(const StSimT *sim, uint8_t frame);
|
static void logoPaletteApply(const StSimT *sim, uint8_t frame);
|
||||||
|
static void starPaletteApply(void);
|
||||||
static void paintCells(jlSurfaceT *stage, StSimT *sim);
|
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 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);
|
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,
|
// The JoeyLib sprite for hardware sprite `idx` of the current frame,
|
||||||
// built on first use from its VIC bitmap and colours.
|
// built on first use from its VIC bitmap and colours.
|
||||||
static jlSpriteT *cachedSprite(StSimT *sim, uint8_t idx) {
|
static jlSpriteT *cachedSprite(StSimT *sim, uint8_t idx) {
|
||||||
uint8_t ptr = sim->frame.ptr[idx];
|
uint8_t ptr = sim->frame.ptr[idx];
|
||||||
uint8_t color = drawColor(sim, 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 mc0 = multi ? sim->spriteMc0 : 0u;
|
||||||
uint8_t mc1 = multi ? sim->spriteMc1 : 0u;
|
uint8_t mc1 = multi ? sim->spriteMc1 : 0u;
|
||||||
uint8_t level = (ptr < ST_SPRITE_PTR_FIRST && sim->level != 0) ? sim->level->levelIndex : 0xFFu;
|
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.
|
// so fail into the interpreter path.
|
||||||
return 0;
|
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) {
|
if (slot->used) {
|
||||||
jlSpriteDestroy(slot->sprite);
|
jlSpriteDestroy(slot->sprite);
|
||||||
slot->sprite = 0;
|
slot->sprite = 0;
|
||||||
slot->used = false;
|
slot->used = false;
|
||||||
|
slot->compiled = false;
|
||||||
}
|
}
|
||||||
buildSpriteCel(stSimSpriteBitmap(sim, ptr), multi, color, mc0, mc1);
|
buildSpriteCel(stSimSpriteBitmap(sim, ptr), multi, color, mc0, mc1);
|
||||||
slot->sprite = jlSpriteCreateFromSurface(gRender.scratch, 0, 0, ST_SPRITE_TILES, ST_SPRITE_TILES);
|
slot->sprite = jlSpriteCreateFromSurface(gRender.scratch, 0, 0, ST_SPRITE_TILES, ST_SPRITE_TILES);
|
||||||
if (slot->sprite == 0) {
|
if (slot->sprite == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Only the cab, exhaust and passenger move every tick; the codegen
|
// Nothing compiles mid-ride: a compile is ~0.5 s on the 65816, a
|
||||||
// arena is theirs. Everything else stays interpreted (drawn seldom).
|
// visible hitch. The cab, exhaust and passenger cels come baked
|
||||||
if (idx <= 2u) {
|
// (stRenderPrewarm), a level's hook cels come baked or are compiled
|
||||||
(void)jlSpriteCompile(slot->sprite);
|
// 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->lastUse = gRender.cacheStamp;
|
||||||
slot->ptr = ptr;
|
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) {
|
static uint8_t cellRow(uint16_t cell) {
|
||||||
return kCellRow[cell >> 3];
|
return kCellRow[cell >> 3];
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +337,7 @@ static uint8_t cellRow(uint16_t cell) {
|
||||||
static void collectGlyphs(StSimT *sim) {
|
static void collectGlyphs(StSimT *sim) {
|
||||||
uint8_t k;
|
uint8_t k;
|
||||||
uint16_t cell;
|
uint16_t cell;
|
||||||
uint16_t last;
|
uint16_t next;
|
||||||
|
|
||||||
if (sim->charDirtyAll) {
|
if (sim->charDirtyAll) {
|
||||||
sim->charDirtyAll = false;
|
sim->charDirtyAll = false;
|
||||||
|
|
@ -283,18 +349,33 @@ static void collectGlyphs(StSimT *sim) {
|
||||||
if (sim->dirtyAll) {
|
if (sim->dirtyAll) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
last = gRender.glyphLast[ch];
|
// Exactly the cells showing `ch`, straight off the reverse index
|
||||||
for (cell = gRender.glyphFirst[ch]; cell <= last; cell++) {
|
// the sim maintains (StSimT in stSim.h). No scan, no screen[]
|
||||||
if (sim->screen[cell] != ch || sim->cellDirty[cell] != 0u) {
|
// test: a cell is in this list if and only if it shows `ch`.
|
||||||
continue;
|
//
|
||||||
}
|
// This replaced a walk of a per-glyph [first, last] span. That
|
||||||
sim->cellDirty[cell] = 1u;
|
// span only ever widened -- pasteCell pushed it out and nothing
|
||||||
if (sim->dirtyCount < (uint16_t)(sizeof(sim->dirtyList) / sizeof(sim->dirtyList[0]))) {
|
// pulled it back -- so a glyph that once appeared in transient
|
||||||
sim->dirtyList[sim->dirtyCount++] = cell;
|
// text kept a screen-wide span for the rest of the level and was
|
||||||
} else {
|
// rescanned on every animation frame, at 24-bit far-pointer cost
|
||||||
sim->dirtyAll = true;
|
// per cell. It measured 22% of the whole program on level H.
|
||||||
break;
|
//
|
||||||
|
// `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;
|
sim->charDirtyCount = 0u;
|
||||||
|
|
@ -331,7 +412,7 @@ static void dirtyBands(const StSimT *sim) {
|
||||||
for (k = 0u; k < sim->dirtyCount; k++) {
|
for (k = 0u; k < sim->dirtyCount; k++) {
|
||||||
uint16_t cell = sim->dirtyList[k];
|
uint16_t cell = sim->dirtyList[k];
|
||||||
uint8_t r = cellRow(cell);
|
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]) {
|
if (col < gRender.dirtyColMin[r]) {
|
||||||
gRender.dirtyColMin[r] = col;
|
gRender.dirtyColMin[r] = col;
|
||||||
}
|
}
|
||||||
|
|
@ -422,7 +503,7 @@ static bool logoBuildTile(const StSimT *sim) {
|
||||||
uint8_t f;
|
uint8_t f;
|
||||||
uint8_t slot;
|
uint8_t slot;
|
||||||
for (f = 0u; f < ST_LOGO_FRAMES; f++) {
|
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);
|
mask |= (uint8_t)(1u << f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -454,7 +535,8 @@ static uint8_t logoFrameIndex(const StSimT *sim) {
|
||||||
uint8_t f;
|
uint8_t f;
|
||||||
|
|
||||||
for (f = 0u; f < ST_LOGO_FRAMES; 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;
|
return f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -494,8 +576,6 @@ static void paintCells(jlSurfaceT *stage, StSimT *sim) {
|
||||||
uint8_t by;
|
uint8_t by;
|
||||||
|
|
||||||
if (sim->dirtyAll) {
|
if (sim->dirtyAll) {
|
||||||
memset(gRender.glyphFirst, 0xFF, sizeof(gRender.glyphFirst));
|
|
||||||
memset(gRender.glyphLast, 0, sizeof(gRender.glyphLast));
|
|
||||||
cell = 0u;
|
cell = 0u;
|
||||||
for (by = 0u; by < ST_SCREEN_ROWS; by++) {
|
for (by = 0u; by < ST_SCREEN_ROWS; by++) {
|
||||||
for (bx = 0u; bx < ST_SCREEN_COLS; bx++) {
|
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++) {
|
for (k = 0u; k < sim->dirtyCount; k++) {
|
||||||
cell = sim->dirtyList[k];
|
cell = sim->dirtyList[k];
|
||||||
by = cellRow(cell);
|
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);
|
pasteCell(stage, sim, cell, bx, by);
|
||||||
sim->cellDirty[cell] = 0u;
|
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) {
|
static void pasteCell(jlSurfaceT *stage, const StSimT *sim, uint16_t cell, uint8_t bx, uint8_t by) {
|
||||||
uint8_t chr = sim->screen[cell];
|
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
|
// 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
|
// once; the palette decides which one shows, so they are pasted as
|
||||||
// they are and never touched again.
|
// 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);
|
jlTilePaste(stage, bx, by, &gRender.logoTile);
|
||||||
return;
|
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);
|
collectGlyphs(sim);
|
||||||
dirtyBands(sim);
|
dirtyBands(sim);
|
||||||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||||
uint8_t idx = (uint8_t)(ST_HW_SPRITES - 1u - k);
|
uint8_t idx = (uint8_t)(ST_HW_SPRITES - 1u - k);
|
||||||
StDrawnT *d = &gRender.slot[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 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);
|
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);
|
bool same = (want == d->drawn);
|
||||||
if (same && want) {
|
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);
|
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;
|
jlSpriteT *sp;
|
||||||
int16_t px;
|
int16_t px;
|
||||||
int16_t py;
|
int16_t py;
|
||||||
if ((sim->frame.enableMask & (uint8_t)(1u << idx)) == 0u) {
|
if ((sim->frame.enableMask & kStBit[idx]) == 0u) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
px = (int16_t)((int16_t)sim->frame.x[idx] - ST_SPRITE_X_ORIGIN);
|
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->y = sim->frame.y[idx];
|
||||||
d->ptr = sim->frame.ptr[idx];
|
d->ptr = sim->frame.ptr[idx];
|
||||||
d->color = drawColor(sim, 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
|
// 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) {
|
void stRenderInit(jlSurfaceT *stage) {
|
||||||
uint8_t k;
|
uint8_t *backupMem = gRender.backupMem;
|
||||||
|
uint8_t k;
|
||||||
|
|
||||||
memset(&gRender, 0, sizeof(gRender));
|
memset(&gRender, 0, sizeof(gRender));
|
||||||
memset(gRender.glyphFirst, 0xFF, sizeof(gRender.glyphFirst));
|
if (backupMem == 0) {
|
||||||
gRender.stage = stage;
|
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++) {
|
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);
|
jlPaletteSet(stage, 0u, kC64Palette);
|
||||||
jlScbSetRange(stage, 0u, (uint16_t)(SURFACE_HEIGHT - 1u), 0u);
|
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
|
// 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
|
// ~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.
|
// 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
|
// 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
|
// count (a stale bake), so the caller falls back to the runtime JIT
|
||||||
// runtime JIT prewarm below. Its cross-platform contract makes this a
|
// prewarm below. Every port stages its own bake (make/<port>.mk).
|
||||||
// no-op everywhere but the IIgs, where the bake is wired.
|
|
||||||
static bool loadPrecompiledCels(void) {
|
static bool loadPrecompiledCels(void) {
|
||||||
jlSpriteT *cels[64];
|
jlSpriteT *cels[64];
|
||||||
uint16_t n;
|
uint16_t n;
|
||||||
|
|
@ -761,8 +1011,10 @@ void stRenderPrewarm(jlSurfaceT *stage, StSimT *sim) {
|
||||||
// Precompiled bank: instant, no per-cel JIT. Falls through to the
|
// Precompiled bank: instant, no per-cel JIT. Falls through to the
|
||||||
// runtime build below on any port without a matching .spc.
|
// runtime build below on any port without a matching .spc.
|
||||||
if (loadPrecompiledCels()) {
|
if (loadPrecompiledCels()) {
|
||||||
|
ST_LOG("spacetaxi: cels from sprites/staxicels.spc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ST_LOG("spacetaxi: ! no usable sprites/staxicels.spc -- JIT prewarm");
|
||||||
saved = sim->frame;
|
saved = sim->frame;
|
||||||
gPrewarming = true;
|
gPrewarming = true;
|
||||||
sim->frame.multiMask = 0x07u;
|
sim->frame.multiMask = 0x07u;
|
||||||
|
|
@ -773,24 +1025,21 @@ void stRenderPrewarm(jlSurfaceT *stage, StSimT *sim) {
|
||||||
sim->frame.color[0] = 0x06u;
|
sim->frame.color[0] = 0x06u;
|
||||||
(void)cachedSprite(sim, 0u);
|
(void)cachedSprite(sim, 0u);
|
||||||
done++;
|
done++;
|
||||||
jlFillRect(stage, 60, 110, (uint16_t)((uint16_t)done * 200u / total), 6u, 1u);
|
loadingBar(stage, done, total);
|
||||||
jlStagePresent();
|
|
||||||
}
|
}
|
||||||
for (k = 0u; k < sizeof(kPassPtrs); k++) {
|
for (k = 0u; k < sizeof(kPassPtrs); k++) {
|
||||||
sim->frame.ptr[1] = kPassPtrs[k];
|
sim->frame.ptr[1] = kPassPtrs[k];
|
||||||
sim->frame.color[1] = 0x06u;
|
sim->frame.color[1] = 0x06u;
|
||||||
(void)cachedSprite(sim, 1u);
|
(void)cachedSprite(sim, 1u);
|
||||||
done++;
|
done++;
|
||||||
jlFillRect(stage, 60, 110, (uint16_t)((uint16_t)done * 200u / total), 6u, 1u);
|
loadingBar(stage, done, total);
|
||||||
jlStagePresent();
|
|
||||||
}
|
}
|
||||||
for (k = 0u; k < sizeof(kFlamePtrs); k++) {
|
for (k = 0u; k < sizeof(kFlamePtrs); k++) {
|
||||||
sim->frame.ptr[2] = kFlamePtrs[k];
|
sim->frame.ptr[2] = kFlamePtrs[k];
|
||||||
sim->frame.color[2] = 0x07u;
|
sim->frame.color[2] = 0x07u;
|
||||||
(void)cachedSprite(sim, 2u);
|
(void)cachedSprite(sim, 2u);
|
||||||
done++;
|
done++;
|
||||||
jlFillRect(stage, 60, 110, (uint16_t)((uint16_t)done * 200u / total), 6u, 1u);
|
loadingBar(stage, done, total);
|
||||||
jlStagePresent();
|
|
||||||
}
|
}
|
||||||
// The intro star is a hires sprite in colour 7. Build it as a moving
|
// 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
|
// (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) {
|
void stRenderSceneChanged(StSimT *sim) {
|
||||||
uint8_t k;
|
uint8_t k;
|
||||||
|
|
||||||
if (gRender.logoMode) {
|
if (gRender.logoMode || gRender.starMode) {
|
||||||
// The logo's reserved slots go back to being C64 colours.
|
// The borrowed slots go back to being C64 colours.
|
||||||
gRender.logoMode = false;
|
gRender.logoMode = false;
|
||||||
gRender.logoTileOk = false;
|
gRender.logoTileOk = false;
|
||||||
|
gRender.starMode = false;
|
||||||
jlPaletteSet(gRender.stage, 0u, kC64Palette);
|
jlPaletteSet(gRender.stage, 0u, kC64Palette);
|
||||||
}
|
}
|
||||||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||||
gRender.slot[k].drawn = false;
|
gRender.slot[k].drawn = false;
|
||||||
}
|
}
|
||||||
stSimDirtyAll(sim);
|
stSimDirtyCells(sim);
|
||||||
sim->charDirtyAll = true;
|
sim->charDirtyAll = true;
|
||||||
sim->charDirtyCount = 0u;
|
sim->charDirtyCount = 0u;
|
||||||
}
|
}
|
||||||
|
|
@ -838,7 +1088,19 @@ void stRenderTitleLogo(StSimT *sim) {
|
||||||
gRender.logoMode = true;
|
gRender.logoMode = true;
|
||||||
gRender.logoTileOk = (frame < ST_LOGO_FRAMES);
|
gRender.logoTileOk = (frame < ST_LOGO_FRAMES);
|
||||||
logoPaletteApply(sim, gRender.logoTileOk ? frame : 0u);
|
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);
|
jlSurfaceDestroy(gRender.scratch);
|
||||||
gRender.scratch = 0;
|
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_COLS 40u
|
||||||
#define ST_SCREEN_ROWS 25u
|
#define ST_SCREEN_ROWS 25u
|
||||||
#define ST_SCREEN_CELLS (ST_SCREEN_COLS * ST_SCREEN_ROWS)
|
#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
|
// 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
|
// no multiply: with a variable row the * form called the compiler's
|
||||||
// software multiply helper, and the collision pre-check does that a
|
// software multiply helper, and the collision pre-check does that a
|
||||||
|
|
@ -43,6 +46,9 @@
|
||||||
#define ST_SPRITE_Y_ORIGIN 50
|
#define ST_SPRITE_Y_ORIGIN 50
|
||||||
#define ST_SPRITE_W 24
|
#define ST_SPRITE_W 24
|
||||||
#define ST_SPRITE_H 21
|
#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
|
#define ST_HW_SPRITES 8u
|
||||||
|
|
||||||
// Fixed screen cells the game writes directly (C64 screen addresses).
|
// 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_SCREENS ST_CELL(23, 32) // $07B8..$07BC
|
||||||
#define ST_CELL_SCORE ST_CELL(24, 2) // $07C2..$07C8, 7 chars
|
#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_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_PAD_DIGIT ST_CELL(24, 18) // $07D2
|
||||||
#define ST_CELL_FARE ST_CELL(24, 32) // $07E0..$07E6, 7 chars
|
#define ST_CELL_FARE ST_CELL(24, 32) // $07E0..$07E6, 7 chars
|
||||||
#define ST_NUMBER_CHARS 7u
|
#define ST_NUMBER_CHARS 7u
|
||||||
|
|
@ -71,7 +79,57 @@
|
||||||
#define ST_CHAR_FUEL_EMPTY 0x7Au
|
#define ST_CHAR_FUEL_EMPTY 0x7Au
|
||||||
#define ST_CHAR_TRANSPORTER 0x67u // animated top-wall hatch
|
#define ST_CHAR_TRANSPORTER 0x67u // animated top-wall hatch
|
||||||
#define ST_CHAR_CAB_ICON 0xC8u
|
#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
|
// 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
|
// 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
|
// Distinct characters whose glyph can change in one frame before the
|
||||||
// renderer gives up and repaints everything.
|
// renderer gives up and repaints everything.
|
||||||
#define ST_CHAR_DIRTY_MAX 8u
|
#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.
|
// Level image as loaded from a .dat (STL4). Kept in the C64's units.
|
||||||
#define ST_MAX_PADS 10u
|
#define ST_MAX_PADS 10u
|
||||||
|
|
@ -98,6 +166,113 @@
|
||||||
#define ST_HOOK_BASE 0x7D98u
|
#define ST_HOOK_BASE 0x7D98u
|
||||||
#define ST_HOOK_BYTES (0x8000u - ST_HOOK_BASE)
|
#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 {
|
typedef struct {
|
||||||
uint8_t x1Hi; // slot byte 0: landing X lower bound, high byte
|
uint8_t x1Hi; // slot byte 0: landing X lower bound, high byte
|
||||||
uint8_t x1Lo; // slot byte 1
|
uint8_t x1Lo; // slot byte 1
|
||||||
|
|
@ -128,7 +303,7 @@ typedef struct {
|
||||||
StPadT pads[ST_MAX_PADS]; // $7D0A..
|
StPadT pads[ST_MAX_PADS]; // $7D0A..
|
||||||
uint8_t screen[ST_SCREEN_CELLS]; // decompressed screen RAM
|
uint8_t screen[ST_SCREEN_CELLS]; // decompressed screen RAM
|
||||||
uint8_t color[ST_SCREEN_CELLS]; // decompressed colour 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;
|
uint8_t spriteCount;
|
||||||
StLevelSpriteT sprites[ST_MAX_LEVEL_SPRITES];
|
StLevelSpriteT sprites[ST_MAX_LEVEL_SPRITES];
|
||||||
uint8_t hookData[ST_HOOK_BYTES]; // $7D98..$7FFF as shipped
|
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 dirtyList[512]; // cells marked since the last frame
|
||||||
uint16_t dirtyCount;
|
uint16_t dirtyCount;
|
||||||
bool dirtyAll; // list overflowed / whole screen
|
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
|
// Characters whose glyph bits the game has edited since the last
|
||||||
// frame -- the transporter hatch, the title logo flip, the laser
|
// frame -- the transporter hatch, the title logo flip, the laser
|
||||||
// beams. A short list, not a 256-entry flag array: the renderer had
|
// 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) ----
|
// ---- level image (mutable copies: hooks edit the pad table) ----
|
||||||
const StLevelT *level;
|
const StLevelT *level;
|
||||||
StPadT pads[ST_MAX_PADS]; // $7D0A working copy
|
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 ----
|
// ---- input ----
|
||||||
uint8_t inputMask; // $7169 EOR $FF of $DC00: 1 = pressed
|
uint8_t inputMask; // $7169 EOR $FF of $DC00: 1 = pressed
|
||||||
|
|
@ -255,12 +459,25 @@ typedef struct {
|
||||||
uint8_t hitDispatchResult; // $721D
|
uint8_t hitDispatchResult; // $721D
|
||||||
uint8_t spriteSpriteColl; // $71CA latched $D01E
|
uint8_t spriteSpriteColl; // $71CA latched $D01E
|
||||||
uint8_t spriteBgColl; // $71CB latched $D01F
|
uint8_t spriteBgColl; // $71CB latched $D01F
|
||||||
// Per-sprite 24-bit row masks of the displayed frame, rebuilt only
|
// Sprites besides the cab whose $D01F bit a hook reads (levels J
|
||||||
// when the sprite's bitmap or multicolour mode changes (derived
|
// and P watch their hazards hit the scenery); the rest are never
|
||||||
// state, not C64 memory).
|
// tested (derived state, not C64 memory).
|
||||||
uint32_t collMask[ST_HW_SPRITES][ST_SPRITE_H];
|
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];
|
const uint8_t *collMaskBm[ST_HW_SPRITES];
|
||||||
uint8_t collMaskMulti[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 ----
|
// ---- fuel ----
|
||||||
uint8_t fuelCountdown; // $71C7
|
uint8_t fuelCountdown; // $71C7
|
||||||
|
|
@ -300,6 +517,12 @@ typedef struct {
|
||||||
uint8_t levelState; // $7215 screens completed
|
uint8_t levelState; // $7215 screens completed
|
||||||
uint8_t demoMode; // $721C
|
uint8_t demoMode; // $721C
|
||||||
uint8_t postMortem; // $5E9D
|
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
|
// ---- demo playback ($48F2): the $0902 buffer a recording is
|
||||||
// loaded into; a shorter recording leaves the previous tail behind
|
// loaded into; a shorter recording leaves the previous tail behind
|
||||||
|
|
@ -318,8 +541,6 @@ typedef struct {
|
||||||
uint8_t logoColorIdx; // $48A4
|
uint8_t logoColorIdx; // $48A4
|
||||||
uint8_t logoCycleAux; // $48A5
|
uint8_t logoCycleAux; // $48A5
|
||||||
uint8_t logoDiv; // $48A6
|
uint8_t logoDiv; // $48A6
|
||||||
uint8_t starTimer[7]; // $44F8
|
|
||||||
uint8_t starReload[7]; // $4500
|
|
||||||
uint8_t introLoopCount; // $4508
|
uint8_t introLoopCount; // $4508
|
||||||
uint8_t introCabDx; // $450A
|
uint8_t introCabDx; // $450A
|
||||||
uint8_t introCabDxTimer; // $450B
|
uint8_t introCabDxTimer; // $450B
|
||||||
|
|
@ -327,7 +548,7 @@ typedef struct {
|
||||||
uint8_t spriteMc1; // $D026
|
uint8_t spriteMc1; // $D026
|
||||||
|
|
||||||
// ---- per-level hook scratch ($7D9C.. and friends) ----
|
// ---- 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 hookLevel; // level index the hook state belongs to
|
||||||
uint8_t warpCounter; // $5A66
|
uint8_t warpCounter; // $5A66
|
||||||
uint8_t warpMask; // $5CE8
|
uint8_t warpMask; // $5CE8
|
||||||
|
|
@ -357,6 +578,29 @@ bool stSimAdvancePlayer(StSimT *sim);
|
||||||
void stSimArchiveHud(StSimT *sim);
|
void stSimArchiveHud(StSimT *sim);
|
||||||
// Mark every cell dirty (scene change).
|
// Mark every cell dirty (scene change).
|
||||||
void stSimDirtyAll(StSimT *sim);
|
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.
|
// A glyph's bits changed: every cell showing it has to be repainted.
|
||||||
void stSimMarkChar(StSimT *sim, uint8_t ch);
|
void stSimMarkChar(StSimT *sim, uint8_t ch);
|
||||||
// Text and HUD primitives (screen RAM writes).
|
// Text and HUD primitives (screen RAM writes).
|
||||||
|
|
@ -404,13 +648,19 @@ void stHookPerTick2(StSimT *sim); // $7D6C
|
||||||
void stHookPerTick3(StSimT *sim); // $7D6F
|
void stHookPerTick3(StSimT *sim); // $7D6F
|
||||||
uint8_t stHookInput(StSimT *sim, uint8_t input); // $7D72
|
uint8_t stHookInput(StSimT *sim, uint8_t input); // $7D72
|
||||||
uint8_t stHookHitVerdict(StSimT *sim); // $7D75: 0 = passenger contact is safe
|
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) ----
|
// ---- audio sink (host provides; stAudio.c / stsim stub) ----
|
||||||
void stAudioSfx(const uint8_t *program9); // $42E9 load
|
void stAudioSfx(const uint8_t *program9); // $42E9 load
|
||||||
void stAudioNoise(bool on); // $D412 = $81 / $80
|
void stAudioNoise(bool on); // $D412 = $81 / $80
|
||||||
void stAudioThrustSweep(uint8_t value); // $D400/$D401 = value
|
void stAudioThrustSweep(uint8_t value); // $D400/$D401 = value
|
||||||
void stAudioSpeech(uint8_t ch); // $9802
|
void stAudioSpeech(uint8_t ch); // $9802
|
||||||
|
void stAudioSpeechPhrase(const uint8_t *speech);
|
||||||
void stAudioSilence(void); // voices 1+2 gate off
|
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 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
|
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
|
// Level intro ($4523..$4727): a black screen with the level name, the
|
||||||
// cab rising from the bottom and seven star sprites streaming out of
|
// cab rising from the bottom and seven star sprites streaming out of
|
||||||
// the centre, until the cab reaches mid-screen.
|
// 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>
|
#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).
|
// Intro cab drift per loop count ($470D).
|
||||||
static const int8_t kIntroCabDy[4] = { -2, 1, -1, 1 };
|
static const int8_t kIntroCabDy[4] = { -2, 1, -1, 1 };
|
||||||
// Intro texts ($4624 / $463F).
|
// 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 kTextDemoExit[] = "DEMO, USE JOYSTICK TO EXIT";
|
||||||
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 kTextScreens[] = "THIS IS 1 OF 25 DIFFERENT SCREENS!";
|
||||||
|
|
||||||
#define ST_TITLE_CAB_LIFT_ROW 0x14u
|
#define ST_TITLE_CAB_LIFT_ROW 0x14u
|
||||||
#define ST_TITLE_SPARKLE_TICKS 0x5Au
|
#define ST_TITLE_SPARKLE_TICKS 0x5Au
|
||||||
#define ST_TITLE_HOVER_COL 0x28u
|
#define ST_TITLE_HOVER_COL 0x28u
|
||||||
#define ST_INTRO_STAR_PTR 0xDAu
|
#define ST_INTRO_STAR_PTR 0xDAu
|
||||||
#define ST_INTRO_STAR_RELOAD 0x20u
|
|
||||||
#define ST_INTRO_CAB_END_ROW 0x94u
|
#define ST_INTRO_CAB_END_ROW 0x94u
|
||||||
#define ST_INTRO_CAB_DX_RELOAD 0x28u
|
#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 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 logoColorCycle(StSimT *sim);
|
||||||
static void logoFlip(StSimT *sim);
|
static void logoFlip(StSimT *sim);
|
||||||
static void marshalFrame(StSimT *sim);
|
static void paintStarfield(StSimT *sim);
|
||||||
static void starRespawn(StSimT *sim, uint8_t idx);
|
|
||||||
|
|
||||||
|
|
||||||
// $4113
|
// $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
|
// $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,
|
// 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
|
// 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) {
|
if (sim->logoDiv != 0u) {
|
||||||
return;
|
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);
|
stSimMarkChar(sim, ST_LOGO_CHAR);
|
||||||
sim->logoCycleAux++;
|
sim->logoCycleAux++;
|
||||||
if (sim->logoCycleAux == 6u) {
|
if (sim->logoCycleAux == 6u) {
|
||||||
|
|
@ -103,32 +124,21 @@ static void logoFlip(StSimT *sim) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// $4253 + $4293 as the title and intro loops call them.
|
// Paint the level-intro starfield into screen RAM, once. A star's cell
|
||||||
static void marshalFrame(StSimT *sim) {
|
// is coloured ST_STAR_RING_FIRST + its ring and never touched again --
|
||||||
uint8_t i;
|
// the renderer animates the warp by cycling those colours, which costs
|
||||||
uint8_t enable = 0u;
|
// 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++) {
|
one[1] = 0u; // stSimDrawText stops below screen code 6
|
||||||
sim->frame.x[i] = (uint16_t)(((uint16_t)(sim->spr[i].msb != 0u ? 1u : 0u) << 8) | sim->spr[i].col);
|
for (k = 0u; k < (uint8_t)ST_INTRO_STAR_COUNT; k++) {
|
||||||
sim->frame.y[i] = sim->spr[i].row;
|
star = &kIntroStar[k];
|
||||||
sim->frame.ptr[i] = sim->spr[i].ptr;
|
one[0] = (star->ring < ST_STAR_FAR_RINGS) ? ST_STAR_GLYPH_FAR : ST_STAR_GLYPH_NEAR;
|
||||||
sim->frame.color[i] = sim->spr[i].color;
|
stSimDrawText(sim, star->col, star->row, one, (uint8_t)(ST_STAR_RING_FIRST + star->ring));
|
||||||
if (sim->spr[i].enable != 0u) {
|
|
||||||
enable |= (uint8_t)(1u << i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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].color = 0x07u;
|
||||||
sim->spr[idx].ptr = ST_INTRO_STAR_PTR;
|
sim->spr[idx].ptr = ST_INTRO_STAR_PTR;
|
||||||
sim->spr[idx].enable = 0u;
|
sim->spr[idx].enable = 0u;
|
||||||
sim->starTimer[idx] = stSimRng(sim, 0x20u);
|
// $44F8/$4500 held each star's spawn timer and reload. Nothing
|
||||||
sim->starReload[idx] = 0u;
|
// 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->borderColor = 0u;
|
||||||
sim->bgColor = 0u;
|
sim->bgColor = 0u;
|
||||||
sim->multiColorMask = 0x80u;
|
sim->multiColorMask = 0x80u;
|
||||||
marshalFrame(sim);
|
stSimMarshal(sim);
|
||||||
// $40CA: blank screen.
|
// $40CA: blank screen.
|
||||||
memset(sim->screen, ST_CHAR_SPACE, ST_SCREEN_CELLS);
|
memset(sim->screen, ST_CHAR_SPACE, ST_SCREEN_CELLS);
|
||||||
memset(sim->color, 0, ST_SCREEN_CELLS);
|
memset(sim->color, 0, ST_SCREEN_CELLS);
|
||||||
stSimDirtyAll(sim);
|
stSimDirtyAll(sim);
|
||||||
memcpy(sim->charset, stC64Charset(), sizeof(sim->charset));
|
stSimGlyphReset(sim);
|
||||||
sim->charDirtyAll = true;
|
sim->charDirtyAll = true;
|
||||||
sim->charDirtyCount = 0u;
|
sim->charDirtyCount = 0u;
|
||||||
stSimDrawText(sim, 10u, 12u, level->name, 3u);
|
stSimDrawText(sim, 10u, 12u, level->name, 3u);
|
||||||
|
paintStarfield(sim);
|
||||||
if (sim->demoMode != 0u && sim->postMortem == 0u) {
|
if (sim->demoMode != 0u && sim->postMortem == 0u) {
|
||||||
stSimDrawText(sim, 7u, 3u, kTextDemoExit, 5u);
|
stSimDrawText(sim, 7u, 3u, kTextDemoExit, 5u);
|
||||||
stSimDrawText(sim, 3u, 24u, kTextScreens, 4u);
|
stSimDrawText(sim, 3u, 24u, kTextScreens, 4u);
|
||||||
|
|
@ -187,27 +202,11 @@ void stIntroEnter(StSimT *sim, const StLevelT *level) {
|
||||||
bool stIntroStep(StSimT *sim) {
|
bool stIntroStep(StSimT *sim) {
|
||||||
uint8_t k;
|
uint8_t k;
|
||||||
|
|
||||||
for (k = 0u; k < 7u; k++) {
|
stSimMarshal(sim);
|
||||||
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);
|
|
||||||
sim->introLoopCount = (uint8_t)((sim->introLoopCount + 1u) & 3u);
|
sim->introLoopCount = (uint8_t)((sim->introLoopCount + 1u) & 3u);
|
||||||
addToRow(sim, 7u, (uint8_t)kIntroCabDy[sim->introLoopCount]);
|
addToRow(sim, 7u, (uint8_t)kIntroCabDy[sim->introLoopCount]);
|
||||||
if ((sim->introLoopCount & 1u) == 0u) {
|
if ((sim->introLoopCount & 1u) == 0u) {
|
||||||
addToSpriteX(sim, 7u, sim->introCabDx);
|
stSimSpriteAddX(sim, 7u, sim->introCabDx);
|
||||||
sim->introCabDxTimer--;
|
sim->introCabDxTimer--;
|
||||||
if (sim->introCabDxTimer == 0u) {
|
if (sim->introCabDxTimer == 0u) {
|
||||||
sim->introCabDxTimer = ST_INTRO_CAB_DX_RELOAD;
|
sim->introCabDxTimer = ST_INTRO_CAB_DX_RELOAD;
|
||||||
|
|
@ -222,7 +221,7 @@ bool stIntroStep(StSimT *sim) {
|
||||||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||||
sim->spr[k].enable = 0u;
|
sim->spr[k].enable = 0u;
|
||||||
}
|
}
|
||||||
marshalFrame(sim);
|
stSimMarshal(sim);
|
||||||
sim->rngT1 = 0x06u;
|
sim->rngT1 = 0x06u;
|
||||||
sim->rngT2 = 0x17u;
|
sim->rngT2 = 0x17u;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -237,7 +236,7 @@ void stTitleEnter(StSimT *sim, const StLevelT *title) {
|
||||||
memcpy(sim->screen, title->screen, ST_SCREEN_CELLS);
|
memcpy(sim->screen, title->screen, ST_SCREEN_CELLS);
|
||||||
memcpy(sim->color, title->color, ST_SCREEN_CELLS);
|
memcpy(sim->color, title->color, ST_SCREEN_CELLS);
|
||||||
stSimDirtyAll(sim);
|
stSimDirtyAll(sim);
|
||||||
memcpy(sim->charset, stC64Charset(), sizeof(sim->charset));
|
stSimGlyphReset(sim);
|
||||||
sim->charDirtyAll = true;
|
sim->charDirtyAll = true;
|
||||||
sim->charDirtyCount = 0u;
|
sim->charDirtyCount = 0u;
|
||||||
logoColorCycle(sim);
|
logoColorCycle(sim);
|
||||||
|
|
@ -260,7 +259,7 @@ void stTitleEnter(StSimT *sim, const StLevelT *title) {
|
||||||
sim->multiColorMask = 0x07u;
|
sim->multiColorMask = 0x07u;
|
||||||
sim->spriteMc1 = 0x07u;
|
sim->spriteMc1 = 0x07u;
|
||||||
sim->spriteMc0 = 0x02u;
|
sim->spriteMc0 = 0x02u;
|
||||||
marshalFrame(sim);
|
stSimMarshal(sim);
|
||||||
sim->stage = ST_STAGE_WAIT;
|
sim->stage = ST_STAGE_WAIT;
|
||||||
sim->introFrameCount = ST_TITLE_SPARKLE_TICKS;
|
sim->introFrameCount = ST_TITLE_SPARKLE_TICKS;
|
||||||
sim->hoverXFrac = 0u;
|
sim->hoverXFrac = 0u;
|
||||||
|
|
@ -313,7 +312,7 @@ bool stTitleTick(StSimT *sim) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
marshalFrame(sim);
|
stSimMarshal(sim);
|
||||||
logoFlip(sim);
|
logoFlip(sim);
|
||||||
return sim->stage == ST_STAGE_DROP_IN;
|
return sim->stage == ST_STAGE_DROP_IN;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,12 @@
|
||||||
// boot with jlSpriteBankLoadPrecompiled, so no cel is JIT-compiled on
|
// boot with jlSpriteBankLoadPrecompiled, so no cel is JIT-compiled on
|
||||||
// the 65816 (which costs ~0.4 s each).
|
// 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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -26,39 +31,87 @@
|
||||||
#define SPR_OFF_HEIGHT 7u
|
#define SPR_OFF_HEIGHT 7u
|
||||||
#define SPR_OFF_CELLS 8u
|
#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) {
|
// A level's own sprite block, or NULL when the level does not ship it.
|
||||||
fprintf(stderr, "usage: staxibake OUTPUT.spr\n");
|
static const uint8_t *levelBitmap(const StLevelT *level, uint8_t ptr) {
|
||||||
return 2;
|
uint8_t k;
|
||||||
}
|
|
||||||
out = fopen(argv[1], "wb");
|
for (k = 0u; k < level->spriteCount; k++) {
|
||||||
if (out == NULL) {
|
if (level->sprites[k].ptr == ptr) {
|
||||||
fprintf(stderr, "staxibake: cannot write %s\n", argv[1]);
|
return level->sprites[k].bitmap;
|
||||||
return 1;
|
}
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool writeHeader(FILE *out, uint16_t count) {
|
||||||
|
uint8_t header[SPR_HEADER_BYTES];
|
||||||
|
|
||||||
memset(header, 0, sizeof(header));
|
memset(header, 0, sizeof(header));
|
||||||
memcpy(header, "JSP1", 4);
|
memcpy(header, "JSP1", 4);
|
||||||
header[SPR_OFF_TARGET] = 0u; // cross-platform chunky
|
header[SPR_OFF_TARGET] = 0u; // cross-platform chunky
|
||||||
header[SPR_OFF_HAS_PAL] = 0u; // the game owns its palette
|
header[SPR_OFF_HAS_PAL] = 0u; // the game owns its palette
|
||||||
header[SPR_OFF_WIDTH] = (uint8_t)ST_CEL_TILES;
|
header[SPR_OFF_WIDTH] = (uint8_t)ST_CEL_TILES;
|
||||||
header[SPR_OFF_HEIGHT] = (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] = (uint8_t)(count & 0xFFu);
|
||||||
header[SPR_OFF_CELLS + 1u] = (uint8_t)(kStCelCount >> 8);
|
header[SPR_OFF_CELLS + 1u] = (uint8_t)(count >> 8);
|
||||||
if (fwrite(header, 1, SPR_HEADER_BYTES, out) != SPR_HEADER_BYTES) {
|
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");
|
fprintf(stderr, "staxibake: header write failed\n");
|
||||||
fclose(out);
|
fclose(out);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for (i = 0u; i < kStCelCount; i++) {
|
for (i = 0u; i < count; i++) {
|
||||||
uint8_t blob[ST_CEL_BYTES];
|
uint8_t blob[ST_CEL_BYTES];
|
||||||
const uint8_t *bm = stC64SpriteBitmap((uint8_t)(kStCels[i].ptr - ST_SPRITE_PTR_FIRST));
|
const uint8_t *bm;
|
||||||
|
if (cels == levelCels) {
|
||||||
stCelBlob(bm, kStCels[i].multi, kStCels[i].color, kStCels[i].mc0, kStCels[i].mc1, blob);
|
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) {
|
if (fwrite(blob, 1, ST_CEL_BYTES, out) != ST_CEL_BYTES) {
|
||||||
fprintf(stderr, "staxibake: cel %u write failed\n", (unsigned)i);
|
fprintf(stderr, "staxibake: cel %u write failed\n", (unsigned)i);
|
||||||
fclose(out);
|
fclose(out);
|
||||||
|
|
@ -66,6 +119,6 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(out);
|
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;
|
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
|
ST := ../../examples/spacetaxi
|
||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS := -O1 -g -Wall -Wextra -std=c99 -I$(ST)
|
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 $@
|
$(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:
|
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),
|
// the VICE tracer records (see stuff/spacetaxi and the compare script),
|
||||||
// so the port's engine can be diffed against the real machine.
|
// 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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../../examples/spacetaxi/stSim.h"
|
#include "../../examples/spacetaxi/stSim.h"
|
||||||
|
#include "../../examples/spacetaxi/stCels.h"
|
||||||
#include "../../examples/spacetaxi/stDemoStreams.h"
|
#include "../../examples/spacetaxi/stDemoStreams.h"
|
||||||
|
#include "gateStreams.h"
|
||||||
|
|
||||||
|
|
||||||
static StLevelT gLevel;
|
static StLevelT gLevel;
|
||||||
|
|
@ -23,11 +28,105 @@ void stAudioSfx(const uint8_t *program9) { (void)program9; }
|
||||||
void stAudioNoise(bool on) { (void)on; }
|
void stAudioNoise(bool on) { (void)on; }
|
||||||
void stAudioThrustSweep(uint8_t value) { (void)value; }
|
void stAudioThrustSweep(uint8_t value) { (void)value; }
|
||||||
void stAudioSpeech(uint8_t ch) { (void)ch; }
|
void stAudioSpeech(uint8_t ch) { (void)ch; }
|
||||||
|
void stAudioSpeechPhrase(const uint8_t *speech) { (void)speech; }
|
||||||
void stAudioSilence(void) { }
|
void stAudioSilence(void) { }
|
||||||
void stAudioVoice2(uint8_t freqLo, uint8_t freqHi, uint8_t ctrl) { (void)freqLo; (void)freqHi; (void)ctrl; }
|
void stAudioVoice2(uint8_t freqLo, uint8_t freqHi, uint8_t ctrl) { (void)freqLo; (void)freqHi; (void)ctrl; }
|
||||||
void stAudioVoice1Freq(uint8_t value) { (void)value; }
|
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) {
|
static void printState(const StSimT *sim, uint32_t tick) {
|
||||||
uint8_t k;
|
uint8_t k;
|
||||||
|
|
||||||
|
|
@ -55,7 +154,11 @@ static void printState(const StSimT *sim, uint32_t tick) {
|
||||||
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
for (k = 0u; k < ST_HW_SPRITES; k++) {
|
||||||
printf("%03X%02X", sim->frame.x[k], sim->frame.y[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;
|
FILE *fp;
|
||||||
const uint8_t *stream = kDemoStreamH;
|
const uint8_t *stream = kDemoStreamH;
|
||||||
uint16_t len = (uint16_t)sizeof(kDemoStreamH);
|
uint16_t len = (uint16_t)sizeof(kDemoStreamH);
|
||||||
|
uint8_t want;
|
||||||
uint32_t ticks;
|
uint32_t ticks;
|
||||||
uint32_t t;
|
uint32_t t;
|
||||||
|
|
||||||
if (argc < 4) {
|
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;
|
return 2;
|
||||||
}
|
}
|
||||||
fp = fopen(argv[1], "rb");
|
fp = fopen(argv[1], "rb");
|
||||||
|
|
@ -76,11 +180,29 @@ int main(int argc, char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
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 'W': stream = kDemoStreamW; len = (uint16_t)sizeof(kDemoStreamW); break;
|
||||||
case 'T': stream = kDemoStreamT; len = (uint16_t)sizeof(kDemoStreamT); break;
|
case 'T': stream = kDemoStreamT; len = (uint16_t)sizeof(kDemoStreamT); break;
|
||||||
case 'X': stream = kDemoStreamX; len = (uint16_t)sizeof(kDemoStreamX); 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);
|
ticks = (uint32_t)strtoul(argv[3], NULL, 0);
|
||||||
stSimNewGame(&gSim, 1u, true);
|
stSimNewGame(&gSim, 1u, true);
|
||||||
|
|
@ -101,10 +223,16 @@ int main(int argc, char **argv) {
|
||||||
StTickResultE r;
|
StTickResultE r;
|
||||||
printState(&gSim, t);
|
printState(&gSim, t);
|
||||||
r = stSimTick(&gSim);
|
r = stSimTick(&gSim);
|
||||||
|
if (getenv("STSIM_CELS") != NULL) {
|
||||||
|
celCensusTick(&gSim);
|
||||||
|
}
|
||||||
if (r != ST_TICK_CONTINUE) {
|
if (r != ST_TICK_CONTINUE) {
|
||||||
printf("{\"tick\":%u,\"end\":%d}\n", t, (int)r);
|
printf("{\"tick\":%u,\"end\":%d}\n", t, (int)r);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (getenv("STSIM_CELS") != NULL) {
|
||||||
|
celCensusReport(&gLevel);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue