diff options
Diffstat (limited to 'src/chips/ymfm/README.md')
-rw-r--r-- | src/chips/ymfm/README.md | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/chips/ymfm/README.md b/src/chips/ymfm/README.md new file mode 100644 index 0000000..29f0d87 --- /dev/null +++ b/src/chips/ymfm/README.md @@ -0,0 +1,125 @@ +# ymfm + +<div style='text-align:center;margin:auto'> +<img src='https://aarongiles.com/img/icon-ymfm.png' width='128px'> +</div> + +[ymfm](https://github.com/aaronsgiles/ymfm) is a collection of BSD-licensed Yamaha FM sound cores (OPM, OPN, OPL, and others), written by [Aaron Giles](https://aarongiles.com) + +## Supported environments + +This code should compile cleanly in any environment that has C++14 support. +It has been tested on gcc, clang, and Microsoft Visual C++ 2019. + +## Supported chip families + +Currently, support is present for the following chips (organized by header file): + +* ymfm_misc.h: + * YM2149 (SSG) [1983: MSX; Atari ST] +* ymfm_opm.h: + * YM2151 (OPM) [1983: Sharp X1, X68000; MSX; synths: DX21, DX27, DX100] + * YM2164 (OPP) [1985: FB-01 MIDI Expander; IBM Music Feature Card; MSX; synths: Korg DS-8, 707] +* ymfm_opn.h: + * YM2203 (OPN) [1984: NEC PC-88, PC-98, NEC PC-6001mkII SR, PC-6601 SR] + * YM2608 (OPNA) [1985: NEC PC-88, PC-98] + * YM2610 (OPNB) [1987: Neo Geo] + * YM2610B (OPNB2) + * YM2612 (OPN2) [1988: Sega Mega Drive/Genesis; FM Towns] + * YM3438 (OPN2C) + * YMF276 (OPN2L) + * YMF288 (OPN3L) [1995: NEC PC-98] +* ymfm_opl.h: + * YM3526 (OPL) [1984: C64 SFX Sound Expander] + * Y8950 (MSX-Audio) [1984: MSX] + * YM3812 (OPL2) [1985: AdLib, Sound Blaster; synths: some Portasound keyboards] + * YMF262 (OPL3) [1988: Sound Blaster Pro 2.0, SB16] + * YMF289B (OPL3L) + * YMF278B (OPL4) [1993: MSX Moonsound cartridge] + * YM2413 (OPLL) [1986: Sega Master System, Mark III; MSX; synths: Portasound PSS-140, PSS-170, PSS-270] + * YM2423 (OPLL-X) + * YMF281 (OPLLP) + * DS1001 (Konami 053982/VRC7) [1991: Famicom cartridge Lagrange Point] +* ymfm_opq.h: + * YM3806 (OPQ) [synths: PSR-60/70] +* ymfm_opz.h: + * YM2414 (OPZ) [1987: synths: TX81Z, DX11, YS200; Korg Z3 guitar synth] + +There are some obviously-related chips that also are on my horizon but have no implementation as yet: + +* YMW-258-F 'GEW8' (aka Sega 315-5560 aka Sega Multi-PCM) +* YMF271 (OPX) +* YM21280 (OPS) / YM21290 (EGS) [synths: DX7, DX1, DX5, DX9, TX7, TX216, TX416, TX816] +* OPK? + +## History + +These cores were originally written during the summer and fall of 2020 as part of the [MAME](https://mamedev.org/) project. +As such, their design started off heavily based on how MAME works. + +The OPM/OPN cores first appeared in MAME 0.230. +The OPL cores were added in MAME 0.231. +A further rewrite to abstract MAME dependencies is planned for MAME 0.232. + +The goal was threefold: +1. provide BSD-licensed emulation cores that are more compatible with MAME's core licensing +1. modernize and unify the code around a common implementation of shared features +1. improve accuracy where possible based on discoveries made by others + +## Accuracy + +The goal of these cores is not 100% digital accuracy. +To achieve that would require full emulation of the pipelines, which would make the code extremely difficult to comprehend. +It would also make it much harder to share common implementations of features, or to add support for less well-known chip types. +If you want that level of accuracy, there are [several](https://github.com/nukeykt/Nuked-OPN2) [decap-based](https://github.com/nukeykt/Nuked-OPM) [emulation cores](https://github.com/nukeykt/Nuked-OPLL) out there. + +Instead, the main goals are: +1. Extremely high (audibly indistinguishable) accuracy +1. Reasonable performance +1. Clean design with readable code +1. Clear documentation of the various chips + +## General approach + +Check out the [examples directory](https://github.com/aaronsgiles/ymfm/tree/main/examples) for some example usage patterns. +I'm not a big fan of makefiles for simple things, so instructions on how to compile each example are provided at the top. + +# IMPORTANT + +As of May 2021, the interface to these is still a bit in flux. +Be prepared when syncing with upstream to make some adjustments. + +### Clocking + +The general philosophy of the emulators provided here is that they are clock-independent. +Much like the actual chips, you (the consumer) control the clock; the chips themselves have no idea what time it is. +They just tick forward each time you ask them to. + +The way you move things along is via the `generate()` function, which ticks the internal system forward one or more samples, and writes out an array out chip-specific `output_data`. +But what, exactly, is a "sample", and how long is it? + +This is where the external clock comes in. +Most of the Yamaha chips are externally clocked in the MHz range. +They then divide that clock by a factor (sometimes dynamically controllable), and then the internal operators are pipelined to further divide the clock. + +For example, the YM2151 internally divides the clock by 2, and has 32 operators to iterate through. +Thus, for a nominal input lock of 3.58MHz, you end up at around a 55.9kHz sample rate. +Fortunately, all the chip implementations can compute this for you; just pass the raw external clock value to the `sample_rate()` method and it will hand you back the output sample rate you want. + +Then call `generate()` that many times per second to output the results. + +But what if I want to output at a "normal" rate, like 44.1kHz? +Sorry, you'll have to rate convert as needed. + +### Reading and Writing + +To read or write to the chips, you can call the `read()` and `write()` methods. +The offset provided corresponds to the addressing input lines in a (hopefully) logical way. + +For reads, almost all chips have a status register, which you can read via `read_status()`. +Some chips have a data port that can be read via `read_data()`. +And chips with extended addressing may also have `read_status_hi()` and `read_data_hi()`. + +For writes, almost all chips have an address register and a data register, and so you can reliably count on there being a `write_address()` and `write_data()` method as well. +If the chip supports extended addressing, it may also have `write_address_hi()` and `write_data_hi()`. + |