EMULib

by Marat Fayzullin

What is EMULib?

EMULib is a set of C library modules which I wrote to use in computer emulators. Some of this modules emulate various computer chips. Others are used to play sound, handle data files, and work with hardware. EMULib is available from

http://www.komkon.org/fms/EMUL8/

Be aware that EMULib is a work in progress. Every now and then I add new modules and extend existing ones. Documentation is incomplete and may not always be up to date. In this situation, the header files are your best friends. Check them out for fresh information on the libraries.

Copyright Notice

Both EMULib source code and documentation are copyrighted by me, Marat Fayzullin. Following restrictions apply to these materials:

How To Use EMULib?

Following chapters will cover various EMULib modules:

Library for Handling GameBoy Cartridges (.GB)

GBCarts.h GBCarts.c

GameBoy, Super GameBoy, GameBoy Color, and Pocket Camera are all trademarks of Nintendo.

The GBCarts library included into EMULib allows to verify ROM images of GameBoy cartridges (.GB) and obtain various information about the cartridge hardware and software. Some of the library functionality is provided through functions in GBCarts.c, while the rest is implemented with macros in GBCarts.h.

GameBoy ROMs contain all the useful information about the cartridge in the first 512 bytes of the ROM also called the "header". To use the GBCarts library, you will have to load this header into memory and pass its address to the library functions.

Some functions, such as GB_RealCRC(), work on the entire contents of the ROM. For such functions, you will have to load entire ROM into memory and pass its address.

The GBCarts functions are divided into several groups:


Library for Handling NES/Famicom Cartridges (.NES)

NESCarts.h NESCarts.c

Nintendo Entertainment System, VS-System, and Famicom are all trademarks of Nintendo.

The NESCarts library included into EMULib allows to obtain hardware and software information from the NES/Famicom cartridge images stored in .NES files. Some of the library functionality is provided through functions in NESCarts.c, while the rest is implemented with macros in NESCarts.h.

.NES files have 16-byte headers that contain cartridge information. To use the NESCarts library, you will have to load a header into memory and pass its address to the library functions.

Some functions, such as NES_CRC(), work on the entire contents of the cartridge. For such functions, you will have to load entire cartridge image into memory and pass its address.


Library for Handling SEGA 8Bit Cartridges (.SMS/.GG)

SMSCarts.h SMSCarts.c

Master System and GameGear are trademarks of SEGA.

The SMSCarts library is very similar to GBCarts and NESCarts libraries but works on the SEGA Master System and GameGear cartridges. Some of the library functionality is provided through functions in SMSCarts.c, while the rest is implemented as macros in SMSCarts.h.

SEGA ROMs do not have definite headers. Instead, the cartridge information is stored in the middle or the end of the ROM. Therefore, all SMSCarts functions require a pointer to entire ROM. Functions that start with SMS_ only work on MasterSystem ROMs (.SMS). Functions that start with GG_ only work on GameGear ROMs (.GG).

The SMSCarts functions are divided into several groups:


Library for Handling GameBoy Advance Cartridges (.GBA)

GBACarts.h GBACarts.c

GameBoy and GameBoy Advance are trademarks of Nintendo.
The GBACarts library allows to verify ROM images of GameBoy Advance cartridges (.GBA) and obtain various information about the cartridge hardware and software. Some of the library functionality is provided through functions in GBACarts.c, while the rest is implemented with macros in GBACarts.h.

Same as GameBoy ROMs, GameBoy Advance ROMs contain all the useful information about the cartridge in a 512-byte header. To use the GBACarts library, you will have to load this header into memory and pass its address to the library functions.

Some functions, such as GBA_RealCRC(), work on the entire contents of the ROM. For such functions, you will have to load entire ROM into memory and pass its address.

The GBACarts functions are divided into several groups:


Sound Playback and MIDI Logging Library

Sound.h Sound.c SndUnix.c SndUnixT.c SndMSDOS.c SndWin.c MIDIFreq.h FMFreq.h

EMULib's unified sound library provides sound chip emulation modules with sound generation capabilities on Unix, MS Windows, and MSDOS platforms. The library also allows to record polyphonic single-track MIDI files (.MID) based on the melodic sound data. Thus, one can use the library for saving soundtrack from an emulator or converting various melodic music formats to the MIDI format.

To make use of the sound library, your program should at least #include Sound.h file and link with the Sound.c file. This will provide you with the minimal platform-independent features, such as MIDI logging. To get the sound generation features, you will need to #define UNIX|MSDOS|WINDOWS and link with one of the platform-dependent files: SndUnix.c, SndUnixT.c, SndMSDOS.c, or SndWin.c. SndUnixT.c uses POSIX Threads, while SndUnix.c is thread-free at the cost of limited sample playback capabilities.

Your typical program has to start by initializing the sound library in one of the following ways:

If you only expect to use the MIDI logging capabilities without producing the actual sound, you do not need to call InitSound() at all. You will need to call the InitMIDI() function described later though.

After you initialize the library, set the master volume and the active channels with the

SetChannels(MasterVolume,ChannelMask);
call. The MasterVolume changes in the 0..255 range and affects all channels. The ChannelMask has bits for up to 16 channels, depending on the platform (see the SND_CHANNELS macro). You can now set sound types for individual channels with the
SetChannels(Channel,SoundType);
call. SoundType may take following values:
SND_MELODIC      -  "Normal" melodic sound (rectangular waveform).
SND_NOISE        -  White noise.
SND_MIDI|PatchN  -  MIDI instrument <PatchN> (MIDI and midiOut only,
                    reverts to SND_MELODIC on other platforms).

The actual sound is generated with the following self-explanatory function call:

Sound(Channel,Frequency,Volume);
Frequency is given in hertz and Volume varies in the 0..255 range. There are also two convinient calls that only change the frequency or the volume:
SetFreq(Channel,Frequency);
SetVolume(Channel,Volume);
They both get converted to Sound() calls anyway. In addition to the predefined sound types, the sound library allows to play arbitrary waveforms on the platforms that use wave synthesis. To set the channel to a waveform, call the following function:
SetWave(Channel,Data,Length,Rate);
Here, Data is an array of Length signed bytes defining the sound sample. Rate defines the frequency at which the sample is played. Usually, you will have to pass Rate=0 to use the sample as a "musical instrument". Platforms that do not support the SetWave() will default to the SND_MELODIC sound.

Certain platforms (such as Windows midiOut) also support drums. You can hit a drum by calling

Drum(DrumType);
where DrumType takes one of the these values:
DRM_CLICK        -  Short click (useful for simulating key clicks).
DRM_MIDI|DrumN   -  MIDI drum <DrumN> (MIDI and midiOut only).
Platforms that do not support drums will ignore Drum() calls.

Let us now look at the MIDI logging facilities. Before recording anything, you have to tell the library which MIDI file to use. This is done with

InitMIDI(FileName);
Don't be afraid to call InitMIDI() multiple times: the library will close any currently open MIDI file and open a new one. You can control the recording of this MIDI file by calling
Status = MIDILogging(Switch);
where Switch is one of
MIDI_ON          - Start logging.
MIDI_OFF         - Stop logging.
MIDI_TOGGLE      - Toggle logging on/off.
MIDI_QUERY       - Don't touch anything, just return the status.
In all cases, MIDILogging() returns Status!=0 if the logging is active or Status==0 otherwise. The MIDI logging applies to all melodic sound and drums, but it will not preserve custom waveforms set with the SetWave() calls due to the natural limitations of the MIDI standard.

Finally, on all platforms, the sound library is shut down in the same way:

TrashSound();

8255 Programmable Parallel Interface

I8255.h I8255.c

To be documented.

93cXX EEPROM with Serial Access

C93XX.h C93XX.c

To be documented.

SN76489 Programmable Sound Generator

SN76489.h SN76489.c

This is an emulation for the 76489 Programmable Sound Generator (PSG) chip produced by National Semiconductors and Intel. This emulation uses the Sound library to play sounds on the four PSG channels. Start by creating the PSG context:
SN76489 PSG;
This structure contains all PSG registers and other data describing PSG state. Now, initialize the PSG structure with
Reset76489(&PSG,FirstChannel);
After that, you can write byte values into PSG chip by issuing
Write76489(&PSG,Value);
calls. These writes will be converted to the Sound() calls on four sound channels starting from the FirstChannel. There are two different ways to issue these Sound() calls though:

Additionally, you may want to simulate the noise channel by hitting drums when you call Sync76489(). To simulate noise with drums, call

Sync76489(&PSG,SN76489_FLUSH|SN76489_DRUMS);

AY8910/8912 Programmable Sound Generator

AY8910.h AY8910.c

To be documented.

YM2413 Programmable Sound Generator

YM2413.h YM2413.c MIDIFreq.h

To be documented.

TMS9918/9928 Video Processor

TMS9918.h TMS9918.c DRV9918.c

To be documented.

Miscellaneous Functions for MSDOS

LibMSDOS.h LibMSDOS.c

To be documented.

Miscellaneous Functions for Unix

LibUnix.h LibUnix.c

To be documented.

Miscellaneous Functions for Windows

LibWin.h LibWin.c

To be documented.

©2001 Copyright by Marat Fayzullin