or something like that. text by freem.
(v0.25, 2015/12/01)
Warning: This document takes advantage of modern crap like inline MathML rendering and SVG rendering using the <img> tag. If you're using a really old browser, or a browser which refuses to implement MathML/do so properly, this will probably not work out for you. There's also some Javascript used for lazy people who don't want to break out a calculator for finding Delta-N values.
You're most likely reading this because you want to program a sound driver for the Neo-Geo (or another YM2610-using system/arcade board/whatever). If that's not why you're reading this, or your reason is not tangentially related, then you probably want to find a much better source of information. This information is primarily written from the perspective of the Neo-Geo, though. Reader beware. (For example, the system clock of the YM2610 in the Neo-Geo has a value of 8000000, and all equations in this document use that number directly instead of saying "system clock".)
The bulk of this page is based on a translation of the Yamaha YM2610 Application Manual (hence the page name). As the YM2610 (OPNB) is in the same family as the YM2608 (OPNA), the Nemesis-transcribed YM2608 Application Manual is also a great source of information. (You will need to watch out for differences between the 2608 and 2610, however.) I don't want to direct link it myself, but do a search for "YM2608 Application Manual" and you should find the PDF on Hacking CulT.
When writing to the registers, first send the address, then send the data. (The order must always be address followed by data.) However, if you're accessing the same address multiple times, you may write the address first and proceed to write the data register multiple times.
After writing to the address or data registers, you must wait before accessing them again. The wait time differs between address and data writes.
Wait Time | |
---|---|
after Address write | 17 cycles |
after Data write | 83 cycles |
Some register pairs must be written in a certain order for proper operation. These will be noted in the relevant sections.
Cleared at initialization time (when IC = "0"), register initial values are as follows:
ADPCM-A | ADPCM-B | ||||
Address | Register | Init. Value | Address | Register | Init. Value |
---|---|---|---|---|---|
00 | Dump/ADPCM-A On | 0 | 10 | Control 1 | 0 |
01 | Total Level | 0 | 11 | Control 2 | 0 |
02 | Test | 0 | 12 | Start Address (LSB) | XX |
08-0D | Output Select Channel Level |
0 | 13 | Start Address (MSB) | XX |
10-15 | Start Address (LSB) | 0 | 14 | End Address (LSB) | XX |
18-1D | Start Address (MSB) | 0 | 15 | End Address (MSB) | XX |
20-25 | End Address (LSB) | 0 | 19 | Delta-N (LSB) | XX |
28-2D | End Address (MSB) | 0 | 1A | Delta-N (MSB) | XX |
1B | EG Control | XX | |||
1C | Flag Control | 0 |
A value of XX
means "undefined".
This controls whether or not you write to ports 4/5 or ports 6/7.
A1=0 (4/5) | A1=1 (6/7) | ||
---|---|---|---|
$00 | SSG | $00 | ADPCM-A |
... | ... | ||
$0F | ... | ||
$10 | ADPCM-B | ... | |
... | ... | ||
$1F | ... | ||
$20 | FM (Common) | ... | |
... | ... | ||
$2F | $2F | ||
$30 | FM (Ch1, Ch2) | $30 | FM (Ch3, Ch4) |
... | ... | ||
$B6 | $B6 |
Note: On other systems (e.g. not the Neo-Geo), you might need to write the values elsewhere. For example, on the Sega Genesis/Mega Drive (which uses the similar YM2612 chip), Z80 programs write addresses and data to the pairs 0x4000/0x4001 (A1=0) and 0x4002/0x4003 (A1=1).
Status registers allow you to access important information about the current status of the YM2610.
To get the values in Status 0, read port 4.
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|
Busy | Timer B | Timer A |
When this bit is set to 1, the YM2610 is busy with the registers. As mentioned in "Register Writing", there has to be a wait after address and data writes. There are two ways of doing this: manually (running some code to burn clock cycles), and by watching this bit. When set to 0, it's safe to write to the address/data registers again.
If one of the timers has expired, the relevant bit will be set to 1. (todo: explain resetting timers)
To get the values in Status 1, read port 6.
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|
B | A5 | A4 | A3 | A2 | A1 | A0 |
The flags here are used to determine if a channel has finished playing its sample. This is an especially useful register for managing both ADPCM-A looping and custom loop points.
The values are set as follows:
Though the timers live in the Common FM section (see below), they're worth talking about separately.
Addr. | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
24 | Timer A | Timer A upper 8 bits | |||||||
25 | TA | Timer A lower 2 bits | |||||||
26 | Timer B | Timer B value | |||||||
27 | Mode | Reset B | Reset A | Enable B | Enable A | Load B | Load A | Timer A/B Control and 2CH Mode |
Timer A is a 10-bit timer with a minimum resolution of 9 microseconds (when Timer A = 1023). It can either be used as a normal timer or a CSM timer. The CSM timer handles the Key On/Off actions.
In theory, the ports should be written in $24,$25 order. In practice, (meaning in existing Neo-Geo M1 drivers) the timer is written in $25,$24 order.
Where NA is the Timer A value (0-1023). tA is in microseconds.
Timer B is an 8-bit timer with a minimum resolution of 144 microseconds (when Timer B = 255).
Where NB is the Timer B value (0-255). tB is in microseconds.
(todo, as this is important)
Setting a 0 in the respective bit will stop that timer. If a 1 is written instead, the timer will begin.
Setting a 0 in the respective bit will disable the timer from setting flags or generating IRQs. If a 1 is written instead, the timer will set the proper status flag once the counter overflows, and an IRQ will be generated.
Setting a 1 in the respective bit will reset the status flags for that timer.
Channel 2's output mode can be changed with these bytes. This has not been fully explored yet, and is partially based off of YM2608 documentation.
D7 | D6 | Mode | Function |
---|---|---|---|
0 | 0 | Normal | Normal output, like other channels. |
0 | 1 | CSM | CSM voice synthesis mode; each slot can use a separate F-Number. In CSM mode, key on/off is done with Timer A. |
1 | 0 | ? | ? (YM2608: "Effect sound"; Each slot can have a separate F-Number and CSM.) |
1 | 1 | ? | ? (YM2608: "Effect sound"; Each slot can have a separate F-Number and CSM.) |
The Simple Sound Generator, originally found in the YM2149, is compatible with the AY-3-8910/PSG. On the YM2610, the I/O ports were removed. (The missing bits in register $07 and missing addresses $0E and $0F correspond to the I/O functions.)
All SSG addresses and data are written to ports 4/5.
Addr. | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
00 | Fine Tune | Channel A Tone Period | |||||||
01 | Coarse Tune | ||||||||
02 | Fine Tune | Channel B Tone Period | |||||||
03 | Coarse Tune | ||||||||
04 | Fine Tune | Channel C Tone Period | |||||||
05 | Coarse Tune | ||||||||
06 | Period Control | Noise Period | |||||||
07 | /nC | /nB | /nA | /tC | /tB | /tA | /Enable (Output when 0; n=noise, t=tone) | ||
08 | M | Level | Channel A Amplitude/Mode | ||||||
09 | M | Level | Channel B Amplitude/Mode | ||||||
0A | M | Level | Channel C Amplitude/Mode | ||||||
0B | Fine Tune | Envelope Period | |||||||
0C | Coarse Tune | ||||||||
0D | CON | ATT | ALT | HLD | Envelope Shape Cycle |
The SSG tone period has a resolution of 12 bits, allowing for values from 1-4095. The "Coarse Tune" registers should be written before the "Fine Tune" registers.
To calculate the frequency from a given tone period, use this equation:
Where TP is the Tone Period in decimal (base 10).
The SSG noise period has a resolution of 5 bits, allowing for values from 1-31. It is shared between all three channels. To calculate the frequency from a given noise period, use this equation:
Where NP is the Noise Period in decimal (base 10).
The "M" bit in the Amplitude/Mode controls determines how the volume is modified.
Values for the "Level" portion of the register:
D3 | D2 | D1 | D0 |
---|---|---|---|
16 | 8 | 4 | 2 |
It should be noted that the default level is 1, meaning if you set 0x00 here, the level will still be 1.
The SSG envelope period controls the repetition period of the envelope generator. It only matters if the "M" bit in Amplitude/Mode is set to 1 for at least one channel. The envelope is shared between all SSG channels.
Write to address $0C first, then $0B.
The SSG envelope period has a resolution of 16 bits, allowing for values from 1-65535. To calculate the frequency from a given envelope period, use this equation:
Where EP is the Envelope Period in decimal (base 10). Cycle tEG (?) is generated by 1/EG freq.
(todo: point out the loop region in each shape)
No. | CON | ATT | ALT | HLD | Envelope Shape |
---|---|---|---|---|---|
0 | 1 | 0 | 0 | 0 | |
1 | 1 | 0 | 0 | 1 | |
2 | 1 | 0 | 1 | 0 | |
3 | 1 | 0 | 1 | 1 | |
4 | 1 | 1 | 0 | 0 | |
5 | 1 | 1 | 0 | 1 | |
6 | 1 | 1 | 1 | 0 | |
7 | 1 | 1 | 1 | 1 |
There is only one ADPCM-B channel, but it allows for varying sample rates (1.8KHz to 55.5KHz), unlike the fixed sample rate of ADPCM-A.
It should be noted that the Neo-Geo CD does not have ADPCM-B, as you're expected to use the CD-DA instead. Go figure.
All ADPCM-B addresses and data are written to ports 4/5.
Addr. | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
10 | Start | Repeat | Reset | Control 1 | |||||
11 | L | R | Left/Right Control | ||||||
12 | Address lower 8 bits | Start Address/256 (LSB) | |||||||
13 | Address upper 8 bits | Start Address/256 (MSB) | |||||||
14 | Address lower 8 bits | End Address/256 (LSB) | |||||||
15 | Address upper 8 bits | End Address/256 (MSB) | |||||||
19 | Delta-N lower 8 bits | Delta-N (LSB) | |||||||
1A | Delta-N upper 8 bits | Delta-N (MSB) | |||||||
1B | Output Level | EG Control (Volume) | |||||||
1C | B | A5 | A4 | A3 | A2 | A1 | A0 | ADPCM Flag Control |
The Start and End address registers only use two bytes, so the third byte of the sample address is forced, dependent on Start (all 0s) or End (all 1s).
For example, if a sound starts at physical address 0x000400 and ends at 0x000800 (non-inclusive), the values to be written would be 0x0004 and 0x0007 (translating to an end address of 0x0007FF).
D23 | D22 | D21 | D20 | D19 | D18 | D17 | D16 | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Start MSB | Start LSB | Fixed 0 |
D23 | D22 | D21 | D20 | D19 | D18 | D17 | D16 | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
End MSB | End LSB | Fixed 1 |
The translated YM2610 datasheet going around gives the following formula for calculating the frequency from a Delta-N value, where △N is a 16-bit unsigned value:
However, the YM2610 datasheet's algorithm doesn't seem to give proper values, so it's easier to follow the equation from the YM2608 datasheet:
If you would like to use the sampling rate in Hertz, expand 55.5 to 55000 and make sure you fill in f accordingly.
Setting any bit to 1 in this register will set the corresponding flag in Status 1 to 0.
All SSG addresses and data are written to ports 6/7.
Addr. | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
00 | DM | Ch5 | Ch4 | Ch3 | Ch2 | Ch1 | Ch0 | Dump/ADPCM-A On | |
01 | Total Level | ADPCM-A Total Level | |||||||
02 | Test | LSI Test Data | |||||||
08-0D | L | R | Channel Level | Output Select/Channel Level | |||||
10-15 | Address lower 8 bits | Start Address/256 (LSB) | |||||||
18-1D | Address upper 8 bits | Start Address/256 (MSB) | |||||||
20-25 | Address lower 8 bits | End Address/256 (LSB) | |||||||
28-2D | Address upper 8 bits | End Address/256 (MSB) |
The "Dump" bit is more like a playback toggle bit. If it's 0, the sound will play. If it's 1, the sound will stop.
ADPCM-A total volume is between 0dB and -47.25db in steps of 0.75dB. When all values are set to 1, the volume is 0dB.
ADPCM-A channel volumes are between 0dB and -23.25dB in steps of 0.75dB. When all values are set to 1, the volume is 0dB.
ADPCM-A Sample Addresses operate under a few specific rules...
D23 | D22 | D21 | D20 | D19 | D18 | D17 | D16 | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Start MSB* | Start MSB | Start LSB | Fixed 0 |
D23 | D22 | D21 | D20 | D19 | D18 | D17 | D16 | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
End MSB* | End MSB | End LSB | Fixed 1 |
* The topmost four bits of the Start and End MSB values must be the same.
The common FM registers are written to ports 4/5.
Addr. | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
21 | Test | LSI Test Data | |||||||
22 | On | LFO Freq. | LFO Frequency Control | ||||||
24 | Timer A | Timer A upper 8 bits | |||||||
25 | TA | Timer A lower 2 bits | |||||||
26 | Timer B | Timer B data | |||||||
27 | Mode | Reset | Enable | Load | Timer A/B Control and 2CH Mode | ||||
28 | Slot | Chan | Key On/Off |
Addresses and data for FM channels 1 and 2 are written to ports 4/5. Channels 3 and 4 use ports 6/7.
Addr. | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Comment |
---|---|---|---|---|---|---|---|---|---|
31-3E | DT | MULTI | Detune (DT)/Multiple | ||||||
41-4E | TL | Total Level (TL) | |||||||
51-5E | KS | AR | Key Scale (KS)/Attack Rate (AR) | ||||||
61-6E | AM | DR | AM On/Decay Rate (DR) | ||||||
71-7E | SR | Sustain Rate (SR) | |||||||
81-8E | SL | RR | Sustain Level (SL)/Release Rate (RR) | ||||||
91-9E | SSG-EG | SSG-type Envelope Generator | |||||||
A1,A2 | F-Num 1 | F-Numbers/Block | |||||||
A5,A6 | Block | F-Num 2 | |||||||
A9,AA | 2CH * F-Num 1 | 2CH - 2 Slot F-Numbers/Block | |||||||
AD,AE | 2CH * Block | 2CH * F-Num 2 | |||||||
B1,B2 | FB | Algorithm | Self Feedback (FB)/Algorithm | ||||||
B5,B6 | L | R | AMS | PMS | LR Sel./AM Sense (AMS)/PM Sense (PMS) |
(todo: does the YM2610 use a similar setup to the YM2608 for CSM mode?)
As the YM2610 has four operators per channel, the above register ranges need to be clarified.
Operator | 1 | 2 | 3 | 4 |
---|---|---|---|---|
Ch.1, Ch.3 | *1 | *5 | *9 | *D |
Ch.2, Ch.4 | *2 | *6 | *A | *E |
(todo: diagrams)
The Algorithm, also known as the Connection, defines how each of the operators interacts with each other. There are eight algorithms. The algorithm can be thought of as the base element of the sound, while the parameters define the rest of the sound's character.
The first slot of each channel provides a self-feedback function. If "π" looks odd on your system, it's meant to be the value of pi.
Feedback | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
Modulation Level | Off | π/16 | π/8 | π/4 | π/2 | π | 2π | 4π |
This is the primary way of starting/stopping notes. The on/off status of the four operators can be set.
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|
Op4 | Op3 | Op2 | Op1 | Channels |
The regular YM2610 only has four channels, but the YM2610B can access all six channels. (Setting all channel bits to 1 is unknown behavior??)
YM2610/Neo-Geo channels are in parentheses. Hard channels 3/4 are unused on the Neo-Geo, with the real channels 3/4 being mapped to hard channels 5/6. I wonder if anyone has the guts to put a YM2610B in their machine and perform some tests...
Channel | D2 | D1 | D0 |
---|---|---|---|
1 (1) | 0 | 0 | 0 |
2 (2) | 0 | 0 | 1 |
3 | 0 | 1 | 0 |
4 | 1 | 0 | 0 |
5 (3) | 1 | 0 | 1 |
6 (4) | 1 | 1 | 0 |
(todo)
The Attack Rate defines how fast the sound reaches its maximum volume after Key On.
Valid values are 0-31. Larger rates mean the sound reaches maximum volume faster. A value of 0 will cause the envelope to not start.
The Decay Rate defines how quickly the sound will drop to the Sustain Level after the initial peak.
Valid values are 0-31. Larger rates mean the sound decays faster. A value of 0 will cause the sound to continue without decaying.
The Sustain Rate defines the speed at which the volume of the sustained note increases or decreases.
The Sustain Level defines the volume of the sound after the decay, but before the note is released (Key off).
Valid values are 0-15.
D7 | D6 | D5 | D4 | |
---|---|---|---|---|
Volume (db) | 24 | 12 | 6 | 3 |
When all bits are set to 1, the value is 93dB.
The Release Rate defines how quicky the sound ends when the key is released (Key off).
Valid values are 0-15. Larger rates provide a shorter wait. A value of 0 will ??
The F-Numbers and Block value set the note frequency. The ideal way to set up your values involves creating a single octave's worth of F-Numbers, and then use that set of values while changing the Block.
To calculate the F-Number from a given frequency, use this equation:
$A5,$A6 (2CH mode: $AD,$AE) | $A1,$A2 (2CH mode: $A9,$AA) | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | | | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
Block | F-Num 2 | F-Num 1 |
Block and F-Num 2 must be written first!
(todo)
D6 is the sign bit.
Value | D6 | D5 | D4 |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 |
2 | 0 | 1 | 0 |
3 | 0 | 1 | 1 |
-0 | 1 | 0 | 0 |
-1 | 1 | 0 | 1 |
-2 | 1 | 1 | 0 |
-3 | 1 | 1 | 1 |
(todo)
0 is equal to 1/2, while 1-F (hex) map to 1-15.
Values for the LFO Frequency Control register ($22) are as follows:
Freq. Cont. | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
freq. (Hz) | 3.98 | 5.56 | 6.02 | 6.37 | 6.88 | 9.63 | 48.1 | 72.2 |
(todo)
PMS Value | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
Diff. (Cents) | 0 | ±3.4 | ±6.7 | ±10 | ±14 | ±20 | ±40 | ±80 |
(todo)
AMS Value | 0 | 1 | 2 | 3 |
---|---|---|---|---|
Diff. (dB) | 0 | 1.44 | 5.9 | 11.8 |
The YM2610 is capable of playing back two different ADPCM types, each with a different task (and encoding).
ADPCM-A has a fixed sample rate of 18.5KHz. It's the primary method for sample playback, as there are 6 channels. It is available on all versions of the Neo-Geo.
Sounds were compressed using SNK's tools; To my knowledge, these tools aren't available to the general public. The first capable ADPCM-A sample compressor available to the public was found in MVSTracker, though it was a bit buggy. This code was later used by HPMAN as part of the base for a new compressor (which is not available as a binary).
There is a command line tool capable of producing working ADPCM-A samples.
ADPCM-B has a variable sample rate, which can be anywhere from 5.55KHz to 55.5KHz. This allows for a single sample to imitate an instrument, or can be exploited for space gains. There is only one ADPCM-B channel available. However, ADPCM-B is not available on the Neo-Geo CD.
There was likely a tool from Yamaha or SNK to encode ADPCM-B, though no records have been found to suggest so. A third-party ADPCM-B encoder by ValleyBell and Fred/FRONT was made available in October 2011.
At this point, we can attempt to write a sound driver for the Neo-Geo. This involves a Z80 driving the YM2610, and the 68K and Z80 exchanging command bytes in order for sounds and music to be played.
A successful driver will make use of at least one of the Timers*, and will allow playback on the FM channels, the SSG channels, and all ADPCM channels. I lack the knowledge to get CDDA working right now, so this primarily focuses on the cart systems.
* It is possible to keep the sound engine running via other means, but timers are the most efficient way.
On the Neo-Geo, the sound CPU and the main CPU are not directly connected;
communication happens via writing to/reading from hardware ports. The 68K (main)
CPU sends commands to the Z80 (sound) CPU via a 68K memory mapped register at
$320000
. On the Z80 side, port $00
is used for
reading the code sent from the 68K, and port $0C
is used to
reply to the 68K.
On the Neo-Geo, the Z80 has 65535 bytes available to it. About 2048 bytes are RAM, while the rest is ROM (banked or not).
Start Address | End Address | Size | Description |
---|---|---|---|
0x0000 |
0x7FFF |
32KiB | Main code bank |
0x8000 |
0xBFFF |
16KiB | Switchable bank 3 |
0xC000 |
0xDFFF |
8KiB | Switchable bank 2 |
0xE000 |
0xEFFF |
4KiB | Switchable bank 1 |
0xF000 |
0xF7FF |
2KiB | Switchable bank 0 |
0xF800 |
0xFFFF |
2KiB | Work RAM |
Z80 code starts at position 0x0000
. The first two instructions are
typically di
(disable interrupts) and jp
(jump) to the
real startup code. Jumping to startup code held elsewhere allows you to use some
of the other top addresses for interrupts (see below).
In your startup code, you'll want to do the following:
0xFFFC
; see below for why).0xF800
-0xFFFF
)1
to port 0x8
.The Z80 features a number of interrupts, as well as a variety of ways to
handle them. Most drivers typically use Interrupt Mode 1 (im 1
),
which puts the IRQ at 0x0038
. This is the recommended course of
action, unless you are a Z80 guru. Everything in this section is written
assuming Interrupt Mode 1 is being used.
The IRQs are generated by the YM2610 when one of the timers expires. The two least significant bits of Status 0 contain the timer status, allowing you to see which timer fired off the IRQ.
The NMI (at address 0x0066
) handles communication between the
68000 and Z80. This is one of the more important parts of your sound driver.
In addition to the NMI and IRQ, interrupt vectors can exist at these locations:
0x0000
, 0x0008
, 0x0010
, 0x0018
,
0x0020
, 0x0028
, 0x0030
, 0x0038
.
These vectors are easily accessed in software via the rst
instruction
(e.g. rst $18
). You should take advantage of them for any code
that's called a lot (e.g. writes to ports 4/5 and 6/7). In Interrupt Mode 1,
you probably won't be calling rst $38
.
This part is something I still don't understand how to write. It involves using a buffer for commands.
The Neo-Geo System ROM (BIOS) expects the Z80 to reply to certain commands in specific ways. Your sound driver might also want to handle its own commands as well.
"sent by the system ROM when the slot is switched. As the Z80 rom will be swapped, all sounds need to be stopped, NMI needs to be activated, $01 needs to be sent back to the 68k and the Z80 code has to sit in a loop in RAM. After receiving that $01 reply, the system ROM can then switch slot without crashing the Z80." - NeoGeo Dev Wiki
(todo)
(todo)
Command $03
tells the Z80 to reset itself; this needs to be
done in under 100ms, according to the Neo-Geo Dev Wiki. No reply to the 68K is
expected, but I give one here anyways. Feel free to nuke it in your code.
While the above three commands are expected by the BIOS, the remaining 252 (since 0 is "no command") can be handled in any way you wish. This can be a blessing and a curse.
A typical sound driver will split the available command range into multiple parts:
Command Range | Usage |
---|---|
$01-$1F (32 cmds) | System Commands |
$20-$5F (64 cmds) | FM music tracks |
$60-$7F (32 cmds) | SSG sound effects |
$80-$BF (64 cmds) | ADPCM-A samples |
$C0-$FF (64 cmds) | ADPCM-B samples |
Sampled audio playback is handled via two different types of ADPCM.
There are six ADPCM-A channels, each one with a fixed sampling rate of 18.5KHz.
(todo)
There is only one ADPCM-B channel, and it only appears on Neo-Geo cart systems. Unlike the ADPCM-A channels, ADPCM-B's sampling rate is variable (5.55KHz to 55.5KHz).
(todo)
The SSG channels are a bit tougher to use than the ADPCM channels, but they're easier than the FM channels.
(todo)
(todo)
(todo)
The hardest part of the YM2610 is the FM. This is typical of FM, with half of the battle being spent tweaking the parameters to make good instruments.
(todo)
Sometimes, 64KiB just isn't enough for all of your sound data. There are a few ways around this, depending on what system you're using. The cart systems allow you to swap out different banks; the CD systems give you a few more options, considering the Z80 section is all RAM.
(todo: how the banks are laid out in a .M1 file based on which bank you're loading into)
The following table shows which Z80 ports control the banking, as well as the bank size for each port.
Z80 port | Bank range | Bank size |
---|---|---|
$0B | $8000-$BFFF | 16KiB |
$0A | $C000-$DFFF | 8KiB |
$09 | $E000-$EFFF | 4KiB |
$08 | $F000-$F7FF | 2KiB |
(todo: Neo-Geo CD specific stuff (e.g. PAT files, editing the RAM directly))
(todo)
This would cover topics such as: