Game_Music_Emu 0.3.0 Design
---------------------------

Interface conventions
----------------------
If a function retains a pointer to or replaces the value of an object
passed, it takes a pointer so that it will be clear in the caller's
source code that care is required.

Multi-word names have an underscore '_' separator between individual
words.

Functions are named with lowercase words. Functions which perform an
action with side-effects are named with a verb phrase (i.e. load, move,
run). Functions which return the value of a piece of state are named
using a noun phrase (i.e. loaded, moved, running).

Classes are named with capitalized words. Only the first letter of an
acronym is capitalized. Class names are nouns, sometimes suggestive of
what they do (i.e. File_Scanner).

Structure, enumeration, and typedefs to these and built-in types are
named using lowercase words with a _t suffix.

Macros are named with all-uppercase words.

Internal names which can't be hidden due to technical reasons have an
underscore '_' suffix.


Managing Complexity
-------------------
Complexity has been a factor in most library decisions. Many features
have been passed by due to the complexity they would add. Once
complexity goes past a certain level, it mentally grasping the library
in its entirety, at which point more defects will occur and be hard to
find.

I chose 16-bit signed samples because it seems to be the most common
format. Supporting multiple formats would add too much complexity to be
worth it. Other formats can be obtained via conversion.

I've kept interfaces fairly lean, leaving many possible features
untapped but easy to add if necessary. For example the classic emulators
could have volume and frequency equalization adjusted separately for
each channel, since they each have an associated Blip_Synth.

Source files of 400 lines or less seem to be the best size to limit
complexity. In a few cases there is no reasonable way to split longer
files, or there is benefit from having the source together in one file.


Preventing Bugs
---------------
I've done many things to reduce the opportunity for defects. A general
principle is to write code so that defects will be as visible as
possible. I've used several techniques to achieve this.

I put assertions at key points where defects seem likely or where
corruption due to a defect is likely to be visible. I've also put
assetions where violations of the interface are likely. In emulators
where I am unsure of exact hardware operation in a particular case, I
output a debug-only message noting that this has occurred; many times I
haven't implemented a hardware feature because nothing uses it. I've
made code brittle where there is no clear reason flexibility; code
written to handle every possibility sacrifices quality and reliability
to handle vaguely defined situations.


Flexibility through indirection
-------------------------------
I've tried to allow the most flexibility of modules by using indirection
to allow extension by the user. This keeps each module simpler and more
focused on its unique task.

The classic emulators use Multi_Buffer, which potentially allows a
separate Blip_Buffer for each channel. This keeps emulators free of
typical code to allow output in mono, stereo, panning, etc.

All emulators use a reader object to access file data, allowing it to be
stored in a regular file, compressed archive, memory, or generated
on-the-fly. Again, the library can be kept free of the particulars of
file access and changes required to support new formats.


CPU Cores
---------
I've spent lots of time coming up with techniques to optimize the CPU
cores. Some of the most important: execute multiple instructions during
an emulation call, keep state in local variables to allow register
assignment, optimize state representation for most common instructions,
defer status flag calculation until actually needed, read program code
directly without a call to the memory read function, always pre-fetch
the operand byte before decoding instruction, and emulate instructions
using common blocks of code.

I've successfully used Nes_Cpu in a fairly complete NES emulator, and
I'd like to make all the CPU emulators suitable for use in emulators. It
seems a waste for them to be used only for the small amount of emulation
necessary for game music files.

I debugged the CPU cores by writing a test shell that ran them in
parallel with other CPU cores and compared all memory accesses and
processor states at each step. This provided good value at little cost.

The CPU mapping page size is adjustable to allow the best tradeoff
between memory/cache usage and handler granularity. The interface allows
code to be somewhat independent of the page size.

I optimize program memory accesses to to direct reads rather than calls
to the memory read function. My assumption is that it would be difficult
to get useful code out of hardware I/O addresses, so no software will
intentionally execute out of I/O space. Since the page size can be
changed easily, most program memory mapping schemes can be accommodated.
This greatly reduces memory access function calls.

