
/*****************************************************************************
*
* These are the data stuctures and defines that describe the data that
* the Interwave version of SBOS uses.
*
*****************************************************************************/

/*****************************************************************************
* SBOS knows about 4 'types' of patches to play. (Currently there are
* no effects patches because there is no way for the 'picker' to 
* pick them. We will probably remove it from the data structures soon)
*****************************************************************************/

#define TYPE_BASIC      1    // Basic FM sine waves
#define TYPE_MELODIC    2    // GM Melodic instruments
#define TYPE_PERC       3    // GM percussion instruments
#define TYPE_EFFECT     4

#define SINES_BANK		254

/*****************************************************************************
* This is the envelope structure that SBOS uses. It does NOT use the 
* multi-point, variable length envelope structure the IW kernel uses.
* We determined that the extra code and data to implement them in the
* SB emulator wasn't worth it. This data is kept in DRAM for each
* known wave sample. They will be used for all instruments in MPU-401 
* mode. NOTE: The levels and rates for FM mode are determined from 
* the FM data, NOT the envelope data.
****************************************************************************/
#ifdef NEVER
typedef struct {
    unsigned int  iw_attack_level;      // level to attack to
    unsigned int  iw_sustain_level;     // level to sustain at
    unsigned char iw_attack_rate;       // rate to use to attack level
    unsigned char iw_decay_rate;        // rate to use to decay to sustain
    unsigned char iw_release_rate;      // rate to use to release to 0
} SYN_ENVELOPE;
#endif

typedef struct {
    unsigned char nattacks;
    unsigned char nreleases;
    char mode;                          // one-shot,sustain etc
    unsigned char  rate[6];             // Volume ramp rates
    unsigned int   level[6];            // Envelope levels per point
} SYN_ENVELOPE;

/*****************************************************************************
* These are the instrument 'maps'. Since we can't load all the GM instruments
* into DRAM, we needed a way to map one instrument that isn't loaded into
* one that is. These maps do that translation. The instrument picker algorithm
* is NOT aware of these maps. That frees up the picker to isolate as many
* instruments as possible without needing to be constrained by what is
* actually loaded. The maps are built such that an unloaded instrument should
* be mapped to something that will sound similar. The particular 
* instrument mappings are defined in an input config file that the vendor
* can specify. (iwsblib.cfg)
****************************************************************************/

#define MAX_MELODICS    128
#define MAX_PERCS       128
#define MAX_BASIC       5
#define MAX_EFFECTS     1

typedef struct {
    unsigned int basic_map[MAX_BASIC];            // no-remapping here
    unsigned int melodic_map[MAX_MELODICS];
    unsigned int perc_map[MAX_PERCS];
    unsigned int effect_map[MAX_EFFECTS];        // Not used
} MAPS;


/*****************************************************************************
* This is some miscellaneous data that SBOS needs to know at run time.
* The offsets are used to index into the wave info structures in DRAM.
* Since the wave nums are stored as 8-bit (to save room) and there are
* more than 256 waves, an offset was needed to know where each set of 
* wave info structures starts. The reserved_dram element tells where
* in DRAM the wave information starts. Everything is indexed off of this.
****************************************************************************/

typedef struct {
    unsigned int start_basic;       // Offset to where basic waves start
    unsigned int start_melodics;    // Offset to where melodics start
    unsigned int start_percs;       // Offset to where percs start
    unsigned int start_effects;     // Offset to where effects start (unused)
} PATCH_INFO;

/*****************************************************************************
* The DRAM_INFO structure describes where alot of the data will end up
* residing in DRAM. It is possible to move the SBOS data block to some
* other place that zero. This may be a hany feature if there were some
* memory manager out there that would allocate SBOS a block of DRAM that 
* it could keep. This could help us not re-load our patches.
****************************************************************************/

typedef struct 
    {
    unsigned long dram_begin;            // Base addr of our DRAM 
    unsigned long dram_stopped_voice;    // Put a stopped voice here
    unsigned long dram_temp_buff;        // temp DRAM buffer
    unsigned long dram_perc_map;         // Where perc map sits ...
    unsigned long dram_wave_info;        // Where wave info resides
    unsigned long dram_mpu_info;         // Where MPU info resides (envels)
    } DRAM_INFO;

/*****************************************************************************
* This is the header on the .SBS library file. The major and minor numbers
* are checked against the driver to make sure we understand the library
* header structure. The sustain bits are used by the picker to help
* isolate the instrument. The loaded reads this structure and pokes them
* into the picker's data table. These are patch-specific parameters that
* the picker needs to know. Immediately after this structure is the image
* of the DRAM. (512K ot 1 MEG). This data is a snapshot of DRAM that
* was built by the library builder. All the loader needs to do is read
* the data and send it to DRAM.
****************************************************************************/

// NOTE: THIS STRUCTURE CANNOT CHANGE !!!!!!!
//       THE SBOS ROMS ARE BUILT AGAINST IT.... There is a little pad space
//       at the end that you MIGHT be able to use for specific versions, but
//       the loader code MUST then check versions. DON'T CHANGE the size
//       of this STRUCTURE. Make the pad are smaller if you add anything,
//       and make sure you add it to the end ........
//		 YOU HAVE BEEN WARNED !!!!!!
//

typedef struct {
    unsigned char major;
    unsigned char minor1;
    unsigned char minor2;
// DO NOT MOVE num_waves. It MUST be the 4-5 bytes in the header. The SBOS
// startup code looks there for it .....
    unsigned int num_waves;       // Total # of waves
    unsigned int num_basic;       // # of basic sine waves
    unsigned int num_melodics;    // number of GM melodics loaded
    unsigned int num_percs;       // number of GM percs loaded
    unsigned int num_effects;     // number of effects loaded (none)
    unsigned char sustain[256];   // default sustains for picker
    PATCH_INFO    patch_info;
    MAPS lib_map;
    DRAM_INFO dram_info;
	unsigned char filler[80];		// For expansion ....
} SBOS_LIB_HEADER; 


/*****************************************************************************
* The structure of the DRAM image is quite important. Most of the data in it
* is sample data from the patch files that the builder loaded into DRAM.However,
* some other things are kept down there also. First is the wave_info structure.
* We keep this in DRAM to drastically cut down on PC-RAM usage. This structure 
* will described below. Since its only in DRAM, the size of SBOS isn't 
* dependant of the number of patches and waves we have loaded. We also keep
* all the envelope information for each wave in DRAM (MPU-401 struct). 
* Currently, this is only used for FM emulatio percussion. It will also be used
* for MPU-401 since all it supplies is note-on/note-off type events. For
* FM melodics, we use the FM parameters to create an envelope.
****************************************************************************/

/*****************************************************************************
*
* This structure defines the data associated with each waveform in DRAM. It
* is encoded to make it as small as possible.
*
* magic num is calculated by:
*
*            UPDATE_RATE
*         -----------------  * Patch Root Freq
*         Patch Sample Freq 
*
* The math is done in floating point with result being saved as a long
* to preserve as much precision as possible. The FC can then be calc'ed
* by a simple equation.
*
*                 frequency
*          FC =   ---------
*                 magic num
*
* The start position only requires 24 bits (3 bytes). To make maximum use
* of the space, the extra byte contains the end fraction (bits 0-3) AND
* and a mulitplier to scale the end address. (bits 4-7). They are put in
* the low bits to make decoding it a little easier.
*
* The end offset is added to the start position. The multiplier is used
* to add 64K chunks to allow a wave to be over 64K.
*
* The mode defines 8 bit/16 bit, looping, RAM/ROM etc.
*
* NOTE: This structure could be kept in DRAM ....
*
****************************************************************************/

typedef struct {
    unsigned long magic_num;    // See above calc.
    unsigned long start_pos;    // DRAM start pos/end frac/addr multiplier
    unsigned int beg_offset;    // Offset to start of loop
    unsigned int end_offset;    // Offset to end of loop
    unsigned char mode;         // 8/16, looping etc
	unsigned char atten;		// layer attenuation
	unsigned int freq_scale;	// frequency scalar
	unsigned char freq_center;		// center note
} WAVE_INFO;

/*****************************************************************************
*
* This structure stays in PC RAM only. This will cut down the amount of
* I/O necessary to determine which wave is will used at this freq.
*
* It is used to see if this sample for this patch is within range for
* the frequency they want to play. This helps us keep the note in tune.
*
* The end frequency is the max frequency / 32. Just shift it up 5 bits to
* see if this wave can be used for this freq. If its 0xFF, then this patch
* is good for the entire rest of the scale.
*
* It is kept as a character to minimize PC-RAM usage.
****************************************************************************/

typedef struct {
    unsigned char end_freq;
} WAVE_DATA;

/*****************************************************************************
*
****************************************************************************/

typedef struct {
// DO NOT MOVE sboslib. It MUST be left at head of this structure. SBOS
// startup code expects to find it here ....
	SBOS_LIB_HEADER sboslib;
	unsigned char spare[32];
	unsigned char stopped[32];
	unsigned int tempbuff[32];
	unsigned int perc_map[128];
} ROMSBOS;

