aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/softseq/opl2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/sfx/softseq/opl2.cpp')
-rw-r--r--engines/sci/sfx/softseq/opl2.cpp579
1 files changed, 0 insertions, 579 deletions
diff --git a/engines/sci/sfx/softseq/opl2.cpp b/engines/sci/sfx/softseq/opl2.cpp
deleted file mode 100644
index 21fe41962c..0000000000
--- a/engines/sci/sfx/softseq/opl2.cpp
+++ /dev/null
@@ -1,579 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/***************************************************************************
- opl2.c Copyright (C) 2002/04 Solomon Peachy, Christoph Reichenbach
-
- This program may be modified and copied freely according to the terms of
- the GNU general public license (GPL), as long as the above copyright
- notice and the licensing information contained herein are preserved.
-
- Please refer to www.gnu.org for licensing details.
-
- This work is provided AS IS, without warranty of any kind, expressed or
- implied, including but not limited to the warranties of merchantibility,
- noninfringement, and fitness for a specific purpose. The author will not
- be held liable for any damage caused by this work or derivatives of it.
-
- By using this source code, you agree to the licensing terms as stated
- above.
-
-***************************************************************************/
-
-#include "common/util.h"
-
-#include "sci/tools.h"
-#include "sci/sfx/iterator.h"
-#include "sci/sfx/softseq.h"
-#include "sci/sfx/adlib_sbi.h"
-#include "sci/sfx/sci_midi.h"
-
-#include "sound/fmopl.h"
-
-namespace Sci {
-
-// FIXME: Instead of hardcoding SAMPLE_RATE we should call Mixer::getOutputRate()
-#ifdef __DC__
-#define SAMPLE_RATE 22050
-#elif defined (__WII__)
-#define SAMPLE_RATE 48000
-#else
-#define SAMPLE_RATE 44100
-#endif
-
-#define CHANNELS SFX_PCM_MONO
-#define STEREO 0
-
-/* local function declarations */
-
-static void opl2_allstop(sfx_softseq_t *self);
-
-//#define DEBUG_ADLIB
-
-/* portions shamelessly lifted from claudio's XMP */
-/* other portions lifted from sound/opl3.c in the Linux kernel */
-
-static int ready = 0;
-
-static int register_base[11] = {
- 0x20, 0x23, 0x40, 0x43,
- 0x60, 0x63, 0x80, 0x83,
- 0xe0, 0xe3, 0xc0
-};
-
-static int register_offset[12] = {
- /* Channel 1 2 3 4 5 6 7 8 9 */
- /* Operator 1 */ 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12, 0x18, 0x19, 0x1A
-
-};
-
-static int ym3812_note[13] = {
- 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca,
- 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287,
- 0x2ae
-};
-
-static uint8 sci_adlib_vol_base[16] = {
- 0x00, 0x11, 0x15, 0x19, 0x1D, 0x22, 0x26, 0x2A,
- 0x2E, 0x23, 0x37, 0x3B, 0x3F, 0x3F, 0x3F, 0x3F
-};
-static uint8 sci_adlib_vol_tables[16][64];
-
-/* back to your regularly scheduled definitions */
-
-static uint8 instr[MIDI_CHANNELS];
-static uint16 pitch[MIDI_CHANNELS];
-static uint8 vol[MIDI_CHANNELS];
-static uint8 pan[MIDI_CHANNELS];
-static int free_voices = ADLIB_VOICES;
-static uint8 oper_note[ADLIB_VOICES];
-static uint8 oper_chn[ADLIB_VOICES];
-
-static FM_OPL *ym3812 = NULL;
-
-static uint8 adlib_reg[256];
-static uint8 adlib_master;
-
-
-/* initialise note/operator lists, etc. */
-void adlibemu_init_lists() {
- int i;
-
- int j;
-
- for (i = 0 ; i < 16 ; i++) {
- for (j = 0; j < 64 ; j++) {
- sci_adlib_vol_tables[i][j] = ((uint16)sci_adlib_vol_base[i]) * j / 63;
- }
- }
-
- for (i = 0; i < MIDI_CHANNELS ; i++) {
- pitch[i] = 8192; /* center the pitch wheel */
- }
-
- free_voices = ADLIB_VOICES;
-
- memset(instr, 0, sizeof(instr));
- memset(vol, 0x7f, sizeof(vol));
- memset(pan, 0x3f, sizeof(pan));
- memset(adlib_reg, 0, sizeof(adlib_reg));
- memset(oper_chn, 0xff, sizeof(oper_chn));
- memset(oper_note, 0xff, sizeof(oper_note));
- adlib_master = 12;
-}
-
-/* more shamelessly lifted from xmp and adplug. And altered. :) */
-
-static void opl_write(int a, int v) {
- adlib_reg[a] = v;
- OPLWrite(ym3812, 0x388, a);
- OPLWrite(ym3812, 0x389, v);
-}
-
-void synth_setpatch(int voice, uint8 *data) {
- int i;
-
- opl_write(0xBD, 0);
-
- for (i = 0; i < 10; i++)
- opl_write(register_base[i] + register_offset[voice], data[i]);
-
- opl_write(register_base[10] + voice, data[10]);
-
- /* mute voice after patch change */
- opl_write(0xb0 + voice, adlib_reg[0xb0+voice] & 0xdf);
-
-#ifdef DEBUG_ADLIB
- for (i = 0; i < 10; i++)
- printf("%02x ", adlib_reg[register_base[i] + register_offset[voice]]);
- printf("%02x ", adlib_reg[register_base[10] + voice]);
-#endif
-
-}
-
-void synth_setvolume(int voice, int volume) {
- int8 level1, level2;
-
- level1 = ~adlib_reg[register_base[2] + register_offset[voice]] & 0x3f;
- level2 = ~adlib_reg[register_base[3] + register_offset[voice]] & 0x3f;
-
- if (level1) {
- level1 += sci_adlib_vol_tables[adlib_master][volume>>1];
- }
-
- if (level2) {
- level2 += sci_adlib_vol_tables[adlib_master][volume>>1];
- }
-
- if (level1 > 0x3f)
- level1 = 0x3f;
- if (level1 < 0)
- level1 = 0;
-
- if (level2 > 0x3f)
- level2 = 0x3f;
- if (level2 < 0)
- level2 = 0;
-
- /* algorithm-dependent; we may need to set both operators. */
- if (adlib_reg[register_base[10] + voice] & 1)
- opl_write(register_base[2] + register_offset[voice],
- (uint8)((~level1 &0x3f) |
- (adlib_reg[register_base[2] + register_offset[voice]]&0xc0)));
-
- opl_write(register_base[3] + register_offset[voice],
- (uint8)((~level2 &0x3f) |
- (adlib_reg[register_base[3] + register_offset[voice]]&0xc0)));
-
-}
-
-void synth_setnote(int voice, int note, int bend) {
- int n, fre, oct;
- float delta;
-
- delta = 0;
-
- n = note % 12;
-
- if (bend < 8192)
- bend = 8192 - bend;
- delta = pow(2.0, (float)(bend % 8192) / 8192.0);
-
- if (bend > 8192)
- fre = (int)(ym3812_note[n] * delta);
- else
- fre = (int)(ym3812_note[n] / delta);
-
- oct = note / 12 - 1;
-
- if (oct < 0)
- oct = 0;
-
- opl_write(0xa0 + voice, fre & 0xff);
- opl_write(0xb0 + voice,
- 0x20 | ((oct << 2) & 0x1c) | ((fre >> 8) & 0x03));
-#ifdef DEBUG_ADLIB
- printf("-- %02x %02x\n", adlib_reg[0xa0+voice], adlib_reg[0xb0+voice]);
-#endif
-
-}
-
-
-/* back to your regularly scheduled driver */
-
-int adlibemu_stop_note(int chn, int note, int velocity) {
- int i, op = 255;
-
- // sciprintf("Note off %d %d %d\n", chn, note, velocity);
-
- for (i = 0;i < ADLIB_VOICES && op == 255;i++) {
- if (oper_chn[i] == chn)
- if (oper_note[i] == note)
- op = i;
- }
-
- if (op == 255) {
-#ifdef DEBUG_ADLIB
- printf("ADLIB: can't stop note: C%02x N%02x V%02x\n", chn, note, velocity);
- printf("C ");
- for (i = 0; i < ADLIB_VOICES ; i++) {
- printf("%02x ", oper_chn[i]);
- }
- printf("\n");
- printf("N ");
- for (i = 0; i < ADLIB_VOICES ; i++) {
- printf("%02x ", oper_note[i]);
- }
- printf("\n");
-#endif
- return -1; /* that note isn't playing.. */
- }
-
- opl_write(0xb0 + op, (adlib_reg[0xb0+op] & 0xdf));
-
- oper_chn[op] = 255;
- oper_note[op] = 255;
-
- free_voices++;
-
-#ifdef DEBUG_ADLIB
- printf("stop voice %d (%d rem): C%02x N%02x V%02x\n", op, free_voices, chn, note, velocity);
-#endif
-
- return 0;
-}
-
-int adlibemu_start_note(int chn, int note, int velocity) {
- int op, volume, inst = 0;
-
- // sciprintf("Note on %d %d %d\n", chn, note, velocity);
-
- if (velocity == 0) {
- return adlibemu_stop_note(chn, note, velocity);
- }
-
- if (free_voices <= 0) {
- printf("ADLIB: All voices full\n"); /* XXX implement overflow code */
- return -1;
- }
-
- for (op = 0; op < ADLIB_VOICES ; op++)
- if (oper_chn[op] == 255)
- break;
-
- if (op == ADLIB_VOICES) {
- printf("ADLIB: WTF? We couldn't find a voice yet it we have %d left.\n", free_voices);
- return -1;
- }
-
- /* Scale channel volume */
- volume = velocity * vol[chn] / 127;
- inst = instr[chn];
-
- synth_setpatch(op, adlib_sbi[inst]);
- synth_setvolume(op, volume);
- synth_setnote(op, note, pitch[chn]);
-
- oper_chn[op] = chn;
- oper_note[op] = note;
- free_voices--;
-
-#ifdef DEBUG_ADLIB
- printf("play voice %d (%d rem): C%02x N%02x V%02x/%02x P%02x (%02x/%02x)\n", op, free_voices, chn, note, velocity, volume, inst,
- adlib_reg[register_base[2] + register_offset[op]] & 0x3f,
- adlib_reg[register_base[3] + register_offset[op]] & 0x3f);
-#endif
-
- return 0;
-}
-
-static void adlibemu_update_pitch(int chn, int note, int newpitch) {
- int i;
- int matched = 0;
-
- pitch[chn] = newpitch;
-
- for (i = 0;i < ADLIB_VOICES;i++) {
- if (oper_chn[i] == chn) {
- matched++;
- synth_setnote(i, oper_note[i], newpitch);
- }
- }
-
-// printf("Matched %d notes on channel %d.\n", matched, chn);
-}
-
-void test_adlib() {
-
- int voice = 0;
-#if 0
- uint8 data[] = { 0x25, 0x21, 0x48, 0x48, 0xf0, 0xf2, 0xf0, 0xa5, 0x00, 0x00, 0x06 };
-#else
- uint8 *data = adlib_sbi[0x0a];
-#endif
-
-#if 1
- opl_write(register_base[0] + register_offset[voice], data[0]);
- opl_write(register_base[1] + register_offset[voice], data[1]);
- opl_write(register_base[2] + register_offset[voice], data[2]);
- opl_write(register_base[3] + register_offset[voice], data[3]);
- opl_write(register_base[4] + register_offset[voice], data[4]);
- opl_write(register_base[5] + register_offset[voice], data[5]);
- opl_write(register_base[6] + register_offset[voice], data[6]);
- opl_write(register_base[7] + register_offset[voice], data[7]);
- opl_write(register_base[8] + register_offset[voice], data[8]);
- opl_write(register_base[9] + register_offset[voice], data[9]);
- opl_write(register_base[10] + register_offset[voice], data[10]);
-#else
- synth_setpatch(voice, data);
-#endif
-
-#if 0
- opl_write(0xA0 + voice, 0x57);
- opl_write(0xB0 + voice, 0x2d);
-#else
- synth_setvolume(voice, 0x50);
- synth_setnote(voice, 0x30, 0);
-#endif
-
- /*
- instr[0x0e] = 0x0a;
- instr[0x03] = 0x26;
-
- adlibemu_start_note(0x0e, 0x30, 0x40);
- sleep(1);
- adlibemu_start_note(0x03, 0x48, 0x40);
- sleep(1);
- */
-}
-
-
-/* count is # of FRAMES, not bytes.
- We assume 16-bit stereo frames (ie 4 bytes)
-*/
-static void opl2_poll(sfx_softseq_t *self, byte *dest, int count) {
- int16 *ptr = (int16 *)dest;
-
- if (!ready)
- error("synth_mixer(): !ready \n");
-
- if (!ptr)
- error("synth_mixer(): !buffer \n");
-
- YM3812UpdateOne(ym3812, ptr, count);
-}
-
-static Common::Error opl2_init(sfx_softseq_t *self, byte *data_ptr, int data_length, byte *data2_ptr,
- int data2_length) {
- int i;
-
- /* load up the patch.003 file, parse out the instruments */
- if (data_length < 1344) {
- sciprintf("[sfx:seq:opl2] Invalid patch.003: Expected %d, got %d\n", 1344, data_length);
- return Common::kUnknownError;
- }
-
- for (i = 0; i < 48; i++)
- make_sbi((adlib_def *)(data_ptr + (28 * i)), adlib_sbi[i]);
-
- if (data_length > 1344)
- for (i = 48; i < 96; i++)
- make_sbi((adlib_def *)(data_ptr + 2 + (28 * i)), adlib_sbi[i]);
-
- if (!(ym3812 = makeAdlibOPL(SAMPLE_RATE))) {
- sciprintf("[sfx:seq:opl2] Failure: Emulator init failed!\n");
- return Common::kUnknownError;
- }
-
- ready = 1;
-
- opl2_allstop(self);
- return Common::kNoError;
-}
-
-
-static void opl2_exit(sfx_softseq_t *self) {
- OPLDestroy(ym3812);
- ym3812 = NULL;
-
- // XXX deregister with pcm layer.
-}
-
-static void opl2_allstop(sfx_softseq_t *self) {
- // printf("AdlibEmu: Reset\n");
- if (! ready)
- return;
-
- adlibemu_init_lists();
-
- OPLResetChip(ym3812);
-
- opl_write(0x01, 0x20);
- opl_write(0xBD, 0xc0);
-
-#ifdef DEBUG_ADLIB
- printf("ADLIB: reset complete\n");
-#endif
- // test_adlib();
-}
-
-int midi_adlibemu_reverb(short param) {
- printf("ADLIB: reverb NYI %04x \n", param);
- return 0;
-}
-
-int midi_adlibemu_event(uint8 command, uint8 note, uint8 velocity, uint32 delta) {
- uint8 channel, oper;
-
- channel = command & 0x0f;
- oper = command & 0xf0;
-
- switch (oper) {
- case 0x80:
- return adlibemu_stop_note(channel, note, velocity);
- case 0x90: /* noteon and noteoff */
- return adlibemu_start_note(channel, note, velocity);
- case 0xe0: { /* Pitch bend */
- int bend = (note & 0x7f) | ((velocity & 0x7f) << 7);
-// printf("Bend to %d\n", bend);
- adlibemu_update_pitch(channel, note, bend);
- }
- case 0xb0: /* CC changes. */
- switch (note) {
- case 0x07:
- vol[channel] = velocity;
- break;
- case 0x0a:
- pan[channel] = velocity;
- break;
- case 0x4b:
- break;
- case 0x7b: { /* all notes off */
- int i = 0;
- for (i = 0;i < ADLIB_VOICES;i++)
- if (oper_chn[i] == channel)
- adlibemu_stop_note(channel, oper_note[i], 0);
- break;
- }
- default:
- ; /* XXXX ignore everything else for now */
- }
- return 0;
- case 0xd0: /* aftertouch */
- /* XXX Aftertouch in the OPL thing? */
- return 0;
- default:
- printf("ADLIB: Unknown event %02x\n", command);
- return 0;
- }
-
- return 0;
-}
-
-int midi_adlibemu_event2(uint8 command, uint8 param, uint32 delta) {
- uint8 channel;
- uint8 oper;
-
- channel = command & 0x0f;
- oper = command & 0xf0;
- switch (oper) {
- case 0xc0: /* change instrument */
-#ifdef DEBUG_ADLIB
- printf("ADLIB: Selecting instrument %d on channel %d\n", param, channel);
-#endif
- instr[channel] = param;
- return 0;
- default:
- printf("ADLIB: Unknown event %02x\n", command);
- }
-
- return 0;
-}
-
-static void opl2_volume(sfx_softseq_t *self, int volume) {
- uint8 i;
-
- i = (uint8)volume * 15 / 100;
-
- adlib_master = i;
-
-#ifdef DEBUG_ADLIB
- printf("ADLIB: master volume set to %d\n", adlib_master);
-#endif
-}
-
-static Common::Error opl2_set_option(sfx_softseq_t *self, const char *name, const char *value) {
- return Common::kUnknownError;
-}
-
-void opl2_event(sfx_softseq_t *self, byte cmd, int argc, byte *argv) {
- if (argc == 1)
- midi_adlibemu_event2(cmd, argv[0], 0);
- else if (argc == 2)
- midi_adlibemu_event(cmd, argv[0], argv[1], 0);
-}
-
-/* the driver struct */
-
-sfx_softseq_t sfx_softseq_opl2 = {
- "adlibemu",
- "0.1",
- opl2_set_option,
- opl2_init,
- opl2_exit,
- opl2_volume,
- opl2_event,
- opl2_poll,
- opl2_allstop,
- NULL,
- 3, /* use patch.003 */
- SFX_SEQ_PATCHFILE_NONE,
- 0x4, /* Play flags */
- 0, /* No rhythm channel (9) */
- ADLIB_VOICES, /* # of voices */
- {SAMPLE_RATE, CHANNELS, SFX_PCM_FORMAT_S16_NATIVE}
-};
-
-} // End of namespace Sci