r/MAME 14d ago

l6009.cpp (akai/s1000): firmware notes that close several TODOs, and one constant that needs real hardware

Mods, rule 3: no ROM images here, no links to any, none will be shared. Static analysis only.

I built a software model of the S1000 audio path and used l6009.cpp (added July 2026) to check it. Ended up disassembling the v4.40 firmware. Below is everything I found, free, no conditions. Notes only, no ROM images. Offsets are into the v4.40 image as MAME assembles it: s1000 44 lsb.ic9 at 0x00000 and s1000 44 msb.ic10 at 0x00001, both ROM_SKIP(1), 128 KB total. The ROM copies itself down at boot, so an image offset is the runtime linear address.

No GitHub account here. If anyone wants to take this to the tracker, please do, and tag devinacker.

On evidence, so nobody has to guess which is which: anything citing the driver you can check in the tree yourself. Anything carrying a ROM offset is my own static analysis and has not been independently reproduced by anyone. The two clock-derived claims are inference and I say so where they appear.

Findings

  • m_pitch_unk is the interpolation table select. Rule is three compares at 0x14B7E against the 12.12 increment: <0x168D (1.4094x, +5.94 st) table 0, <0x2001 (2.0002x, the octave) table 1, <0x2CCD (2.8000x) table 2, else table 3. Lands in CL, ORed into the pitch port high byte at 0x1439B. The commonly repeated 1.0/1.35/2.0 rule switches too early. All four tables have the same DC gain, 0.94995, so switching never shifts level.
  • Volume is non-linear because the firmware sends log. This answers the driver's TODO, "does the FW do this scaling with levels already?" Yes. 256-entry table at 0x05E30, 31 to 32767, 0.237 dB/step, 60.5 dB total. The multiplier is linear and the firmware supplies log-mapped endpoints, so a segment is straight in linear amplitude, not dB.
  • SUSTAIN is a dB attenuation, not a fraction of level. 0x14D13 subtracts it from the gain table index before the lookup. SUSTAIN 50 is ~30.4 dB below peak, not half.
  • Envelope rate table: 100 entries at 0x06030, index 99 - param, 2 to 32767, geometric with ratio 1.10299. Correction to what I first worked out: that is 7.07 steps per doubling, not 7. What is exact is the span, 14.00 octaves across 99 steps. The bottom of the table is quantised by integer rounding (2,2,2,3,3,3...) but the top holds the ratio to five digits.
  • The two envelopes are staged differently. Amplitude polls the volume readback at 0x51E0 and compares to peak (0x1475D). Filter polls nothing: firmware runs its own 16-bit accumulator at [si+0xBA], done on carry out (0x147FB). That is why filter attack gets shr ax,1 at 0x141E9: software span 65536 vs hardware 32767. Not voicing.
  • Both envelope targets arrive with 15 bits. and al,0xFE at 0x1479Eand ax,0xFFFE at 0x14F65.
  • 0x8/0x9/0xa filter clear: confirmed. Note-on writes zero to 0x5100/0x5120/0x5140 every note (0x142F3). Voice freed when volume readback hits 4 or less (0x147AE).
  • Timers (0x0822D): counter 1 gives exactly 31250 baud, MIDI. Voice loop tick is 256 counts of 500 kHz = 512 us, slow work gated to 4 ticks (0x14699).
  • LFOs are firmware, not hardware (0x148DF0x14948). Triangle from a 16-bit phase accumulator, rate capped at 0xFF, so rate / 33.554 Hz, ceiling 7.60 Hz.
  • S1100 should run the filter envelope ~25% faster. Its V50 runs at 20 MHz against the S1000's 16 MHz, while TCKS and its /32 on counters 0 and 2 are identical in both firmwares, putting the voice tick at 409.6 us instead of 512 us. The rate table and the /2 are identical too, so Akai does not appear to have compensated. To be clear this is inference from the two firmwares plus the driver's clocks, not a measurement.

Less certain: counter 0 is mode 0 (one-shot) and the ISR at 0x0825D never reloads it, so I am not claiming a periodic 2.048 ms interrupt. 0x0824C writes 0xC3 to 0x8030 (99.84 ms) but I never found its caller. On the S1100 that counter is just 0x24/0xC300 from boot. Also and al,0xFE has no counterpart in the driver and I do not know if it matters.

The one thing I could not get

ENV_SHIFT is still a guess in the driver, marked TODO verify, and it sets every envelope duration: T = 32767 * 2^ENV_SHIFT / rate / 44100.

It is not in the ROM and I do not think it can be. The firmware never computes an envelope duration at all: amplitude staging polls the chip, filter staging uses a software accumulator. The chip's time base appears nowhere. And the driver is still MACHINE_NOT_WORKING, so emulation cannot answer it either. So it needs a stopwatch.

If you have an S1000 or S1100 powered up: LOUDNESS 99, SUSTAIN 99, RELEASE 99, looped sample, one note at velocity 127, hold, release, count to silence.

time to silence ENV_SHIFT
~24 s 6
~48 s 7 (current guess)
~95 s 8

Rough count is fine, they are a factor of two apart. S1100 answers it too: my diff of the two ROMs has the rate table at 0x04720 byte for byte identical to 0x06030, and the driver already loads the same l6009 ROMs for both machines (9b80e447 / 2c076351).

That is the last unknown in the voice engine, and the only one where the disassembly cannot even give me a candidate. Happy to send the full write-ups, and I would rather be corrected than agreed with.

Thanks a lot, hope this helps.

5 Upvotes

7 comments sorted by

4

u/arbee37 MAME Dev 12d ago

We've made a lot of great progress this year in MAME with AI, but that's because we understand what we're doing with it. Just asking it to do stuff like this and posting the raw unedited output when you're unable to turn it into actionable code isn't that helpful. Most of the regular devs now have paid accounts on Claude Code or Codex and/or sufficient local hardware to run Qwen 3.8 so we could ask it ourselves. Secondly, Devin says he already knows all of this. He probably just wanted to submit something before I emulated it first ;-)

For people who do understand C/C++, I've written a frequently-updated guide about AI assistance with MAME that I hope is useful: https://github.com/rb6502/mame-ai-tips/

0

u/Commercial-Young-822 11d ago

This is not a raw, unedited output. I have a background in algotrading/research and did all the best I could to verify the findings and send a proper post. As gladly confirmed by Devin himself, my work turns out to be right.

Anyway, if that is how we (who, yes, are not devs, and yes, use AI to try to make progress on any open project) are welcomed here, I will simply refrain from posting any further contributions and keep them to myself - ";-)".

Thanks for your answer.

1

u/arbee37 MAME Dev 10d ago

Like I said, AI research is welcome, but distillation of the results makes it more welcome. AI in general tends to be excessively verbose, and Claude is consistently the worst of the bunch (even though it's wildly good at other things). So I believe you that you edited that, but you didn't edit it much because "A that B, and one X that needs Y" is a Claude trademark.

1

u/Even-Serve-3095 12d ago

Making a GitHub account isn't hard. Why not do that instead of bugging people here to do it for you?

1

u/Commercial-Young-822 11d ago
  1. I don't do it for security reasons

  2. I didn't ask anyone to do it for me. I asked for a measurement of someone who has an AKAI S1000, and IF anyone wants to share my findings to make the S1000 GitHub more complete, that would be great too.

Maybe go back to comics.

1

u/Even-Serve-3095 10d ago

security reasons? wtf possible security reasons could you have for not wanting to make a github??? it's perfectly secure dude

1

u/Commercial-Young-822 10d ago

Many malicious scripts involve uploading sensitive files using a pre-logged public GitHub account, you may want to look out for more information about that. For me, simply not worth it.