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.
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:
GB_RAMSize(Header) - Size of the cartridge RAM in bytes GB_ROMSize(Header) - Size of the cartridge ROM in bytes GB_ROMBanks(Header) - Size of the cartridge ROM in 16kB banks
GB_ValidType(Header) - TRUE if the cartridge type is valid GB_CRC(Header) - Control sum stored in the header GB_CMP(Header) - Complement byte stored in the header GB_RealCRC(ROM) - Real (computed) ROM control sum GB_RealCMP(Header) - Real (computed) complement byte
GB_TypeID(Header) - Cartridge type ID GB_Type(Header) - Description of cartridge hardware as a string GB_MBC1(Header) - TRUE if the cartridge contains MBC1 chip GB_MBC2(Header) - TRUE if the cartridge contains MBC2 chip GB_MBC3(Header) - TRUE if the cartridge contains MBC3 chip GB_MBC4(Header) - TRUE if the cartridge contains MBC4 chip GB_MBC5(Header) - TRUE if the cartridge contains MBC5 chip GB_HuC1(Header) - TRUE if the cartridge contains Hudson HuC-1 chip GB_HuC3(Header) - TRUE if the cartridge contains Hudson HuC-3 chip GB_MMM01(Header) - TRUE if the cartridge contains MMM-01 chip GB_Camera(Header) - TRUE for Nintendo Pocket Camera GB_Battery(Header) - TRUE if the cartridge contains a battery GB_Timer(Header) - TRUE if the cartridge contains a real-time timer GB_Rumble(Header) - TRUE if the cartridge contains a rumble pack
GB_Name(Header) - Software name as a string GB_MakerID(Header) - Software producer ID GB_Maker(Header) - Producer name as a string, if known GB_Version(Header) - Software revision GB_ColorGB(Header) - TRUE if software supports GameBoy Color GB_SuperGB(Header) - TRUE if software supports Super GameBoy GB_Japanese(Header) - TRUE if software is produced for Japanese market GB_Developer(Header) - TRUE if this is a developer version GB_OnlyColor(Header) - TRUE if software works only on GameBoy Color GB_WithColor(Header) - TRUE if software is enchanced for GameBoy Color
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.
NES_ROMSize(Header) - ROM size in bytes NES_VROMSize(Header) - VROM size in bytes NES_ROMBanks(Header) - ROM size in 16kB ROM banks NES_VROMBanks(Header) - VROM size in 8kB VROM banks NES_Mapper(Header) - Mapper type NES_4Screens(Header) - TRUE if cartridge has no mirroring NES_Mirroring(Header) - TRUE for horizontal mirroring, FALSE for vertical NES_Battery(Header) - TRUE if cartridge has a battery NES_Trainer(Header) - TRUE if .NES file contains a trainer NES_VSSystem(Header) - TRUE if it is a VS-System cartridge NES_CRC(Data,N) - Compute CRC of N bytes of data
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:
SMS_ROMSize(Cart) - MasterSystem ROM size in bytes GG_ROMSize(Cart) - GameGear ROM size in bytes SMS_ROMPages(Cart) - MasterSystem ROM size in 16kB pages GG_ROMPages(Cart) - GameGear ROM size in 16kB pages
SMS_Valid(Cart) - TRUE if the ROM contains SEGA's "magic string" SMS_CRC(Cart) - Control sum stored in the ROM SMS_RealCRC(Cart,N) - Real (computed) ROM control sum
SMS_PartNo(Cart) - Cartridge part number SMS_Config(Cart) - Cartridge configuration SMS_Battery(Cart) - TRUE is cartridge has a battery SMS_Combo(Cart) - TRUE if cartridge contains several games SMS_3D(Cart) - TRUE if cartridge requires 3D glasses
SMS_Date(Cart) - Year when the cartridge was released GG_Country(Cart) - Country for which the cartridge was released GG_Japanese(Cart) - TRUE for Japanese releases GG_European(Cart) - TRUE for European releases GG_US(Cart) - TRUE for US releases
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:
GBA_Valid(Header) - TRUE if ROM contains the "magic number" GBA_CMP(Header) - Complement byte stored in the header GBA_CRC(Header) - Control sum stored in the header (not used) GBA_RealCRC(Data,N) - Real (computed) ROM control sum GBA_RealCMP(Header) - Real (computed) ROM complement byte
GBA_UnitID(Header) - Unit ID GBA_DevType(Header) - Device type
GBA_GameID(Header) - Game ID GBA_MakerID(Header) - Producer's ID GBA_Title(Header) - Game title, as a string (returns internal buffer) GBA_Maker(Header) - Game producer, as a string (if known) GBA_Version(Header) - Software version GBA_Start(Header) - Starting address of the executable code GBA_Japanese(Header) - TRUE for Japanese releases GBA_European(Header) - TRUE for European (multilingual) releases GBA_American(Header) - TRUE for US releases GBA_German(Header) - TRUE for German releases
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:
Result = InitSound(Rate,Verbose);where
Rate
is the wave synthesis rate in the
8000Hz..44100Hz
range (or 0
for silence) and
Verbose
should be set to !=0
if you wish to print
the debugging messages. The function will return Result!=0
on success or Result==0
on failure.
Result = InitSound(Rate);where
Rate
is the SoundBlaster wave synthesis rate
in the 8000Hz..44100Hz
range, 1
for melodic
Adlib sound, or 0
for silence. The function will
return Result!=0
on success or Result==0
on
failure.
Result = InitSound(hInst,Rate,Buffers);where
hInst
is the current application instance.
Rate
is the waveOut
synthesis rate in the
8000Hz..44100Hz
range, 1
for
midiOut
, or 0
for silence. Buffers
is the number of wave synthesis buffers, in the
2..SND_BUFFERS
range. The function will return
Result!=0
on success or Result==0
on failure.
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();
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:
Sound()
immediately when
a value is written into the PSG chip. To do this, call
Sync76489(&PSG,SN76489_ASYNC);after resetting the PSG.
Sound()
calls about 50-60 times a second, at
the end of a video frame. To do this, call
Sync76489(&PSG,SN76489_SYNC);after resetting the PSG. Now, every time you want to put accumulated changes into effect, call
Sync76489(&PSG,SN76489_FLUSH);
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);