diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/i_oplmusic.c | 171 | ||||
-rw-r--r-- | src/m_config.c | 2 |
3 files changed, 172 insertions, 3 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 66909dd1..406d0af8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,7 +3,7 @@ gamesdir = $(prefix)/games games_PROGRAMS = chocolate-doom chocolate-server -AM_CFLAGS = -I../textscreen -I../pcsound @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ +AM_CFLAGS = -I../opl -I../textscreen -I../pcsound @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ DEDSERV_FILES=\ d_dedicated.c \ diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c index ee909193..98170284 100644 --- a/src/i_oplmusic.c +++ b/src/i_oplmusic.c @@ -27,6 +27,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "doomdef.h" #include "memio.h" @@ -38,23 +39,191 @@ #include "w_wad.h" #include "z_zone.h" +#include "opl.h" + #define MAXMIDLENGTH (96 * 1024) +#define GENMIDI_NUM_INSTRS 128 + +#define GENMIDI_HEADER "#OPL_II#" +#define GENMIDI_FLAG_FIXED 0x0000 /* fixed pitch */ +#define GENMIDI_FLAG_2VOICE 0x0002 /* double voice (OPL3) */ + +typedef struct +{ + byte tremolo; + byte attack; + byte sustain; + byte waveform; + byte scale; + byte level; +} PACKEDATTR genmidi_op_t; + +typedef struct +{ + genmidi_op_t modulator; + byte feedback; + genmidi_op_t carrier; + byte unused; + byte base_note_offset; +} PACKEDATTR genmidi_voice_t; + +typedef struct +{ + unsigned short flags; + byte fine_tuning; + byte fixed_note; + + genmidi_voice_t opl2_voice; + genmidi_voice_t opl3_voice; +} PACKEDATTR genmidi_instr_t; static boolean music_initialised = false; //static boolean musicpaused = false; static int current_music_volume; +static genmidi_instr_t *main_instrs; +static genmidi_instr_t *percussion_instrs; + +// Configuration file variable, containing the port number for the +// adlib chip. + +int snd_mport = 0x388; + +static unsigned int GetStatus(void) +{ + return OPL_ReadPort(OPL_REGISTER_PORT); +} + +// Write an OPL register value + +static void WriteRegister(int reg, int value) +{ + int i; + + OPL_WritePort(OPL_REGISTER_PORT, reg); + + // For timing, read the register port six times after writing the + // register number to cause the appropriate delay + + for (i=0; i<6; ++i) + { + GetStatus(); + } + + OPL_WritePort(OPL_DATA_PORT, value); + + // Read the register port 25 times after writing the value to + // cause the appropriate delay + + for (i=0; i<25; ++i) + { + GetStatus(); + } +} + +// Detect the presence of an OPL chip + +static boolean DetectOPL(void) +{ + int result1, result2; + + // Reset both timers: + WriteRegister(OPL_REG_TIMER_CTRL, 0x60); + + // Enable interrupts: + WriteRegister(OPL_REG_TIMER_CTRL, 0x80); + + // Read status + result1 = GetStatus(); + + // Set timer: + WriteRegister(OPL_REG_TIMER1, 0xff); + + // Start timer 1: + WriteRegister(OPL_REG_TIMER_CTRL, 0x21); + + // Wait for 80 microseconds + + // Read status + result2 = GetStatus(); + + // Reset both timers: + WriteRegister(OPL_REG_TIMER_CTRL, 0x60); + + // Enable interrupts: + WriteRegister(OPL_REG_TIMER_CTRL, 0x80); + + return (result1 & 0xe0) == 0x00 + && (result2 & 0xe0) == 0xc0; +} + + +// Load instrument table from GENMIDI lump: + +static boolean LoadInstrumentTable(void) +{ + byte *lump; + + lump = W_CacheLumpName("GENMIDI", PU_STATIC); + + // Check header + + if (strncmp((char *) lump, GENMIDI_HEADER, strlen(GENMIDI_HEADER)) != 0) + { + W_ReleaseLumpName("GENMIDI"); + + return false; + } + + main_instrs = (genmidi_instr_t *) (lump + strlen(GENMIDI_HEADER)); + percussion_instrs = main_instrs + GENMIDI_NUM_INSTRS; + + return true; +} + // Shutdown music static void I_OPL_ShutdownMusic(void) { + if (music_initialised) + { + OPL_Shutdown(); + + // Release GENMIDI lump + + W_ReleaseLumpName("GENMIDI"); + + music_initialised = false; + } } // Initialise music subsystem static boolean I_OPL_InitMusic(void) -{ +{ + if (!OPL_Init(snd_mport)) + { + return false; + } + + // Doom does the detection sequence twice, for some reason: + + if (!DetectOPL() || !DetectOPL()) + { + printf("Dude. The Adlib isn't responding.\n"); + OPL_Shutdown(); + return false; + } + + // Load instruments from GENMIDI lump: + + if (!LoadInstrumentTable()) + { + OPL_Shutdown(); + return false; + } + music_initialised = true; return true; diff --git a/src/m_config.c b/src/m_config.c index 4066cb3c..c54b3774 100644 --- a/src/m_config.c +++ b/src/m_config.c @@ -124,6 +124,7 @@ extern int vanilla_demo_limit; extern int snd_musicdevice; extern int snd_sfxdevice; extern int snd_samplerate; +extern int snd_mport; // controls whether to use libsamplerate for sample rate conversions @@ -136,7 +137,6 @@ extern int use_libsamplerate; static int snd_sbport = 0; static int snd_sbirq = 0; static int snd_sbdma = 0; -static int snd_mport = 0; typedef enum { |