ANESE/thirdparty/nes_snd_emu/notes.txt
Daniel Prilik edb40e42e7 APU courtesy of Blargg's 💯 nes_snd_emu library
I started looking into how to make the APU, and boy, let me tell
ya, it's going to be a massive undertaking.

Undoubtedly a fun undertaking, but still...

Since it's a personal goal to get Super Mario Bros 2 running
before new years (after all, that game has won
game-of-the-year i don't even know _how_ many years in a row),
i've decided to just use Blargg's venerable `nes_snd_emu` library
for now.

It took some wrestling, it it's in, and it works!

Almost.

I still don't know why enabling the Frame IRQ kills most games, but
i'll look into that!

Welp, on to bigger and better things!
Namely: MMC1, which will give me Zelda and... Super Mario Bros 2!
2017-12-20 00:00:56 -05:00

169 lines
7.1 KiB
Text
Executable file

Nes_Snd_Emu 0.1.7 Notes
-----------------------
Overview
--------
The library includes a NES APU sound chip emulator, sound sample buffer,
support for state snapshots, a Namco 106 sound chip emulator, a Konami VRC6
sound chip emulator, and a nonlinear sound buffer.
The sound chip emulators handle reads and writes to their registers and
generate samples into one or more sound buffers. Register accesses take a CPU
clock count, relative to the current time frame. When a time frame is ended all
samples from it are added to the sound buffer.
The sound buffer accumulates samples generated by the sound chips and allows
them to be read out at any time. The sample rate can be adjusted freely.
Using the APU
-------------
Simple_Apu is recommended instead of Nes_Apu when using the library for the
first time (see Simple_Apu.h for reference). Its source code demonstrates basic
use of the APU.
To use Nes_Apu (or the other sound chips), its output must be routed to a
Blip_Buffer. Then pass CPU reads and writes to the sound chip, end its time
frame periodically and read samples from the sound buffer.
Nes_Apu apu;
Blip_Buffer buf;
Setup
buf.sample_rate() Set sample rate and allocate memory for buffer
buf.clock_rate() Set clock rate (1789773 for NTSC NES)
apu.output() Route APU output to buffer
apu.dmc_reader() Set function APU calls to read memory
Emulation
apu.write_register() Emulate write to APU register
apu.read_status() Emulate reads APU status register
apu.end_frame() Generate samples for time frame
buf.end_frame() Make samples for time frame available for reading
buf.samples_avail() Number of samples in sound buffer
buf.read_samples() Read samples out of sound buffer
Nonlinear Sound Emulation
-------------------------
Nonlinear_Buffer is a special sound buffer which emulates the non-linearity of
the NES APU sound chip on the triangle, noise, and DMC channels. It can be used
in place of Blip_Buffer, except that the APU should be assigned using
buf.enable_nonlinearity( apu ), and other sound chips using
other_sound_chip.output( buf.buffer() ).
Blip_Buffer
-----------
Basic Blip_Buffer operation is covered. Further features like frequency
equalization and other features are not described. For more information and
examples of using Blip_Buffer, download the full Blip_Buffer library package
Emulation Accuracy
------------------
Nes_Apu accuracy has some room for improvement, especially regarding IRQ
handling. I am still working on reverse-engineering the NES APU and designing
an improved APU.
Nes_Namco and Nes_Vrc6 accuracy is based on the documentation I have. I have
made many tweaks to make them sound similar to a couple of samples I've heard
of the real thing.
Solving Problems
----------------
If you're having problems, check the following:
- If multiple threads are being used, ensure that only one at a time is
accessing objects from the library. This library is not thread-safe.
- Turn the compiler's optimizer is off. Sometimes an optimizer generates bad
code.
- Enable debugging support. This enables assertions and other run-time checks.
- See if the demo works. If not, contact me.
Error handling
--------------
Functions which can fail have a return type of blargg_err_t, which is a pointer
to an error string (const char*). If the function is successful it returns
blargg_success (NULL), otherwise it returns a pointer to an error string.
To allow compatibility with older C++ compilers, no exceptions are thrown by
any of the modules. The library is exception-safe, and any exceptions which
occur are not intercepted. Any exceptions thrown by the standard library or
caller-supplied functions are not caught.
The library uses BLARGG_NEW instead of new for allocations. By default,
BLARGG_NEW is #defined to new (nothrow) so that a failed allocation won't cause
an exception. This can be overriden in your config.h file (see below).
Significant violations of the documented interface are flagged with debug-only
assertions. Failure of these usually indicates a caller error rather than a
defect in the library.
Configuration
-------------
The header "blargg_common.h" is used to establish a common environment, and is
#included at the beginning of all library headers and sources. It attempts to
automatically determine the features of the environment, but might need help.
If HAVE_CONFIG_H is defined in the compiler options, the file "config.h" is
included at the beginning of each library header file, allowing configuration
options for the library to be set. It's fine if other libraries also use this
scheme, as they won't conflict.
I have attempted to design the library so that configuration can be done
without modifying any of the library sources and header files. This makes it
easy to upgrade to a new version without losing any customizations to its
configuration.
Some parts of the library might depend on the order of bytes in multibyte
types. If so, they will cause a compilation error if the order can't be
determined (rather than silently fail). If this occurs, define the appropriate
symbol. For big-endian (most significant byte first, i.e. Motorola 68000,
PowerPC), #define BLARGG_BIG_ENDIAN to 1. For little-endian (least significant
byte first, i.e. Intel x86), #define BLARGG_LITTLE_ENDIAN to 1.
Older C++ compilers might not support bool. Support is provided where bool is
not available, but the compiler's support of bool might not be properly
determined. If errors occur in "blargg_common.h" in the bool section, #define
BLARGG_COMPILER_HAS_BOOL to 1 if your compiler supports bool, otherwise 0.
If your compiler doesn't support static_cast<>, #define STATIC_CAST( type ) to
(type) so that old-style casts are used instead.
If your compiler supports namespaces, blargg_common.h uses standard headers
with the "c" prefix to avoid bringing names from std into the global namespace.
If your compiler supports namespaces but this isn't being detected by
blargg_common.h, #define BLARGG_COMPILER_HAS_NAMESPACE to 1.
Every library source file has #include BLARGG_SOURCE_BEGIN after all other
#include lines, to allow setting compiler options and disabling warnings for
library sources only. By default, this is #defined to "blargg_source.h".
In library source files, #include BLARGG_ENABLE_OPTIMIZER is used before
performance-critical code. By default it doesn't do anything, since enabling
compiler options involves compiler-specific #pragma directives.
After you've got the library working, you can enable platform-specific
optimizations by #defining BLARGG_NONPORTABLE to 1. Contact me if you encounter
any problems that only occur when these are enabled.
If you have any problems with "blargg_common.h", contact me.
Boost Compatibility
-------------------
Boost is a collection of small, useful C++ libraries which provide basic
services. If it's not installed in your environment or your environment isn't
supported, a tiny substitute is included in the "boost/" directory. This
implements only that boost functionality used, and is written to work with most
compilers. If boost is already installed, you can delete the included "boost/"
directory. For more information about boost, see http://boost.org/