Alley Cat Sound Table Format
Besides the title tune, the IBM PC version of Alley Cat contains direct PIT-divisor sequences, rhythm tables and speaker-bit patterns. Other effects calculate pitches in code. There is no single sound bank, sample container or per-effect record format.
File format
The following embedded tables are decoded by src/game/sound.js. Addresses are IBM DS offsets (file offset = DS offset + 0x300); words are little-endian. The extents below are stated only where the consumer establishes them.
| DS address | Encoding | Consumer / interpretation |
|---|---|---|
| 0x5934 | UINT16LE divisors | tuneStep(): word index in bytes, stepped by 2; wraps at byte offset 0x86 |
| 0x5A87 | UINT16LE divisors | returnTune(): successful-return sequence, a new divisor every two ticks; the caller governs its lifetime |
| 0x5AA3 | UINT16LE divisors | returnTune(): failure-return sequence; zero silences the speaker for that call |
| 0x5A64 | UINT16LE divisors | twoTone()/twoToneNext(): alternating adjacent note words and a movable base index |
| 0x5A5A | UINT16LE[4] | wipeTick(): reads offsets 0, 2, 4, 6 cyclically |
| 0x5A44 | UINT16LE[8] addressed by melody path | alleyMusic(): pitch lookup indexed by a word offset masked with 0x0E; another path cycles the first three words |
| 0x5A1A | UINT16LE[16] | hitSound(): base pitches selected by a byte offset masked with 0x1E |
| 0x5AD2 | UINT8[16] | clickPattern(): low speaker-control bits, indexed with 0x0F |
| 0x5AE6 | UINT8[32] | flashClicks(): values XORed into port 61h, indexed with 0x1F |
These are table uses, not self-describing headers. Do not infer arbitrary table lengths from the distance between addresses: state variables and unrelated data are interspersed with constants.
Alley rhythm parameters
alleyMusic() selects a context si from 0–3, with di = 2 * si. It reads the following parameter bases:
| DS expression | Read as | Use |
|---|---|---|
| 0x59F2 + di | UINT16LE | Minimum tick interval |
| 0x59FA + si | UINT8 | Counter mask |
| 0x59FC + si | UINT8 | Pattern mask |
| 0x59FE + di | UINT16LE | Offset into rhythm-byte data |
| 0x5A02 + di | UINT16LE | Normal blip duration in PIT counts |
| 0x5A06 + di | UINT16LE | Alternate blip duration in PIT counts |
| 0x5A0A + si | UINT8 | Pattern increment |
| 0x5A0C + si | UINT8 | Random-choice threshold |
| 0x59C2 + computedIndex | UINT8 | Rhythm bits tested against a rotating mask |
The expressions reproduce the consumer's addressing. They are not a proposed fixed-size struct, and their apparent ranges must not be assumed to be independent allocations. Pitch and rhythm also depend on game state and random values.
Playback
For divisor-based tones, frequency is approximately 1193182 / divisor Hz; a PIT divisor word of zero represents 65536. A consumer-specific zero check can instead mute a sequence before programming the PIT.
tuneStep() advances every two BIOS ticks. It silences a step whose divisor equals the previous divisor, so repeated equal words are not automatically a held note. tunePlay() stops its enclosing loop when the sequence byte index reaches 0x7C, earlier than tuneStep()'s wrap threshold of 0x86.
The failure branch of returnTune() increments its index before checking a zero word and returning. Zero therefore silences that call; it is not a general parser sentinel that guarantees all later calls stop reading. The return sequence's caller controls how long playback continues.
Direct speaker-bit patterns operate on port 61h and must not be interpreted as unsigned PCM. Sweeps, random noise, jump sounds and other effects combine constants, timers and code. Reproducing them requires the corresponding routine as well as its data.
Notes
- The sound-enable flag is DS:0000. Some effects skip busy waits when disabled, which also changes game timing.
- The asset viewer reconstructs title music only; it does not export or play each of these effect tables as an independent asset.
- These addresses and routines document the IBM executable. Tandy's player and hardware writes differ; do not assume that a shifted data address supplies a complete Tandy implementation.
Source code
From re-alleycat, the open-source HTML5 port (revision b003aa63ffbb):
- src/game/sound.js – secondary tune readers, rhythm parameters and procedural effects
- src/machine/speaker.js – PIT and port 61h audio model
- docs/RE_NOTES.md – hardware touchpoints and timing caveats
Credits
This file format was reverse engineered by VorticonCmdr. Please credit the original research when using this information in your own project, and include a link back to this wiki.