aboutsummaryrefslogtreecommitdiff
path: root/sound/softsynth
diff options
context:
space:
mode:
authorMax Horn2011-02-09 01:09:01 +0000
committerMax Horn2011-02-09 01:09:01 +0000
commit42ab839dd6c8a1570b232101eb97f4e54de57935 (patch)
tree3b763d8913a87482b793e0348c88b9a5f40eecc9 /sound/softsynth
parent386203a3d6ce1abf457c9110d695408ec5f01b85 (diff)
downloadscummvm-rg350-42ab839dd6c8a1570b232101eb97f4e54de57935.tar.gz
scummvm-rg350-42ab839dd6c8a1570b232101eb97f4e54de57935.tar.bz2
scummvm-rg350-42ab839dd6c8a1570b232101eb97f4e54de57935.zip
AUDIO: Rename sound/ dir to audio/
svn-id: r55850
Diffstat (limited to 'sound/softsynth')
-rw-r--r--sound/softsynth/adlib.cpp1617
-rw-r--r--sound/softsynth/appleiigs.cpp57
-rw-r--r--sound/softsynth/cms.cpp376
-rw-r--r--sound/softsynth/cms.h92
-rw-r--r--sound/softsynth/emumidi.h116
-rw-r--r--sound/softsynth/fluidsynth.cpp254
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_audio.cpp1583
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_audio.h179
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_euphony.cpp905
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_euphony.h187
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp1428
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_driver.h135
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp1548
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h196
-rw-r--r--sound/softsynth/mt32.cpp573
-rw-r--r--sound/softsynth/mt32/freeverb.cpp310
-rw-r--r--sound/softsynth/mt32/freeverb.h244
-rw-r--r--sound/softsynth/mt32/i386.cpp849
-rw-r--r--sound/softsynth/mt32/i386.h49
-rw-r--r--sound/softsynth/mt32/module.mk14
-rw-r--r--sound/softsynth/mt32/mt32_file.cpp70
-rw-r--r--sound/softsynth/mt32/mt32_file.h52
-rw-r--r--sound/softsynth/mt32/mt32emu.h70
-rw-r--r--sound/softsynth/mt32/part.cpp633
-rw-r--r--sound/softsynth/mt32/part.h113
-rw-r--r--sound/softsynth/mt32/partial.cpp968
-rw-r--r--sound/softsynth/mt32/partial.h148
-rw-r--r--sound/softsynth/mt32/partialManager.cpp272
-rw-r--r--sound/softsynth/mt32/partialManager.h56
-rw-r--r--sound/softsynth/mt32/structures.h284
-rw-r--r--sound/softsynth/mt32/synth.cpp1198
-rw-r--r--sound/softsynth/mt32/synth.h300
-rw-r--r--sound/softsynth/mt32/tables.cpp757
-rw-r--r--sound/softsynth/mt32/tables.h116
-rw-r--r--sound/softsynth/opl/dbopl.cpp1536
-rw-r--r--sound/softsynth/opl/dbopl.h283
-rw-r--r--sound/softsynth/opl/dosbox.cpp335
-rw-r--r--sound/softsynth/opl/dosbox.h110
-rw-r--r--sound/softsynth/opl/mame.cpp1234
-rw-r--r--sound/softsynth/opl/mame.h202
-rw-r--r--sound/softsynth/pcspk.cpp187
-rw-r--r--sound/softsynth/pcspk.h88
-rw-r--r--sound/softsynth/sid.cpp1456
-rw-r--r--sound/softsynth/sid.h348
-rw-r--r--sound/softsynth/wave6581.cpp2098
-rw-r--r--sound/softsynth/ym2612.cpp789
-rw-r--r--sound/softsynth/ym2612.h179
47 files changed, 0 insertions, 24594 deletions
diff --git a/sound/softsynth/adlib.cpp b/sound/softsynth/adlib.cpp
deleted file mode 100644
index ffb359e816..0000000000
--- a/sound/softsynth/adlib.cpp
+++ /dev/null
@@ -1,1617 +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$
- */
-
-#include "sound/softsynth/emumidi.h"
-#include "common/debug.h"
-#include "common/util.h"
-#include "sound/fmopl.h"
-#include "sound/musicplugin.h"
-#include "common/translation.h"
-
-#ifdef DEBUG_ADLIB
-static int tick;
-#endif
-
-class MidiDriver_ADLIB;
-struct AdLibVoice;
-
-// We use packing for the following two structs, because the code
-// does simply copy them over from byte streams, without any
-// serialization. Check AdLibPart::sysEx_customInstrument for an
-// example of this.
-//
-// It might be very well possible, that none of the compilers we support
-// add any padding bytes at all, since the structs contain only variables
-// of the type 'byte'. But better safe than sorry.
-#include "common/pack-start.h"
-struct InstrumentExtra {
- byte a, b, c, d, e, f, g, h;
-} PACKED_STRUCT;
-
-struct AdLibInstrument {
- byte mod_characteristic;
- byte mod_scalingOutputLevel;
- byte mod_attackDecay;
- byte mod_sustainRelease;
- byte mod_waveformSelect;
- byte car_characteristic;
- byte car_scalingOutputLevel;
- byte car_attackDecay;
- byte car_sustainRelease;
- byte car_waveformSelect;
- byte feedback;
- byte flags_a;
- InstrumentExtra extra_a;
- byte flags_b;
- InstrumentExtra extra_b;
- byte duration;
-
- AdLibInstrument() { memset(this, 0, sizeof(AdLibInstrument)); }
-} PACKED_STRUCT;
-#include "common/pack-end.h"
-
-class AdLibPart : public MidiChannel {
- friend class MidiDriver_ADLIB;
-
-protected:
-// AdLibPart *_prev, *_next;
- AdLibVoice *_voice;
- int16 _pitchbend;
- byte _pitchbend_factor;
- int8 _transpose_eff;
- byte _vol_eff;
- int8 _detune_eff;
- byte _modwheel;
- bool _pedal;
- byte _program;
- byte _pri_eff;
- AdLibInstrument _part_instr;
-
-protected:
- MidiDriver_ADLIB *_owner;
- bool _allocated;
- byte _channel;
-
- void init(MidiDriver_ADLIB *owner, byte channel);
- void allocate() { _allocated = true; }
-
-public:
- AdLibPart() {
- _voice = 0;
- _pitchbend = 0;
- _pitchbend_factor = 2;
- _transpose_eff = 0;
- _vol_eff = 0;
- _detune_eff = 0;
- _modwheel = 0;
- _pedal = 0;
- _program = 0;
- _pri_eff = 0;
-
- _owner = 0;
- _allocated = false;
- _channel = 0;
- }
-
- MidiDriver *device();
- byte getNumber() { return _channel; }
- void release() { _allocated = false; }
-
- void send (uint32 b);
-
- // Regular messages
- void noteOff(byte note);
- void noteOn(byte note, byte velocity);
- void programChange(byte program);
- void pitchBend(int16 bend);
-
- // Control Change messages
- void controlChange(byte control, byte value);
- void modulationWheel(byte value);
- void volume(byte value);
- void panPosition(byte value) { return; } // Not supported
- void pitchBendFactor(byte value);
- void detune(byte value);
- void priority(byte value);
- void sustain(bool value);
- void effectLevel(byte value) { return; } // Not supported
- void chorusLevel(byte value) { return; } // Not supported
- void allNotesOff();
-
- // SysEx messages
- void sysEx_customInstrument(uint32 type, const byte *instr);
-};
-
-// FYI (Jamieson630)
-// It is assumed that any invocation to AdLibPercussionChannel
-// will be done through the MidiChannel base class as opposed to the
-// AdLibPart base class. If this were NOT the case, all the functions
-// listed below would need to be virtual in AdLibPart as well as MidiChannel.
-class AdLibPercussionChannel : public AdLibPart {
- friend class MidiDriver_ADLIB;
-
-protected:
- void init(MidiDriver_ADLIB *owner, byte channel);
-
-public:
- ~AdLibPercussionChannel();
-
- void noteOff(byte note);
- void noteOn(byte note, byte velocity);
- void programChange(byte program) { }
- void pitchBend(int16 bend) { }
-
- // Control Change messages
- void modulationWheel(byte value) { }
- void pitchBendFactor(byte value) { }
- void detune(byte value) { }
- void priority(byte value) { }
- void sustain(bool value) { }
-
- // SysEx messages
- void sysEx_customInstrument(uint32 type, const byte *instr);
-
-private:
- byte _notes[256];
- AdLibInstrument *_customInstruments[256];
-};
-
-struct Struct10 {
- byte active;
- int16 cur_val;
- int16 count;
- uint16 max_value;
- int16 start_value;
- byte loop;
- byte table_a[4];
- byte table_b[4];
- int8 unk3;
- int8 modwheel;
- int8 modwheel_last;
- uint16 speed_lo_max;
- uint16 num_steps;
- int16 speed_hi;
- int8 direction;
- uint16 speed_lo;
- uint16 speed_lo_counter;
-};
-
-struct Struct11 {
- int16 modify_val;
- byte param, flag0x40, flag0x10;
- Struct10 *s10;
-};
-
-struct AdLibVoice {
- AdLibPart *_part;
- AdLibVoice *_next, *_prev;
- byte _waitforpedal;
- byte _note;
- byte _channel;
- byte _twochan;
- byte _vol_1, _vol_2;
- int16 _duration;
-
- Struct10 _s10a;
- Struct11 _s11a;
- Struct10 _s10b;
- Struct11 _s11b;
-
- AdLibVoice() { memset(this, 0, sizeof(AdLibVoice)); }
-};
-
-struct AdLibSetParams {
- byte a, b, c, d;
-};
-
-static const byte channel_mappings[9] = {
- 0, 1, 2, 8,
- 9, 10, 16, 17,
- 18
-};
-
-static const byte channel_mappings_2[9] = {
- 3, 4, 5, 11,
- 12, 13, 19, 20,
- 21
-};
-
-static const AdLibSetParams adlib_setparam_table[] = {
- {0x40, 0, 63, 63}, // level
- {0xE0, 2, 0, 0}, // unused
- {0x40, 6, 192, 0}, // level key scaling
- {0x20, 0, 15, 0}, // modulator frequency multiple
- {0x60, 4, 240, 15}, // attack rate
- {0x60, 0, 15, 15}, // decay rate
- {0x80, 4, 240, 15}, // sustain level
- {0x80, 0, 15, 15}, // release rate
- {0xE0, 0, 3, 0}, // waveformSelect select
- {0x20, 7, 128, 0}, // amp mod
- {0x20, 6, 64, 0}, // vib
- {0x20, 5, 32, 0}, // eg typ
- {0x20, 4, 16, 0}, // ksr
- {0xC0, 0, 1, 0}, // decay alg
- {0xC0, 1, 14, 0} // feedback
-};
-
-static const byte param_table_1[16] = {
- 29, 28, 27, 0,
- 3, 4, 7, 8,
- 13, 16, 17, 20,
- 21, 30, 31, 0
-};
-
-static const uint16 maxval_table[16] = {
- 0x2FF, 0x1F, 0x7, 0x3F,
- 0x0F, 0x0F, 0x0F, 0x3,
- 0x3F, 0x0F, 0x0F, 0x0F,
- 0x3, 0x3E, 0x1F, 0
-};
-
-static const uint16 num_steps_table[] = {
- 1, 2, 4, 5,
- 6, 7, 8, 9,
- 10, 12, 14, 16,
- 18, 21, 24, 30,
- 36, 50, 64, 82,
- 100, 136, 160, 192,
- 240, 276, 340, 460,
- 600, 860, 1200, 1600
-};
-
-static const byte note_to_f_num[] = {
- 90, 91, 92, 92, 93, 94, 94, 95,
- 96, 96, 97, 98, 98, 99, 100, 101,
- 101, 102, 103, 104, 104, 105, 106, 107,
- 107, 108, 109, 110, 111, 111, 112, 113,
- 114, 115, 115, 116, 117, 118, 119, 120,
- 121, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 132, 133, 134,
- 135, 136, 137, 138, 139, 140, 141, 142,
- 143, 145, 146, 147, 148, 149, 150, 151,
- 152, 153, 154, 155, 157, 158, 159, 160,
- 161, 162, 163, 165, 166, 167, 168, 169,
- 171, 172, 173, 174, 176, 177, 178, 180,
- 181, 182, 184, 185, 186, 188, 189, 190,
- 192, 193, 194, 196, 197, 199, 200, 202,
- 203, 205, 206, 208, 209, 211, 212, 214,
- 215, 217, 218, 220, 222, 223, 225, 226,
- 228, 230, 231, 233, 235, 236, 238, 240,
- 242, 243, 245, 247, 249, 251, 252, 254
-};
-
-static const byte map_gm_to_fm[128][30] = {
- // 0x00
-{ 0xC2, 0xC5, 0x2B, 0x99, 0x58, 0xC2, 0x1F, 0x1E, 0xC8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x23 },
-{ 0x22, 0x53, 0x0E, 0x8A, 0x30, 0x14, 0x06, 0x1D, 0x7A, 0x5C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x06, 0x00, 0x1C, 0x79, 0x40, 0x02, 0x00, 0x4B, 0x79, 0x58, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC2, 0x89, 0x2A, 0x89, 0x49, 0xC2, 0x16, 0x1C, 0xB8, 0x7C, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x23 },
-{ 0xC2, 0x17, 0x3D, 0x6A, 0x00, 0xC4, 0x2E, 0x2D, 0xC9, 0x20, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x06, 0x1E, 0x1C, 0x99, 0x00, 0x02, 0x3A, 0x4C, 0x79, 0x00, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x84, 0x40, 0x3B, 0x5A, 0x6F, 0x81, 0x0E, 0x3B, 0x5A, 0x7F, 0x0B, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x84, 0x40, 0x3B, 0x5A, 0x63, 0x81, 0x00, 0x3B, 0x5A, 0x7F, 0x01, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x8C, 0x80, 0x05, 0xEA, 0x59, 0x82, 0x0A, 0x3C, 0xAA, 0x64, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x85, 0x40, 0x0D, 0xEC, 0x71, 0x84, 0x58, 0x3E, 0xCB, 0x7C, 0x01, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x8A, 0xC0, 0x0C, 0xDC, 0x50, 0x88, 0x58, 0x3D, 0xDA, 0x7C, 0x01, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC9, 0x40, 0x2B, 0x78, 0x42, 0xC2, 0x04, 0x4C, 0x8A, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x1A },
-{ 0x2A, 0x0E, 0x17, 0x89, 0x28, 0x22, 0x0C, 0x1B, 0x09, 0x70, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE7, 0x9B, 0x08, 0x08, 0x26, 0xE2, 0x06, 0x0A, 0x08, 0x70, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC5, 0x05, 0x00, 0xFC, 0x40, 0x84, 0x00, 0x00, 0xDC, 0x50, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x86, 0x40, 0x5D, 0x5A, 0x41, 0x81, 0x00, 0x0B, 0x5A, 0x7F, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
- // 0x10
-{ 0xED, 0x00, 0x7B, 0xC8, 0x40, 0xE1, 0x99, 0x4A, 0xE9, 0x7E, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE8, 0x4F, 0x3A, 0xD7, 0x7C, 0xE2, 0x97, 0x49, 0xF9, 0x7D, 0x05, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE1, 0x10, 0x2F, 0xF7, 0x7D, 0xF3, 0x45, 0x8F, 0xC7, 0x62, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x01, 0x8C, 0x9F, 0xDA, 0x70, 0xE4, 0x50, 0x9F, 0xDA, 0x6A, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x08, 0xD5, 0x9D, 0xA5, 0x45, 0xE2, 0x3F, 0x9F, 0xD6, 0x49, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE5, 0x0F, 0x7D, 0xB8, 0x2E, 0xA2, 0x0F, 0x7C, 0xC7, 0x61, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xF2, 0x2A, 0x9F, 0xDB, 0x01, 0xE1, 0x04, 0x8F, 0xD7, 0x62, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x88, 0x9C, 0x50, 0x64, 0xE2, 0x18, 0x70, 0xC4, 0x7C, 0x0B, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x02, 0xA3, 0x0D, 0xDA, 0x01, 0xC2, 0x35, 0x5D, 0x58, 0x00, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x18 },
-{ 0x42, 0x55, 0x3E, 0xEB, 0x24, 0xD4, 0x08, 0x0D, 0xA9, 0x71, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x18 },
-{ 0xC2, 0x00, 0x2B, 0x17, 0x51, 0xC2, 0x1E, 0x4D, 0x97, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x19 },
-{ 0xC6, 0x01, 0x2D, 0xA7, 0x44, 0xC2, 0x06, 0x0E, 0xA7, 0x79, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC2, 0x0C, 0x06, 0x06, 0x55, 0xC2, 0x3F, 0x09, 0x86, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0A },
-{ 0xC2, 0x2E, 0x4F, 0x77, 0x00, 0xC4, 0x08, 0x0E, 0x98, 0x59, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC2, 0x30, 0x4F, 0xCA, 0x01, 0xC4, 0x0D, 0x0E, 0xB8, 0x7F, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC4, 0x29, 0x4F, 0xCA, 0x03, 0xC8, 0x0D, 0x0C, 0xB7, 0x7D, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0B },
- // 0x20
-{ 0xC2, 0x40, 0x3C, 0x96, 0x58, 0xC4, 0xDE, 0x0E, 0xC7, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x20 },
-{ 0x31, 0x13, 0x2D, 0xD7, 0x3C, 0xE2, 0x18, 0x2E, 0xB8, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x22, 0x86, 0x0D, 0xD7, 0x50, 0xE4, 0x18, 0x5E, 0xB8, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x28 },
-{ 0xF2, 0x0A, 0x0D, 0xD7, 0x40, 0xE4, 0x1F, 0x5E, 0xB8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xF2, 0x09, 0x4B, 0xD6, 0x48, 0xE4, 0x1F, 0x1C, 0xB8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x28 },
-{ 0x62, 0x11, 0x0C, 0xE6, 0x3C, 0xE4, 0x1F, 0x0C, 0xC8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x12, 0x3D, 0xE6, 0x34, 0xE4, 0x1F, 0x7D, 0xB8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x13, 0x3D, 0xE6, 0x34, 0xE4, 0x1F, 0x5D, 0xB8, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xA2, 0x40, 0x5D, 0xBA, 0x3F, 0xE2, 0x00, 0x8F, 0xD8, 0x79, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x40, 0x3D, 0xDA, 0x3B, 0xE1, 0x00, 0x7E, 0xD8, 0x7A, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x62, 0x00, 0x6D, 0xFA, 0x5D, 0xE2, 0x00, 0x8F, 0xC8, 0x79, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE1, 0x00, 0x4E, 0xDB, 0x4A, 0xE3, 0x18, 0x6F, 0xE9, 0x7E, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE1, 0x00, 0x4E, 0xDB, 0x66, 0xE2, 0x00, 0x7F, 0xE9, 0x7E, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x02, 0x0F, 0x66, 0xAA, 0x51, 0x02, 0x64, 0x29, 0xF9, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
-{ 0x16, 0x4A, 0x04, 0xBA, 0x39, 0xC2, 0x58, 0x2D, 0xCA, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0x02, 0x00, 0x01, 0x7A, 0x79, 0x02, 0x3F, 0x28, 0xEA, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
- // 0x30
-{ 0x62, 0x53, 0x9C, 0xBA, 0x31, 0x62, 0x5B, 0xAD, 0xC9, 0x55, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xF2, 0x40, 0x6E, 0xDA, 0x49, 0xE2, 0x13, 0x8F, 0xF9, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x40, 0x8F, 0xFA, 0x50, 0xF2, 0x04, 0x7F, 0xFA, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0xA0, 0xCE, 0x5B, 0x02, 0xE2, 0x32, 0x7F, 0xFB, 0x3D, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE6, 0x80, 0x9C, 0x99, 0x42, 0xE2, 0x04, 0x7D, 0x78, 0x60, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xEA, 0xA0, 0xAC, 0x67, 0x02, 0xE2, 0x00, 0x7C, 0x7A, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE7, 0x94, 0xAD, 0xB7, 0x03, 0xE2, 0x00, 0x7C, 0xBA, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC3, 0x3F, 0x4B, 0xE9, 0x7E, 0xC1, 0x3F, 0x9B, 0xF9, 0x7F, 0x0B, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x06 },
-{ 0xB2, 0x20, 0xAD, 0xE9, 0x00, 0x62, 0x05, 0x8F, 0xC8, 0x68, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xF2, 0x00, 0x8F, 0xFB, 0x50, 0xF6, 0x47, 0x8F, 0xE9, 0x68, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xF2, 0x00, 0xAF, 0x88, 0x58, 0xF2, 0x54, 0x6E, 0xC9, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xF2, 0x2A, 0x9F, 0x98, 0x01, 0xE2, 0x84, 0x4E, 0x78, 0x6C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x02, 0x9F, 0xB8, 0x48, 0x22, 0x89, 0x9F, 0xE8, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x2A, 0x7F, 0xB8, 0x01, 0xE4, 0x00, 0x0D, 0xC5, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x28, 0x8E, 0xE8, 0x01, 0xF2, 0x00, 0x4D, 0xD6, 0x7D, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x62, 0x23, 0x8F, 0xEA, 0x00, 0xF2, 0x00, 0x5E, 0xD9, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
- // 0x40
-{ 0xB4, 0x26, 0x6E, 0x98, 0x01, 0x62, 0x00, 0x7D, 0xC8, 0x7D, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x2E, 0x20, 0xD9, 0x01, 0xF2, 0x0F, 0x90, 0xF8, 0x78, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xB8, 0x28, 0x9E, 0x98, 0x01, 0x62, 0x00, 0x3D, 0xC8, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x62, 0x00, 0x8E, 0xC9, 0x3D, 0xE6, 0x00, 0x7E, 0xD8, 0x68, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x00, 0x5F, 0xF9, 0x48, 0xE6, 0x98, 0x8F, 0xF8, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x62, 0x0C, 0x6E, 0xD8, 0x3D, 0x2A, 0x06, 0x7D, 0xD8, 0x58, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x00, 0x7E, 0x89, 0x38, 0xE6, 0x84, 0x80, 0xF8, 0x68, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x80, 0x6C, 0xD9, 0x30, 0xE2, 0x00, 0x8D, 0xC8, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x80, 0x88, 0x48, 0x40, 0xE2, 0x0A, 0x7D, 0xA8, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x00, 0x77, 0xC5, 0x54, 0xE2, 0x00, 0x9E, 0xD7, 0x70, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x80, 0x86, 0xB9, 0x64, 0xE2, 0x05, 0x9F, 0xD7, 0x78, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x00, 0x68, 0x68, 0x56, 0xE2, 0x08, 0x9B, 0xB3, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x00, 0xA6, 0x87, 0x41, 0xE2, 0x0A, 0x7E, 0xC9, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x80, 0x9A, 0xB8, 0x48, 0xE2, 0x00, 0x9E, 0xF9, 0x60, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x80, 0x8E, 0x64, 0x68, 0xE2, 0x28, 0x6F, 0x73, 0x7C, 0x01, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
- // 0x50
-{ 0xE8, 0x00, 0x7D, 0x99, 0x54, 0xE6, 0x80, 0x80, 0xF8, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE6, 0x00, 0x9F, 0xB9, 0x6D, 0xE1, 0x00, 0x8F, 0xC8, 0x7D, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x00, 0x09, 0x68, 0x4A, 0xE2, 0x2B, 0x9E, 0xF3, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC4, 0x00, 0x99, 0xE8, 0x3B, 0xE2, 0x25, 0x6F, 0x93, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE6, 0x00, 0x6F, 0xDA, 0x69, 0xE2, 0x05, 0x2F, 0xD8, 0x6A, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xEC, 0x60, 0x9D, 0xC7, 0x00, 0xE2, 0x21, 0x7F, 0xC9, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE3, 0x00, 0x0F, 0xF7, 0x7D, 0xE1, 0x3F, 0x0F, 0xA7, 0x01, 0x0D, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0xA9, 0x0F, 0xA8, 0x02, 0xE2, 0x3C, 0x5F, 0xDA, 0x3C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE8, 0x40, 0x0D, 0x89, 0x7D, 0xE2, 0x17, 0x7E, 0xD9, 0x7C, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE1, 0x00, 0xDF, 0x8A, 0x56, 0xE2, 0x5E, 0xCF, 0xBA, 0x7E, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE2, 0x00, 0x0B, 0x68, 0x60, 0xE2, 0x01, 0x9E, 0xB8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xEA, 0x00, 0xAE, 0xAB, 0x49, 0xE2, 0x00, 0xAE, 0xBA, 0x6C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xEB, 0x80, 0x8C, 0xCB, 0x3A, 0xE2, 0x86, 0xAF, 0xCA, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE5, 0x40, 0xDB, 0x3B, 0x3C, 0xE2, 0x80, 0xBE, 0xCA, 0x71, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE4, 0x00, 0x9E, 0xAA, 0x3D, 0xE1, 0x43, 0x0F, 0xBA, 0x7E, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE7, 0x40, 0xEC, 0xCA, 0x44, 0xE2, 0x03, 0xBF, 0xBA, 0x66, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
- // 0x60
-{ 0xEA, 0x00, 0x68, 0xB8, 0x48, 0xE2, 0x0A, 0x8E, 0xB8, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x61, 0x00, 0xBE, 0x99, 0x7E, 0xE3, 0x40, 0xCF, 0xCA, 0x7D, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xCD, 0x00, 0x0B, 0x00, 0x48, 0xC2, 0x58, 0x0C, 0x00, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x1C },
-{ 0xE2, 0x00, 0x0E, 0x00, 0x52, 0xE2, 0x58, 0x5F, 0xD0, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xCC, 0x00, 0x7D, 0xDA, 0x40, 0xC2, 0x00, 0x5E, 0x9B, 0x58, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE9, 0xC0, 0xEE, 0xD8, 0x43, 0xE2, 0x05, 0xDD, 0xAA, 0x70, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xDA, 0x00, 0x8F, 0xAC, 0x4A, 0x22, 0x05, 0x8D, 0x8A, 0x75, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x62, 0x8A, 0xCB, 0x7A, 0x74, 0xE6, 0x56, 0xAF, 0xDB, 0x70, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xC2, 0x41, 0xAC, 0x5B, 0x5B, 0xC2, 0x80, 0x0D, 0xCB, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x12 },
-{ 0x75, 0x00, 0x0E, 0xCB, 0x5A, 0xE2, 0x1E, 0x0A, 0xC9, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x10 },
-{ 0x41, 0x00, 0x0E, 0xEA, 0x53, 0xC2, 0x00, 0x08, 0xCA, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x07 },
-{ 0xC1, 0x40, 0x0C, 0x59, 0x6A, 0xC2, 0x80, 0x3C, 0xAB, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0D },
-{ 0x4B, 0x00, 0x0A, 0xF5, 0x61, 0xC2, 0x19, 0x0C, 0xE9, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x07 },
-{ 0x62, 0x00, 0x7F, 0xD8, 0x54, 0xEA, 0x00, 0x8F, 0xD8, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE1, 0x00, 0x7F, 0xD9, 0x56, 0xE1, 0x00, 0x8F, 0xD8, 0x7E, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0xE1, 0x00, 0x7F, 0xD9, 0x56, 0xE1, 0x00, 0x8F, 0xD8, 0x7E, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
- // 0x70
-{ 0xCF, 0x40, 0x09, 0xEA, 0x54, 0xC4, 0x00, 0x0C, 0xDB, 0x64, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0xCF, 0x40, 0x0C, 0xAA, 0x54, 0xC4, 0x00, 0x18, 0xF9, 0x64, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0xC9, 0x0E, 0x88, 0xD9, 0x3E, 0xC2, 0x08, 0x1A, 0xEA, 0x6C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
-{ 0x03, 0x00, 0x15, 0x00, 0x64, 0x02, 0x00, 0x08, 0x00, 0x7C, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x01, 0x00, 0x47, 0xD7, 0x6C, 0x01, 0x3F, 0x0C, 0xFB, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
-{ 0x00, 0x00, 0x36, 0x67, 0x7C, 0x01, 0x3F, 0x0E, 0xFA, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
-{ 0x02, 0x00, 0x36, 0x68, 0x7C, 0x01, 0x3F, 0x0E, 0xFA, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
-{ 0xCB, 0x00, 0xAF, 0x00, 0x7E, 0xC0, 0x00, 0xC0, 0x06, 0x7F, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0F },
-{ 0x05, 0x0D, 0x80, 0xA6, 0x7F, 0x0B, 0x38, 0xA9, 0xD8, 0x00, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
-{ 0x0F, 0x00, 0x90, 0xFA, 0x68, 0x06, 0x00, 0xA7, 0x39, 0x54, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x06 },
-{ 0xC9, 0x15, 0xDD, 0xFF, 0x7C, 0x00, 0x00, 0xE7, 0xFC, 0x6C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x38 },
-{ 0x48, 0x3C, 0x30, 0xF6, 0x03, 0x0A, 0x38, 0x97, 0xE8, 0x00, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
-{ 0x07, 0x80, 0x0B, 0xC8, 0x65, 0x02, 0x3F, 0x0C, 0xEA, 0x7C, 0x0F, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
-{ 0x00, 0x21, 0x66, 0x40, 0x03, 0x00, 0x3F, 0x47, 0x00, 0x00, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x08, 0x00, 0x0B, 0x3C, 0x7C, 0x08, 0x3F, 0x06, 0xF3, 0x00, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x00, 0x3F, 0x4C, 0xFB, 0x00, 0x00, 0x3F, 0x0A, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 }
-};
-
-static byte gm_percussion_to_fm[39][30] = {
-{ 0x1A, 0x3F, 0x15, 0x05, 0x7C, 0x02, 0x21, 0x2B, 0xE4, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x06 },
-{ 0x11, 0x12, 0x04, 0x07, 0x7C, 0x02, 0x23, 0x0B, 0xE5, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
-{ 0x0A, 0x3F, 0x0B, 0x01, 0x7C, 0x1F, 0x1C, 0x46, 0xD0, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x01 },
-{ 0x00, 0x3F, 0x0F, 0x00, 0x7C, 0x10, 0x12, 0x07, 0x00, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x0F, 0x3F, 0x0B, 0x00, 0x7C, 0x1F, 0x0F, 0x19, 0xD0, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x00, 0x3F, 0x1F, 0x00, 0x7E, 0x1F, 0x16, 0x07, 0x00, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0x12, 0x3F, 0x05, 0x06, 0x7C, 0x03, 0x1F, 0x4A, 0xD9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0xCF, 0x7F, 0x08, 0xFF, 0x7E, 0x00, 0xC7, 0x2D, 0xF7, 0x73, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x12, 0x3F, 0x05, 0x06, 0x7C, 0x43, 0x21, 0x0C, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0xCF, 0x7F, 0x08, 0xCF, 0x7E, 0x00, 0x45, 0x2A, 0xF8, 0x4B, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0C },
-{ 0x12, 0x3F, 0x06, 0x17, 0x7C, 0x03, 0x27, 0x0B, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0xCF, 0x7F, 0x08, 0xCD, 0x7E, 0x00, 0x40, 0x1A, 0x69, 0x63, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0C },
-{ 0x13, 0x3F, 0x05, 0x06, 0x7C, 0x03, 0x17, 0x0A, 0xD9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0x15, 0x3F, 0x05, 0x06, 0x7C, 0x03, 0x21, 0x0C, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0xCF, 0x3F, 0x2B, 0xFB, 0x7E, 0xC0, 0x1E, 0x1A, 0xCA, 0x7F, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x10 },
-{ 0x17, 0x3F, 0x04, 0x09, 0x7C, 0x03, 0x22, 0x0D, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0xCF, 0x3F, 0x0F, 0x5E, 0x7C, 0xC6, 0x13, 0x00, 0xCA, 0x7F, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0xCF, 0x3F, 0x7E, 0x9D, 0x7C, 0xC8, 0xC0, 0x0A, 0xBA, 0x74, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x06 },
-{ 0xCF, 0x3F, 0x4D, 0x9F, 0x7C, 0xC6, 0x00, 0x08, 0xDA, 0x5B, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
-{ 0xCF, 0x3F, 0x5D, 0xAA, 0x7A, 0xC0, 0xA4, 0x67, 0x99, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0xCF, 0x3F, 0x4A, 0xFD, 0x7C, 0xCF, 0x00, 0x59, 0xEA, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x0F, 0x18, 0x0A, 0xFA, 0x57, 0x06, 0x07, 0x06, 0x39, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0xCF, 0x3F, 0x2B, 0xFC, 0x7C, 0xCC, 0xC6, 0x0B, 0xEA, 0x7F, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x10 },
-{ 0x05, 0x1A, 0x04, 0x00, 0x7C, 0x12, 0x10, 0x0C, 0xEA, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x07 },
-{ 0x04, 0x19, 0x04, 0x00, 0x7C, 0x12, 0x10, 0x2C, 0xEA, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
-{ 0x04, 0x0A, 0x04, 0x00, 0x6C, 0x01, 0x07, 0x0D, 0xFA, 0x74, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x07 },
-{ 0x15, 0x14, 0x05, 0x00, 0x7D, 0x01, 0x07, 0x5C, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
-{ 0x10, 0x10, 0x05, 0x08, 0x7C, 0x01, 0x08, 0x0D, 0xEA, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
-{ 0x11, 0x00, 0x06, 0x87, 0x7F, 0x02, 0x40, 0x09, 0x59, 0x68, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x08 },
-{ 0x13, 0x26, 0x04, 0x6A, 0x7F, 0x01, 0x00, 0x08, 0x5A, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x08 },
-{ 0xCF, 0x4E, 0x0C, 0xAA, 0x50, 0xC4, 0x00, 0x18, 0xF9, 0x54, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0xCF, 0x4E, 0x0C, 0xAA, 0x50, 0xC3, 0x00, 0x18, 0xF8, 0x54, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0xCB, 0x3F, 0x8F, 0x00, 0x7E, 0xC5, 0x00, 0x98, 0xD6, 0x5F, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0D },
-{ 0x0C, 0x18, 0x87, 0xB3, 0x7F, 0x19, 0x10, 0x55, 0x75, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x05, 0x11, 0x15, 0x00, 0x64, 0x02, 0x08, 0x08, 0x00, 0x5C, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0x04, 0x08, 0x15, 0x00, 0x48, 0x01, 0x08, 0x08, 0x00, 0x60, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
-{ 0xDA, 0x00, 0x53, 0x30, 0x68, 0x07, 0x1E, 0x49, 0xC4, 0x7E, 0x03, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
-{ 0x1C, 0x00, 0x07, 0xBC, 0x6C, 0x0C, 0x14, 0x0B, 0x6A, 0x7E, 0x0B, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
-{ 0x0A, 0x0E, 0x7F, 0x00, 0x7D, 0x13, 0x20, 0x28, 0x03, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 }
-};
-
-static const byte gm_percussion_lookup[128] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
- 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0xFF, 0xFF, 0x17, 0x18, 0x19, 0x1A,
- 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0x22, 0x23, 0xFF, 0xFF,
- 0x24, 0x25, 0xFF, 0xFF, 0xFF, 0x26, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-static byte lookup_table[64][32];
-
-static const byte volume_table[] = {
- 0, 4, 7, 11,
- 13, 16, 18, 20,
- 22, 24, 26, 27,
- 29, 30, 31, 33,
- 34, 35, 36, 37,
- 38, 39, 40, 41,
- 42, 43, 44, 44,
- 45, 46, 47, 47,
- 48, 49, 49, 50,
- 51, 51, 52, 53,
- 53, 54, 54, 55,
- 55, 56, 56, 57,
- 57, 58, 58, 59,
- 59, 60, 60, 60,
- 61, 61, 62, 62,
- 62, 63, 63, 63
-};
-
-static int lookup_volume(int a, int b) {
- if (b == 0)
- return 0;
-
- if (b == 31)
- return a;
-
- if (a < -63 || a > 63) {
- return b * (a + 1) >> 5;
- }
-
- if (b < 0) {
- if (a < 0) {
- return lookup_table[-a][-b];
- } else {
- return -lookup_table[a][-b];
- }
- } else {
- if (a < 0) {
- return -lookup_table[-a][b];
- } else {
- return lookup_table[a][b];
- }
- }
-}
-
-static void create_lookup_table() {
- int i, j;
- int sum;
-
- for (i = 0; i < 64; i++) {
- sum = i;
- for (j = 0; j < 32; j++) {
- lookup_table[i][j] = sum >> 5;
- sum += i;
- }
- }
- for (i = 0; i < 64; i++)
- lookup_table[i][0] = 0;
-}
-
-////////////////////////////////////////
-//
-// AdLib MIDI driver
-//
-////////////////////////////////////////
-
-class MidiDriver_ADLIB : public MidiDriver_Emulated {
- friend class AdLibPart;
- friend class AdLibPercussionChannel;
-
-public:
- MidiDriver_ADLIB(Audio::Mixer *mixer);
-
- int open();
- void close();
- void send(uint32 b);
- void send(byte channel, uint32 b); // Supports higher than channel 15
- uint32 property(int prop, uint32 param);
-
- void setPitchBendRange(byte channel, uint range);
- void sysEx_customInstrument(byte channel, uint32 type, const byte *instr);
-
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel() { return &_percussion; } // Percussion partially supported
-
-
- // AudioStream API
- bool isStereo() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
-
-private:
- bool _scummSmallHeader; // FIXME: This flag controls a special mode for SCUMM V3 games
-
- FM_OPL *_opl;
- byte *_adlib_reg_cache;
-
- int _adlib_timer_counter;
-
- uint16 channel_table_2[9];
- int _voice_index;
- int _timer_p;
- int _timer_q;
- uint16 curnote_table[9];
- AdLibVoice _voices[9];
- AdLibPart _parts[32];
- AdLibPercussionChannel _percussion;
-
- void generateSamples(int16 *buf, int len);
- void onTimer();
- void part_key_on(AdLibPart *part, AdLibInstrument *instr, byte note, byte velocity);
- void part_key_off(AdLibPart *part, byte note);
-
- void adlib_key_off(int chan);
- void adlib_note_on(int chan, byte note, int mod);
- void adlib_note_on_ex(int chan, byte note, int mod);
- int adlib_get_reg_value_param(int chan, byte data);
- void adlib_setup_channel(int chan, AdLibInstrument * instr, byte vol_1, byte vol_2);
- byte adlib_get_reg_value(byte reg) {
- return _adlib_reg_cache[reg];
- }
- void adlib_set_param(int channel, byte param, int value);
- void adlib_key_onoff(int channel);
- void adlib_write(byte reg, byte value);
- void adlib_playnote(int channel, int note);
-
- AdLibVoice *allocate_voice(byte pri);
-
- void mc_off(AdLibVoice * voice);
-
- static void link_mc(AdLibPart *part, AdLibVoice *voice);
- void mc_inc_stuff(AdLibVoice *voice, Struct10 * s10, Struct11 * s11);
- void mc_init_stuff(AdLibVoice *voice, Struct10 * s10, Struct11 * s11, byte flags,
- InstrumentExtra * ie);
-
- void struct10_init(Struct10 * s10, InstrumentExtra * ie);
- static byte struct10_ontimer(Struct10 * s10, Struct11 * s11);
- static void struct10_setup(Struct10 * s10);
- static int random_nr(int a);
- void mc_key_on(AdLibVoice *voice, AdLibInstrument *instr, byte note, byte velocity);
-};
-
-// MidiChannel method implementations
-
-void AdLibPart::init(MidiDriver_ADLIB *owner, byte channel) {
- _owner = owner;
- _channel = channel;
- _pri_eff = 127;
- programChange(0);
-}
-
-MidiDriver *AdLibPart::device() {
- return _owner;
-}
-
-void AdLibPart::send(uint32 b) {
- _owner->send(_channel, b);
-}
-
-void AdLibPart::noteOff(byte note) {
-#ifdef DEBUG_ADLIB
- debug(6, "%10d: noteOff(%d)", tick, note);
-#endif
- _owner->part_key_off(this, note);
-}
-
-void AdLibPart::noteOn(byte note, byte velocity) {
-#ifdef DEBUG_ADLIB
- debug(6, "%10d: noteOn(%d,%d)", tick, note, velocity);
-#endif
- _owner->part_key_on(this, &_part_instr, note, velocity);
-}
-
-void AdLibPart::programChange(byte program) {
- if (program > 127)
- return;
-
- uint i;
- uint count = 0;
- for (i = 0; i < ARRAYSIZE(map_gm_to_fm[0]); ++i)
- count += map_gm_to_fm[program][i];
- if (!count)
- warning("No AdLib instrument defined for GM program %d", (int) program);
- _program = program;
- memcpy(&_part_instr, &map_gm_to_fm[program], sizeof(AdLibInstrument));
-}
-
-void AdLibPart::pitchBend(int16 bend) {
- AdLibVoice *voice;
-
- _pitchbend = bend;
- for (voice = _voice; voice; voice = voice->_next) {
- _owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
- (_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
- }
-}
-
-void AdLibPart::controlChange(byte control, byte value) {
- switch (control) {
- case 0:
- case 32:
- break; // Bank select. Not supported
- case 1: modulationWheel(value); break;
- case 7: volume(value); break;
- case 10: break; // Pan position. Not supported.
- case 16: pitchBendFactor(value); break;
- case 17: detune(value); break;
- case 18: priority(value); break;
- case 64: sustain(value > 0); break;
- case 91: break; // Effects level. Not supported.
- case 93: break; // Chorus level. Not supported.
- case 119: break; // Unknown, used in Simon the Sorcerer 2
- case 121: // reset all controllers
- modulationWheel(0);
- pitchBendFactor(0);
- detune(0);
- sustain(0);
- break;
- case 123: allNotesOff(); break;
- default:
- warning("AdLib: Unknown control change message %d (%d)", (int) control, (int)value);
- }
-}
-
-void AdLibPart::modulationWheel(byte value) {
- AdLibVoice *voice;
-
- _modwheel = value;
- for (voice = _voice; voice; voice = voice->_next) {
- if (voice->_s10a.active && voice->_s11a.flag0x40)
- voice->_s10a.modwheel = _modwheel >> 2;
- if (voice->_s10b.active && voice->_s11b.flag0x40)
- voice->_s10b.modwheel = _modwheel >> 2;
- }
-}
-
-void AdLibPart::volume(byte value) {
- AdLibVoice *voice;
-
- _vol_eff = value;
- for (voice = _voice; voice; voice = voice->_next) {
- _owner->adlib_set_param(voice->_channel, 0, volume_table[lookup_table[voice->_vol_2][_vol_eff >> 2]]);
- if (voice->_twochan) {
- _owner->adlib_set_param(voice->_channel, 13, volume_table[lookup_table[voice->_vol_1][_vol_eff >> 2]]);
- }
- }
-}
-
-void AdLibPart::pitchBendFactor(byte value) {
- AdLibVoice *voice;
-
- _pitchbend_factor = value;
- for (voice = _voice; voice; voice = voice->_next) {
- _owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
- (_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
- }
-}
-
-void AdLibPart::detune(byte value) {
- AdLibVoice *voice;
-
- _detune_eff = value;
- for (voice = _voice; voice; voice = voice->_next) {
- _owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
- (_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
- }
-}
-
-void AdLibPart::priority(byte value) {
- _pri_eff = value;
-}
-
-void AdLibPart::sustain(bool value) {
- AdLibVoice *voice;
-
- _pedal = value;
- if (!value) {
- for (voice = _voice; voice; voice = voice->_next) {
- if (voice->_waitforpedal)
- _owner->mc_off(voice);
- }
- }
-}
-
-void AdLibPart::allNotesOff() {
- while (_voice)
- _owner->mc_off(_voice);
-}
-
-void AdLibPart::sysEx_customInstrument(uint32 type, const byte *instr) {
- if (type == 'ADL ') {
- AdLibInstrument *i = &_part_instr;
- memcpy(i, instr, sizeof(AdLibInstrument));
- }
-}
-
-// MidiChannel method implementations for percussion
-
-AdLibPercussionChannel::~AdLibPercussionChannel() {
- for (int i = 0; i < ARRAYSIZE(_customInstruments); ++i) {
- delete _customInstruments[i];
- }
-}
-
-void AdLibPercussionChannel::init(MidiDriver_ADLIB *owner, byte channel) {
- AdLibPart::init(owner, channel);
- _pri_eff = 0;
- _vol_eff = 127;
-
- // Initialize the custom instruments data
- memset(_notes, 0, sizeof(_notes));
- memset(_customInstruments, 0, sizeof(_customInstruments));
-}
-
-void AdLibPercussionChannel::noteOff(byte note) {
- // Jamieson630: Unless I run into a specific instrument that
- // may require a key off, I'm going to ignore this message.
- // The rationale is that a percussion instrument should
- // fade out of its own accord, and the AdLib instrument
- // definitions used should follow this rule. Since
- // percussion voices are allocated at the lowest priority
- // anyway, we know that "hanging" percussion sounds will
- // not prevent later musical instruments (or even other
- // percussion sounds) from playing.
-/*
- _owner->part_key_off(this, note);
-*/
-}
-
-void AdLibPercussionChannel::noteOn(byte note, byte velocity) {
- AdLibInstrument *inst = NULL;
-
- // The custom instruments have priority over the default mapping
- inst = _customInstruments[note];
- if (inst)
- note = _notes[note];
-
- if (!inst) {
- // Use the default GM to FM mapping as a fallback as a fallback
- byte key = gm_percussion_lookup[note];
- if (key != 0xFF)
- inst = (AdLibInstrument *)&gm_percussion_to_fm[key];
- }
-
- if (!inst) {
- debug(2, "No instrument FM definition for GM percussion key %d", (int)note);
- return;
- }
-
- _owner->part_key_on(this, inst, note, velocity);
-}
-
-void AdLibPercussionChannel::sysEx_customInstrument(uint32 type, const byte *instr) {
- if (type == 'ADLP') {
- byte note = instr[0];
- _notes[note] = instr[1];
-
- // Allocate memory for the new instruments
- if (!_customInstruments[note]) {
- _customInstruments[note] = new AdLibInstrument;
- }
-
- // Save the new instrument data
- _customInstruments[note]->mod_characteristic = instr[2];
- _customInstruments[note]->mod_scalingOutputLevel = instr[3];
- _customInstruments[note]->mod_attackDecay = instr[4];
- _customInstruments[note]->mod_sustainRelease = instr[5];
- _customInstruments[note]->mod_waveformSelect = instr[6];
- _customInstruments[note]->car_characteristic = instr[7];
- _customInstruments[note]->car_scalingOutputLevel = instr[8];
- _customInstruments[note]->car_attackDecay = instr[9];
- _customInstruments[note]->car_sustainRelease = instr[10];
- _customInstruments[note]->car_waveformSelect = instr[11];
- _customInstruments[note]->feedback = instr[12];
- }
-}
-
-// MidiDriver method implementations
-
-MidiDriver_ADLIB::MidiDriver_ADLIB(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer) {
- uint i;
-
- _scummSmallHeader = false;
-
- _adlib_reg_cache = 0;
-
- _adlib_timer_counter = 0;
- _voice_index = 0;
- for (i = 0; i < ARRAYSIZE(curnote_table); ++i) {
- curnote_table[i] = 0;
- }
-
- for (i = 0; i < ARRAYSIZE(_parts); ++i) {
- _parts[i].init(this, i + ((i >= 9) ? 1 : 0));
- }
- _percussion.init(this, 9);
- _timer_p = 0xD69;
- _timer_q = 0x411B;
-}
-
-int MidiDriver_ADLIB::open() {
- if (_isOpen)
- return MERR_ALREADY_OPEN;
-
- MidiDriver_Emulated::open();
-
- int i;
- AdLibVoice *voice;
-
- for (i = 0, voice = _voices; i != ARRAYSIZE(_voices); i++, voice++) {
- voice->_channel = i;
- voice->_s11a.s10 = &voice->_s10b;
- voice->_s11b.s10 = &voice->_s10a;
- }
-
- _adlib_reg_cache = (byte *)calloc(256, 1);
-
- _opl = makeAdLibOPL(getRate());
-
- adlib_write(1, 0x20);
- adlib_write(8, 0x40);
- adlib_write(0xBD, 0x00);
- create_lookup_table();
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- return 0;
-}
-
-void MidiDriver_ADLIB::close() {
- if (!_isOpen)
- return;
- _isOpen = false;
-
- _mixer->stopHandle(_mixerSoundHandle);
-
- uint i;
- for (i = 0; i < ARRAYSIZE(_voices); ++i) {
- if (_voices[i]._part)
- mc_off(&_voices[i]);
- }
-
- // Turn off the OPL emulation
- OPLDestroy(_opl);
-// YM3812Shutdown();
-
- free(_adlib_reg_cache);
-}
-
-void MidiDriver_ADLIB::send(uint32 b) {
- send(b & 0xF, b & 0xFFFFFFF0);
-}
-
-void MidiDriver_ADLIB::send(byte chan, uint32 b) {
- //byte param3 = (byte) ((b >> 24) & 0xFF);
- byte param2 = (byte) ((b >> 16) & 0xFF);
- byte param1 = (byte) ((b >> 8) & 0xFF);
- byte cmd = (byte) (b & 0xF0);
-
- AdLibPart *part;
- if (chan == 9)
- part = &_percussion;
- else
- part = &_parts[chan];
-
- switch (cmd) {
- case 0x80:// Note Off
- part->noteOff(param1);
- break;
- case 0x90: // Note On
- part->noteOn(param1, param2);
- break;
- case 0xA0: // Aftertouch
- break; // Not supported.
- case 0xB0: // Control Change
- part->controlChange(param1, param2);
- break;
- case 0xC0: // Program Change
- part->programChange(param1);
- break;
- case 0xD0: // Channel Pressure
- break; // Not supported.
- case 0xE0: // Pitch Bend
- part->pitchBend((param1 | (param2 << 7)) - 0x2000);
- break;
- case 0xF0: // SysEx
- // We should never get here! SysEx information has to be
- // sent via high-level semantic methods.
- warning("MidiDriver_ADLIB: Receiving SysEx command on a send() call");
- break;
-
- default:
- warning("MidiDriver_ADLIB: Unknown send() command 0x%02X", cmd);
- }
-}
-
-uint32 MidiDriver_ADLIB::property(int prop, uint32 param) {
- switch (prop) {
- case PROP_OLD_ADLIB: // Older games used a different operator volume algorithm
- _scummSmallHeader = (param > 0);
- if (_scummSmallHeader) {
- _timer_p = 473;
- _timer_q = 1000;
- } else {
- _timer_p = 0xD69;
- _timer_q = 0x411B;
- }
- return 1;
- }
-
- return 0;
-}
-
-void MidiDriver_ADLIB::setPitchBendRange(byte channel, uint range) {
- AdLibVoice *voice;
- AdLibPart *part = &_parts[channel];
-
- part->_pitchbend_factor = range;
- for (voice = part->_voice; voice; voice = voice->_next) {
- adlib_note_on(voice->_channel, voice->_note + part->_transpose_eff,
- (part->_pitchbend * part->_pitchbend_factor >> 6) + part->_detune_eff);
- }
-}
-
-void MidiDriver_ADLIB::sysEx_customInstrument(byte channel, uint32 type, const byte *instr) {
- _parts[channel].sysEx_customInstrument(type, instr);
-}
-
-MidiChannel *MidiDriver_ADLIB::allocateChannel() {
- AdLibPart *part;
- uint i;
-
- for (i = 0; i < ARRAYSIZE(_parts); ++i) {
- part = &_parts[i];
- if (!part->_allocated) {
- part->allocate();
- return part;
- }
- }
- return NULL;
-}
-
-// All the code brought over from IMuseAdLib
-
-void MidiDriver_ADLIB::adlib_write(byte reg, byte value) {
- if (_adlib_reg_cache[reg] == value)
- return;
-#ifdef DEBUG_ADLIB
- debug(6, "%10d: adlib_write[%x] = %x", tick, reg, value);
-#endif
- _adlib_reg_cache[reg] = value;
-
- OPLWriteReg(_opl, reg, value);
-}
-
-void MidiDriver_ADLIB::generateSamples(int16 *data, int len) {
- memset(data, 0, sizeof(int16) * len);
- YM3812UpdateOne(_opl, data, len);
-}
-
-void MidiDriver_ADLIB::onTimer() {
- AdLibVoice *voice;
- int i;
-
- _adlib_timer_counter += _timer_p;
- while (_adlib_timer_counter >= _timer_q) {
- _adlib_timer_counter -= _timer_q;
-#ifdef DEBUG_ADLIB
- tick++;
-#endif
- voice = _voices;
- for (i = 0; i != ARRAYSIZE(_voices); i++, voice++) {
- if (!voice->_part)
- continue;
- if (voice->_duration && (voice->_duration -= 0x11) <= 0) {
- mc_off(voice);
- return;
- }
- if (voice->_s10a.active) {
- mc_inc_stuff(voice, &voice->_s10a, &voice->_s11a);
- }
- if (voice->_s10b.active) {
- mc_inc_stuff(voice, &voice->_s10b, &voice->_s11b);
- }
- }
- }
-}
-
-void MidiDriver_ADLIB::mc_off(AdLibVoice *voice) {
- AdLibVoice *tmp;
-
- adlib_key_off(voice->_channel);
-
- tmp = voice->_prev;
-
- if (voice->_next)
- voice->_next->_prev = tmp;
- if (tmp)
- tmp->_next = voice->_next;
- else
- voice->_part->_voice = voice->_next;
- voice->_part = NULL;
-}
-
-void MidiDriver_ADLIB::mc_inc_stuff(AdLibVoice *voice, Struct10 *s10, Struct11 *s11) {
- byte code;
- AdLibPart *part = voice->_part;
-
- code = struct10_ontimer(s10, s11);
-
- if (code & 1) {
- switch (s11->param) {
- case 0:
- voice->_vol_2 = s10->start_value + s11->modify_val;
- if (!_scummSmallHeader) {
- adlib_set_param(voice->_channel, 0,
- volume_table[lookup_table[voice->_vol_2]
- [part->_vol_eff >> 2]]);
- } else {
- adlib_set_param(voice->_channel, 0, voice->_vol_2);
- }
- break;
- case 13:
- voice->_vol_1 = s10->start_value + s11->modify_val;
- if (voice->_twochan && !_scummSmallHeader) {
- adlib_set_param(voice->_channel, 13,
- volume_table[lookup_table[voice->_vol_1]
- [part->_vol_eff >> 2]]);
- } else {
- adlib_set_param(voice->_channel, 13, voice->_vol_1);
- }
- break;
- case 30:
- s11->s10->modwheel = (char)s11->modify_val;
- break;
- case 31:
- s11->s10->unk3 = (char)s11->modify_val;
- break;
- default:
- adlib_set_param(voice->_channel, s11->param,
- s10->start_value + s11->modify_val);
- break;
- }
- }
-
- if (code & 2 && s11->flag0x10)
- adlib_key_onoff(voice->_channel);
-}
-
-void MidiDriver_ADLIB::adlib_key_off(int chan){
- byte reg = chan + 0xB0;
- adlib_write(reg, adlib_get_reg_value(reg) & ~0x20);
-}
-
-byte MidiDriver_ADLIB::struct10_ontimer(Struct10 *s10, Struct11 *s11) {
- byte result = 0;
- int i;
-
- if (s10->count && (s10->count -= 17) <= 0) {
- s10->active = 0;
- return 0;
- }
-
- i = s10->cur_val + s10->speed_hi;
- s10->speed_lo_counter += s10->speed_lo;
- if (s10->speed_lo_counter >= s10->speed_lo_max) {
- s10->speed_lo_counter -= s10->speed_lo_max;
- i += s10->direction;
- }
- if (s10->cur_val != i || s10->modwheel != s10->modwheel_last) {
- s10->cur_val = i;
- s10->modwheel_last = s10->modwheel;
- i = lookup_volume(i, s10->modwheel_last);
- if (i != s11->modify_val) {
- s11->modify_val = i;
- result = 1;
- }
- }
-
- if (!--s10->num_steps) {
- s10->active++;
- if (s10->active > 4) {
- if (s10->loop) {
- s10->active = 1;
- result |= 2;
- struct10_setup(s10);
- } else {
- s10->active = 0;
- }
- } else {
- struct10_setup(s10);
- }
- }
-
- return result;
-}
-
-void MidiDriver_ADLIB::adlib_set_param(int channel, byte param, int value) {
- const AdLibSetParams *as;
- byte reg;
-
- assert(channel >= 0 && channel < 9);
-
- if (param <= 12) {
- reg = channel_mappings_2[channel];
- } else if (param <= 25) {
- param -= 13;
- reg = channel_mappings[channel];
- } else if (param <= 27) {
- param -= 13;
- reg = channel;
- } else if (param == 28 || param == 29) {
- if (param == 28)
- value -= 15;
- else
- value -= 383;
- value <<= 4;
- channel_table_2[channel] = value;
- adlib_playnote(channel, curnote_table[channel] + value);
- return;
- } else {
- return;
- }
-
- as = &adlib_setparam_table[param];
- if (as->d)
- value = as->d - value;
- reg += as->a;
- adlib_write(reg, (adlib_get_reg_value(reg) & ~as->c) | (((byte)value) << as->b));
-}
-
-void MidiDriver_ADLIB::adlib_key_onoff(int channel) {
- byte val;
- byte reg = channel + 0xB0;
- assert(channel >= 0 && channel < 9);
-
- val = adlib_get_reg_value(reg);
- adlib_write(reg, val & ~0x20);
- adlib_write(reg, val | 0x20);
-}
-
-void MidiDriver_ADLIB::struct10_setup(Struct10 *s10) {
- int b, c, d, e, f, g, h;
- byte t;
-
- b = s10->unk3;
- f = s10->active - 1;
-
- t = s10->table_a[f];
- e = num_steps_table[lookup_table[t & 0x7F][b]];
- if (t & 0x80) {
- e = random_nr(e);
- }
- if (e == 0)
- e++;
-
- s10->num_steps = s10->speed_lo_max = e;
-
- if (f != 2) {
- c = s10->max_value;
- g = s10->start_value;
- t = s10->table_b[f];
- d = lookup_volume(c, (t & 0x7F) - 31);
- if (t & 0x80) {
- d = random_nr(d);
- }
- if (d + g > c) {
- h = c - g;
- } else {
- h = d;
- if (d + g < 0)
- h = -g;
- }
- h -= s10->cur_val;
- } else {
- h = 0;
- }
-
- s10->speed_hi = h / e;
- if (h < 0) {
- h = -h;
- s10->direction = -1;
- } else {
- s10->direction = 1;
- }
-
- s10->speed_lo = h % e;
- s10->speed_lo_counter = 0;
-}
-
-void MidiDriver_ADLIB::adlib_playnote(int channel, int note) {
- byte old, oct, notex;
- int note2;
- int i;
-
- note2 = (note >> 7) - 4;
- note2 = (note2 < 128) ? note2 : 0;
-
- oct = (note2 / 12);
- if (oct > 7)
- oct = 7 << 2;
- else
- oct <<= 2;
- notex = note2 % 12 + 3;
-
- old = adlib_get_reg_value(channel + 0xB0);
- if (old & 0x20) {
- old &= ~0x20;
- if (oct > old) {
- if (notex < 6) {
- notex += 12;
- oct -= 4;
- }
- } else if (oct < old) {
- if (notex > 11) {
- notex -= 12;
- oct += 4;
- }
- }
- }
-
- i = (notex << 3) + ((note >> 4) & 0x7);
- adlib_write(channel + 0xA0, note_to_f_num[i]);
- adlib_write(channel + 0xB0, oct | 0x20);
-}
-
-int MidiDriver_ADLIB::random_nr(int a) {
- static byte _rand_seed = 1;
- if (_rand_seed & 1) {
- _rand_seed >>= 1;
- _rand_seed ^= 0xB8;
- } else {
- _rand_seed >>= 1;
- }
- return _rand_seed * a >> 8;
-}
-
-void MidiDriver_ADLIB::part_key_off(AdLibPart *part, byte note) {
- AdLibVoice *voice;
-
- for (voice = part->_voice; voice; voice = voice->_next) {
- if (voice->_note == note) {
- if (part->_pedal)
- voice->_waitforpedal = true;
- else
- mc_off(voice);
- }
- }
-}
-
-void MidiDriver_ADLIB::part_key_on(AdLibPart *part, AdLibInstrument *instr, byte note, byte velocity) {
- AdLibVoice *voice;
-
- voice = allocate_voice(part->_pri_eff);
- if (!voice)
- return;
-
- link_mc(part, voice);
- mc_key_on(voice, instr, note, velocity);
-}
-
-AdLibVoice *MidiDriver_ADLIB::allocate_voice(byte pri) {
- AdLibVoice *ac, *best = NULL;
- int i;
-
- for (i = 0; i < 9; i++) {
- if (++_voice_index >= 9)
- _voice_index = 0;
- ac = &_voices[_voice_index];
- if (!ac->_part)
- return ac;
- if (!ac->_next) {
- if (ac->_part->_pri_eff <= pri) {
- pri = ac->_part->_pri_eff;
- best = ac;
- }
- }
- }
-
- /* SCUMM V3 games don't have note priorities, first comes wins. */
- if (_scummSmallHeader)
- return NULL;
-
- if (best)
- mc_off(best);
- return best;
-}
-
-void MidiDriver_ADLIB::link_mc(AdLibPart *part, AdLibVoice *voice) {
- voice->_part = part;
- voice->_next = (AdLibVoice *)part->_voice;
- part->_voice = voice;
- voice->_prev = NULL;
-
- if (voice->_next)
- voice->_next->_prev = voice;
-}
-
-void MidiDriver_ADLIB::mc_key_on(AdLibVoice *voice, AdLibInstrument *instr, byte note, byte velocity) {
- AdLibPart *part = voice->_part;
- int c;
- byte vol_1, vol_2;
-
- voice->_twochan = instr->feedback & 1;
- voice->_note = note;
- voice->_waitforpedal = false;
- voice->_duration = instr->duration;
- if (voice->_duration != 0)
- voice->_duration *= 63;
-
- if (!_scummSmallHeader)
- vol_1 = (instr->mod_scalingOutputLevel & 0x3F) + lookup_table[velocity >> 1][instr->mod_waveformSelect >> 2];
- else
- vol_1 = 0x3f - (instr->mod_scalingOutputLevel & 0x3F);
- if (vol_1 > 0x3F)
- vol_1 = 0x3F;
- voice->_vol_1 = vol_1;
-
- if (!_scummSmallHeader)
- vol_2 = (instr->car_scalingOutputLevel & 0x3F) + lookup_table[velocity >> 1][instr->car_waveformSelect >> 2];
- else
- vol_2 = 0x3f - (instr->car_scalingOutputLevel & 0x3F);
- if (vol_2 > 0x3F)
- vol_2 = 0x3F;
- voice->_vol_2 = vol_2;
-
- c = part->_vol_eff >> 2;
-
- if (!_scummSmallHeader) {
- vol_2 = volume_table[lookup_table[vol_2][c]];
- if (voice->_twochan)
- vol_1 = volume_table[lookup_table[vol_1][c]];
- }
-
- adlib_setup_channel(voice->_channel, instr, vol_1, vol_2);
- adlib_note_on_ex(voice->_channel, part->_transpose_eff + note, part->_detune_eff + (part->_pitchbend * part->_pitchbend_factor >> 6));
-
- if (instr->flags_a & 0x80) {
- mc_init_stuff(voice, &voice->_s10a, &voice->_s11a, instr->flags_a, &instr->extra_a);
- } else {
- voice->_s10a.active = 0;
- }
-
- if (instr->flags_b & 0x80) {
- mc_init_stuff(voice, &voice->_s10b, &voice->_s11b, instr->flags_b, &instr->extra_b);
- } else {
- voice->_s10b.active = 0;
- }
-}
-
-void MidiDriver_ADLIB::adlib_setup_channel(int chan, AdLibInstrument *instr, byte vol_1, byte vol_2) {
- byte channel;
-
- assert(chan >= 0 && chan < 9);
-
- channel = channel_mappings[chan];
- adlib_write(channel + 0x20, instr->mod_characteristic);
- adlib_write(channel + 0x40, (instr->mod_scalingOutputLevel | 0x3F) - vol_1 );
- adlib_write(channel + 0x60, 0xff & (~instr->mod_attackDecay));
- adlib_write(channel + 0x80, 0xff & (~instr->mod_sustainRelease));
- adlib_write(channel + 0xE0, instr->mod_waveformSelect);
-
- channel = channel_mappings_2[chan];
- adlib_write(channel + 0x20, instr->car_characteristic);
- adlib_write(channel + 0x40, (instr->car_scalingOutputLevel | 0x3F) - vol_2 );
- adlib_write(channel + 0x60, 0xff & (~instr->car_attackDecay));
- adlib_write(channel + 0x80, 0xff & (~instr->car_sustainRelease));
- adlib_write(channel + 0xE0, instr->car_waveformSelect);
-
- adlib_write((byte)chan + 0xC0, instr->feedback);
-}
-
-void MidiDriver_ADLIB::adlib_note_on_ex(int chan, byte note, int mod)
-{
- int code;
- assert(chan >= 0 && chan < 9);
- code = (note << 7) + mod;
- curnote_table[chan] = code;
- channel_table_2[chan] = 0;
- adlib_playnote(chan, code);
-}
-
-void MidiDriver_ADLIB::mc_init_stuff(AdLibVoice *voice, Struct10 * s10,
- Struct11 * s11, byte flags, InstrumentExtra * ie) {
- AdLibPart *part = voice->_part;
- s11->modify_val = 0;
- s11->flag0x40 = flags & 0x40;
- s10->loop = flags & 0x20;
- s11->flag0x10 = flags & 0x10;
- s11->param = param_table_1[flags & 0xF];
- s10->max_value = maxval_table[flags & 0xF];
- s10->unk3 = 31;
- if (s11->flag0x40) {
- s10->modwheel = part->_modwheel >> 2;
- } else {
- s10->modwheel = 31;
- }
-
- switch (s11->param) {
- case 0:
- s10->start_value = voice->_vol_2;
- break;
- case 13:
- s10->start_value = voice->_vol_1;
- break;
- case 30:
- s10->start_value = 31;
- s11->s10->modwheel = 0;
- break;
- case 31:
- s10->start_value = 0;
- s11->s10->unk3 = 0;
- break;
- default:
- s10->start_value = adlib_get_reg_value_param(voice->_channel, s11->param);
- }
-
- struct10_init(s10, ie);
-}
-
-void MidiDriver_ADLIB::struct10_init(Struct10 *s10, InstrumentExtra *ie) {
- s10->active = 1;
- if (!_scummSmallHeader) {
- s10->cur_val = 0;
- } else {
- s10->cur_val = s10->start_value;
- s10->start_value = 0;
- }
- s10->modwheel_last = 31;
- s10->count = ie->a;
- if (s10->count)
- s10->count *= 63;
- s10->table_a[0] = ie->b;
- s10->table_a[1] = ie->d;
- s10->table_a[2] = ie->f;
- s10->table_a[3] = ie->g;
-
- s10->table_b[0] = ie->c;
- s10->table_b[1] = ie->e;
- s10->table_b[2] = 0;
- s10->table_b[3] = ie->h;
-
- struct10_setup(s10);
-}
-
-int MidiDriver_ADLIB::adlib_get_reg_value_param(int chan, byte param) {
- const AdLibSetParams *as;
- byte val;
- byte channel;
-
- assert(chan >= 0 && chan < 9);
-
- if (param <= 12) {
- channel = channel_mappings_2[chan];
- } else if (param <= 25) {
- param -= 13;
- channel = channel_mappings[chan];
- } else if (param <= 27) {
- param -= 13;
- channel = chan;
- } else if (param == 28) {
- return 0xF;
- } else if (param == 29) {
- return 0x17F;
- } else {
- return 0;
- }
-
- as = &adlib_setparam_table[param];
- val = adlib_get_reg_value(channel + as->a);
- val &= as->c;
- val >>= as->b;
- if (as->d)
- val = as->d - val;
-
- return val;
-}
-
-void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod) {
- int code;
- assert(chan >= 0 && chan < 9);
- code = (note << 7) + mod;
- curnote_table[chan] = code;
- adlib_playnote(chan, (int16) channel_table_2[chan] + code);
-}
-
-
-// Plugin interface
-
-class AdLibEmuMusicPlugin : public MusicPluginObject {
-public:
- const char *getName() const {
- return _s("AdLib Emulator");
- }
-
- const char *getId() const {
- return "adlib";
- }
-
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
-};
-
-MusicDevices AdLibEmuMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_ADLIB));
- return devices;
-}
-
-Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_ADLIB(g_system->getMixer());
-
- return Common::kNoError;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(ADLIB)
- //REGISTER_PLUGIN_DYNAMIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);
-//#endif
diff --git a/sound/softsynth/appleiigs.cpp b/sound/softsynth/appleiigs.cpp
deleted file mode 100644
index 9004d1f0ab..0000000000
--- a/sound/softsynth/appleiigs.cpp
+++ /dev/null
@@ -1,57 +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$
-*
-*/
-
-#include "sound/null.h"
-
-// Plugin interface
-// (This can only create a null driver since apple II gs support seeems not to be implemented
-// and also is not part of the midi driver architecture. But we need the plugin for the options
-// menu in the launcher and for MidiDriver::detectDevice() which is more or less used by all engines.)
-
-class AppleIIGSMusicPlugin : public NullMusicPlugin {
-public:
- const char *getName() const {
- return _s("Apple II GS Emulator (NOT IMPLEMENTED)");
- }
-
- const char *getId() const {
- return "appleIIgs";
- }
-
- MusicDevices getDevices() const;
-};
-
-MusicDevices AppleIIGSMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_APPLEIIGS));
- return devices;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(APPLEIIGS)
- //REGISTER_PLUGIN_DYNAMIC(APPLEIIGS, PLUGIN_TYPE_MUSIC, AppleIIGSMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(APPLEIIGS, PLUGIN_TYPE_MUSIC, AppleIIGSMusicPlugin);
-//#endif
-
diff --git a/sound/softsynth/cms.cpp b/sound/softsynth/cms.cpp
deleted file mode 100644
index b307146f14..0000000000
--- a/sound/softsynth/cms.cpp
+++ /dev/null
@@ -1,376 +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$
- */
-
-#include "sound/softsynth/cms.h"
-#include "sound/null.h"
-
-#include "common/textconsole.h"
-#include "common/translation.h"
-#include "common/debug.h"
-
-// CMS/Gameblaster Emulation taken from DosBox
-
-#define LEFT 0x00
-#define RIGHT 0x01
-
-static const byte envelope[8][64] = {
- /* zero amplitude */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* maximum amplitude */
- {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, },
- /* single decay */
- {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* repetitive decay */
- {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
- 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
- 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
- 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
- /* single triangular */
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
- 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* repetitive triangular */
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
- 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
- 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
- /* single attack */
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* repetitive attack */
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 }
-};
-
-static const int amplitude_lookup[16] = {
- 0*32767/16, 1*32767/16, 2*32767/16, 3*32767/16,
- 4*32767/16, 5*32767/16, 6*32767/16, 7*32767/16,
- 8*32767/16, 9*32767/16, 10*32767/16, 11*32767/16,
- 12*32767/16, 13*32767/16, 14*32767/16, 15*32767/16
-};
-
-void CMSEmulator::portWrite(int port, int val) {
- switch (port) {
- case 0x220:
- portWriteIntern(0, 1, val);
- break;
-
- case 0x221:
- _saa1099[0].selected_reg = val & 0x1f;
- if (_saa1099[0].selected_reg == 0x18 || _saa1099[0].selected_reg == 0x19) {
- /* clock the envelope channels */
- if (_saa1099[0].env_clock[0])
- envelope(0, 0);
- if (_saa1099[0].env_clock[1])
- envelope(0, 1);
- }
- break;
-
- case 0x222:
- portWriteIntern(1, 1, val);
- break;
-
- case 0x223:
- _saa1099[1].selected_reg = val & 0x1f;
- if (_saa1099[1].selected_reg == 0x18 || _saa1099[1].selected_reg == 0x19) {
- /* clock the envelope channels */
- if (_saa1099[1].env_clock[0])
- envelope(1, 0);
- if (_saa1099[1].env_clock[1])
- envelope(1, 1);
- }
- break;
-
- default:
- warning("CMSEmulator got port: 0x%X", port);
- break;
- }
-}
-
-void CMSEmulator::readBuffer(int16 *buffer, const int numSamples) {
- update(0, &buffer[0], numSamples);
- update(1, &buffer[0], numSamples);
-}
-
-void CMSEmulator::envelope(int chip, int ch) {
- SAA1099 *saa = &_saa1099[chip];
- if (saa->env_enable[ch]) {
- int step, mode, mask;
- mode = saa->env_mode[ch];
- /* step from 0..63 and then loop in steps 32..63 */
- step = saa->env_step[ch] = ((saa->env_step[ch] + 1) & 0x3f) | (saa->env_step[ch] & 0x20);
-
- mask = 15;
- if (saa->env_bits[ch])
- mask &= ~1; /* 3 bit resolution, mask LSB */
-
- saa->channels[ch*3+0].envelope[ LEFT] =
- saa->channels[ch*3+1].envelope[ LEFT] =
- saa->channels[ch*3+2].envelope[ LEFT] = ::envelope[mode][step] & mask;
- if (saa->env_reverse_right[ch] & 0x01) {
- saa->channels[ch*3+0].envelope[RIGHT] =
- saa->channels[ch*3+1].envelope[RIGHT] =
- saa->channels[ch*3+2].envelope[RIGHT] = (15 - ::envelope[mode][step]) & mask;
- } else {
- saa->channels[ch*3+0].envelope[RIGHT] =
- saa->channels[ch*3+1].envelope[RIGHT] =
- saa->channels[ch*3+2].envelope[RIGHT] = ::envelope[mode][step] & mask;
- }
- } else {
- /* envelope mode off, set all envelope factors to 16 */
- saa->channels[ch*3+0].envelope[ LEFT] =
- saa->channels[ch*3+1].envelope[ LEFT] =
- saa->channels[ch*3+2].envelope[ LEFT] =
- saa->channels[ch*3+0].envelope[RIGHT] =
- saa->channels[ch*3+1].envelope[RIGHT] =
- saa->channels[ch*3+2].envelope[RIGHT] = 16;
- }
-}
-
-void CMSEmulator::update(int chip, int16 *buffer, int length) {
- struct SAA1099 *saa = &_saa1099[chip];
- int j, ch;
-
- /* if the channels are disabled we're done */
- if (!saa->all_ch_enable) {
- /* init output data */
- if (chip == 0) {
- memset(buffer, 0, sizeof(int16)*length*2);
- }
- return;
- }
-
- if (chip == 0) {
- memset(buffer, 0, sizeof(int16)*length*2);
- }
-
- for (ch = 0; ch < 2; ch++) {
- switch (saa->noise_params[ch]) {
- case 0: saa->noise[ch].freq = 31250.0 * 2; break;
- case 1: saa->noise[ch].freq = 15625.0 * 2; break;
- case 2: saa->noise[ch].freq = 7812.5 * 2; break;
- case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break;
- }
- }
-
- /* fill all data needed */
- for (j = 0; j < length; ++j) {
- int output_l = 0, output_r = 0;
-
- /* for each channel */
- for (ch = 0; ch < 6; ch++) {
- if (saa->channels[ch].freq == 0.0)
- saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) /
- (511.0 - (double)saa->channels[ch].frequency);
-
- /* check the actual position in the square wave */
- saa->channels[ch].counter -= saa->channels[ch].freq;
- while (saa->channels[ch].counter < 0) {
- /* calculate new frequency now after the half wave is updated */
- saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) /
- (511.0 - (double)saa->channels[ch].frequency);
-
- saa->channels[ch].counter += _sampleRate;
- saa->channels[ch].level ^= 1;
-
- /* eventually clock the envelope counters */
- if (ch == 1 && saa->env_clock[0] == 0)
- envelope(chip, 0);
- if (ch == 4 && saa->env_clock[1] == 0)
- envelope(chip, 1);
- }
-
- /* if the noise is enabled */
- if (saa->channels[ch].noise_enable) {
- /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */
- if (saa->noise[ch/3].level & 1) {
- /* subtract to avoid overflows, also use only half amplitude */
- output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2;
- output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2;
- }
- }
-
- /* if the square wave is enabled */
- if (saa->channels[ch].freq_enable) {
- /* if the channel level is high */
- if (saa->channels[ch].level & 1) {
- output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16;
- output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16;
- }
- }
- }
-
- for (ch = 0; ch < 2; ch++) {
- /* check the actual position in noise generator */
- saa->noise[ch].counter -= saa->noise[ch].freq;
- while (saa->noise[ch].counter < 0) {
- saa->noise[ch].counter += _sampleRate;
- if (((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) )
- saa->noise[ch].level = (saa->noise[ch].level << 1) | 1;
- else
- saa->noise[ch].level <<= 1;
- }
- }
- /* write sound data to the buffer */
- buffer[j*2] += output_l / 6;
- buffer[j*2+1] += output_r / 6;
- }
-}
-
-void CMSEmulator::portWriteIntern(int chip, int offset, int data) {
- SAA1099 *saa = &_saa1099[chip];
- int reg = saa->selected_reg;
- int ch;
-
- switch (reg) {
- /* channel i amplitude */
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- ch = reg & 7;
- saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f];
- saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f];
- break;
-
- /* channel i frequency */
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- ch = reg & 7;
- saa->channels[ch].frequency = data & 0xff;
- break;
-
- /* channel i octave */
- case 0x10:
- case 0x11:
- case 0x12:
- ch = (reg - 0x10) << 1;
- saa->channels[ch + 0].octave = data & 0x07;
- saa->channels[ch + 1].octave = (data >> 4) & 0x07;
- break;
-
- /* channel i frequency enable */
- case 0x14:
- saa->channels[0].freq_enable = data & 0x01;
- saa->channels[1].freq_enable = data & 0x02;
- saa->channels[2].freq_enable = data & 0x04;
- saa->channels[3].freq_enable = data & 0x08;
- saa->channels[4].freq_enable = data & 0x10;
- saa->channels[5].freq_enable = data & 0x20;
- break;
-
- /* channel i noise enable */
- case 0x15:
- saa->channels[0].noise_enable = data & 0x01;
- saa->channels[1].noise_enable = data & 0x02;
- saa->channels[2].noise_enable = data & 0x04;
- saa->channels[3].noise_enable = data & 0x08;
- saa->channels[4].noise_enable = data & 0x10;
- saa->channels[5].noise_enable = data & 0x20;
- break;
-
- /* noise generators parameters */
- case 0x16:
- saa->noise_params[0] = data & 0x03;
- saa->noise_params[1] = (data >> 4) & 0x03;
- break;
-
- /* envelope generators parameters */
- case 0x18:
- case 0x19:
- ch = reg - 0x18;
- saa->env_reverse_right[ch] = data & 0x01;
- saa->env_mode[ch] = (data >> 1) & 0x07;
- saa->env_bits[ch] = data & 0x10;
- saa->env_clock[ch] = data & 0x20;
- saa->env_enable[ch] = data & 0x80;
- /* reset the envelope */
- saa->env_step[ch] = 0;
- break;
-
- /* channels enable & reset generators */
- case 0x1c:
- saa->all_ch_enable = data & 0x01;
- saa->sync_state = data & 0x02;
- if (data & 0x02) {
- int i;
- /* Synch & Reset generators */
- for (i = 0; i < 6; i++) {
- saa->channels[i].level = 0;
- saa->channels[i].counter = 0.0;
- }
- }
- break;
-
- default:
- // The CMS allows all registers to be written, so we just output some debug
- // message here
- debug(5, "CMS Unknown write to reg %x with %x",reg, data);
- }
-}
-
-class CMSMusicPlugin : public NullMusicPlugin {
-public:
- const char *getName() const {
- return _s("Creative Music System Emulator");
- }
-
- const char *getId() const {
- return "cms";
- }
-
- MusicDevices getDevices() const;
-};
-
-MusicDevices CMSMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_CMS));
- return devices;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(CMS)
- //REGISTER_PLUGIN_DYNAMIC(CMS, PLUGIN_TYPE_MUSIC, CMSMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(CMS, PLUGIN_TYPE_MUSIC, CMSMusicPlugin);
-//#endif
diff --git a/sound/softsynth/cms.h b/sound/softsynth/cms.h
deleted file mode 100644
index d5bb7f0a42..0000000000
--- a/sound/softsynth/cms.h
+++ /dev/null
@@ -1,92 +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$
- */
-
-#ifndef SOUND_SOFTSYNTH_CMS_H
-#define SOUND_SOFTSYNTH_CMS_H
-
-#include "common/scummsys.h"
-
-/* this structure defines a channel */
-struct saa1099_channel {
- int frequency; /* frequency (0x00..0xff) */
- int freq_enable; /* frequency enable */
- int noise_enable; /* noise enable */
- int octave; /* octave (0x00..0x07) */
- int amplitude[2]; /* amplitude (0x00..0x0f) */
- int envelope[2]; /* envelope (0x00..0x0f or 0x10 == off) */
-
- /* vars to simulate the square wave */
- double counter;
- double freq;
- int level;
-};
-
-/* this structure defines a noise channel */
-struct saa1099_noise {
- /* vars to simulate the noise generator output */
- double counter;
- double freq;
- int level; /* noise polynomal shifter */
-};
-
-/* this structure defines a SAA1099 chip */
-struct SAA1099 {
- int stream; /* our stream */
- int noise_params[2]; /* noise generators parameters */
- int env_enable[2]; /* envelope generators enable */
- int env_reverse_right[2]; /* envelope reversed for right channel */
- int env_mode[2]; /* envelope generators mode */
- int env_bits[2]; /* non zero = 3 bits resolution */
- int env_clock[2]; /* envelope clock mode (non-zero external) */
- int env_step[2]; /* current envelope step */
- int all_ch_enable; /* all channels enable */
- int sync_state; /* sync all channels */
- int selected_reg; /* selected register */
- struct saa1099_channel channels[6]; /* channels */
- struct saa1099_noise noise[2]; /* noise generators */
-};
-
-class CMSEmulator {
-public:
- CMSEmulator(uint32 sampleRate) {
- _sampleRate = sampleRate;
- memset(_saa1099, 0, sizeof(SAA1099)*2);
- }
-
- ~CMSEmulator() { }
-
- void portWrite(int port, int val);
- void readBuffer(int16 *buffer, const int numSamples);
-private:
- uint32 _sampleRate;
-
- SAA1099 _saa1099[2];
-
- void envelope(int chip, int ch);
- void update(int chip, int16 *buffer, int length);
- void portWriteIntern(int chip, int offset, int data);
-};
-
-
-#endif
diff --git a/sound/softsynth/emumidi.h b/sound/softsynth/emumidi.h
deleted file mode 100644
index 3fb2733b71..0000000000
--- a/sound/softsynth/emumidi.h
+++ /dev/null
@@ -1,116 +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$
- */
-
-#ifndef SOUND_SOFTSYNTH_EMUMIDI_H
-#define SOUND_SOFTSYNTH_EMUMIDI_H
-
-#include "sound/audiostream.h"
-#include "sound/mididrv.h"
-#include "sound/mixer.h"
-
-#define FIXP_SHIFT 16
-
-class MidiDriver_Emulated : public Audio::AudioStream, public MidiDriver {
-protected:
- bool _isOpen;
- Audio::Mixer *_mixer;
- Audio::SoundHandle _mixerSoundHandle;
-
-private:
- Common::TimerManager::TimerProc _timerProc;
- void *_timerParam;
-
- int _nextTick;
- int _samplesPerTick;
-
-protected:
- virtual void generateSamples(int16 *buf, int len) = 0;
- virtual void onTimer() {}
-
- int _baseFreq;
-
-public:
- MidiDriver_Emulated(Audio::Mixer *mixer) : _mixer(mixer) {
- _isOpen = false;
-
- _timerProc = 0;
- _timerParam = 0;
-
- _nextTick = 0;
- _samplesPerTick = 0;
-
- _baseFreq = 250;
- }
-
- int open() {
- _isOpen = true;
-
- int d = getRate() / _baseFreq;
- int r = getRate() % _baseFreq;
-
- // This is equivalent to (getRate() << FIXP_SHIFT) / BASE_FREQ
- // but less prone to arithmetic overflow.
-
- _samplesPerTick = (d << FIXP_SHIFT) + (r << FIXP_SHIFT) / _baseFreq;
- return 0;
- }
-
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
- _timerProc = timer_proc;
- _timerParam = timer_param;
- }
-
- uint32 getBaseTempo() { return 1000000 / _baseFreq; }
-
-
- // AudioStream API
- int readBuffer(int16 *data, const int numSamples) {
- const int stereoFactor = isStereo() ? 2 : 1;
- int len = numSamples / stereoFactor;
- int step;
-
- do {
- step = len;
- if (step > (_nextTick >> FIXP_SHIFT))
- step = (_nextTick >> FIXP_SHIFT);
-
- generateSamples(data, step);
-
- _nextTick -= step << FIXP_SHIFT;
- if (!(_nextTick >> FIXP_SHIFT)) {
- if (_timerProc)
- (*_timerProc)(_timerParam);
- onTimer();
- _nextTick += _samplesPerTick;
- }
- data += step * stereoFactor;
- len -= step;
- } while (len);
-
- return numSamples;
- }
- bool endOfData() const { return false; }
-};
-
-#endif
diff --git a/sound/softsynth/fluidsynth.cpp b/sound/softsynth/fluidsynth.cpp
deleted file mode 100644
index fcb4591a20..0000000000
--- a/sound/softsynth/fluidsynth.cpp
+++ /dev/null
@@ -1,254 +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$
- */
-
-#include "common/scummsys.h"
-
-#ifdef USE_FLUIDSYNTH
-
-#include "common/config-manager.h"
-#include "sound/musicplugin.h"
-#include "sound/mpu401.h"
-#include "sound/softsynth/emumidi.h"
-
-#include <fluidsynth.h>
-
-class MidiDriver_FluidSynth : public MidiDriver_Emulated {
-private:
- MidiChannel_MPU401 _midiChannels[16];
- fluid_settings_t *_settings;
- fluid_synth_t *_synth;
- int _soundFont;
- int _outputRate;
- Audio::SoundHandle _handle;
-
-protected:
- // Because GCC complains about casting from const to non-const...
- void setInt(const char *name, int val);
- void setNum(const char *name, double num);
- void setStr(const char *name, const char *str);
-
- void generateSamples(int16 *buf, int len);
-
-public:
- MidiDriver_FluidSynth(Audio::Mixer *mixer);
-
- int open();
- void close();
- void send(uint32 b);
-
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel();
-
- // AudioStream API
- bool isStereo() const { return true; }
- int getRate() const { return _outputRate; }
-};
-
-// MidiDriver method implementations
-
-MidiDriver_FluidSynth::MidiDriver_FluidSynth(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer) {
-
- for (int i = 0; i < ARRAYSIZE(_midiChannels); i++) {
- _midiChannels[i].init(this, i);
- }
-
- // It ought to be possible to get FluidSynth to generate samples at
- // lower
-
- _outputRate = _mixer->getOutputRate();
- if (_outputRate < 22050)
- _outputRate = 22050;
- else if (_outputRate > 96000)
- _outputRate = 96000;
-}
-
-void MidiDriver_FluidSynth::setInt(const char *name, int val) {
- char *name2 = strdup(name);
-
- fluid_settings_setint(_settings, name2, val);
- free(name2);
-}
-
-void MidiDriver_FluidSynth::setNum(const char *name, double val) {
- char *name2 = strdup(name);
-
- fluid_settings_setnum(_settings, name2, val);
- free(name2);
-}
-
-void MidiDriver_FluidSynth::setStr(const char *name, const char *val) {
- char *name2 = strdup(name);
- char *val2 = strdup(val);
-
- fluid_settings_setstr(_settings, name2, val2);
- free(name2);
- free(val2);
-}
-
-int MidiDriver_FluidSynth::open() {
- if (_isOpen)
- return MERR_ALREADY_OPEN;
-
- if (!ConfMan.hasKey("soundfont"))
- error("FluidSynth requires a 'soundfont' setting");
-
- _settings = new_fluid_settings();
-
- // The default gain setting is ridiculously low - at least for me. This
- // cannot be fixed by ScummVM's volume settings because they can only
- // soften the sound, not amplify it, so instead we add an option to
- // adjust the gain of FluidSynth itself.
-
- double gain = (double)ConfMan.getInt("midi_gain") / 100.0;
-
- setNum("synth.gain", gain);
- setNum("synth.sample-rate", _outputRate);
-
- _synth = new_fluid_synth(_settings);
-
- // In theory, this ought to reduce CPU load... but it doesn't make any
- // noticeable difference for me, so disable it for now.
-
- // fluid_synth_set_interp_method(_synth, -1, FLUID_INTERP_LINEAR);
- // fluid_synth_set_reverb_on(_synth, 0);
- // fluid_synth_set_chorus_on(_synth, 0);
-
- const char *soundfont = ConfMan.get("soundfont").c_str();
-
- _soundFont = fluid_synth_sfload(_synth, soundfont, 1);
- if (_soundFont == -1)
- error("Failed loading custom sound font '%s'", soundfont);
-
- MidiDriver_Emulated::open();
-
- // The MT-32 emulator uses kSFXSoundType here. I don't know why.
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
- return 0;
-}
-
-void MidiDriver_FluidSynth::close() {
- if (!_isOpen)
- return;
- _isOpen = false;
-
- _mixer->stopHandle(_handle);
-
- if (_soundFont != -1)
- fluid_synth_sfunload(_synth, _soundFont, 1);
-
- delete_fluid_synth(_synth);
- delete_fluid_settings(_settings);
-}
-
-void MidiDriver_FluidSynth::send(uint32 b) {
- //byte param3 = (byte) ((b >> 24) & 0xFF);
- uint param2 = (byte) ((b >> 16) & 0xFF);
- uint param1 = (byte) ((b >> 8) & 0xFF);
- byte cmd = (byte) (b & 0xF0);
- byte chan = (byte) (b & 0x0F);
-
- switch (cmd) {
- case 0x80: // Note Off
- fluid_synth_noteoff(_synth, chan, param1);
- break;
- case 0x90: // Note On
- fluid_synth_noteon(_synth, chan, param1, param2);
- break;
- case 0xA0: // Aftertouch
- break;
- case 0xB0: // Control Change
- fluid_synth_cc(_synth, chan, param1, param2);
- break;
- case 0xC0: // Program Change
- fluid_synth_program_change(_synth, chan, param1);
- break;
- case 0xD0: // Channel Pressure
- break;
- case 0xE0: // Pitch Bend
- fluid_synth_pitch_bend(_synth, chan, (param2 << 7) | param1);
- break;
- case 0xF0: // SysEx
- // We should never get here! SysEx information has to be
- // sent via high-level semantic methods.
- warning("MidiDriver_FluidSynth: Receiving SysEx command on a send() call");
- break;
- default:
- warning("MidiDriver_FluidSynth: Unknown send() command 0x%02X", cmd);
- break;
- }
-}
-
-MidiChannel *MidiDriver_FluidSynth::allocateChannel() {
- for (int i = 0; i < ARRAYSIZE(_midiChannels); i++) {
- if (i != 9 && _midiChannels[i].allocate())
- return &_midiChannels[i];
- }
- return NULL;
-}
-
-MidiChannel *MidiDriver_FluidSynth::getPercussionChannel() {
- return &_midiChannels[9];
-}
-
-void MidiDriver_FluidSynth::generateSamples(int16 *data, int len) {
- fluid_synth_write_s16(_synth, len, data, 0, 2, data, 1, 2);
-}
-
-
-// Plugin interface
-
-class FluidSynthMusicPlugin : public MusicPluginObject {
-public:
- const char *getName() const {
- return "FluidSynth";
- }
-
- const char *getId() const {
- return "fluidsynth";
- }
-
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
-};
-
-MusicDevices FluidSynthMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_GM));
- return devices;
-}
-
-Common::Error FluidSynthMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_FluidSynth(g_system->getMixer());
-
- return Common::kNoError;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(FLUIDSYNTH)
- //REGISTER_PLUGIN_DYNAMIC(FLUIDSYNTH, PLUGIN_TYPE_MUSIC, FluidSynthMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(FLUIDSYNTH, PLUGIN_TYPE_MUSIC, FluidSynthMusicPlugin);
-//#endif
-
-#endif
diff --git a/sound/softsynth/fmtowns_pc98/towns_audio.cpp b/sound/softsynth/fmtowns_pc98/towns_audio.cpp
deleted file mode 100644
index 14bc840326..0000000000
--- a/sound/softsynth/fmtowns_pc98/towns_audio.cpp
+++ /dev/null
@@ -1,1583 +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$
- *
- */
-
-#include "sound/softsynth/fmtowns_pc98/towns_audio.h"
-#include "common/endian.h"
-#include "backends/audiocd/audiocd.h"
-
-
-class TownsAudio_PcmChannel {
-friend class TownsAudioInterface;
-public:
- TownsAudio_PcmChannel();
- ~TownsAudio_PcmChannel();
-
-private:
- void loadExtData(uint8 *buffer, uint32 size);
- void setupLoop(uint32 start, uint32 len);
- void clear();
-
- void envAttack();
- void envDecay();
- void envSustain();
- void envRelease();
-
- uint8 *curInstrument;
- uint8 note;
- uint8 velo;
-
- int8 *data;
- int8 *dataEnd;
-
- int8 *loopEnd;
- uint32 loopLen;
-
- uint16 stepNote;
- uint16 stepPitch;
- uint16 step;
-
- uint8 panLeft;
- uint8 panRight;
-
- uint32 pos;
-
- uint8 envTotalLevel;
- uint8 envAttackRate;
- uint8 envDecayRate;
- uint8 envSustainLevel;
- uint8 envSustainRate;
- uint8 envReleaseRate;
-
- int16 envStep;
- int16 envCurrentLevel;
-
- EnvelopeState envState;
-
- int8 *extData;
-};
-
-class TownsAudio_WaveTable {
-friend class TownsAudioInterface;
-public:
- TownsAudio_WaveTable();
- ~TownsAudio_WaveTable();
-
-private:
- void readHeader(const uint8 *buffer);
- void readData(const uint8 *buffer);
- void clear();
-
- char name[9];
- int32 id;
- uint32 size;
- uint32 loopStart;
- uint32 loopLen;
- uint16 rate;
- uint16 rateOffs;
- uint16 baseNote;
- int8 *data;
-};
-
-TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns),
- _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0),
- _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver),
- _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume),
- _outputVolumeFlags(0), _outputMuteFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0),
- _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _ready(false) {
-
-#define INTCB(x) &TownsAudioInterface::intf_##x
- static const TownsAudioIntfCallback intfCb[] = {
- // 0
- INTCB(reset),
- INTCB(keyOn),
- INTCB(keyOff),
- INTCB(setPanPos),
- // 4
- INTCB(setInstrument),
- INTCB(loadInstrument),
- INTCB(notImpl),
- INTCB(setPitch),
- // 8
- INTCB(setLevel),
- INTCB(chanOff),
- INTCB(notImpl),
- INTCB(notImpl),
- // 12
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- // 16
- INTCB(notImpl),
- INTCB(writeReg),
- INTCB(notImpl),
- INTCB(writeRegBuffer),
- // 20
- INTCB(readRegBuffer),
- INTCB(setTimerA),
- INTCB(setTimerB),
- INTCB(enableTimerA),
- // 24
- INTCB(enableTimerB),
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- // 28
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- // 32
- INTCB(loadSamples),
- INTCB(reserveEffectChannels),
- INTCB(loadWaveTable),
- INTCB(unloadWaveTable),
- // 36
- INTCB(notImpl),
- INTCB(pcmPlayEffect),
- INTCB(notImpl),
- INTCB(pcmChanOff),
- // 40
- INTCB(pcmEffectPlaying),
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- // 44
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- // 48
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(fmKeyOn),
- INTCB(fmKeyOff),
- // 52
- INTCB(fmSetPanPos),
- INTCB(fmSetInstrument),
- INTCB(fmLoadInstrument),
- INTCB(notImpl),
- // 56
- INTCB(fmSetPitch),
- INTCB(fmSetLevel),
- INTCB(fmReset),
- INTCB(notImpl),
- // 60
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- // 64
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(setOutputVolume),
- // 68
- INTCB(resetOutputVolume),
- INTCB(notImpl),
- INTCB(updateOutputVolume),
- INTCB(notImpl),
- // 72
- INTCB(notImpl),
- INTCB(cdaToggle),
- INTCB(notImpl),
- INTCB(notImpl),
- // 76
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- INTCB(notImpl),
- // 80
- INTCB(pcmUpdateEnvelopeGenerator),
- INTCB(notImpl)
- };
-#undef INTCB
-
- _intfOpcodes = intfCb;
-
- memset(_fmSaveReg, 0, sizeof(_fmSaveReg));
- memset(_outputLevel, 0, sizeof(_outputLevel));
-
- _timerBase = (uint32)(_baserate * 1000000.0f);
- _tickLength = 2 * _timerBase;
-}
-
-TownsAudioInterface::~TownsAudioInterface() {
- _ready = false;
- deinit();
-
- delete[] _fmSaveReg[0];
- delete[] _fmSaveReg[1];
- delete[] _fmInstruments;
- delete[] _pcmInstruments;
- delete[] _waveTables;
- delete[] _pcmChan;
-}
-
-bool TownsAudioInterface::init() {
- if (_ready)
- return true;
-
- if (!TownsPC98_FmSynth::init())
- return false;
-
- _fmSaveReg[0] = new uint8[256];
- _fmSaveReg[1] = new uint8[256];
- _fmInstruments = new uint8[128 * 48];
- _pcmInstruments = new uint8[32 * 128];
- _waveTables = new TownsAudio_WaveTable[128];
- _pcmChan = new TownsAudio_PcmChannel[8];
-
- _timer = 0;
-
- setVolumeChannelMasks(-1, 0);
-
- _ready = true;
- callback(0);
-
- return true;
-}
-
-int TownsAudioInterface::callback(int command, ...) {
- if (!_ready)
- return 1;
-
- va_list args;
- va_start(args, command);
-
- if (command > 81) {
- va_end(args);
- return 4;
- }
-
- int res = (this->*_intfOpcodes[command])(args);
-
- va_end(args);
- return res;
-}
-
-void TownsAudioInterface::setMusicVolume(int volume) {
- _musicVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
- setVolumeIntern(_musicVolume, _sfxVolume);
-}
-
-void TownsAudioInterface::setSoundEffectVolume(int volume) {
- _sfxVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
- setVolumeIntern(_musicVolume, _sfxVolume);
-}
-
-void TownsAudioInterface::setSoundEffectChanMask(int mask) {
- _pcmSfxChanMask = mask >> 6;
- mask &= 0x3f;
- setVolumeChannelMasks(~mask, mask);
-}
-
-void TownsAudioInterface::nextTickEx(int32 *buffer, uint32 bufferSize) {
- if (!_ready)
- return;
-
- for (uint32 i = 0; i < bufferSize; i++) {
- _timer += _tickLength;
- while (_timer > 0x514767) {
- _timer -= 0x514767;
-
- for (int ii = 0; ii < 8; ii++) {
- if ((_pcmChanKeyPlaying & _chanFlags[ii]) || (_pcmChanEffectPlaying & _chanFlags[ii])) {
- TownsAudio_PcmChannel *s = &_pcmChan[ii];
- s->pos += s->step;
-
- if (&s->data[s->pos >> 11] >= s->loopEnd) {
- if (s->loopLen) {
- s->pos -= s->loopLen;
- } else {
- s->pos = 0;
- _pcmChanEffectPlaying &= ~_chanFlags[ii];
- _pcmChanKeyPlaying &= ~_chanFlags[ii];
- }
- }
- }
- }
- }
-
- int32 finOutL = 0;
- int32 finOutR = 0;
-
- for (int ii = 0; ii < 8; ii++) {
- if (_pcmChanOut & _chanFlags[ii]) {
- int32 o = _pcmChan[ii].data[_pcmChan[ii].pos >> 11] * _pcmChan[ii].velo;
- if ((1 << ii) & (~_pcmSfxChanMask))
- o = (o * _musicVolume) / Audio::Mixer::kMaxMixerVolume;
- if ((1 << ii) & _pcmSfxChanMask)
- o = (o * _sfxVolume) / Audio::Mixer::kMaxMixerVolume;
- if (_pcmChan[ii].panLeft)
- finOutL += ((o * _pcmChan[ii].panLeft) >> 3);
- if (_pcmChan[ii].panRight)
- finOutR += ((o * _pcmChan[ii].panRight) >> 3);
- if (!((_pcmChanKeyPlaying & _chanFlags[ii]) || (_pcmChanEffectPlaying & _chanFlags[ii])))
- _pcmChanOut &= ~_chanFlags[ii];
- }
- }
-
- buffer[i << 1] += finOutL;
- buffer[(i << 1) + 1] += finOutR;
- }
-}
-
-void TownsAudioInterface::timerCallbackA() {
- Common::StackLock lock(_mutex);
- if (_drv && _ready)
- _drv->timerCallback(0);
-}
-
-void TownsAudioInterface::timerCallbackB() {
- Common::StackLock lock(_mutex);
- if (_ready) {
- if (_drv)
- _drv->timerCallback(1);
- callback(80);
- }
-}
-
-int TownsAudioInterface::intf_reset(va_list &args) {
- fmReset();
- pcmReset();
- callback(68);
- return 0;
-}
-
-int TownsAudioInterface::intf_keyOn(va_list &args) {
- int chan = va_arg(args, int);
- int note = va_arg(args, int);
- int velo = va_arg(args, int);
- return (chan & 0x40) ? pcmKeyOn(chan, note, velo) : fmKeyOn(chan, note, velo);
-}
-
-int TownsAudioInterface::intf_keyOff(va_list &args) {
- int chan = va_arg(args, int);
- return (chan & 0x40) ? pcmKeyOff(chan) : fmKeyOff(chan);
-}
-
-int TownsAudioInterface::intf_setPanPos(va_list &args) {
- int chan = va_arg(args, int);
- int mode = va_arg(args, int);
- return (chan & 0x40) ? pcmSetPanPos(chan, mode) : fmSetPanPos(chan, mode);
-}
-
-int TownsAudioInterface::intf_setInstrument(va_list &args) {
- int chan = va_arg(args, int);
- int instrId = va_arg(args, int);
- return (chan & 0x40) ? pcmSetInstrument(chan, instrId) : fmSetInstrument(chan, instrId);
-}
-
-int TownsAudioInterface::intf_loadInstrument(va_list &args) {
- int chanType = va_arg(args, int);
- int instrId = va_arg(args, int);
- uint8 *instrData = va_arg(args, uint8 *);
- return (chanType & 0x40) ? pcmLoadInstrument(instrId, instrData) : fmLoadInstrument(instrId, instrData);
-}
-
-int TownsAudioInterface::intf_setPitch(va_list &args) {
- int chan = va_arg(args, int);
- int16 pitch = (int16)(va_arg(args, int) & 0xffff);
- return (chan & 0x40) ? pcmSetPitch(chan, pitch) : fmSetPitch(chan, pitch);
-}
-
-int TownsAudioInterface::intf_setLevel(va_list &args) {
- int chan = va_arg(args, int);
- int lvl = va_arg(args, int);
- return (chan & 0x40) ? pcmSetLevel(chan, lvl) : fmSetLevel(chan, lvl);
-}
-
-int TownsAudioInterface::intf_chanOff(va_list &args) {
- int chan = va_arg(args, int);
- return (chan & 0x40) ? pcmChanOff(chan) : fmChanOff(chan);
-}
-
-int TownsAudioInterface::intf_writeReg(va_list &args) {
- int part = va_arg(args, int) ? 1 : 0;
- int reg = va_arg(args, int);
- int val = va_arg(args, int);
- if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xb6))
- return 3;
-
- bufferedWriteReg(part, reg, val);
- return 0;
-}
-
-int TownsAudioInterface::intf_writeRegBuffer(va_list &args) {
- int part = va_arg(args, int) ? 1 : 0;
- int reg = va_arg(args, int);
- int val = va_arg(args, int);
-
- if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xef))
- return 3;
-
- _fmSaveReg[part][reg] = val;
- return 0;
-}
-
-int TownsAudioInterface::intf_readRegBuffer(va_list &args) {
- int part = va_arg(args, int) ? 1 : 0;
- int reg = va_arg(args, int);
- uint8 *dst = va_arg(args, uint8 *);
- *dst = 0;
-
- if ((!part && reg < 0x20) || (part && reg < 0x30) || (reg > 0xef))
- return 3;
-
- *dst = _fmSaveReg[part][reg];
- return 0;
-}
-
-int TownsAudioInterface::intf_setTimerA(va_list &args) {
- int enable = va_arg(args, int);
- int tempo = va_arg(args, int);
-
- if (enable) {
- bufferedWriteReg(0, 0x25, tempo & 3);
- bufferedWriteReg(0, 0x24, (tempo >> 2) & 0xff);
- bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x05);
- } else {
- bufferedWriteReg(0, 0x27, (_fmSaveReg[0][0x27] & 0xfa) | 0x10);
- }
-
- return 0;
-}
-
-int TownsAudioInterface::intf_setTimerB(va_list &args) {
- int enable = va_arg(args, int);
- int tempo = va_arg(args, int);
-
- if (enable) {
- bufferedWriteReg(0, 0x26, tempo & 0xff);
- bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x0A);
- } else {
- bufferedWriteReg(0, 0x27, (_fmSaveReg[0][0x27] & 0xf5) | 0x20);
- }
-
- return 0;
-}
-
-int TownsAudioInterface::intf_enableTimerA(va_list &args) {
- bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x15);
- return 0;
-}
-
-int TownsAudioInterface::intf_enableTimerB(va_list &args) {
- bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x2a);
- return 0;
-}
-
-int TownsAudioInterface::intf_loadSamples(va_list &args) {
- uint32 dest = va_arg(args, uint32);
- int size = va_arg(args, int);
- uint8 *src = va_arg(args, uint8*);
-
- if (dest >= 65536 || size == 0 || size > 65536)
- return 3;
- if (size + dest > 65536)
- return 5;
-
- int dwIndex = _numWaveTables - 1;
- for (uint32 t = _waveTablesTotalDataSize; dwIndex && (dest < t); dwIndex--)
- t -= _waveTables[dwIndex].size;
-
- TownsAudio_WaveTable *s = &_waveTables[dwIndex];
- _waveTablesTotalDataSize -= s->size;
- s->size = size;
- s->readData(src);
- _waveTablesTotalDataSize += s->size;
-
- return 0;
-}
-
-int TownsAudioInterface::intf_reserveEffectChannels(va_list &args) {
- int numChan = va_arg(args, int);
- if (numChan > 8)
- return 3;
- if ((numChan << 13) + _waveTablesTotalDataSize > 65536)
- return 5;
-
- if (numChan == _numReservedChannels)
- return 0;
-
- if (numChan < _numReservedChannels) {
- int c = 8 - _numReservedChannels;
- for (int i = numChan; i; i--) {
- uint8 f = ~_chanFlags[c--];
- _pcmChanEffectPlaying &= f;
- }
- } else {
- int c = 7 - _numReservedChannels;
- for (int i = numChan - _numReservedChannels; i; i--) {
- uint8 f = ~_chanFlags[c--];
- _pcmChanKeyPressed &= f;
- _pcmChanKeyPlaying &= f;
- }
- }
-
- static const uint8 reserveChanFlags[] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
- _numReservedChannels = numChan;
- _pcmChanReserved = reserveChanFlags[_numReservedChannels];
-
- return 0;
-}
-
-int TownsAudioInterface::intf_loadWaveTable(va_list &args) {
- uint8 *data = va_arg(args, uint8 *);
- if (_numWaveTables > 127)
- return 3;
-
- TownsAudio_WaveTable w;
- w.readHeader(data);
- if (!w.size)
- return 6;
-
- if (_waveTablesTotalDataSize + w.size > 65504)
- return 5;
-
- for (int i = 0; i < _numWaveTables; i++) {
- if (_waveTables[i].id == w.id)
- return 10;
- }
-
- TownsAudio_WaveTable *s = &_waveTables[_numWaveTables++];
- s->readHeader(data);
-
- _waveTablesTotalDataSize += s->size;
- callback(32, _waveTablesTotalDataSize, s->size, data + 32);
-
- return 0;
-}
-
-int TownsAudioInterface::intf_unloadWaveTable(va_list &args) {
- int id = va_arg(args, int);
-
- if (id == -1) {
- for (int i = 0; i < 128; i++)
- _waveTables[i].clear();
- _numWaveTables = 0;
- _waveTablesTotalDataSize = 0;
- } else {
- if (_waveTables) {
- for (int i = 0; i < _numWaveTables; i++) {
- if (_waveTables[i].id == id) {
- _numWaveTables--;
- _waveTablesTotalDataSize -= _waveTables[i].size;
- _waveTables[i].clear();
- for (; i < _numWaveTables; i++)
- memcpy(&_waveTables[i], &_waveTables[i + 1], sizeof(TownsAudio_WaveTable));
- return 0;
- }
- return 9;
- }
- }
- }
-
- return 0;
-}
-
-int TownsAudioInterface::intf_pcmPlayEffect(va_list &args) {
- int chan = va_arg(args, int);
- int note = va_arg(args, int);
- int velo = va_arg(args, int);
- uint8 *data = va_arg(args, uint8 *);
-
- if (chan < 0x40 || chan > 0x47)
- return 1;
-
- if (note & 0x80 || velo & 0x80)
- return 3;
-
- chan -= 0x40;
-
- if (!(_pcmChanReserved & _chanFlags[chan]))
- return 7;
-
- if ((_pcmChanEffectPlaying & _chanFlags[chan]))
- return 2;
-
- TownsAudio_WaveTable w;
- w.readHeader(data);
-
- if (w.size < (w.loopStart + w.loopLen))
- return 13;
-
- if (!w.size)
- return 6;
-
- TownsAudio_PcmChannel *p = &_pcmChan[chan];
-
- _pcmChanNote[chan] = note;
- _pcmChanVelo[chan] = velo;
-
- p->note = note;
- p->velo = velo << 1;
-
- p->loadExtData(data + 32, w.size);
- p->setupLoop(w.loopStart, w.loopLen);
-
- pcmCalcPhaseStep(p, &w);
- if (p->step > 2048)
- p->step = 2048;
-
- _pcmChanEffectPlaying |= _chanFlags[chan];
- _pcmChanOut |= _chanFlags[chan];
-
- return 0;
-}
-
-int TownsAudioInterface::intf_pcmChanOff(va_list &args) {
- int chan = va_arg(args, int);
- pcmChanOff(chan);
- return 0;
-}
-
-int TownsAudioInterface::intf_pcmEffectPlaying(va_list &args) {
- int chan = va_arg(args, int);
- if (chan < 0x40 || chan > 0x47)
- return 1;
- chan -= 0x40;
- return (_pcmChanEffectPlaying & _chanFlags[chan]) ? 1 : 0;
-}
-
-int TownsAudioInterface::intf_fmKeyOn(va_list &args) {
- int chan = va_arg(args, int);
- int note = va_arg(args, int);
- int velo = va_arg(args, int);
- return fmKeyOn(chan, note, velo);
-}
-
-int TownsAudioInterface::intf_fmKeyOff(va_list &args) {
- int chan = va_arg(args, int);
- return fmKeyOff(chan);
-}
-
-int TownsAudioInterface::intf_fmSetPanPos(va_list &args) {
- int chan = va_arg(args, int);
- int mode = va_arg(args, int);
- return fmSetPanPos(chan, mode);
-}
-
-int TownsAudioInterface::intf_fmSetInstrument(va_list &args) {
- int chan = va_arg(args, int);
- int instrId = va_arg(args, int);
- return fmSetInstrument(chan, instrId);
-}
-
-int TownsAudioInterface::intf_fmLoadInstrument(va_list &args) {
- int instrId = va_arg(args, int);
- uint8 *instrData = va_arg(args, uint8 *);
- return fmLoadInstrument(instrId, instrData);
-}
-
-int TownsAudioInterface::intf_fmSetPitch(va_list &args) {
- int chan = va_arg(args, int);
- uint16 freq = va_arg(args, int) & 0xffff;
- return fmSetPitch(chan, freq);
-}
-
-int TownsAudioInterface::intf_fmSetLevel(va_list &args) {
- int chan = va_arg(args, int);
- int lvl = va_arg(args, int);
- return fmSetLevel(chan, lvl);
-}
-
-int TownsAudioInterface::intf_fmReset(va_list &args) {
- fmReset();
- return 0;
-}
-
-int TownsAudioInterface::intf_setOutputVolume(va_list &args) {
- int chanType = va_arg(args, int);
- int left = va_arg(args, int);
- int right = va_arg(args, int);
-
- if (left & 0xff80 || right & 0xff80)
- return 3;
-
- static const uint8 flags[] = { 0x0C, 0x30, 0x40, 0x80 };
-
- uint8 chan = (chanType & 0x40) ? 8 : 12;
-
- chanType &= 3;
- left = (left & 0x7e) >> 1;
- right = (right & 0x7e) >> 1;
-
- if (chan)
- _outputVolumeFlags |= flags[chanType];
- else
- _outputVolumeFlags &= ~flags[chanType];
-
- if (chanType > 1) {
- _outputLevel[chan + chanType] = left;
- } else {
- if (chanType == 0)
- chan -= 8;
- _outputLevel[chan] = left;
- _outputLevel[chan + 1] = right;
- }
-
- updateOutputVolume();
-
- return 0;
-}
-
-int TownsAudioInterface::intf_resetOutputVolume(va_list &args) {
- memset(_outputLevel, 0, sizeof(_outputLevel));
- _outputMuteFlags = 0;
- _outputVolumeFlags = 0;
- updateOutputVolume();
- return 0;
-}
-
-int TownsAudioInterface::intf_updateOutputVolume(va_list &args) {
- int flags = va_arg(args, int);
- _outputMuteFlags = flags & 3;
- updateOutputVolume();
- return 0;
-}
-
-int TownsAudioInterface::intf_cdaToggle(va_list &args) {
- //int mode = va_arg(args, int);
- //_unkMask = mode ? 0x7f : 0x3f;
- return 0;
-}
-
-int TownsAudioInterface::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
- for (int i = 0; i < 8; i++)
- pcmUpdateEnvelopeGenerator(i);
- return 0;
-}
-
-int TownsAudioInterface::intf_notImpl(va_list &args) {
- return 4;
-}
-
-void TownsAudioInterface::fmReset() {
- TownsPC98_FmSynth::reset();
-
- _fmChanPlaying = 0;
- memset(_fmChanNote, 0, sizeof(_fmChanNote));
- memset(_fmChanPitch, 0, sizeof(_fmChanPitch));
-
- memset(_fmSaveReg[0], 0, 240);
- memset(&_fmSaveReg[0][240], 0x7f, 16);
- memset(_fmSaveReg[1], 0, 256);
- memset(&_fmSaveReg[1][240], 0x7f, 16);
- _fmSaveReg[0][243] = _fmSaveReg[0][247] = _fmSaveReg[0][251] = _fmSaveReg[0][255] = _fmSaveReg[1][243] = _fmSaveReg[1][247] = _fmSaveReg[1][251] = _fmSaveReg[1][255] = 0xff;
-
- for (int i = 0; i < 128; i++)
- fmLoadInstrument(i, _fmDefaultInstrument);
-
- bufferedWriteReg(0, 0x21, 0);
- bufferedWriteReg(0, 0x2C, 0x80);
- bufferedWriteReg(0, 0x2B, 0);
- bufferedWriteReg(0, 0x27, 0x30);
-
- for (int i = 0; i < 6; i++) {
- fmKeyOff(i);
- fmSetInstrument(i, 0);
- fmSetLevel(i, 127);
- }
-}
-
-int TownsAudioInterface::fmKeyOn(int chan, int note, int velo) {
- if (chan > 5)
- return 1;
- if (note < 12 || note > 107 || (velo & 0x80))
- return 3;
- if (_fmChanPlaying & _chanFlags[chan])
- return 2;
-
- _fmChanPlaying |= _chanFlags[chan];
- note -= 12;
-
- _fmChanNote[chan] = note;
- int16 pitch = _fmChanPitch[chan];
-
- uint8 part = chan > 2 ? 1 : 0;
- if (chan > 2)
- chan -= 3;
-
- int frq = 0;
- uint8 bl = 0;
-
- if (note) {
- frq = _frequency[(note - 1) % 12];
- bl = (note - 1) / 12;
- } else {
- frq = 616;
- }
-
- frq += pitch;
-
- if (frq < 616) {
- if (!bl) {
- frq = 616;
- } else {
- frq += 616;
- --bl;
- }
- } else if (frq > 1232) {
- if (bl == 7) {
- frq = 15500;
- } else {
- frq -= 616;
- ++bl;
- }
- }
-
- frq |= (bl << 11);
-
- bufferedWriteReg(part, chan + 0xa4, (frq >> 8) & 0xff);
- bufferedWriteReg(part, chan + 0xa0, frq & 0xff);
-
- velo = (velo >> 2) + 96;
- uint16 c = _carrier[_fmSaveReg[part][0xb0 + chan] & 7];
- _fmSaveReg[part][0xe0 + chan] = velo;
-
- for (uint8 reg = 0x40 + chan; reg < 0x50; reg += 4) {
- c += c;
- if (c & 0x100) {
- c &= 0xff;
- bufferedWriteReg(part, reg, (((((((_fmSaveReg[part][0x80 + reg] ^ 0x7f) * velo) >> 7) + 1) * _fmSaveReg[part][0xd0 + chan]) >> 7) + 1) ^ 0x7f);
- }
- }
-
- uint8 v = chan;
- if (part)
- v |= 4;
-
- for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
- writeReg(part, reg, _fmSaveReg[part][reg] | 0x0f);
-
- writeReg(0, 0x28, v);
-
- for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
- writeReg(part, reg, _fmSaveReg[part][reg]);
-
- bufferedWriteReg(0, 0x28, v | 0xf0);
-
- return 0;
-}
-
-int TownsAudioInterface::fmKeyOff(int chan) {
- if (chan > 5)
- return 1;
- _fmChanPlaying &= ~_chanFlags[chan];
- if (chan > 2)
- chan++;
- bufferedWriteReg(0, 0x28, chan);
- return 0;
-}
-
-int TownsAudioInterface::fmChanOff(int chan) {
- if (chan > 5)
- return 1;
- _fmChanPlaying &= ~_chanFlags[chan];
-
- uint8 part = chan > 2 ? 1 : 0;
- if (chan > 2)
- chan -= 3;
-
- for (uint8 reg = 0x80 + chan; reg < 0x90; reg += 4)
- writeReg(part, reg, _fmSaveReg[part][reg] | 0x0f);
-
- if (part)
- chan += 4;
- writeReg(0, 0x28, chan);
- return 0;
-}
-
-int TownsAudioInterface::fmSetPanPos(int chan, int value) {
- if (chan > 5)
- return 1;
-
- uint8 part = chan > 2 ? 1 : 0;
- if (chan > 2)
- chan -= 3;
-
- if (value > 0x40)
- value = 0x40;
- else if (value < 0x40)
- value = 0x80;
- else
- value = 0xC0;
-
- bufferedWriteReg(part, 0xb4 + chan, (_fmSaveReg[part][0xb4 + chan] & 0x3f) | value);
- return 0;
-}
-
-int TownsAudioInterface::fmSetInstrument(int chan, int instrId) {
- if (chan > 5)
- return 1;
- if (instrId > 127)
- return 3;
-
- uint8 part = chan > 2 ? 1 : 0;
- if (chan > 2)
- chan -= 3;
-
- uint8 *src = &_fmInstruments[instrId * 48 + 8];
-
- uint16 c = _carrier[src[24] & 7];
- uint8 reg = 0x30 + chan;
-
- for (; reg < 0x40; reg += 4)
- bufferedWriteReg(part, reg, *src++);
-
- for (; reg < 0x50; reg += 4) {
- uint8 v = *src++;
- _fmSaveReg[part][0x80 + reg] = _fmSaveReg[part][reg] = v;
- c += c;
- if (c & 0x100) {
- c &= 0xff;
- v = 127;
- }
- writeReg(part, reg, v);
- }
-
- for (; reg < 0x90; reg += 4)
- bufferedWriteReg(part, reg, *src++);
-
- reg += 0x20;
- bufferedWriteReg(part, reg, *src++);
-
- uint8 v = *src++;
- reg += 4;
- if (v < 64)
- v |= (_fmSaveReg[part][reg] & 0xc0);
- bufferedWriteReg(part, reg, v);
-
- return 0;
-}
-
-int TownsAudioInterface::fmLoadInstrument(int instrId, const uint8 *data) {
- if (instrId > 127)
- return 3;
- assert(data);
- memcpy(&_fmInstruments[instrId * 48], data, 48);
- return 0;
-}
-
-int TownsAudioInterface::fmSetPitch(int chan, int pitch) {
- if (chan > 5)
- return 1;
-
- uint8 bl = _fmChanNote[chan];
- int frq = 0;
-
- if (pitch < 0) {
- if (bl) {
- if (pitch < -8008)
- pitch = -8008;
- pitch *= -1;
- pitch /= 13;
- frq = _frequency[(bl - 1) % 12] - pitch;
- bl = (bl - 1) / 12;
- _fmChanPitch[chan] = -pitch;
-
- if (frq < 616) {
- if (bl) {
- frq += 616;
- bl--;
- } else {
- frq = 616;
- bl = 0;
- }
- }
- } else {
- frq = 616;
- bl = 0;
- }
-
- } else if (pitch > 0) {
- if (bl < 96) {
- if (pitch > 8008)
- pitch = 8008;
- pitch /= 13;
-
- if (bl) {
- frq = _frequency[(bl - 1) % 12] + pitch;
- bl = (bl - 1) / 12;
- } else {
- frq = 616;
- bl = 0;
- }
-
- _fmChanPitch[chan] = pitch;
-
- if (frq > 1232) {
- if (bl < 7) {
- frq -= 616;
- bl++;
- } else {
- frq = 1164;
- bl = 7;
- }
- } else {
- if (bl >= 7 && frq > 1164)
- frq = 1164;
- }
-
- } else {
- frq = 1164;
- bl = 7;
- }
- } else {
- _fmChanPitch[chan] = 0;
- if (bl) {
- frq = _frequency[(bl - 1) % 12];
- bl = (bl - 1) / 12;
- } else {
- frq = 616;
- bl = 0;
- }
- }
-
- uint8 part = chan > 2 ? 1 : 0;
- if (chan > 2)
- chan -= 3;
-
- frq |= (bl << 11);
-
- bufferedWriteReg(part, chan + 0xa4, (frq >> 8));
- bufferedWriteReg(part, chan + 0xa0, (frq & 0xff));
-
- return 0;
-}
-
-int TownsAudioInterface::fmSetLevel(int chan, int lvl) {
- if (chan > 5)
- return 1;
- if (lvl > 127)
- return 3;
-
- uint8 part = chan > 2 ? 1 : 0;
- if (chan > 2)
- chan -= 3;
-
- uint16 c = _carrier[_fmSaveReg[part][0xb0 + chan] & 7];
- _fmSaveReg[part][0xd0 + chan] = lvl;
-
- for (uint8 reg = 0x40 + chan; reg < 0x50; reg += 4) {
- c += c;
- if (c & 0x100) {
- c &= 0xff;
- bufferedWriteReg(part, reg, (((((((_fmSaveReg[part][0x80 + reg] ^ 0x7f) * lvl) >> 7) + 1) * _fmSaveReg[part][0xe0 + chan]) >> 7) + 1) ^ 0x7f);
- }
- }
- return 0;
-}
-
-void TownsAudioInterface::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) {
- _fmSaveReg[part][regAddress] = value;
- writeReg(part, regAddress, value);
-}
-
-void TownsAudioInterface::pcmReset() {
- _pcmChanOut = 0;
- _pcmChanReserved = _pcmChanKeyPressed = _pcmChanEffectPlaying = _pcmChanKeyPlaying = 0;
- _numReservedChannels = 0;
-
- memset(_pcmChanNote, 0, 8);
- memset(_pcmChanVelo, 0, 8);
- memset(_pcmChanLevel, 0, 8);
-
- for (int i = 0; i < 8; i++)
- _pcmChan[i].clear();
-
- memset(_pcmInstruments, 0, 128 * 32);
- static uint8 name[] = { 0x4E, 0x6F, 0x20, 0x44, 0x61, 0x74, 0x61, 0x21 };
- for (int i = 0; i < 32; i++)
- memcpy(_pcmInstruments + i * 128, name, 8);
-
- for (int i = 0; i < 128; i++)
- _waveTables[i].clear();
- _numWaveTables = 0;
- _waveTablesTotalDataSize = 0;
-
- for (int i = 0x40; i < 0x48; i++) {
- pcmSetInstrument(i, 0);
- pcmSetLevel(i, 127);
- }
-}
-
-int TownsAudioInterface::pcmKeyOn(int chan, int note, int velo) {
- if (chan < 0x40 || chan > 0x47)
- return 1;
-
- if (note & 0x80 || velo & 0x80)
- return 3;
-
- chan -= 0x40;
-
- if ((_pcmChanReserved & _chanFlags[chan]) || (_pcmChanKeyPressed & _chanFlags[chan]))
- return 2;
-
- _pcmChanNote[chan] = note;
- _pcmChanVelo[chan] = velo;
-
- TownsAudio_PcmChannel *p = &_pcmChan[chan];
- p->note = note;
-
- uint8 *instr = _pcmChan[chan].curInstrument;
- int i = 0;
- for (; i < 8; i++) {
- if (note <= instr[16 + 2 * i])
- break;
- }
-
- if (i == 8)
- return 8;
-
- int il = i << 3;
- p->note += instr[il + 70];
-
- p->envTotalLevel = instr[il + 64];
- p->envAttackRate = instr[il + 65];
- p->envDecayRate = instr[il + 66];
- p->envSustainLevel = instr[il + 67];
- p->envSustainRate = instr[il + 68];
- p->envReleaseRate = instr[il + 69];
- p->envStep = 0;
-
- int32 id = (int32)READ_LE_UINT32(&instr[i * 4 + 32]);
-
- for (i = 0; i < _numWaveTables; i++) {
- if (id == _waveTables[i].id)
- break;
- }
-
- if (i == _numWaveTables)
- return 9;
-
- TownsAudio_WaveTable *w = &_waveTables[i];
-
- p->data = w->data;
- p->dataEnd = w->data + w->size;
- p->setupLoop(w->loopStart, w->loopLen);
-
- pcmCalcPhaseStep(p, w);
-
- uint32 lvl = _pcmChanLevel[chan] * _pcmChanVelo[chan];
- p->envTotalLevel = ((p->envTotalLevel * lvl) >> 14) & 0xff;
- p->envSustainLevel = ((p->envSustainLevel * lvl) >> 14) & 0xff;
-
- p->envAttack();
- p->velo = (p->envCurrentLevel >> 8) << 1;
-
- _pcmChanKeyPressed |= _chanFlags[chan];
- _pcmChanKeyPlaying |= _chanFlags[chan];
- _pcmChanOut |= _chanFlags[chan];
-
- return 0;
-}
-
-int TownsAudioInterface::pcmKeyOff(int chan) {
- if (chan < 0x40 || chan > 0x47)
- return 1;
-
- chan -= 0x40;
- _pcmChanKeyPressed &= ~_chanFlags[chan];
- _pcmChan[chan].envRelease();
- return 0;
-}
-
-int TownsAudioInterface::pcmChanOff(int chan) {
- if (chan < 0x40 || chan > 0x47)
- return 1;
-
- chan -= 0x40;
-
- _pcmChanKeyPressed &= ~_chanFlags[chan];
- _pcmChanEffectPlaying &= ~_chanFlags[chan];
- _pcmChanKeyPlaying &= ~_chanFlags[chan];
- _pcmChanOut &= ~_chanFlags[chan];
-
- return 0;
-}
-
-int TownsAudioInterface::pcmSetPanPos(int chan, int mode) {
- if (chan > 0x47)
- return 1;
- if (mode & 0x80)
- return 3;
-
- chan -= 0x40;
- uint8 blc = 0x77;
-
- if (mode > 64) {
- mode -= 64;
- blc = ((blc ^ (mode >> 3)) + (mode << 4)) & 0xff;
- } else if (mode < 64) {
- mode = (mode >> 3) ^ 7;
- blc = ((119 + mode) ^ (mode << 4)) & 0xff;
- }
-
- _pcmChan[chan].panLeft = blc & 0x0f;
- _pcmChan[chan].panRight = blc >> 4;
-
- return 0;
-}
-
-int TownsAudioInterface::pcmSetInstrument(int chan, int instrId) {
- if (chan > 0x47)
- return 1;
- if (instrId > 31)
- return 3;
- chan -= 0x40;
- _pcmChan[chan].curInstrument = &_pcmInstruments[instrId * 128];
- return 0;
-}
-
-int TownsAudioInterface::pcmLoadInstrument(int instrId, const uint8 *data) {
- if (instrId > 31)
- return 3;
- assert(data);
- memcpy(&_pcmInstruments[instrId * 128], data, 128);
- return 0;
-}
-
-int TownsAudioInterface::pcmSetPitch(int chan, int pitch) {
- if (chan > 0x47)
- return 1;
-
- if (pitch < -8192 || pitch > 8191)
- return 3;
-
- chan -= 0x40;
- TownsAudio_PcmChannel *p = &_pcmChan[chan];
-
- uint32 pts = 0x4000;
-
- if (pitch < 0)
- pts = (0x20000000 / (-pitch + 0x2001)) >> 2;
- else if (pitch > 0)
- pts = (((pitch + 0x2001) << 16) / 0x2000) >> 2;
-
- p->stepPitch = pts & 0xffff;
- p->step = (p->stepNote * p->stepPitch) >> 14;
-
-// if (_pcmChanUnkFlag & _chanFlags[chan])
-// unk[chan] = (((p->step * 1000) << 11) / 98) / 20833;
-
- /*else*/
- if ((_pcmChanEffectPlaying & _chanFlags[chan]) && (p->step > 2048))
- p->step = 2048;
-
- return 0;
-}
-
-int TownsAudioInterface::pcmSetLevel(int chan, int lvl) {
- if (chan > 0x47)
- return 1;
-
- if (lvl & 0x80)
- return 3;
-
- chan -= 0x40;
- TownsAudio_PcmChannel *p = &_pcmChan[chan];
-
- if (_pcmChanReserved & _chanFlags[chan]) {
- _pcmChanVelo[chan] = lvl;
- p->velo = lvl << 1;
- } else {
- int32 t = p->envStep * lvl;
- if (_pcmChanLevel[chan])
- t /= _pcmChanLevel[chan];
- p->envStep = t;
- t = p->envCurrentLevel * lvl;
- if (_pcmChanLevel[chan])
- t /= _pcmChanLevel[chan];
- p->envCurrentLevel = t;
- _pcmChanLevel[chan] = lvl;
- p->velo = p->envCurrentLevel >> 8;
- }
-
- return 0;
-}
-
-void TownsAudioInterface::pcmUpdateEnvelopeGenerator(int chan) {
- TownsAudio_PcmChannel *p = &_pcmChan[chan];
- if (!p->envCurrentLevel) {
- _pcmChanKeyPlaying &= ~_chanFlags[chan];
- p->envState = kEnvReady;
- }
-
- if (!(_pcmChanKeyPlaying & _chanFlags[chan]))
- return;
-
- switch (p->envState) {
- case kEnvAttacking:
- if (((p->envCurrentLevel + p->envStep) >> 8) > p->envTotalLevel) {
- p->envDecay();
- return;
- } else {
- p->envCurrentLevel += p->envStep;
- }
- break;
-
- case kEnvDecaying:
- if (((p->envCurrentLevel - p->envStep) >> 8) < p->envSustainLevel) {
- p->envSustain();
- return;
- } else {
- p->envCurrentLevel -= p->envStep;
- }
- break;
-
- case kEnvSustaining:
- case kEnvReleasing:
- p->envCurrentLevel -= p->envStep;
- if (p->envCurrentLevel <= 0)
- p->envCurrentLevel = 0;
- break;
-
- default:
- break;
- }
- p->velo = (p->envCurrentLevel >> 8) << 1;
-}
-
-void TownsAudioInterface::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) {
- int8 diff = p->note - w->baseNote;
- uint16 r = w->rate + w->rateOffs;
- uint16 bl = 0;
- uint32 s = 0;
-
- if (diff < 0) {
- diff *= -1;
- bl = diff % 12;
- diff /= 12;
- s = (r >> diff);
- if (bl)
- s = (s * _pcmPhase2[bl]) >> 16;
-
- } else if (diff > 0) {
- bl = diff % 12;
- diff /= 12;
- s = (r << diff);
- if (bl)
- s += ((s * _pcmPhase1[bl]) >> 16);
-
- } else {
- s = r;
- }
-
- p->stepNote = s & 0xffff;
- p->step = (s * p->stepPitch) >> 14;
-}
-
-void TownsAudioInterface::updateOutputVolume() {
- // FM Towns seems to support volumes of 0 - 63 for each channel.
- // We recalculate sane values for our 0 to 255 volume range and
- // balance values for our -128 to 127 volume range
-
- // CD-AUDIO
- uint32 maxVol = MAX(_outputLevel[12], _outputLevel[13]);
-
- int volume = (int)(((float)(maxVol * 255) / 63.0f));
- int balance = maxVol ? (int)( ( ((int)_outputLevel[13] - _outputLevel[12]) * 127) / (float)maxVol) : 0;
-
- g_system->getAudioCDManager()->setVolume(volume);
- g_system->getAudioCDManager()->setBalance(balance);
-}
-
-const uint8 TownsAudioInterface::_chanFlags[] = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
-};
-
-const uint16 TownsAudioInterface::_frequency[] = {
- 0x028C, 0x02B4, 0x02DC, 0x030A, 0x0338, 0x0368, 0x039C, 0x03D4, 0x040E, 0x044A, 0x048C, 0x04D0
-};
-
-const uint8 TownsAudioInterface::_carrier[] = {
- 0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0
-};
-
-const uint8 TownsAudioInterface::_fmDefaultInstrument[] = {
- 0x45, 0x4C, 0x45, 0x50, 0x49, 0x41, 0x4E, 0x4F, 0x01, 0x0A, 0x02, 0x01,
- 0x1E, 0x32, 0x05, 0x00, 0x9C, 0xDC, 0x9C, 0xDC, 0x07, 0x03, 0x14, 0x08,
- 0x00, 0x03, 0x05, 0x05, 0x55, 0x45, 0x27, 0xA7, 0x04, 0xC0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const uint16 TownsAudioInterface::_pcmPhase1[] = {
- 0x879B, 0x0F37, 0x1F58, 0x306E, 0x4288, 0x55B6, 0x6A08, 0x7F8F, 0x965E, 0xAE88, 0xC882, 0xE341
-};
-
-const uint16 TownsAudioInterface::_pcmPhase2[] = {
- 0xFEFE, 0xF1A0, 0xE411, 0xD744, 0xCB2F, 0xBFC7, 0xB504, 0xAAE2, 0xA144, 0x9827, 0x8FAC
-};
-
-TownsAudio_PcmChannel::TownsAudio_PcmChannel() {
- extData = 0;
- clear();
-}
-
-TownsAudio_PcmChannel::~TownsAudio_PcmChannel() {
- clear();
-}
-
-void TownsAudio_PcmChannel::loadExtData(uint8 *buffer, uint32 size) {
- delete[] extData;
- extData = new int8[size];
- int8 *src = (int8 *)buffer;
- int8 *dst = extData;
- for (uint32 i = 0; i < size; i++)
- *dst++ = *src & 0x80 ? (*src++ & 0x7f) : -*src++;
-
- data = extData;
- dataEnd = extData + size;
- pos = 0;
-}
-
-void TownsAudio_PcmChannel::setupLoop(uint32 start, uint32 len) {
- loopLen = len << 11;
- loopEnd = loopLen ? &data[(start + loopLen) >> 11] : dataEnd;
- pos = start;
-}
-
-void TownsAudio_PcmChannel::clear() {
- curInstrument = 0;
- note = 0;
- velo = 0;
-
- data = 0;
- dataEnd = 0;
- loopLen = 0;
-
- pos = 0;
- loopEnd = 0;
-
- step = 0;
- stepNote = 0x4000;
- stepPitch = 0x4000;
-
- panLeft = panRight = 7;
-
- envTotalLevel = envAttackRate = envDecayRate = envSustainLevel = envSustainRate = envReleaseRate = 0;
- envStep = envCurrentLevel = 0;
-
- envState = kEnvReady;
-
- delete[] extData;
- extData = 0;
-}
-
-void TownsAudio_PcmChannel::envAttack() {
- envState = kEnvAttacking;
- int16 t = envTotalLevel << 8;
- if (envAttackRate == 127) {
- envStep = 0;
- } else if (envAttackRate) {
- envStep = t / envAttackRate;
- envCurrentLevel = 1;
- } else {
- envCurrentLevel = t;
- envDecay();
- }
-}
-
-void TownsAudio_PcmChannel::envDecay() {
- envState = kEnvDecaying;
- int16 t = envTotalLevel - envSustainLevel;
- if (t < 0 || envDecayRate == 127) {
- envStep = 0;
- } else if (envDecayRate) {
- envStep = (t << 8) / envDecayRate;
- } else {
- envCurrentLevel = envSustainLevel << 8;
- envSustain();
- }
-}
-
-void TownsAudio_PcmChannel::envSustain() {
- envState = kEnvSustaining;
- if (envSustainLevel && envSustainRate)
- envStep = (envSustainRate == 127) ? 0 : (envCurrentLevel / envSustainRate) >> 1;
- else
- envStep = envCurrentLevel = 1;
-}
-
-void TownsAudio_PcmChannel::envRelease() {
- envState = kEnvReleasing;
- if (envReleaseRate == 127)
- envStep = 0;
- else if (envReleaseRate)
- envStep = envCurrentLevel / envReleaseRate;
- else
- envStep = envCurrentLevel = 1;
-}
-
-TownsAudio_WaveTable::TownsAudio_WaveTable() {
- data = 0;
- clear();
-}
-
-TownsAudio_WaveTable::~TownsAudio_WaveTable() {
- clear();
-}
-
-void TownsAudio_WaveTable::readHeader(const uint8 *buffer) {
- memcpy(name, buffer, 8);
- name[8] = 0;
- id = READ_LE_UINT32(&buffer[8]);
- size = READ_LE_UINT32(&buffer[12]);
- loopStart = READ_LE_UINT32(&buffer[16]);
- loopLen = READ_LE_UINT32(&buffer[20]);
- rate = READ_LE_UINT16(&buffer[24]);
- rateOffs = READ_LE_UINT16(&buffer[26]);
- baseNote = READ_LE_UINT32(&buffer[28]);
-}
-
-void TownsAudio_WaveTable::readData(const uint8 *buffer) {
- if (!size)
- return;
-
- delete[] data;
- data = new int8[size];
-
- const int8 *src = (const int8 *)buffer;
- int8 *dst = data;
- for (uint32 i = 0; i < size; i++)
- *dst++ = *src & 0x80 ? (*src++ & 0x7f) : -*src++;
-}
-
-void TownsAudio_WaveTable::clear() {
- name[0] = name[8] = 0;
- id = -1;
- size = 0;
- loopStart = 0;
- loopLen = 0;
- rate = 0;
- rateOffs = 0;
- baseNote = 0;
- delete[] data;
- data = 0;
-}
-
diff --git a/sound/softsynth/fmtowns_pc98/towns_audio.h b/sound/softsynth/fmtowns_pc98/towns_audio.h
deleted file mode 100644
index 95fb1ded59..0000000000
--- a/sound/softsynth/fmtowns_pc98/towns_audio.h
+++ /dev/null
@@ -1,179 +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$
- *
- */
-
-#ifndef TOWNS_AUDIO_H
-#define TOWNS_AUDIO_H
-
-#include "sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
-
-class TownsAudioInterfacePluginDriver {
-public:
- virtual ~TownsAudioInterfacePluginDriver() {}
- virtual void timerCallback(int timerId) = 0;
-};
-
-class TownsAudio_PcmChannel;
-class TownsAudio_WaveTable;
-
-class TownsAudioInterface : public TownsPC98_FmSynth {
-public:
- TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
- ~TownsAudioInterface();
-
- bool init();
-
- int callback(int command, ...);
-
- void setMusicVolume(int volume);
- void setSoundEffectVolume(int volume);
- // Defines the channels used as sound effect channels for the purpose of ScummVM GUI volume control.
- // The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels.
- void setSoundEffectChanMask(int mask);
-
-private:
- void nextTickEx(int32 *buffer, uint32 bufferSize);
-
- void timerCallbackA();
- void timerCallbackB();
-
- typedef int (TownsAudioInterface::*TownsAudioIntfCallback)(va_list &);
- const TownsAudioIntfCallback *_intfOpcodes;
-
- int intf_reset(va_list &args);
- int intf_keyOn(va_list &args);
- int intf_keyOff(va_list &args);
- int intf_setPanPos(va_list &args);
- int intf_setInstrument(va_list &args);
- int intf_loadInstrument(va_list &args);
- int intf_setPitch(va_list &args);
- int intf_setLevel(va_list &args);
- int intf_chanOff(va_list &args);
- int intf_writeReg(va_list &args);
- int intf_writeRegBuffer(va_list &args);
- int intf_readRegBuffer(va_list &args);
- int intf_setTimerA(va_list &args);
- int intf_setTimerB(va_list &args);
- int intf_enableTimerA(va_list &args);
- int intf_enableTimerB(va_list &args);
- int intf_loadSamples(va_list &args);
- int intf_reserveEffectChannels(va_list &args);
- int intf_loadWaveTable(va_list &args);
- int intf_unloadWaveTable(va_list &args);
- int intf_pcmPlayEffect(va_list &args);
- int intf_pcmChanOff(va_list &args);
- int intf_pcmEffectPlaying(va_list &args);
- int intf_fmKeyOn(va_list &args);
- int intf_fmKeyOff(va_list &args);
- int intf_fmSetPanPos(va_list &args);
- int intf_fmSetInstrument(va_list &args);
- int intf_fmLoadInstrument(va_list &args);
- int intf_fmSetPitch(va_list &args);
- int intf_fmSetLevel(va_list &args);
- int intf_fmReset(va_list &args);
- int intf_setOutputVolume(va_list &args);
- int intf_resetOutputVolume(va_list &args);
- int intf_updateOutputVolume(va_list &args);
- int intf_cdaToggle(va_list &args);
- int intf_pcmUpdateEnvelopeGenerator(va_list &args);
-
- int intf_notImpl(va_list &args);
-
- void fmReset();
- int fmKeyOn(int chan, int note, int velo);
- int fmKeyOff(int chan);
- int fmChanOff(int chan);
- int fmSetPanPos(int chan, int mode);
- int fmSetInstrument(int chan, int instrId);
- int fmLoadInstrument(int instrId, const uint8 *data);
- int fmSetPitch(int chan, int pitch);
- int fmSetLevel(int chan, int lvl);
-
- void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value);
-
- uint8 _fmChanPlaying;
- uint8 _fmChanNote[6];
- int16 _fmChanPitch[6];
-
- uint8 *_fmSaveReg[2];
- uint8 *_fmInstruments;
-
- void pcmReset();
- int pcmKeyOn(int chan, int note, int velo);
- int pcmKeyOff(int chan);
- int pcmChanOff(int chan);
- int pcmSetPanPos(int chan, int mode);
- int pcmSetInstrument(int chan, int instrId);
- int pcmLoadInstrument(int instrId, const uint8 *data);
- int pcmSetPitch(int chan, int pitch);
- int pcmSetLevel(int chan, int lvl);
- void pcmUpdateEnvelopeGenerator(int chan);
-
- TownsAudio_PcmChannel *_pcmChan;
- uint8 _pcmChanOut;
- uint8 _pcmChanReserved;
- uint8 _pcmChanKeyPressed;
- uint8 _pcmChanEffectPlaying;
- uint8 _pcmChanKeyPlaying;
-
- uint8 _pcmChanNote[8];
- uint8 _pcmChanVelo[8];
- uint8 _pcmChanLevel[8];
-
- uint8 _numReservedChannels;
- uint8 *_pcmInstruments;
-
- TownsAudio_WaveTable *_waveTables;
- uint8 _numWaveTables;
- uint32 _waveTablesTotalDataSize;
-
- void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w);
-
- void updateOutputVolume();
- uint8 _outputVolumeFlags;
- uint8 _outputLevel[16];
- uint8 _outputMuteFlags;
-
- const float _baserate;
- uint32 _timerBase;
- uint32 _tickLength;
- uint32 _timer;
-
- uint16 _musicVolume;
- uint16 _sfxVolume;
- int _pcmSfxChanMask;
-
- TownsAudioInterfacePluginDriver *_drv;
- bool _ready;
-
- static const uint8 _chanFlags[];
- static const uint16 _frequency[];
- static const uint8 _carrier[];
- static const uint8 _fmDefaultInstrument[];
- static const uint16 _pcmPhase1[];
- static const uint16 _pcmPhase2[];
-};
-
-#endif
-
diff --git a/sound/softsynth/fmtowns_pc98/towns_euphony.cpp b/sound/softsynth/fmtowns_pc98/towns_euphony.cpp
deleted file mode 100644
index 3a691c407d..0000000000
--- a/sound/softsynth/fmtowns_pc98/towns_euphony.cpp
+++ /dev/null
@@ -1,905 +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$
- *
- */
-
-#include "sound/softsynth/fmtowns_pc98/towns_euphony.h"
-#include "common/endian.h"
-
-TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0),
- _assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0),
- _tTranspose(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0),
- _tempoControlMode(0) {
- _para[0] = _para[1] = 0;
- _intf = new TownsAudioInterface(mixer, this);
- resetTempo();
-}
-
-TownsEuphonyDriver::~TownsEuphonyDriver() {
- delete _intf;
- delete[] _activeChannels;
- delete[] _sustainChannels;
- delete[] _assignedChannels;
- delete[] _tEnable;
- delete[] _tMode;
- delete[] _tOrdr;
- delete[] _tLevel;
- delete[] _tTranspose;
-}
-
-bool TownsEuphonyDriver::init() {
- if (!_intf->init())
- return false;
-
- _activeChannels = new int8[16];
- _sustainChannels = new int8[16];
- _assignedChannels = new ActiveChannel[128];
- _eventBuffer = new DlEvent[64];
-
- _tEnable = new uint8[32];
- _tMode = new uint8[32];
- _tOrdr = new uint8[32];
- _tLevel = new int8[32];
- _tTranspose = new int8[32];
-
- reset();
-
- return true;
-}
-
-void TownsEuphonyDriver::reset() {
- _intf->callback(0);
-
- _intf->callback(74);
- _intf->callback(70);
- _intf->callback(75, 3);
-
- setTimerA(true, 1);
- setTimerA(false, 1);
- setTimerB(true, 221);
-
- _paraCount = _command = _para[0] = _para[1] = 0;
- memset(_sustainChannels, 0, 16);
- memset(_activeChannels, -1, 16);
- for (int i = 0; i < 128; i++) {
- _assignedChannels[i].chan = _assignedChannels[i].next = -1;
- _assignedChannels[i].note = _assignedChannels[i].sub = 0;
- }
-
- int e = 0;
- for (int i = 0; i < 6; i++)
- assignChannel(i, e++);
- for (int i = 0x40; i < 0x48; i++)
- assignChannel(i, e++);
-
- resetTables();
-
- memset(_eventBuffer, 0, 64 * sizeof(DlEvent));
- _bufferedEventsCount = 0;
-
- _playing = _endOfTrack = _suspendParsing = _loop = false;
- _elapsedEvents = 0;
- _tempoDiff = 0;
-
- resetTempo();
-
- if (_tempoControlMode == 1) {
- //if (///)
- // return;
- setTempoIntern(_defaultTempo);
- } else {
- setTempoIntern(_defaultTempo);
- }
-
- resetControl();
-}
-
-void TownsEuphonyDriver::loadInstrument(int chanType, int id, const uint8 *data) {
- _intf->callback(5, chanType, id, data);
-}
-
-void TownsEuphonyDriver::loadWaveTable(const uint8 *data) {
- _intf->callback(34, data);
-}
-
-void TownsEuphonyDriver::unloadWaveTable(int id) {
- _intf->callback(35, id);
-}
-
-void TownsEuphonyDriver::reserveSoundEffectChannels(int num) {
- _intf->callback(33, num);
- uint32 volMask = 0;
-
- if (num > 8)
- return;
-
- for (uint32 v = 1 << 13; num; num--) {
- volMask |= v;
- v >>= 1;
- }
-
- _intf->setSoundEffectChanMask(volMask);
-}
-
-int TownsEuphonyDriver::setMusicTempo(int tempo) {
- if (tempo > 250)
- return 3;
- _defaultTempo = tempo;
- _trackTempo = tempo;
- setTempoIntern(tempo);
- return 0;
-}
-
-int TownsEuphonyDriver::startMusicTrack(const uint8 *data, int trackSize, int startTick) {
- if (_playing)
- return 2;
-
- _musicPos = _musicStart = data;
- _defaultBaseTickLen = _baseTickLen = startTick;
- _musicTrackSize = trackSize;
- _timeStampBase = _timeStampDest = 0;
- _tickCounter = 0;
- _playing = true;
-
- return 0;
-}
-
-void TownsEuphonyDriver::setMusicLoop(bool loop) {
- _loop = loop;
-}
-
-void TownsEuphonyDriver::stopParser() {
- if (_playing) {
- _playing = false;
- _pulseCount = 0;
- _endOfTrack = false;
- flushEventBuffer();
- resetControl();
- }
-}
-
-void TownsEuphonyDriver::continueParsing() {
- _suspendParsing = false;
-}
-
-void TownsEuphonyDriver::playSoundEffect(int chan, int note, int velo, const uint8 *data) {
- _intf->callback(37, chan, note, velo, data);
-}
-
-void TownsEuphonyDriver::stopSoundEffect(int chan) {
- _intf->callback(39, chan);
-}
-
-bool TownsEuphonyDriver::soundEffectIsPlaying(int chan) {
- return _intf->callback(40, chan) ? true : false;
-}
-
-void TownsEuphonyDriver::chanPanPos(int chan, int mode) {
- _intf->callback(3, chan, mode);
-}
-
-void TownsEuphonyDriver::chanPitch(int chan, int pitch) {
- _intf->callback(7, chan, pitch);
-}
-
-void TownsEuphonyDriver::chanVolume(int chan, int vol) {
- _intf->callback(8, chan, vol);
-}
-
-void TownsEuphonyDriver::setOutputVolume(int mode, int volLeft, int volRight) {
- _intf->callback(67, mode, volLeft, volRight);
-}
-
-int TownsEuphonyDriver::chanEnable(int tableEntry, int val) {
- if (tableEntry > 31)
- return 3;
- _tEnable[tableEntry] = val;
- return 0;
-}
-
-int TownsEuphonyDriver::chanMode(int tableEntry, int val) {
- if (tableEntry > 31)
- return 3;
- _tMode[tableEntry] = val;
- return 0;
-}
-
-int TownsEuphonyDriver::chanOrdr(int tableEntry, int val) {
- if (tableEntry > 31)
- return 3;
- if (val < 16)
- _tOrdr[tableEntry] = val;
- return 0;
-}
-
-int TownsEuphonyDriver::chanVolumeShift(int tableEntry, int val) {
- if (tableEntry > 31)
- return 3;
- if (val <= 40)
- _tLevel[tableEntry] = (int8)(val & 0xff);
- return 0;
-}
-
-int TownsEuphonyDriver::chanNoteShift(int tableEntry, int val) {
- if (tableEntry > 31)
- return 3;
- if (val <= 40)
- _tTranspose[tableEntry] = (int8)(val & 0xff);
- return 0;
-}
-
-int TownsEuphonyDriver::assignChannel(int chan, int tableEntry) {
- if (tableEntry > 15 || chan > 127 || chan < 0)
- return 3;
-
- ActiveChannel *a = &_assignedChannels[chan];
- if (a->chan == tableEntry)
- return 0;
-
- if (a->chan != -1) {
- int8 *b = &_activeChannels[a->chan];
- while (*b != chan) {
- b = &_assignedChannels[*b].next;
- if (*b == -1 && *b != chan)
- return 3;
- }
-
- *b = a->next;
-
- if (a->note)
- _intf->callback(2, chan);
-
- a->chan = a->next = -1;
- a->note = 0;
- }
-
- a->next = _activeChannels[tableEntry];
- _activeChannels[tableEntry] = chan;
- a->chan = tableEntry;
- a->note = a->sub = 0;
-
- return 0;
-}
-
-void TownsEuphonyDriver::timerCallback(int timerId) {
- switch (timerId) {
- case 0:
- updatePulseCount();
- while (_pulseCount > 0) {
- --_pulseCount;
- updateTimeStampBase();
- if (!_playing)
- continue;
- updateEventBuffer();
- updateParser();
- updateCheckEot();
- }
- break;
- default:
- break;
- }
-}
-
-void TownsEuphonyDriver::setMusicVolume(int volume) {
- _intf->setMusicVolume(volume);
-}
-
-void TownsEuphonyDriver::setSoundEffectVolume(int volume) {
- _intf->setSoundEffectVolume(volume);
-}
-
-void TownsEuphonyDriver::resetTables() {
- memset(_tEnable, 0xff, 32);
- memset(_tMode, 0xff, 16);
- memset(_tMode + 16, 0, 16);
- for (int i = 0; i < 32; i++)
- _tOrdr[i] = i & 0x0f;
- memset(_tLevel, 0, 32);
- memset(_tTranspose, 0, 32);
-}
-
-void TownsEuphonyDriver::resetTempo() {
- _defaultBaseTickLen = _baseTickLen = 0x33;
- _pulseCount = 0;
- _extraTimingControlRemainder = 0;
- _extraTimingControl = 16;
- _tempoModifier = 0;
- _timeStampDest = 0;
- _deltaTicks = 0;
- _tickCounter = 0;
- _defaultTempo = 90;
- _trackTempo = 90;
-}
-
-void TownsEuphonyDriver::setTempoIntern(int tempo) {
- tempo = CLIP(tempo + _tempoModifier, 0, 500);
- if (_tempoControlMode == 0) {
- _timerSetting = 34750 / (tempo + 30);
- _extraTimingControl = 16;
-
- while (_timerSetting < 126) {
- _timerSetting <<= 1;
- _extraTimingControl <<= 1;
- }
-
- while (_timerSetting > 383) {
- _timerSetting >>= 1;
- _extraTimingControl >>= 1;
- }
-
- setTimerA(true, -(_timerSetting - 2));
-
- } else if (_tempoControlMode == 1) {
- _timerSetting = 312500 / (tempo + 30);
- _extraTimingControl = 16;
- while (_timerSetting < 1105) {
- _timerSetting <<= 1;
- _extraTimingControl <<= 1;
- }
-
- } else if (_tempoControlMode == 2) {
- _timerSetting = 625000 / (tempo + 30);
- _extraTimingControlRemainder = 0;
- }
-}
-
-void TownsEuphonyDriver::setTimerA(bool enable, int tempo) {
- _intf->callback(21, enable ? 255 : 0, tempo);
-}
-
-void TownsEuphonyDriver::setTimerB(bool enable, int tempo) {
- _intf->callback(22, enable ? 255 : 0, tempo);
-}
-
-void TownsEuphonyDriver::updatePulseCount() {
- int tc = _extraTimingControl + _extraTimingControlRemainder;
- _extraTimingControlRemainder = tc & 0x0f;
- tc >>= 4;
- _tempoDiff -= tc;
-
- while (_tempoDiff < 0) {
- _elapsedEvents++;
- _tempoDiff += 4;
- }
-
- if (_playing && !_suspendParsing)
- _pulseCount += tc;
-}
-
-void TownsEuphonyDriver::updateTimeStampBase() {
- static const uint16 table[] = { 0x180, 0xC0, 0x80, 0x60, 0x40, 0x30, 0x20, 0x18 };
- if ((uint32)(table[_baseTickLen >> 4] * ((_baseTickLen & 0x0f) + 1)) > ++_tickCounter)
- return;
- ++_timeStampDest;
- _tickCounter = 0;
- _deltaTicks = 0;
-}
-
-void TownsEuphonyDriver::updateParser() {
- for (bool loop = true; loop;) {
- uint8 cmd = _musicPos[0];
-
- if (cmd == 0xff || cmd == 0xf7) {
- jumpNextLoop();
-
- } else if (cmd < 0x90) {
- _endOfTrack = true;
- flushEventBuffer();
- loop = false;
-
- } else if (_timeStampBase > _timeStampDest) {
- loop = false;
-
- } else {
- if (_timeStampBase == _timeStampDest) {
- uint16 timeStamp = READ_LE_UINT16(&_musicPos[2]);
- uint8 l = (timeStamp & 0xff) + (timeStamp & 0xff);
- timeStamp = ((timeStamp & 0xff00) | l) >> 1;
- if (timeStamp > _tickCounter)
- loop = false;
- }
-
- if (loop) {
- if (parseNext())
- loop = false;
- }
- }
- }
-}
-
-void TownsEuphonyDriver::updateCheckEot() {
- if (!_endOfTrack || _bufferedEventsCount)
- return;
- stopParser();
-}
-
-bool TownsEuphonyDriver::parseNext() {
-#define OPC(x) &TownsEuphonyDriver::evt##x
- static const EuphonyOpcode opcodes[] = {
- OPC(NotImpl),
- OPC(SetupNote),
- OPC(PolyphonicAftertouch),
- OPC(ControlPitch),
- OPC(InstrumentChanAftertouch),
- OPC(InstrumentChanAftertouch),
- OPC(ControlPitch)
- };
-#undef OPC
-
- uint cmd = _musicPos[0];
- if (cmd != 0xfe && cmd != 0xfd) {
- if (cmd >= 0xf0) {
- cmd &= 0x0f;
- if (cmd == 0)
- evtLoadInstrument();
- else if (cmd == 2)
- evtAdvanceTimestampOffset();
- else if (cmd == 8)
- evtTempo();
- else if (cmd == 12)
- evtModeOrdrChange();
- jumpNextLoop();
- return false;
-
- } else if (!(this->*opcodes[(cmd - 0x80) >> 4])()) {
- jumpNextLoop();
- return false;
- }
- }
-
- if (cmd == 0xfd) {
- _suspendParsing = true;
- return true;
- }
-
- if (!_loop) {
- _endOfTrack = true;
- return true;
- }
-
- _endOfTrack = false;
- _musicPos = _musicStart;
- _timeStampBase = _timeStampDest = _tickCounter = 0;
- _baseTickLen = _defaultBaseTickLen;
-
- return false;
-}
-
-void TownsEuphonyDriver::jumpNextLoop() {
- _musicPos += 6;
- if (_musicPos >= _musicStart + _musicTrackSize)
- _musicPos = _musicStart;
-}
-
-void TownsEuphonyDriver::updateEventBuffer() {
- DlEvent *e = _eventBuffer;
- for (int i = _bufferedEventsCount; i; e++) {
- if (e->evt == 0)
- continue;
- if (--e->len) {
- --i;
- continue;
- }
- processBufferNote(e->mode, e->evt, e->note, e->velo);
- e->evt = 0;
- --i;
- --_bufferedEventsCount;
- }
-}
-
-void TownsEuphonyDriver::flushEventBuffer() {
- DlEvent *e = _eventBuffer;
- for (int i = _bufferedEventsCount; i; e++) {
- if (e->evt == 0)
- continue;
- processBufferNote(e->mode, e->evt, e->note, e->velo);
- e->evt = 0;
- --i;
- --_bufferedEventsCount;
- }
-}
-
-void TownsEuphonyDriver::processBufferNote(int mode, int evt, int note, int velo) {
- if (!velo)
- evt &= 0x8f;
- sendEvent(mode, evt);
- sendEvent(mode, note);
- sendEvent(mode, velo);
-}
-
-void TownsEuphonyDriver::resetControl() {
- for (int i = 0; i < 32; i++) {
- if (_tOrdr[i] > 15) {
- for (int ii = 0; ii < 16; ii++)
- resetControlIntern(_tMode[i], ii);
- } else {
- resetControlIntern(_tMode[i], _tOrdr[i]);
- }
- }
-}
-
-void TownsEuphonyDriver::resetControlIntern(int mode, int chan) {
- sendEvent(mode, 0xb0 | chan);
- sendEvent(mode, 0x40);
- sendEvent(mode, 0);
- sendEvent(mode, 0xb0 | chan);
- sendEvent(mode, 0x7b);
- sendEvent(mode, 0);
- sendEvent(mode, 0xb0 | chan);
- sendEvent(mode, 0x79);
- sendEvent(mode, 0x40);
-}
-
-uint8 TownsEuphonyDriver::appendEvent(uint8 evt, uint8 chan) {
- if (evt >= 0x80 && evt < 0xf0 && _tOrdr[chan] < 16)
- return (evt & 0xf0) | _tOrdr[chan];
- return evt;
-}
-
-void TownsEuphonyDriver::sendEvent(uint8 mode, uint8 command) {
- if (mode == 0) {
- // warning("TownsEuphonyDriver: Mode 0 not implemented");
-
- } else if (mode == 0x10) {
- warning("TownsEuphonyDriver: Mode 0x10 not implemented");
-
- } else if (mode == 0xff) {
- if (command >= 0xf0) {
- _paraCount = 1;
- _command = 0;
- } else if (command >= 0x80) {
- _paraCount = 1;
- _command = command;
- } else if (_command >= 0x80) {
- switch ((_command - 0x80) >> 4) {
- case 0:
- if (_paraCount < 2) {
- _paraCount++;
- _para[0] = command;
- } else {
- _paraCount = 1;
- _para[1] = command;
- sendNoteOff();
- }
- break;
-
- case 1:
- if (_paraCount < 2) {
- _paraCount++;
- _para[0] = command;
- } else {
- _paraCount = 1;
- _para[1] = command;
- if (command)
- sendNoteOn();
- else
- sendNoteOff();
- }
- break;
-
- case 2:
- if (_paraCount < 2) {
- _paraCount++;
- _para[0] = command;
- } else {
- _paraCount = 1;
- }
- break;
-
- case 3:
- if (_paraCount < 2) {
- _paraCount++;
- _para[0] = command;
- } else {
- _paraCount = 1;
- _para[1] = command;
-
- if (_para[0] == 7)
- sendChanVolume();
- else if (_para[0] == 10)
- sendPanPosition();
- else if (_para[0] == 64)
- sendAllNotesOff();
- }
- break;
-
- case 4:
- _paraCount = 1;
- _para[0] = command;
- sendSetInstrument();
- break;
-
- case 5:
- _paraCount = 1;
- _para[0] = command;
- break;
-
- case 6:
- if (_paraCount < 2) {
- _paraCount++;
- _para[0] = command;
- } else {
- _paraCount = 1;
- _para[1] = command;
- sendPitch();
- }
- break;
- }
- }
- }
-}
-
-bool TownsEuphonyDriver::evtSetupNote() {
- if (_musicPos[1] > 31)
- return false;
- if (!_tEnable[_musicPos[1]]) {
- jumpNextLoop();
- return (_musicPos[0] == 0xfe || _musicPos[0] == 0xfd) ? true : false;
- }
- uint8 evt = appendEvent(_musicPos[0], _musicPos[1]);
- uint8 mode = _tMode[_musicPos[1]];
- uint8 note = _musicPos[4];
- uint8 velo = _musicPos[5];
-
- sendEvent(mode, evt);
- sendEvent(mode, applyNoteShift(note));
- sendEvent(mode, applyVolumeShift(velo));
-
- jumpNextLoop();
- if (_musicPos[0] == 0xfe || _musicPos[0] == 0xfd)
- return true;
-
- velo = _musicPos[5];
- uint16 len = ((((_musicPos[1] << 4) | (_musicPos[2] << 8)) >> 4) & 0xff) | ((((_musicPos[3] << 4) | (_musicPos[4] << 8)) >> 4) << 8);
-
- int i = 0;
- for (; i < 64; i++) {
- if (_eventBuffer[i].evt == 0)
- break;
- }
-
- if (i == 64) {
- processBufferNote(mode, evt, note, velo);
- } else {
- _eventBuffer[i].evt = evt;
- _eventBuffer[i].mode = mode;
- _eventBuffer[i].note = note;
- _eventBuffer[i].velo = velo;
- _eventBuffer[i].len = len ? len : 1;
- _bufferedEventsCount++;
- }
-
- return false;
-}
-
-bool TownsEuphonyDriver::evtPolyphonicAftertouch() {
- if (_musicPos[1] > 31)
- return false;
- if (!_tEnable[_musicPos[1]])
- return false;
-
- uint8 evt = appendEvent(_musicPos[0], _musicPos[1]);
- uint8 mode = _tMode[_musicPos[1]];
-
- sendEvent(mode, evt);
- sendEvent(mode, applyNoteShift(_musicPos[4]));
- sendEvent(mode, _musicPos[5]);
-
- return false;
-}
-
-bool TownsEuphonyDriver::evtControlPitch() {
- if (_musicPos[1] > 31)
- return false;
- if (!_tEnable[_musicPos[1]])
- return false;
-
- uint8 evt = appendEvent(_musicPos[0], _musicPos[1]);
- uint8 mode = _tMode[_musicPos[1]];
-
- sendEvent(mode, evt);
- sendEvent(mode, _musicPos[4]);
- sendEvent(mode, _musicPos[5]);
-
- return false;
-}
-
-bool TownsEuphonyDriver::evtInstrumentChanAftertouch() {
- if (_musicPos[1] > 31)
- return false;
- if (!_tEnable[_musicPos[1]])
- return false;
-
- uint8 evt = appendEvent(_musicPos[0], _musicPos[1]);
- uint8 mode = _tMode[_musicPos[1]];
-
- sendEvent(mode, evt);
- sendEvent(mode, _musicPos[4]);
-
- return false;
-}
-
-bool TownsEuphonyDriver::evtLoadInstrument() {
- return false;
-}
-
-bool TownsEuphonyDriver::evtAdvanceTimestampOffset() {
- ++_timeStampBase;
- _baseTickLen = _musicPos[1];
- return false;
-}
-
-bool TownsEuphonyDriver::evtTempo() {
- uint8 l = _musicPos[4] << 1;
- _trackTempo = (l | (_musicPos[5] << 8)) >> 1;
- setTempoIntern(_trackTempo);
- return false;
-}
-
-bool TownsEuphonyDriver::evtModeOrdrChange() {
- if (_musicPos[1] > 31)
- return false;
- if (!_tEnable[_musicPos[1]])
- return false;
-
- if (_musicPos[4] == 1)
- _tMode[_musicPos[1]] = _musicPos[5];
- else if (_musicPos[4] == 2)
- _tOrdr[_musicPos[1]] = _musicPos[5];
-
- return false;
-}
-
-uint8 TownsEuphonyDriver::applyNoteShift(uint8 in) {
- int out = _tTranspose[_musicPos[1]];
- if (!out)
- return in;
- out += (in & 0x7f);
-
- if (out > 127)
- out -= 12;
-
- if (out < 0)
- out += 12;
-
- return out & 0xff;
-}
-
-uint8 TownsEuphonyDriver::applyVolumeShift(uint8 in) {
- int out = _tLevel[_musicPos[1]];
- out += (in & 0x7f);
- out = CLIP(out, 1, 127);
-
- return out & 0xff;
-}
-
-void TownsEuphonyDriver::sendNoteOff() {
- int8 *chan = &_activeChannels[_command & 0x0f];
- if (*chan == -1)
- return;
-
- while (_assignedChannels[*chan].note != _para[0]) {
- chan = &_assignedChannels[*chan].next;
- if (*chan == -1)
- return;
- }
-
- if (_sustainChannels[_command & 0x0f]) {
- _assignedChannels[*chan].note |= 0x80;
- } else {
- _assignedChannels[*chan].note = 0;
- _intf->callback(2, *chan);
- }
-}
-
-void TownsEuphonyDriver::sendNoteOn() {
- if (!_para[0])
- return;
- int8 *chan = &_activeChannels[_command & 0x0f];
- if (*chan == -1)
- return;
-
- do {
- _assignedChannels[*chan].sub++;
- chan = &_assignedChannels[*chan].next;
- } while (*chan != -1);
-
- chan = &_activeChannels[_command & 0x0f];
-
- int d = 0;
- int c = 0;
- bool found = false;
-
- do {
- if (!_assignedChannels[*chan].note) {
- found = true;
- break;
- }
- if (d <= _assignedChannels[*chan].sub) {
- c = *chan;
- d = _assignedChannels[*chan].sub;
- }
- chan = &_assignedChannels[*chan].next;
- } while (*chan != -1);
-
- if (found)
- c = *chan;
- else
- _intf->callback(2, c);
-
- _assignedChannels[c].note = _para[0];
- _assignedChannels[c].sub = 0;
- _intf->callback(1, c, _para[0], _para[1]);
-}
-
-void TownsEuphonyDriver::sendChanVolume() {
- int8 *chan = &_activeChannels[_command & 0x0f];
- while (*chan != -1) {
- _intf->callback(8, *chan, _para[1] & 0x7f);
- chan = &_assignedChannels[*chan].next;
- }
-}
-
-void TownsEuphonyDriver::sendPanPosition() {
- int8 *chan = &_activeChannels[_command & 0x0f];
- while (*chan != -1) {
- _intf->callback(3, *chan, _para[1] & 0x7f);
- chan = &_assignedChannels[*chan].next;
- }
-}
-
-void TownsEuphonyDriver::sendAllNotesOff() {
- if (_para[1] > 63) {
- _sustainChannels[_command & 0x0f] = -1;
- return;
- }
-
- _sustainChannels[_command & 0x0f] = 0;
- int8 *chan = &_activeChannels[_command & 0x0f];
- while (*chan != -1) {
- if (_assignedChannels[*chan].note & 0x80) {
- _assignedChannels[*chan].note = 0;
- _intf->callback(2, *chan);
- }
- chan = &_assignedChannels[*chan].next;
- }
-}
-
-void TownsEuphonyDriver::sendSetInstrument() {
- int8 *chan = &_activeChannels[_command & 0x0f];
- while (*chan != -1) {
- _intf->callback(4, *chan, _para[0]);
- _intf->callback(7, *chan, 0);
- chan = &_assignedChannels[*chan].next;
- }
-}
-
-void TownsEuphonyDriver::sendPitch() {
- int8 *chan = &_activeChannels[_command & 0x0f];
- while (*chan != -1) {
- _para[0] += _para[0];
- int16 pitch = (((READ_LE_UINT16(_para)) >> 1) & 0x3fff) - 0x2000;
- _intf->callback(7, *chan, pitch);
- chan = &_assignedChannels[*chan].next;
- }
-}
diff --git a/sound/softsynth/fmtowns_pc98/towns_euphony.h b/sound/softsynth/fmtowns_pc98/towns_euphony.h
deleted file mode 100644
index fa1f8ba496..0000000000
--- a/sound/softsynth/fmtowns_pc98/towns_euphony.h
+++ /dev/null
@@ -1,187 +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$
- *
- */
-
-#ifndef TOWNS_EUP_H
-#define TOWNS_EUP_H
-
-#include "sound/softsynth/fmtowns_pc98/towns_audio.h"
-
-class TownsEuphonyDriver : public TownsAudioInterfacePluginDriver {
-public:
- TownsEuphonyDriver(Audio::Mixer *mixer);
- virtual ~TownsEuphonyDriver();
-
- bool init();
- void reset();
-
- void loadInstrument(int chanType, int id, const uint8 *data);
- void loadWaveTable(const uint8 *data);
- void unloadWaveTable(int id);
- void reserveSoundEffectChannels(int num);
-
- int setMusicTempo(int tempo);
- int startMusicTrack(const uint8 *data, int trackSize, int startTick);
- void setMusicLoop(bool loop);
- void stopParser();
- bool parserIsPlaying() {return _playing; }
- void continueParsing();
-
- void playSoundEffect(int chan, int note, int velo, const uint8 *data);
- void stopSoundEffect(int chan);
- bool soundEffectIsPlaying(int chan);
-
- void chanPanPos(int chan, int mode);
- void chanPitch(int chan, int pitch);
- void chanVolume(int chan, int vol);
-
- void setOutputVolume(int chanType, int volLeft, int volRight);
-
- int chanEnable(int tableEntry, int val);
- int chanMode(int tableEntry, int val);
- int chanOrdr(int tableEntry, int val);
- int chanVolumeShift(int tableEntry, int val);
- int chanNoteShift(int tableEntry, int val);
-
- int assignChannel(int chan, int tableEntry);
-
- void timerCallback(int timerId);
-
- void setMusicVolume(int volume);
- void setSoundEffectVolume(int volume);
-
- TownsAudioInterface *intf() {
- return _intf;
- }
-
-private:
- void resetTables();
-
- void resetTempo();
- void setTempoIntern(int tempo);
- void setTimerA(bool enable, int tempo);
- void setTimerB(bool enable, int tempo);
-
- void updatePulseCount();
- void updateTimeStampBase();
- void updateParser();
- void updateCheckEot();
-
- bool parseNext();
- void jumpNextLoop();
-
- void updateEventBuffer();
- void flushEventBuffer();
- void processBufferNote(int mode, int evt, int note, int velo);
-
- void resetControl();
- void resetControlIntern(int mode, int chan);
- uint8 appendEvent(uint8 evt, uint8 chan);
-
- void sendEvent(uint8 mode, uint8 command);
-
- typedef bool(TownsEuphonyDriver::*EuphonyOpcode)();
- bool evtSetupNote();
- bool evtPolyphonicAftertouch();
- bool evtControlPitch();
- bool evtInstrumentChanAftertouch();
- bool evtLoadInstrument();
- bool evtAdvanceTimestampOffset();
- bool evtTempo();
- bool evtModeOrdrChange();
- bool evtNotImpl() {
- return false;
- }
-
- uint8 applyNoteShift(uint8 in);
- uint8 applyVolumeShift(uint8 in);
-
- void sendNoteOff();
- void sendNoteOn();
- void sendChanVolume();
- void sendPanPosition();
- void sendAllNotesOff();
- void sendSetInstrument();
- void sendPitch();
-
- int8 *_activeChannels;
- int8 *_sustainChannels;
-
- struct ActiveChannel {
- int8 chan;
- int8 next;
- uint8 note;
- uint8 sub;
- } *_assignedChannels;
-
- uint8 *_tEnable;
- uint8 *_tMode;
- uint8 *_tOrdr;
- int8 *_tLevel;
- int8 *_tTranspose;
-
- struct DlEvent {
- uint8 evt;
- uint8 mode;
- uint8 note;
- uint8 velo;
- uint16 len;
- } *_eventBuffer;
- int _bufferedEventsCount;
-
- uint8 _para[2];
- uint8 _paraCount;
- uint8 _command;
-
- uint8 _defaultBaseTickLen;
- uint8 _baseTickLen;
- uint32 _pulseCount;
- int _tempoControlMode;
- int _extraTimingControlRemainder;
- int _extraTimingControl;
- int _timerSetting;
- int8 _tempoDiff;
- int _tempoModifier;
- uint32 _timeStampDest;
- uint32 _timeStampBase;
- int8 _elapsedEvents;
- uint8 _deltaTicks;
- uint32 _tickCounter;
- uint8 _defaultTempo;
- int _trackTempo;
-
- bool _loop;
- bool _playing;
- bool _endOfTrack;
- bool _suspendParsing;
-
- const uint8 *_musicStart;
- const uint8 *_musicPos;
- uint32 _musicTrackSize;
-
- TownsAudioInterface *_intf;
-};
-
-#endif
-
diff --git a/sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
deleted file mode 100644
index 303f08e6b1..0000000000
--- a/sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
+++ /dev/null
@@ -1,1428 +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$
- *
- */
-
-#include "sound/softsynth/fmtowns_pc98/towns_pc98_driver.h"
-#include "common/endian.h"
-
-class TownsPC98_MusicChannel {
-public:
- TownsPC98_MusicChannel(TownsPC98_AudioDriver *driver, uint8 regOffs, uint8 flgs, uint8 num,
- uint8 key, uint8 prt, uint8 id);
- virtual ~TownsPC98_MusicChannel();
- virtual void init();
-
- typedef enum channelState {
- CHS_RECALCFREQ = 0x01,
- CHS_KEYOFF = 0x02,
- CHS_SSGOFF = 0x04,
- CHS_VBROFF = 0x08,
- CHS_ALLOFF = 0x0f,
- CHS_PROTECT = 0x40,
- CHS_EOT = 0x80
- } ChannelState;
-
- virtual void loadData(uint8 *data);
- virtual void processEvents();
- virtual void processFrequency();
- virtual bool processControlEvent(uint8 cmd);
-
- virtual void keyOn();
- void keyOff();
-
- void setOutputLevel();
- virtual void fadeStep();
- virtual void reset();
-
- const uint8 _idFlag;
-
-protected:
- void setupVibrato();
- bool processVibrato();
-
- bool control_dummy(uint8 para);
- bool control_f0_setPatch(uint8 para);
- bool control_f1_presetOutputLevel(uint8 para);
- bool control_f2_setKeyOffTime(uint8 para);
- bool control_f3_setFreqLSB(uint8 para);
- bool control_f4_setOutputLevel(uint8 para);
- bool control_f5_setTempo(uint8 para);
- bool control_f6_repeatSection(uint8 para);
- bool control_f7_setupVibrato(uint8 para);
- bool control_f8_toggleVibrato(uint8 para);
- bool control_fa_writeReg(uint8 para);
- virtual bool control_fb_incOutLevel(uint8 para);
- virtual bool control_fc_decOutLevel(uint8 para);
- bool control_fd_jump(uint8 para);
- virtual bool control_ff_endOfTrack(uint8 para);
-
- uint8 _ticksLeft;
- uint8 _algorithm;
- uint8 _instr;
- uint8 _totalLevel;
- uint8 _frqBlockMSB;
- int8 _frqLSB;
- uint8 _keyOffTime;
- bool _hold;
- uint8 *_dataPtr;
- uint8 _vbrInitDelayHi;
- uint8 _vbrInitDelayLo;
- int16 _vbrModInitVal;
- uint8 _vbrDuration;
- uint8 _vbrCurDelay;
- int16 _vbrModCurVal;
- uint8 _vbrDurLeft;
- uint16 _frequency;
- uint8 _block;
- uint8 _regOffset;
- uint8 _flags;
- uint8 _ssgTl;
- uint8 _ssgStep;
- uint8 _ssgTicksLeft;
- uint8 _ssgTargetLvl;
- uint8 _ssgStartLvl;
-
- const uint8 _chanNum;
- const uint8 _keyNum;
- const uint8 _part;
-
- TownsPC98_AudioDriver *_drv;
-
- typedef bool (TownsPC98_MusicChannel::*ControlEventFunc)(uint8 para);
- const ControlEventFunc *controlEvents;
-};
-
-class TownsPC98_MusicChannelSSG : public TownsPC98_MusicChannel {
-public:
- TownsPC98_MusicChannelSSG(TownsPC98_AudioDriver *driver, uint8 regOffs,
- uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
- virtual ~TownsPC98_MusicChannelSSG() {}
- void init();
-
- virtual void loadData(uint8 *data);
- void processEvents();
- void processFrequency();
- bool processControlEvent(uint8 cmd);
-
- void keyOn();
- void nextShape();
-
- void protect();
- void restore();
- virtual void reset();
-
- void fadeStep();
-
-protected:
- void setOutputLevel(uint8 lvl);
-
- bool control_f0_setPatch(uint8 para);
- bool control_f1_setTotalLevel(uint8 para);
- bool control_f4_setAlgorithm(uint8 para);
- bool control_f9_loadCustomPatch(uint8 para);
- bool control_fb_incOutLevel(uint8 para);
- bool control_fc_decOutLevel(uint8 para);
- bool control_ff_endOfTrack(uint8 para);
-
- typedef bool (TownsPC98_MusicChannelSSG::*ControlEventFunc)(uint8 para);
- const ControlEventFunc *controlEvents;
-};
-
-class TownsPC98_SfxChannel : public TownsPC98_MusicChannelSSG {
-public:
- TownsPC98_SfxChannel(TownsPC98_AudioDriver *driver, uint8 regOffs,
- uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
- TownsPC98_MusicChannelSSG(driver, regOffs, flgs, num, key, prt, id) {}
- ~TownsPC98_SfxChannel() {}
-
- void loadData(uint8 *data);
- void reset();
-};
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
-class TownsPC98_MusicChannelPCM : public TownsPC98_MusicChannel {
-public:
- TownsPC98_MusicChannelPCM(TownsPC98_AudioDriver *driver, uint8 regOffs,
- uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
- ~TownsPC98_MusicChannelPCM() {}
- void init();
-
- void loadData(uint8 *data);
- void processEvents();
- bool processControlEvent(uint8 cmd);
-
-private:
- bool control_f1_prcStart(uint8 para);
- bool control_ff_endOfTrack(uint8 para);
-
- typedef bool (TownsPC98_MusicChannelPCM::*ControlEventFunc)(uint8 para);
- const ControlEventFunc *controlEvents;
-};
-#endif
-
-TownsPC98_MusicChannel::TownsPC98_MusicChannel(TownsPC98_AudioDriver *driver, uint8 regOffs, uint8 flgs, uint8 num,
- uint8 key, uint8 prt, uint8 id) : _drv(driver), _regOffset(regOffs), _flags(flgs), _chanNum(num), _keyNum(key),
- _part(prt), _idFlag(id), controlEvents(0) {
-
- _ticksLeft = _algorithm = _instr = _totalLevel = _frqBlockMSB = _keyOffTime = 0;
- _ssgStartLvl = _ssgTl = _ssgStep = _ssgTicksLeft = _ssgTargetLvl = _block = 0;
- _vbrInitDelayHi = _vbrInitDelayLo = _vbrDuration = _vbrCurDelay = _vbrDurLeft = 0;
- _frqLSB = 0;
- _hold = false;
- _dataPtr = 0;
- _vbrModInitVal = _vbrModCurVal = 0;
- _frequency = 0;
-}
-
-TownsPC98_MusicChannel::~TownsPC98_MusicChannel() {
-}
-
-void TownsPC98_MusicChannel::init() {
-#define Control(x) &TownsPC98_MusicChannel::control_##x
- static const ControlEventFunc ctrlEvents[] = {
- Control(f0_setPatch),
- Control(f1_presetOutputLevel),
- Control(f2_setKeyOffTime),
- Control(f3_setFreqLSB),
- Control(f4_setOutputLevel),
- Control(f5_setTempo),
- Control(f6_repeatSection),
- Control(f7_setupVibrato),
- Control(f8_toggleVibrato),
- Control(dummy),
- Control(fa_writeReg),
- Control(fb_incOutLevel),
- Control(fc_decOutLevel),
- Control(fd_jump),
- Control(dummy),
- Control(ff_endOfTrack)
- };
-#undef Control
-
- controlEvents = ctrlEvents;
-}
-
-void TownsPC98_MusicChannel::keyOff() {
- // all operators off
- uint8 value = _keyNum & 0x0f;
- if (_part)
- value |= 4;
- uint8 regAddress = 0x28;
- _drv->writeReg(0, regAddress, value);
- _flags |= CHS_KEYOFF;
-}
-
-void TownsPC98_MusicChannel::keyOn() {
- // all operators on
- uint8 value = _keyNum | 0xf0;
- if (_part)
- value |= 4;
- uint8 regAddress = 0x28;
- _drv->writeReg(0, regAddress, value);
-}
-
-void TownsPC98_MusicChannel::loadData(uint8 *data) {
- _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
- _ticksLeft = 1;
- _dataPtr = data;
- _totalLevel = 0x7F;
-
- uint8 *tmp = _dataPtr;
- for (bool loop = true; loop;) {
- uint8 cmd = *tmp++;
- if (cmd < 0xf0) {
- tmp++;
- } else if (cmd == 0xff) {
- if (READ_LE_UINT16(tmp)) {
- _drv->_looping |= _idFlag;
- tmp += _drv->_opnFxCmdLen[cmd - 240];
- } else
- loop = false;
- } else if (cmd == 0xf6) {
- // reset repeat section countdown
- tmp[0] = tmp[1];
- tmp += 4;
- } else {
- tmp += _drv->_opnFxCmdLen[cmd - 240];
- }
- }
-}
-
-void TownsPC98_MusicChannel::processEvents() {
- if (_flags & CHS_EOT)
- return;
-
- if (!_hold && _ticksLeft == _keyOffTime)
- keyOff();
-
- if (--_ticksLeft)
- return;
-
- if (!_hold)
- keyOff();
-
- uint8 cmd = 0;
- bool loop = true;
-
- while (loop) {
- cmd = *_dataPtr++;
- if (cmd < 0xf0)
- loop = false;
- else if (!processControlEvent(cmd))
- return;
- }
-
- uint8 para = *_dataPtr++;
-
- if (cmd == 0x80) {
- keyOff();
- _hold = false;
- } else {
- keyOn();
-
- if (_hold == false || cmd != _frqBlockMSB)
- _flags |= CHS_RECALCFREQ;
-
- _hold = (para & 0x80) ? true : false;
- _frqBlockMSB = cmd;
- }
-
- _ticksLeft = para & 0x7f;
-}
-
-void TownsPC98_MusicChannel::processFrequency() {
- if (_flags & CHS_RECALCFREQ) {
-
- _frequency = (READ_LE_UINT16(&_drv->_opnFreqTable[(_frqBlockMSB & 0x0f) << 1]) + _frqLSB) | (((_frqBlockMSB & 0x70) >> 1) << 8);
-
- _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
- _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
-
- setupVibrato();
- }
-
- if (!(_flags & CHS_VBROFF)) {
- if (!processVibrato())
- return;
-
- _drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
- _drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
- }
-}
-
-void TownsPC98_MusicChannel::setupVibrato() {
- _vbrCurDelay = _vbrInitDelayHi;
- if (_flags & CHS_KEYOFF) {
- _vbrModCurVal = _vbrModInitVal;
- _vbrCurDelay += _vbrInitDelayLo;
- }
- _vbrDurLeft = (_vbrDuration >> 1);
- _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ);
-}
-
-bool TownsPC98_MusicChannel::processVibrato() {
- if (--_vbrCurDelay)
- return false;
-
- _vbrCurDelay = _vbrInitDelayHi;
- _frequency += _vbrModCurVal;
-
- if (!--_vbrDurLeft) {
- _vbrDurLeft = _vbrDuration;
- _vbrModCurVal = -_vbrModCurVal;
- }
-
- return true;
-}
-
-bool TownsPC98_MusicChannel::processControlEvent(uint8 cmd) {
- uint8 para = *_dataPtr++;
- return (this->*controlEvents[cmd & 0x0f])(para);
-}
-
-void TownsPC98_MusicChannel::setOutputLevel() {
- uint8 outopr = _drv->_opnCarrier[_algorithm];
- uint8 reg = 0x40 + _regOffset;
-
- for (int i = 0; i < 4; i++) {
- if (outopr & 1)
- _drv->writeReg(_part, reg, _totalLevel);
- outopr >>= 1;
- reg += 4;
- }
-}
-
-void TownsPC98_MusicChannel::fadeStep() {
- _totalLevel += 3;
- if (_totalLevel > 0x7f)
- _totalLevel = 0x7f;
- setOutputLevel();
-}
-
-void TownsPC98_MusicChannel::reset() {
- _hold = false;
- _keyOffTime = 0;
- _ticksLeft = 1;
-
- _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
-
- _totalLevel = 0;
- _algorithm = 0;
- _flags = CHS_EOT;
- _algorithm = 0;
-
- _block = 0;
- _frequency = 0;
- _frqBlockMSB = 0;
- _frqLSB = 0;
-
- _ssgTl = 0;
- _ssgStartLvl = 0;
- _ssgTargetLvl = 0;
- _ssgStep = 0;
- _ssgTicksLeft = 0;
-
- _vbrInitDelayHi = 0;
- _vbrInitDelayLo = 0;
- _vbrModInitVal = 0;
- _vbrDuration = 0;
- _vbrCurDelay = 0;
- _vbrModCurVal = 0;
- _vbrDurLeft = 0;
-}
-
-bool TownsPC98_MusicChannel::control_f0_setPatch(uint8 para) {
- _instr = para;
- uint8 reg = _regOffset + 0x80;
-
- for (int i = 0; i < 4; i++) {
- // set release rate for each operator
- _drv->writeReg(_part, reg, 0x0f);
- reg += 4;
- }
-
- const uint8 *tptr = _drv->_patches + ((uint32)_instr << 5);
- reg = _regOffset + 0x30;
-
- // write registers 0x30 to 0x8f
- for (int i = 0; i < 6; i++) {
- _drv->writeReg(_part, reg, tptr[0]);
- reg += 4;
- _drv->writeReg(_part, reg, tptr[2]);
- reg += 4;
- _drv->writeReg(_part, reg, tptr[1]);
- reg += 4;
- _drv->writeReg(_part, reg, tptr[3]);
- reg += 4;
- tptr += 4;
- }
-
- reg = _regOffset + 0xB0;
- _algorithm = tptr[0] & 7;
- // set feedback and algorithm
- _drv->writeReg(_part, reg, tptr[0]);
-
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_f1_presetOutputLevel(uint8 para) {
- if (_drv->_fading)
- return true;
-
- _totalLevel = _drv->_opnLvlPresets[para];
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_f2_setKeyOffTime(uint8 para) {
- _keyOffTime = para;
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_f3_setFreqLSB(uint8 para) {
- _frqLSB = (int8) para;
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_f4_setOutputLevel(uint8 para) {
- if (_drv->_fading)
- return true;
-
- _totalLevel = para;
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_f5_setTempo(uint8 para) {
- _drv->setMusicTempo(para);
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_f6_repeatSection(uint8 para) {
- _dataPtr--;
- _dataPtr[0]--;
-
- if (*_dataPtr) {
- // repeat section until counter has reached zero
- _dataPtr = _drv->_trackPtr + READ_LE_UINT16(_dataPtr + 2);
- } else {
- // reset counter, advance to next section
- _dataPtr[0] = _dataPtr[1];
- _dataPtr += 4;
- }
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_f7_setupVibrato(uint8 para) {
- _vbrInitDelayHi = _dataPtr[0];
- _vbrInitDelayLo = para;
- _vbrModInitVal = (int16) READ_LE_UINT16(_dataPtr + 1);
- _vbrDuration = _dataPtr[3];
- _dataPtr += 4;
- _flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF | CHS_RECALCFREQ;
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_f8_toggleVibrato(uint8 para) {
- if (para == 0x10) {
- if (*_dataPtr++) {
- _flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF;
- } else {
- _flags |= CHS_VBROFF;
- }
- } else {
- /* NOT IMPLEMENTED
- uint8 skipChannels = para / 36;
- uint8 entry = para % 36;
- TownsPC98_AudioDriver::TownsPC98_MusicChannel *t = &chan[skipChannels];
-
- t->unnamedEntries[entry] = *_dataPtr++;*/
- }
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_fa_writeReg(uint8 para) {
- _drv->writeReg(_part, para, *_dataPtr++);
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_fb_incOutLevel(uint8 para) {
- _dataPtr--;
- if (_drv->_fading)
- return true;
-
- uint8 val = (_totalLevel + 3);
- if (val > 0x7f)
- val = 0x7f;
-
- _totalLevel = val;
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_fc_decOutLevel(uint8 para) {
- _dataPtr--;
- if (_drv->_fading)
- return true;
-
- int8 val = (int8)(_totalLevel - 3);
- if (val < 0)
- val = 0;
-
- _totalLevel = (uint8) val;
- setOutputLevel();
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_fd_jump(uint8 para) {
- uint8 *tmp = _drv->_trackPtr + READ_LE_UINT16(_dataPtr - 1);
- _dataPtr = (tmp[1] == 1) ? tmp : (_dataPtr + 1);
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_dummy(uint8 para) {
- _dataPtr--;
- return true;
-}
-
-bool TownsPC98_MusicChannel::control_ff_endOfTrack(uint8 para) {
- uint16 val = READ_LE_UINT16(--_dataPtr);
- if (val) {
- // loop
- _dataPtr = _drv->_trackPtr + val;
- return true;
- } else {
- // quit parsing for active channel
- --_dataPtr;
- _flags |= CHS_EOT;
- _drv->_finishedChannelsFlag |= _idFlag;
- keyOff();
- return false;
- }
-}
-
-TownsPC98_MusicChannelSSG::TownsPC98_MusicChannelSSG(TownsPC98_AudioDriver *driver, uint8 regOffs,
- uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
- TownsPC98_MusicChannel(driver, regOffs, flgs, num, key, prt, id), controlEvents(0) {
-}
-
-void TownsPC98_MusicChannelSSG::init() {
- _algorithm = 0x80;
-
-#define Control(x) &TownsPC98_MusicChannelSSG::control_##x
- static const ControlEventFunc ctrlEventsSSG[] = {
- Control(f0_setPatch),
- Control(f1_setTotalLevel),
- Control(f2_setKeyOffTime),
- Control(f3_setFreqLSB),
- Control(f4_setAlgorithm),
- Control(f5_setTempo),
- Control(f6_repeatSection),
- Control(f7_setupVibrato),
- Control(f8_toggleVibrato),
- Control(f9_loadCustomPatch),
- Control(fa_writeReg),
- Control(fb_incOutLevel),
- Control(fc_decOutLevel),
- Control(fd_jump),
- Control(dummy),
- Control(ff_endOfTrack)
- };
-#undef Control
-
- controlEvents = ctrlEventsSSG;
-}
-
-void TownsPC98_MusicChannelSSG::processEvents() {
- if (_flags & CHS_EOT)
- return;
-
- _drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false);
-
- if (!_hold && _ticksLeft == _keyOffTime)
- nextShape();
-
- if (!--_ticksLeft) {
-
- uint8 cmd = 0;
- bool loop = true;
-
- while (loop) {
- cmd = *_dataPtr++;
- if (cmd < 0xf0)
- loop = false;
- else if (!processControlEvent(cmd))
- return;
- }
-
- uint8 para = *_dataPtr++;
-
- if (cmd == 0x80) {
- nextShape();
- _hold = false;
- } else {
- if (!_hold) {
- _instr &= 0xf0;
- _ssgStep = _drv->_ssgPatches[_instr];
- _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
- _ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
- _ssgStartLvl = _drv->_ssgPatches[_instr + 3];
- _flags = (_flags & ~CHS_SSGOFF) | CHS_KEYOFF;
- }
-
- keyOn();
-
- if (_hold == false || cmd != _frqBlockMSB)
- _flags |= CHS_RECALCFREQ;
-
- _hold = (para & 0x80) ? true : false;
- _frqBlockMSB = cmd;
- }
-
- _ticksLeft = para & 0x7f;
- }
-
- if (!(_flags & CHS_SSGOFF)) {
- if (--_ssgTicksLeft) {
- if (!_drv->_fading)
- setOutputLevel(_ssgStartLvl);
- return;
- }
-
- _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
-
- if (_drv->_ssgPatches[_instr + 1] & 0x80) {
- uint8 t = _ssgStartLvl - _ssgStep;
-
- if (_ssgStep <= _ssgStartLvl && _ssgTargetLvl < t) {
- if (!_drv->_fading)
- setOutputLevel(t);
- return;
- }
- } else {
- int t = _ssgStartLvl + _ssgStep;
- uint8 p = (uint8)(t & 0xff);
-
- if (t < 256 && _ssgTargetLvl > p) {
- if (!_drv->_fading)
- setOutputLevel(p);
- return;
- }
- }
-
- setOutputLevel(_ssgTargetLvl);
- if (_ssgStartLvl && !(_instr & 8)) {
- _instr += 4;
- _ssgStep = _drv->_ssgPatches[_instr];
- _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
- _ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
- } else {
- _flags |= CHS_SSGOFF;
- setOutputLevel(0);
- }
- }
-}
-
-void TownsPC98_MusicChannelSSG::processFrequency() {
- if (_algorithm & 0x40)
- return;
-
- if (_flags & CHS_RECALCFREQ) {
- _block = _frqBlockMSB >> 4;
- _frequency = READ_LE_UINT16(&_drv->_opnFreqTableSSG[(_frqBlockMSB & 0x0f) << 1]) + _frqLSB;
-
- uint16 f = _frequency >> _block;
- _drv->writeReg(_part, _regOffset << 1, f & 0xff);
- _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
-
- setupVibrato();
- }
-
- if (!(_flags & (CHS_EOT | CHS_VBROFF | CHS_SSGOFF))) {
- if (!processVibrato())
- return;
-
- uint16 f = _frequency >> _block;
- _drv->writeReg(_part, _regOffset << 1, f & 0xff);
- _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
- }
-}
-
-bool TownsPC98_MusicChannelSSG::processControlEvent(uint8 cmd) {
- uint8 para = *_dataPtr++;
- return (this->*controlEvents[cmd & 0x0f])(para);
-}
-
-void TownsPC98_MusicChannelSSG::nextShape() {
- _instr = (_instr & 0xf0) + 0x0c;
- _ssgStep = _drv->_ssgPatches[_instr];
- _ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
- _ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
-}
-
-void TownsPC98_MusicChannelSSG::keyOn() {
- uint8 c = 0x7b;
- uint8 t = (_algorithm & 0xC0) << 1;
- if (_algorithm & 0x80)
- t |= 4;
-
- c = (c << (_regOffset + 1)) | (c >> (7 - _regOffset));
- t = (t << (_regOffset + 1)) | (t >> (7 - _regOffset));
-
- if (!(_algorithm & 0x80))
- _drv->writeReg(_part, 6, _algorithm & 0x7f);
-
- uint8 e = (_drv->readSSGStatus() & c) | t;
- _drv->writeReg(_part, 7, e);
-}
-
-void TownsPC98_MusicChannelSSG::protect() {
- _flags |= CHS_PROTECT;
-}
-
-void TownsPC98_MusicChannelSSG::restore() {
- _flags &= ~CHS_PROTECT;
- keyOn();
- _drv->writeReg(_part, 8 + _regOffset, _ssgTl);
- uint16 f = _frequency >> _block;
- _drv->writeReg(_part, _regOffset << 1, f & 0xff);
- _drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
-}
-
-void TownsPC98_MusicChannelSSG::loadData(uint8 *data) {
- _drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false);
- TownsPC98_MusicChannel::loadData(data);
- setOutputLevel(0);
- _algorithm = 0x80;
-}
-
-void TownsPC98_MusicChannelSSG::setOutputLevel(uint8 lvl) {
- _ssgStartLvl = lvl;
- uint16 newTl = (((uint16)_totalLevel + 1) * (uint16)lvl) >> 8;
- if (newTl == _ssgTl)
- return;
- _ssgTl = newTl;
- _drv->writeReg(_part, 8 + _regOffset, _ssgTl);
-}
-
-void TownsPC98_MusicChannelSSG::reset() {
- TownsPC98_MusicChannel::reset();
-
- // Unlike the original we restore the default patch data. This fixes a bug
- // where certain sound effects would bring each other out of tune (e.g. the
- // dragon's fire in Darm's house in Kyra 1 would sound different each time
- // you triggered another sfx by dropping an item etc.)
- uint8 i = (10 + _regOffset) << 4;
- const uint8 *src = &_drv->_drvTables[156];
- _drv->_ssgPatches[i] = src[i];
- _drv->_ssgPatches[i + 3] = src[i + 3];
- _drv->_ssgPatches[i + 4] = src[i + 4];
- _drv->_ssgPatches[i + 6] = src[i + 6];
- _drv->_ssgPatches[i + 8] = src[i + 8];
- _drv->_ssgPatches[i + 12] = src[i + 12];
-}
-
-void TownsPC98_MusicChannelSSG::fadeStep() {
- _totalLevel--;
- if ((int8)_totalLevel < 0)
- _totalLevel = 0;
- setOutputLevel(_ssgStartLvl);
-}
-
-bool TownsPC98_MusicChannelSSG::control_f0_setPatch(uint8 para) {
- _instr = para << 4;
- para = (para >> 3) & 0x1e;
- if (para)
- return control_f4_setAlgorithm(para | 0x40);
- return true;
-}
-
-bool TownsPC98_MusicChannelSSG::control_f1_setTotalLevel(uint8 para) {
- if (!_drv->_fading)
- _totalLevel = para;
- return true;
-}
-
-bool TownsPC98_MusicChannelSSG::control_f4_setAlgorithm(uint8 para) {
- _algorithm = para;
- return true;
-}
-
-bool TownsPC98_MusicChannelSSG::control_f9_loadCustomPatch(uint8 para) {
- _instr = (_drv->_sfxOffs + 10 + _regOffset) << 4;
- _drv->_ssgPatches[_instr] = *_dataPtr++;
- _drv->_ssgPatches[_instr + 3] = para;
- _drv->_ssgPatches[_instr + 4] = *_dataPtr++;
- _drv->_ssgPatches[_instr + 6] = *_dataPtr++;
- _drv->_ssgPatches[_instr + 8] = *_dataPtr++;
- _drv->_ssgPatches[_instr + 12] = *_dataPtr++;
- return true;
-}
-
-bool TownsPC98_MusicChannelSSG::control_fb_incOutLevel(uint8 para) {
- _dataPtr--;
- if (_drv->_fading)
- return true;
-
- _totalLevel--;
- if ((int8)_totalLevel < 0)
- _totalLevel = 0;
-
- return true;
-}
-
-bool TownsPC98_MusicChannelSSG::control_fc_decOutLevel(uint8 para) {
- _dataPtr--;
- if (_drv->_fading)
- return true;
-
- if (_totalLevel + 1 < 0x10)
- _totalLevel++;
-
- return true;
-}
-
-bool TownsPC98_MusicChannelSSG::control_ff_endOfTrack(uint8 para) {
- if (!_drv->_sfxOffs) {
- uint16 val = READ_LE_UINT16(--_dataPtr);
- if (val) {
- // loop
- _dataPtr = _drv->_trackPtr + val;
- return true;
- } else {
- // stop parsing
- if (!_drv->_fading)
- setOutputLevel(0);
- --_dataPtr;
- _flags |= CHS_EOT;
- _drv->_finishedSSGFlag |= _idFlag;
- }
- } else {
- // end of sfx track - restore ssg music channel
- _flags |= CHS_EOT;
- _drv->_finishedSfxFlag |= _idFlag;
- _drv->_ssgChannels[_chanNum]->restore();
- }
-
- return false;
-}
-
-void TownsPC98_SfxChannel::loadData(uint8 *data) {
- _flags = CHS_ALLOFF;
- _ticksLeft = 1;
- _dataPtr = data;
- _ssgTl = 0xff;
- _algorithm = 0x80;
-
- uint8 *tmp = _dataPtr;
- for (bool loop = true; loop;) {
- uint8 cmd = *tmp++;
- if (cmd < 0xf0) {
- tmp++;
- } else if (cmd == 0xff) {
- loop = false;
- } else if (cmd == 0xf6) {
- // reset repeat section countdown
- tmp[0] = tmp[1];
- tmp += 4;
- } else {
- tmp += _drv->_opnFxCmdLen[cmd - 240];
- }
- }
-}
-
-void TownsPC98_SfxChannel::reset() {
- TownsPC98_MusicChannel::reset();
-
- // Unlike the original we restore the default patch data. This fixes a bug
- // where certain sound effects would bring each other out of tune (e.g. the
- // dragon's fire in Darm's house in Kyra 1 would sound different each time
- // you triggered another sfx by dropping an item etc.)
- uint8 i = (13 + _regOffset) << 4;
- const uint8 *src = &_drv->_drvTables[156];
- _drv->_ssgPatches[i] = src[i];
- _drv->_ssgPatches[i + 3] = src[i + 3];
- _drv->_ssgPatches[i + 4] = src[i + 4];
- _drv->_ssgPatches[i + 6] = src[i + 6];
- _drv->_ssgPatches[i + 8] = src[i + 8];
- _drv->_ssgPatches[i + 12] = src[i + 12];
-}
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
-TownsPC98_MusicChannelPCM::TownsPC98_MusicChannelPCM(TownsPC98_AudioDriver *driver, uint8 regOffs,
- uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
- TownsPC98_MusicChannel(driver, regOffs, flgs, num, key, prt, id), controlEvents(0) {
-}
-
-void TownsPC98_MusicChannelPCM::init() {
- _algorithm = 0x80;
-
-#define Control(x) &TownsPC98_MusicChannelPCM::control_##x
- static const ControlEventFunc ctrlEventsPCM[] = {
- Control(dummy),
- Control(f1_prcStart),
- Control(dummy),
- Control(dummy),
- Control(dummy),
- Control(dummy),
- Control(f6_repeatSection),
- Control(dummy),
- Control(dummy),
- Control(dummy),
- Control(fa_writeReg),
- Control(dummy),
- Control(dummy),
- Control(dummy),
- Control(dummy),
- Control(ff_endOfTrack)
- };
-#undef Control
-
- controlEvents = ctrlEventsPCM;
-}
-
-void TownsPC98_MusicChannelPCM::loadData(uint8 *data) {
- _flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
- _ticksLeft = 1;
- _dataPtr = data;
- _totalLevel = 0x7F;
-}
-
-void TownsPC98_MusicChannelPCM::processEvents() {
- if (_flags & CHS_EOT)
- return;
-
- if (--_ticksLeft)
- return;
-
- uint8 cmd = 0;
- bool loop = true;
-
- while (loop) {
- cmd = *_dataPtr++;
- if (cmd == 0x80) {
- loop = false;
- } else if (cmd < 0xf0) {
- _drv->writeReg(_part, 0x10, cmd);
- } else if (!processControlEvent(cmd)) {
- return;
- }
- }
-
- _ticksLeft = *_dataPtr++;
-}
-
-bool TownsPC98_MusicChannelPCM::processControlEvent(uint8 cmd) {
- uint8 para = *_dataPtr++;
- return (this->*controlEvents[cmd & 0x0f])(para);
-}
-
-bool TownsPC98_MusicChannelPCM::control_f1_prcStart(uint8 para) {
- _totalLevel = para;
- _drv->writeReg(_part, 0x11, para);
- return true;
-}
-
-bool TownsPC98_MusicChannelPCM::control_ff_endOfTrack(uint8 para) {
- uint16 val = READ_LE_UINT16(--_dataPtr);
- if (val) {
- // loop
- _dataPtr = _drv->_trackPtr + val;
- return true;
- } else {
- // quit parsing for active channel
- --_dataPtr;
- _flags |= CHS_EOT;
- _drv->_finishedRhythmFlag |= _idFlag;
- return false;
- }
-}
-#endif // DISABLE_PC98_RHYTHM_CHANNEL
-
-TownsPC98_AudioDriver::TownsPC98_AudioDriver(Audio::Mixer *mixer, EmuType type) : TownsPC98_FmSynth(mixer, type),
- _channels(0), _ssgChannels(0), _sfxChannels(0),
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- _rhythmChannel(0),
-#endif
- _trackPtr(0), _sfxData(0), _sfxOffs(0), _ssgPatches(0),
- _patches(0), _sfxBuffer(0), _musicBuffer(0),
-
- _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 108), _opnFreqTableSSG(_drvTables + 132),
- _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == kTypeTowns ? 52 : 84)),
-
- _updateChannelsFlag(type == kType26 ? 0x07 : 0x3F), _finishedChannelsFlag(0),
- _updateSSGFlag(type == kTypeTowns ? 0x00 : 0x07), _finishedSSGFlag(0),
- _updateRhythmFlag(type == kType86 ?
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- 0x01
-#else
- 0x00
-#endif
- : 0x00), _finishedRhythmFlag(0),
- _updateSfxFlag(0), _finishedSfxFlag(0),
-
- _musicTickCounter(0),
-
- _musicVolume(255), _sfxVolume(255),
-
- _musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) {
-
- _sfxOffsets[0] = _sfxOffsets[1] = 0;
-}
-
-TownsPC98_AudioDriver::~TownsPC98_AudioDriver() {
- _ready = false;
- deinit();
-
- if (_channels) {
- for (int i = 0; i < _numChan; i++)
- delete _channels[i];
- delete[] _channels;
- }
-
- if (_ssgChannels) {
- for (int i = 0; i < _numSSG; i++)
- delete _ssgChannels[i];
- delete[] _ssgChannels;
- }
-
- if (_sfxChannels) {
- for (int i = 0; i < 2; i++)
- delete _sfxChannels[i];
- delete[] _sfxChannels;
- }
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- delete _rhythmChannel;
-#endif
-
- delete[] _ssgPatches;
-}
-
-bool TownsPC98_AudioDriver::init() {
- if (_ready) {
- reset();
- return true;
- }
-
- TownsPC98_FmSynth::init();
-
- setVolumeChannelMasks(-1, 0);
-
- _channels = new TownsPC98_MusicChannel *[_numChan];
- for (int i = 0; i < _numChan; i++) {
- int ii = i * 6;
- _channels[i] = new TownsPC98_MusicChannel(this, _drvTables[ii], _drvTables[ii + 1],
- _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
- _channels[i]->init();
- }
-
- if (_numSSG) {
- _ssgPatches = new uint8[256];
- memcpy(_ssgPatches, _drvTables + 156, 256);
-
- _ssgChannels = new TownsPC98_MusicChannelSSG *[_numSSG];
- for (int i = 0; i < _numSSG; i++) {
- int ii = i * 6;
- _ssgChannels[i] = new TownsPC98_MusicChannelSSG(this, _drvTables[ii], _drvTables[ii + 1],
- _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
- _ssgChannels[i]->init();
- }
-
- _sfxChannels = new TownsPC98_SfxChannel *[2];
- for (int i = 0; i < 2; i++) {
- int ii = (i + 1) * 6;
- _sfxChannels[i] = new TownsPC98_SfxChannel(this, _drvTables[ii], _drvTables[ii + 1],
- _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
- _sfxChannels[i]->init();
- }
- }
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_hasPercussion) {
- _rhythmChannel = new TownsPC98_MusicChannelPCM(this, 0, 0, 0, 0, 0, 1);
- _rhythmChannel->init();
- }
-#endif
-
- setMusicTempo(84);
- setSfxTempo(654);
-
- _ready = true;
-
- return true;
-}
-
-void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) {
- if (!_ready) {
- warning("TownsPC98_AudioDriver: Driver must be initialized before loading data");
- return;
- }
-
- if (!data) {
- warning("TownsPC98_AudioDriver: Invalid music file data");
- return;
- }
-
- reset();
-
- Common::StackLock lock(_mutex);
- uint8 *src_a = _trackPtr = _musicBuffer = data;
-
- for (uint8 i = 0; i < 3; i++) {
- _channels[i]->loadData(data + READ_LE_UINT16(src_a));
- src_a += 2;
- }
-
- for (int i = 0; i < _numSSG; i++) {
- _ssgChannels[i]->loadData(data + READ_LE_UINT16(src_a));
- src_a += 2;
- }
-
- for (uint8 i = 3; i < _numChan; i++) {
- _channels[i]->loadData(data + READ_LE_UINT16(src_a));
- src_a += 2;
- }
-
- if (_hasPercussion) {
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- _rhythmChannel->loadData(data + READ_LE_UINT16(src_a));
-#endif
- src_a += 2;
- }
-
- toggleRegProtection(false);
-
- _patches = src_a + 4;
- _finishedChannelsFlag = _finishedSSGFlag = _finishedRhythmFlag = 0;
-
- _musicPlaying = (loadPaused ? false : true);
-}
-
-void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) {
- if (!_ready) {
- warning("TownsPC98_AudioDriver: Driver must be initialized before loading data");
- return;
- }
-
- if (!_sfxChannels) {
- warning("TownsPC98_AudioDriver: Sound effects not supported by this configuration");
- return;
- }
-
- if (!data) {
- warning("TownsPC98_AudioDriver: Invalid sound effects file data");
- return;
- }
-
- Common::StackLock lock(_mutex);
- _sfxData = _sfxBuffer = data;
- _sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]);
- _sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]);
- _sfxPlaying = true;
- _finishedSfxFlag = 0;
-}
-
-void TownsPC98_AudioDriver::reset() {
- Common::StackLock lock(_mutex);
-
- _musicPlaying = false;
- _sfxPlaying = false;
- _fading = false;
- _looping = 0;
- _musicTickCounter = 0;
- _sfxData = 0;
-
- TownsPC98_FmSynth::reset();
-
- for (int i = 0; i < _numChan; i++)
- _channels[i]->reset();
- for (int i = 0; i < _numSSG; i++)
- _ssgChannels[i]->reset();
-
- if (_numSSG) {
- for (int i = 0; i < 2; i++)
- _sfxChannels[i]->reset();
-
- memcpy(_ssgPatches, _drvTables + 156, 256);
- }
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_rhythmChannel)
- _rhythmChannel->reset();
-#endif
-}
-
-void TownsPC98_AudioDriver::fadeStep() {
- if (!_musicPlaying)
- return;
-
- Common::StackLock lock(_mutex);
- for (int j = 0; j < _numChan; j++) {
- if (_updateChannelsFlag & _channels[j]->_idFlag)
- _channels[j]->fadeStep();
- }
-
- for (int j = 0; j < _numSSG; j++) {
- if (_updateSSGFlag & _ssgChannels[j]->_idFlag)
- _ssgChannels[j]->fadeStep();
- }
-
- if (!_fading) {
- _fading = 19;
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_hasPercussion) {
- if (_updateRhythmFlag & _rhythmChannel->_idFlag)
- _rhythmChannel->reset();
- }
-#endif
- } else {
- if (!--_fading)
- reset();
- }
-}
-
-void TownsPC98_AudioDriver::timerCallbackB() {
- _sfxOffs = 0;
-
- if (_musicPlaying) {
- _musicTickCounter++;
-
- for (int i = 0; i < _numChan; i++) {
- if (_updateChannelsFlag & _channels[i]->_idFlag) {
- _channels[i]->processEvents();
- _channels[i]->processFrequency();
- }
- }
-
- for (int i = 0; i < _numSSG; i++) {
- if (_updateSSGFlag & _ssgChannels[i]->_idFlag) {
- _ssgChannels[i]->processEvents();
- _ssgChannels[i]->processFrequency();
- }
- }
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_hasPercussion)
- if (_updateRhythmFlag & _rhythmChannel->_idFlag)
- _rhythmChannel->processEvents();
-#endif
- }
-
- toggleRegProtection(false);
-
- if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedRhythmFlag == _updateRhythmFlag)
- _musicPlaying = false;
-}
-
-void TownsPC98_AudioDriver::timerCallbackA() {
- if (_sfxChannels && _sfxPlaying) {
- if (_sfxData)
- startSoundEffect();
-
- _sfxOffs = 3;
- _trackPtr = _sfxBuffer;
-
- for (int i = 0; i < 2; i++) {
- if (_updateSfxFlag & _sfxChannels[i]->_idFlag) {
- _sfxChannels[i]->processEvents();
- _sfxChannels[i]->processFrequency();
- }
- }
-
- _trackPtr = _musicBuffer;
- }
-
- if (_updateSfxFlag && _finishedSfxFlag == _updateSfxFlag) {
- _sfxPlaying = false;
- _updateSfxFlag = 0;
- setVolumeChannelMasks(-1, 0);
- }
-}
-
-void TownsPC98_AudioDriver::setMusicTempo(uint8 tempo) {
- writeReg(0, 0x26, tempo);
- writeReg(0, 0x27, 0x33);
-}
-
-void TownsPC98_AudioDriver::setSfxTempo(uint16 tempo) {
- writeReg(0, 0x24, tempo & 0xff);
- writeReg(0, 0x25, tempo >> 8);
- writeReg(0, 0x27, 0x33);
-}
-
-void TownsPC98_AudioDriver::startSoundEffect() {
- int volFlags = 0;
-
- for (int i = 0; i < 2; i++) {
- if (_sfxOffsets[i]) {
- _ssgChannels[i + 1]->protect();
- _sfxChannels[i]->reset();
- _sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]);
- _updateSfxFlag |= _sfxChannels[i]->_idFlag;
- volFlags |= (_sfxChannels[i]->_idFlag << _numChan);
- } else {
- _ssgChannels[i + 1]->restore();
- _updateSfxFlag &= ~_sfxChannels[i]->_idFlag;
- }
- }
-
- setVolumeChannelMasks(~volFlags, volFlags);
- _sfxData = 0;
-}
-
-const uint8 TownsPC98_AudioDriver::_drvTables[] = {
- // channel presets
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x80, 0x01, 0x01, 0x00, 0x02,
- 0x02, 0x80, 0x02, 0x02, 0x00, 0x04,
- 0x00, 0x80, 0x03, 0x04, 0x01, 0x08,
- 0x01, 0x80, 0x04, 0x05, 0x01, 0x10,
- 0x02, 0x80, 0x05, 0x06, 0x01, 0x20,
-
- // control event size
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05,
- 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02,
-
- // fmt level presets
- 0x54, 0x50, 0x4C, 0x48, 0x44, 0x40, 0x3C, 0x38,
- 0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18,
- 0x14, 0x10, 0x0C, 0x08, 0x04, 0x90, 0x90, 0x90,
-
- // carriers
- 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F,
-
- // pc98 level presets
- 0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25,
- 0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10,
- 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90,
-
- // frequencies
- 0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02,
- 0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03,
- 0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04,
-
- // ssg frequencies
- 0xE8, 0x0E, 0x12, 0x0E, 0x48, 0x0D, 0x89, 0x0C,
- 0xD5, 0x0B, 0x2B, 0x0B, 0x8A, 0x0A, 0xF3, 0x09,
- 0x64, 0x09, 0xDD, 0x08, 0x5E, 0x08, 0xE6, 0x07,
-
- // ssg patch data
- 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
- 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00,
- 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00,
- 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
- 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
- 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
- 0x04, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
- 0x0A, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0x01, 0x00,
- 0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
- 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00,
- 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
- 0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00,
- 0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-
- 0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00,
- 0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00,
- 0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00,
- 0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
- 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
- 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
- 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
- 0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00
-};
-
-#undef EUPHONY_FADEOUT_TICKS
-
diff --git a/sound/softsynth/fmtowns_pc98/towns_pc98_driver.h b/sound/softsynth/fmtowns_pc98/towns_pc98_driver.h
deleted file mode 100644
index 00fcf7c5d5..0000000000
--- a/sound/softsynth/fmtowns_pc98/towns_pc98_driver.h
+++ /dev/null
@@ -1,135 +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$
- *
- */
-
-#ifndef TOWNS_PC98_AUDIODRIVER_H
-#define TOWNS_PC98_AUDIODRIVER_H
-
-#include "sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
-
-class TownsPC98_MusicChannel;
-class TownsPC98_MusicChannelSSG;
-class TownsPC98_SfxChannel;
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
-class TownsPC98_MusicChannelPCM;
-#endif
-
-class TownsPC98_AudioDriver : public TownsPC98_FmSynth {
-friend class TownsPC98_MusicChannel;
-friend class TownsPC98_MusicChannelSSG;
-friend class TownsPC98_SfxChannel;
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
-friend class TownsPC98_MusicChannelPCM;
-#endif
-public:
- TownsPC98_AudioDriver(Audio::Mixer *mixer, EmuType type);
- ~TownsPC98_AudioDriver();
-
- void loadMusicData(uint8 *data, bool loadPaused = false);
- void loadSoundEffectData(uint8 *data, uint8 trackNum);
- bool init();
- void reset();
-
- void fadeStep();
-
- void pause() {
- _musicPlaying = false;
- }
- void cont() {
- _musicPlaying = true;
- }
-
- void timerCallbackB();
- void timerCallbackA();
-
- bool looping() {
- return _looping == _updateChannelsFlag ? true : false;
- }
- bool musicPlaying() {
- return _musicPlaying;
- }
-
- void setMusicVolume(int volume) {
- _musicVolume = volume;
- setVolumeIntern(_musicVolume, _sfxVolume);
- }
- void setSoundEffectVolume(int volume) {
- _sfxVolume = volume;
- setVolumeIntern(_musicVolume, _sfxVolume);
- }
-
-protected:
- void startSoundEffect();
-
- void setMusicTempo(uint8 tempo);
- void setSfxTempo(uint16 tempo);
-
- TownsPC98_MusicChannel **_channels;
- TownsPC98_MusicChannelSSG **_ssgChannels;
- TownsPC98_SfxChannel **_sfxChannels;
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- TownsPC98_MusicChannelPCM *_rhythmChannel;
-#endif
-
- const uint8 *_opnCarrier;
- const uint8 *_opnFreqTable;
- const uint8 *_opnFreqTableSSG;
- const uint8 *_opnFxCmdLen;
- const uint8 *_opnLvlPresets;
-
- uint8 *_musicBuffer;
- uint8 *_sfxBuffer;
- uint8 *_trackPtr;
- uint8 *_patches;
- uint8 *_ssgPatches;
-
- uint8 _updateChannelsFlag;
- uint8 _updateSSGFlag;
- uint8 _updateRhythmFlag;
- uint8 _updateSfxFlag;
- uint8 _finishedChannelsFlag;
- uint8 _finishedSSGFlag;
- uint8 _finishedRhythmFlag;
- uint8 _finishedSfxFlag;
-
- bool _musicPlaying;
- bool _sfxPlaying;
- uint8 _fading;
- uint8 _looping;
- uint32 _musicTickCounter;
-
- int _sfxOffs;
- uint8 *_sfxData;
- uint16 _sfxOffsets[2];
-
- uint16 _musicVolume;
- uint16 _sfxVolume;
-
- static const uint8 _drvTables[];
-
- bool _ready;
-};
-
-#endif
-
diff --git a/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
deleted file mode 100644
index 62f7d39771..0000000000
--- a/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ /dev/null
@@ -1,1548 +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$
- *
- */
-
-#include "sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
-#include "common/endian.h"
-
-class TownsPC98_FmSynthOperator {
-public:
- TownsPC98_FmSynthOperator(const uint32 timerbase, const uint32 rtt, const uint8 *rateTable,
- const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable,
- const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable);
- ~TownsPC98_FmSynthOperator() {}
-
- void keyOn();
- void keyOff();
- void frequency(int freq);
- void updatePhaseIncrement();
- void recalculateRates();
- void generateOutput(int32 phasebuf, int32 *feedbuf, int32 &out);
-
- void feedbackLevel(int32 level) {
- _feedbackLevel = level ? level + 6 : 0;
- }
- void detune(int value) {
- _detn = &_detnTbl[value << 5];
- }
- void multiple(uint32 value) {
- _multiple = value ? (value << 1) : 1;
- }
- void attackRate(uint32 value) {
- _specifiedAttackRate = value;
- }
- bool scaleRate(uint8 value);
- void decayRate(uint32 value) {
- _specifiedDecayRate = value;
- recalculateRates();
- }
- void sustainRate(uint32 value) {
- _specifiedSustainRate = value;
- recalculateRates();
- }
- void sustainLevel(uint32 value) {
- _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5;
- }
- void releaseRate(uint32 value) {
- _specifiedReleaseRate = value;
- recalculateRates();
- }
- void totalLevel(uint32 value) {
- _totalLevel = value << 3;
- }
- void ampModulation(bool enable) {
- _ampMod = enable;
- }
- void reset();
-
-protected:
- EnvelopeState _state;
- bool _playing;
- uint32 _feedbackLevel;
- uint32 _multiple;
- uint32 _totalLevel;
- uint8 _keyScale1;
- uint8 _keyScale2;
- uint32 _specifiedAttackRate;
- uint32 _specifiedDecayRate;
- uint32 _specifiedSustainRate;
- uint32 _specifiedReleaseRate;
- uint32 _tickCount;
- uint32 _sustainLevel;
-
- bool _ampMod;
- uint32 _frequency;
- uint8 _kcode;
- uint32 _phase;
- uint32 _phaseIncrement;
- const int32 *_detn;
-
- const uint8 *_rateTbl;
- const uint8 *_rshiftTbl;
- const uint8 *_adTbl;
- const uint32 *_fTbl;
- const uint32 *_sinTbl;
- const int32 *_tLvlTbl;
- const int32 *_detnTbl;
-
- const uint32 _tickLength;
- uint32 _timer;
- const uint32 _rtt;
- int32 _currentLevel;
-
- struct EvpState {
- uint8 rate;
- uint8 shift;
- } fs_a, fs_d, fs_s, fs_r;
-};
-
-TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(const uint32 timerbase, const uint32 rtt,
- const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable,
- const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) :
- _rtt(rtt), _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable),
- _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2),
- _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0),
- _phase(0), _state(kEnvReady), _playing(false), _timer(0), _keyScale1(0),
- _keyScale2(0), _currentLevel(1023), _ampMod(false), _tickCount(0) {
-
- fs_a.rate = fs_a.shift = fs_d.rate = fs_d.shift = fs_s.rate = fs_s.shift = fs_r.rate = fs_r.shift = 0;
-
- reset();
-}
-
-void TownsPC98_FmSynthOperator::keyOn() {
- if (_playing)
- return;
-
- _playing = true;
- _state = kEnvAttacking;
- _phase = 0;
-}
-
-void TownsPC98_FmSynthOperator::keyOff() {
- if (!_playing)
- return;
-
- _playing = false;
- if (_state != kEnvReady)
- _state = kEnvReleasing;
-}
-
-void TownsPC98_FmSynthOperator::frequency(int freq) {
- uint8 block = (freq >> 11);
- uint16 pos = (freq & 0x7ff);
- uint8 c = pos >> 7;
-
- _kcode = (block << 2) | ((c < 7) ? 0 : ((c > 8) ? 3 : c - 6));
- _frequency = _fTbl[pos << 1] >> (7 - block);
-}
-
-void TownsPC98_FmSynthOperator::updatePhaseIncrement() {
- _phaseIncrement = ((_frequency + _detn[_kcode]) * _multiple) >> 1;
- uint8 keyscale = _kcode >> _keyScale1;
- if (_keyScale2 != keyscale) {
- _keyScale2 = keyscale;
- recalculateRates();
- }
-}
-
-void TownsPC98_FmSynthOperator::recalculateRates() {
- int k = _keyScale2;
- int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
- fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
- fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
-
- r = _specifiedDecayRate ? (_specifiedDecayRate << 1) + 0x20 : 0;
- fs_d.rate = _rateTbl[r + k];
- fs_d.shift = _rshiftTbl[r + k];
-
- r = _specifiedSustainRate ? (_specifiedSustainRate << 1) + 0x20 : 0;
- fs_s.rate = _rateTbl[r + k];
- fs_s.shift = _rshiftTbl[r + k];
-
- r = (_specifiedReleaseRate << 2) + 0x22;
- fs_r.rate = _rateTbl[r + k];
- fs_r.shift = _rshiftTbl[r + k];
-}
-
-void TownsPC98_FmSynthOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &out) {
- if (_state == kEnvReady)
- return;
-
- _timer += _tickLength;
- while (_timer > _rtt) {
- _timer -= _rtt;
- ++_tickCount;
-
- int32 levelIncrement = 0;
- uint32 targetTime = 0;
- int32 targetLevel = 0;
- EnvelopeState nextState = kEnvReady;
-
- switch (_state) {
- case kEnvReady:
- return;
- case kEnvAttacking:
- targetLevel = 0;
- nextState = kEnvDecaying;
- if ((_specifiedAttackRate << 1) + _keyScale2 < 64) {
- targetTime = (1 << fs_a.shift) - 1;
- levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4;
- break;
- } else {
- _currentLevel = targetLevel;
- _state = nextState;
- }
- // Fall through
- case kEnvDecaying:
- targetTime = (1 << fs_d.shift) - 1;
- nextState = kEnvSustaining;
- targetLevel = _sustainLevel;
- levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)];
- break;
- case kEnvSustaining:
- targetTime = (1 << fs_s.shift) - 1;
- nextState = kEnvSustaining;
- targetLevel = 1023;
- levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)];
- break;
- case kEnvReleasing:
- targetTime = (1 << fs_r.shift) - 1;
- nextState = kEnvReady;
- targetLevel = 1023;
- levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)];
- break;
- }
-
- if (!(_tickCount & targetTime)) {
- _currentLevel += levelIncrement;
- if ((_state == kEnvAttacking && _currentLevel <= targetLevel) || (_state != kEnvAttacking && _currentLevel >= targetLevel)) {
- if (_state != kEnvDecaying)
- _currentLevel = targetLevel;
- _state = nextState;
- }
- }
- }
-
- uint32 lvlout = _totalLevel + (uint32) _currentLevel;
-
-
- int32 outp = 0;
- int32 *i = &outp, *o = &outp;
- int phaseShift = 0;
-
- if (feed) {
- o = &feed[0];
- i = &feed[1];
- phaseShift = _feedbackLevel ? ((*o + *i) << _feedbackLevel) : 0;
- *o = *i;
- } else {
- phaseShift = phasebuf << 15;
- }
-
- if (lvlout < 832) {
- uint32 index = (lvlout << 3) + _sinTbl[(((int32)((_phase & 0xffff0000)
- + phaseShift)) >> 16) & 0x3ff];
- *i = ((index < 6656) ? _tLvlTbl[index] : 0);
- } else {
- *i = 0;
- }
-
- _phase += _phaseIncrement;
- out += *o;
-}
-
-void TownsPC98_FmSynthOperator::reset() {
- keyOff();
- _timer = 0;
- _keyScale2 = 0;
- _currentLevel = 1023;
-
- frequency(0);
- detune(0);
- scaleRate(0);
- multiple(0);
- updatePhaseIncrement();
- attackRate(0);
- decayRate(0);
- releaseRate(0);
- sustainRate(0);
- feedbackLevel(0);
- totalLevel(127);
- ampModulation(false);
-}
-
-bool TownsPC98_FmSynthOperator::scaleRate(uint8 value) {
- value = 3 - value;
- if (_keyScale1 != value) {
- _keyScale1 = value;
- return true;
- }
-
- int k = _keyScale2;
- int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
- fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
- fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
- return false;
-}
-
-class TownsPC98_FmSynthSquareSineSource {
-public:
- TownsPC98_FmSynthSquareSineSource(const uint32 timerbase, const uint32 rtt);
- ~TownsPC98_FmSynthSquareSineSource();
-
- void init(const int *rsTable, const int *rseTable);
- void reset();
- void writeReg(uint8 address, uint8 value, bool force = false);
-
- void nextTick(int32 *buffer, uint32 bufferSize);
-
- void setVolumeIntern(int volA, int volB) {
- _volumeA = volA;
- _volumeB = volB;
- }
- void setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
- _volMaskA = channelMaskA;
- _volMaskB = channelMaskB;
- }
-
- uint8 chanEnable() const {
- return _chanEnable;
- }
-private:
- void updateRegs();
-
- uint8 _updateRequestBuf[64];
- int _updateRequest;
- int _rand;
-
- int8 _evpTimer;
- uint32 _pReslt;
- uint8 _attack;
-
- bool _evpUpdate, _cont;
-
- int _evpUpdateCnt;
- uint8 _outN;
- int _nTick;
-
- int32 *_tlTable;
- int32 *_tleTable;
-
- const uint32 _tickLength;
- uint32 _timer;
- const uint32 _rtt;
-
- struct Channel {
- int tick;
- uint8 smp;
- uint8 out;
-
- uint8 frqL;
- uint8 frqH;
- uint8 vol;
- } _channels[3];
-
- uint8 _noiseGenerator;
- uint8 _chanEnable;
-
- uint8 **_reg;
-
- uint16 _volumeA;
- uint16 _volumeB;
- int _volMaskA;
- int _volMaskB;
-
- bool _ready;
-};
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
-class TownsPC98_FmSynthPercussionSource {
-public:
- TownsPC98_FmSynthPercussionSource(const uint32 timerbase, const uint32 rtt);
- ~TownsPC98_FmSynthPercussionSource() {
- delete[] _reg;
- }
-
- void init(const uint8 *instrData = 0);
- void reset();
- void writeReg(uint8 address, uint8 value);
-
- void nextTick(int32 *buffer, uint32 bufferSize);
-
- void setVolumeIntern(int volA, int volB) {
- _volumeA = volA;
- _volumeB = volB;
- }
- void setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
- _volMaskA = channelMaskA;
- _volMaskB = channelMaskB;
- }
-
-private:
- struct RhtChannel {
- const uint8 *data;
-
- const uint8 *start;
- const uint8 *end;
- const uint8 *pos;
- uint32 size;
- bool active;
- uint8 level;
-
- int8 decState;
- uint8 decStep;
-
- int16 samples[2];
- int out;
-
- uint8 startPosH;
- uint8 startPosL;
- uint8 endPosH;
- uint8 endPosL;
- };
-
- void recalcOuput(RhtChannel *ins);
- void advanceInput(RhtChannel *ins);
-
- RhtChannel _rhChan[6];
-
- uint8 _totalLevel;
-
- const uint32 _tickLength;
- uint32 _timer;
- const uint32 _rtt;
-
- uint8 **_reg;
-
- uint16 _volumeA;
- uint16 _volumeB;
- int _volMaskA;
- int _volMaskB;
-
- bool _ready;
-};
-#endif // DISABLE_PC98_RHYTHM_CHANNEL
-
-TownsPC98_FmSynthSquareSineSource::TownsPC98_FmSynthSquareSineSource(const uint32 timerbase, const uint32 rtt) : _tlTable(0),
- _rtt(rtt), _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1),
- _nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true),
- _timer(0), _noiseGenerator(0), _chanEnable(0),
- _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
-
- memset(_channels, 0, sizeof(_channels));
- memset(_updateRequestBuf, 0, sizeof(_updateRequestBuf));
- _reg = new uint8 *[11];
-
- _reg[0] = &_channels[0].frqL;
- _reg[1] = &_channels[0].frqH;
- _reg[2] = &_channels[1].frqL;
- _reg[3] = &_channels[1].frqH;
- _reg[4] = &_channels[2].frqL;
- _reg[5] = &_channels[2].frqH;
- _reg[6] = &_noiseGenerator;
- _reg[7] = &_chanEnable;
- _reg[8] = &_channels[0].vol;
- _reg[9] = &_channels[1].vol;
- _reg[10] = &_channels[2].vol;
-
- reset();
-}
-
-TownsPC98_FmSynthSquareSineSource::~TownsPC98_FmSynthSquareSineSource() {
- delete[] _tlTable;
- delete[] _tleTable;
- delete[] _reg;
-}
-
-void TownsPC98_FmSynthSquareSineSource::init(const int *rsTable, const int *rseTable) {
- if (_ready) {
- reset();
- return;
- }
-
- delete[] _tlTable;
- delete[] _tleTable;
- _tlTable = new int32[16];
- _tleTable = new int32[32];
- float a, b, d;
- d = 801.0f;
-
- for (int i = 0; i < 16; i++) {
- b = 1.0f / rsTable[i];
- a = 1.0f / d + b + 1.0f / 1000.0f;
- float v = (b / a) * 32767.0f;
- _tlTable[i] = (int32) v;
-
- b = 1.0f / rseTable[i];
- a = 1.0f / d + b + 1.0f / 1000.0f;
- v = (b / a) * 32767.0f;
- _tleTable[i] = (int32) v;
- }
-
- for (int i = 16; i < 32; i++) {
- b = 1.0f / rseTable[i];
- a = 1.0f / d + b + 1.0f / 1000.0f;
- float v = (b / a) * 32767.0f;
- _tleTable[i] = (int32) v;
- }
-
- _ready = true;
-}
-
-void TownsPC98_FmSynthSquareSineSource::reset() {
- _rand = 1;
- _outN = 1;
- _updateRequest = -1;
- _nTick = _evpUpdateCnt = 0;
- _evpTimer = 0x1f;
- _pReslt = 0x1f;
- _attack = 0;
- _cont = false;
- _evpUpdate = true;
- _timer = 0;
-
- for (int i = 0; i < 3; i++) {
- _channels[i].tick = 0;
- _channels[i].smp = _channels[i].out = 0;
- }
-
- for (int i = 0; i < 14; i++)
- writeReg(i, 0, true);
-
- writeReg(7, 0xbf, true);
-}
-
-void TownsPC98_FmSynthSquareSineSource::writeReg(uint8 address, uint8 value, bool force) {
- if (!_ready)
- return;
-
- if (address > 10 || *_reg[address] == value) {
- if ((address == 11 || address == 12 || address == 13) && value)
- warning("TownsPC98_FmSynthSquareSineSource: unsupported reg address: %d", address);
- return;
- }
-
- if (!force) {
- if (_updateRequest >= 63) {
- warning("TownsPC98_FmSynthSquareSineSource: event buffer overflow");
- _updateRequest = -1;
- }
- _updateRequestBuf[++_updateRequest] = value;
- _updateRequestBuf[++_updateRequest] = address;
- return;
- }
-
- *_reg[address] = value;
-}
-
-void TownsPC98_FmSynthSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) {
- if (!_ready)
- return;
-
- for (uint32 i = 0; i < bufferSize; i++) {
- _timer += _tickLength;
- while (_timer > _rtt) {
- _timer -= _rtt;
-
- if (++_nTick >= (_noiseGenerator & 0x1f)) {
- if ((_rand + 1) & 2)
- _outN ^= 1;
-
- _rand = (((_rand & 1) ^ ((_rand >> 3) & 1)) << 16) | (_rand >> 1);
- _nTick = 0;
- }
-
- for (int ii = 0; ii < 3; ii++) {
- if (++_channels[ii].tick >= (((_channels[ii].frqH & 0x0f) << 8) | _channels[ii].frqL)) {
- _channels[ii].tick = 0;
- _channels[ii].smp ^= 1;
- }
- _channels[ii].out = (_channels[ii].smp | ((_chanEnable >> ii) & 1)) & (_outN | ((_chanEnable >> (ii + 3)) & 1));
- }
-
- if (_evpUpdate) {
- if (++_evpUpdateCnt >= 0) {
- _evpUpdateCnt = 0;
-
- if (--_evpTimer < 0) {
- if (_cont) {
- _evpTimer &= 0x1f;
- } else {
- _evpUpdate = false;
- _evpTimer = 0;
- }
- }
- }
- }
- _pReslt = _evpTimer ^ _attack;
- updateRegs();
- }
-
- int32 finOut = 0;
- for (int ii = 0; ii < 3; ii++) {
- int32 finOutTemp = ((_channels[ii].vol >> 4) & 1) ? _tleTable[_channels[ii].out ? _pReslt : 0] : _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0];
-
- if ((1 << ii) & _volMaskA)
- finOutTemp = (finOutTemp * _volumeA) / Audio::Mixer::kMaxMixerVolume;
-
- if ((1 << ii) & _volMaskB)
- finOutTemp = (finOutTemp * _volumeB) / Audio::Mixer::kMaxMixerVolume;
-
- finOut += finOutTemp;
- }
-
- finOut /= 3;
-
- buffer[i << 1] += finOut;
- buffer[(i << 1) + 1] += finOut;
- }
-}
-
-void TownsPC98_FmSynthSquareSineSource::updateRegs() {
- for (int i = 0; i < _updateRequest;) {
- uint8 b = _updateRequestBuf[i++];
- uint8 a = _updateRequestBuf[i++];
- writeReg(a, b, true);
- }
- _updateRequest = -1;
-}
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
-TownsPC98_FmSynthPercussionSource::TownsPC98_FmSynthPercussionSource(const uint32 timerbase, const uint32 rtt) :
- _rtt(rtt), _tickLength(timerbase * 2), _timer(0), _ready(false), _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
-
- memset(_rhChan, 0, sizeof(RhtChannel) * 6);
- _reg = new uint8 *[40];
-
- _reg[0] = _reg[1] = _reg[2] = _reg[3] = _reg[4] = _reg[5] = _reg[6] = _reg[7] = _reg[8] = _reg[9] = _reg[10] = _reg[11] = _reg[12] = _reg[13] = _reg[14] = _reg[15] = 0;
- _reg[16] = &_rhChan[0].startPosL;
- _reg[17] = &_rhChan[1].startPosL;
- _reg[18] = &_rhChan[2].startPosL;
- _reg[19] = &_rhChan[3].startPosL;
- _reg[20] = &_rhChan[4].startPosL;
- _reg[21] = &_rhChan[5].startPosL;
- _reg[22] = &_rhChan[0].startPosH;
- _reg[23] = &_rhChan[1].startPosH;
- _reg[24] = &_rhChan[2].startPosH;
- _reg[25] = &_rhChan[3].startPosH;
- _reg[26] = &_rhChan[4].startPosH;
- _reg[27] = &_rhChan[5].startPosH;
- _reg[28] = &_rhChan[0].endPosL;
- _reg[29] = &_rhChan[1].endPosL;
- _reg[30] = &_rhChan[2].endPosL;
- _reg[31] = &_rhChan[3].endPosL;
- _reg[32] = &_rhChan[4].endPosL;
- _reg[33] = &_rhChan[5].endPosL;
- _reg[34] = &_rhChan[0].endPosH;
- _reg[35] = &_rhChan[1].endPosH;
- _reg[36] = &_rhChan[2].endPosH;
- _reg[37] = &_rhChan[3].endPosH;
- _reg[38] = &_rhChan[4].endPosH;
- _reg[39] = &_rhChan[5].endPosH;
-}
-
-void TownsPC98_FmSynthPercussionSource::init(const uint8 *instrData) {
- if (_ready) {
- reset();
- return;
- }
-
- const uint8 *start = instrData;
- const uint8 *pos = start;
-
- if (instrData) {
- for (int i = 0; i < 6; i++) {
- _rhChan[i].data = start + READ_BE_UINT16(pos);
- pos += 2;
- _rhChan[i].size = READ_BE_UINT16(pos);
- pos += 2;
- }
- reset();
- _ready = true;
- } else {
- memset(_rhChan, 0, sizeof(RhtChannel) * 6);
- _ready = false;
- }
-}
-
-void TownsPC98_FmSynthPercussionSource::reset() {
- _timer = 0;
- _totalLevel = 63;
-
- for (int i = 0; i < 6; i++) {
- RhtChannel *s = &_rhChan[i];
- s->pos = s->start = s->data;
- s->end = s->data + s->size;
- s->active = false;
- s->level = 0;
- s->out = 0;
- s->decStep = 1;
- s->decState = 0;
- s->samples[0] = s->samples[1] = 0;
- s->startPosH = s->startPosL = s->endPosH = s->endPosL = 0;
- }
-}
-
-void TownsPC98_FmSynthPercussionSource::writeReg(uint8 address, uint8 value) {
- if (!_ready)
- return;
-
- uint8 h = address >> 4;
- uint8 l = address & 15;
-
- if (address > 15)
- *_reg[address] = value;
-
- if (address == 0) {
- if (value & 0x80) {
- //key off
- for (int i = 0; i < 6; i++) {
- if ((value >> i) & 1)
- _rhChan[i].active = false;
- }
- } else {
- //key on
- for (int i = 0; i < 6; i++) {
- if ((value >> i) & 1) {
- RhtChannel *s = &_rhChan[i];
- s->pos = s->start;
- s->active = true;
- s->out = 0;
- s->samples[0] = s->samples[1] = 0;
- s->decStep = 1;
- s->decState = 0;
- }
- }
- }
- } else if (address == 1) {
- // total level
- _totalLevel = (value & 63) ^ 63;
- for (int i = 0; i < 6; i++)
- recalcOuput(&_rhChan[i]);
- } else if (!h && l & 8) {
- // instrument level
- l &= 7;
- _rhChan[l].level = (value & 0x1f) ^ 0x1f;
- recalcOuput(&_rhChan[l]);
- } else if (h & 3) {
- l &= 7;
- if (h == 1) {
- // set start offset
- _rhChan[l].start = _rhChan[l].data + ((_rhChan[l].startPosH << 8 | _rhChan[l].startPosL) << 8);
- } else if (h == 2) {
- // set end offset
- _rhChan[l].end = _rhChan[l].data + ((_rhChan[l].endPosH << 8 | _rhChan[l].endPosL) << 8) + 255;
- }
- }
-}
-
-void TownsPC98_FmSynthPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
- if (!_ready)
- return;
-
- for (uint32 i = 0; i < bufferSize; i++) {
- _timer += _tickLength;
- while (_timer > _rtt) {
- _timer -= _rtt;
-
- for (int ii = 0; ii < 6; ii++) {
- RhtChannel *s = &_rhChan[ii];
- if (s->active) {
- recalcOuput(s);
- if (s->decStep) {
- advanceInput(s);
- if (s->pos == s->end)
- s->active = false;
- }
- s->decStep ^= 1;
- }
- }
- }
-
- int32 finOut = 0;
-
- for (int ii = 0; ii < 6; ii++) {
- if (_rhChan[ii].active)
- finOut += _rhChan[ii].out;
- }
-
- finOut <<= 1;
-
- if (1 & _volMaskA)
- finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
-
- if (1 & _volMaskB)
- finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
-
- buffer[i << 1] += finOut;
- buffer[(i << 1) + 1] += finOut;
- }
-}
-
-void TownsPC98_FmSynthPercussionSource::recalcOuput(RhtChannel *ins) {
- uint32 s = _totalLevel + ins->level;
- uint32 x = s > 62 ? 0 : (1 + (s >> 3));
- int32 y = s > 62 ? 0 : (15 - (s & 7));
- ins->out = ((ins->samples[ins->decStep] * y) >> x) & ~3;
-}
-
-void TownsPC98_FmSynthPercussionSource::advanceInput(RhtChannel *ins) {
- static const int8 adjustIndex[] = { -1, -1, -1, -1, 2, 5, 7, 9 };
-
- static const int16 stepTable[] = {
- 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55,
- 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337,
- 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
- };
-
- uint8 cur = (int8)*ins->pos++;
-
- for (int i = 0; i < 2; i++) {
- int b = (2 * (cur & 7) + 1) * stepTable[ins->decState] / 8;
- ins->samples[i] = CLIP<int16>(ins->samples[i ^ 1] + (cur & 8 ? b : -b), -2048, 2047);
- ins->decState = CLIP<int8>(ins->decState + adjustIndex[cur & 7], 0, 48);
- cur >>= 4;
- }
-}
-#endif // DISABLE_PC98_RHYTHM_CHANNEL
-
-TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) :
- _mixer(mixer),
- _chanInternal(0), _ssg(0),
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- _prc(0),
-#endif
- _numChan(type == kType26 ? 3 : 6), _numSSG(type == kTypeTowns ? 0 : 3),
- _hasPercussion(type == kType86 ? true : false),
- _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
- _rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()),
- _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255),
- _regProtectionFlag(false), _ready(false) {
-
- memset(&_timers[0], 0, sizeof(ChipTimer));
- memset(&_timers[1], 0, sizeof(ChipTimer));
-
- _timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback;
- _timerbase = (uint32)(_baserate * 1000000.0f);
-}
-
-TownsPC98_FmSynth::~TownsPC98_FmSynth() {
- if (_ready)
- deinit();
-
- delete _ssg;
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- delete _prc;
-#endif
- delete[] _chanInternal;
-
- delete[] _oprRates;
- delete[] _oprRateshift;
- delete[] _oprFrq;
- delete[] _oprAttackDecay;
- delete[] _oprSinTbl;
- delete[] _oprLevelOut;
- delete[] _oprDetune;
-}
-
-bool TownsPC98_FmSynth::init() {
- if (_ready) {
- reset();
- return true;
- }
-
- generateTables();
-
- _chanInternal = new ChanInternal[_numChan];
- for (int i = 0; i < _numChan; i++) {
- memset(&_chanInternal[i], 0, sizeof(ChanInternal));
- for (int j = 0; j < 4; ++j)
- _chanInternal[i].opr[j] = new TownsPC98_FmSynthOperator(_timerbase, _rtt, _oprRates, _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune);
- }
-
- if (_numSSG) {
- _ssg = new TownsPC98_FmSynthSquareSineSource(_timerbase, _rtt);
- _ssg->init(&_ssgTables[0], &_ssgTables[16]);
- }
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_hasPercussion) {
- _prc = new TownsPC98_FmSynthPercussionSource(_timerbase, _rtt);
- _prc->init(_percussionData);
- }
-#endif
-
- _timers[0].cb = &TownsPC98_FmSynth::timerCallbackA;
- _timers[1].cb = &TownsPC98_FmSynth::timerCallbackB;
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType,
- &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- _ready = true;
-
- return true;
-}
-
-void TownsPC98_FmSynth::reset() {
- Common::StackLock lock(_mutex);
- for (int i = 0; i < _numChan; i++) {
- for (int ii = 0; ii < 4; ii++)
- _chanInternal[i].opr[ii]->reset();
- memset(_chanInternal[i].feedbuf, 0, 3);
- _chanInternal[i].algorithm = 0;
- _chanInternal[i].frqTemp = 0;
- _chanInternal[i].enableLeft = _chanInternal[i].enableRight = true;
- _chanInternal[i].updateEnvelopeParameters = false;
- }
-
- writeReg(0, 0x27, 0x33);
-
- if (_ssg)
- _ssg->reset();
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_prc)
- _prc->reset();
-#endif
-}
-
-void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
- if (_regProtectionFlag || !_ready)
- return;
-
- static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
-
- Common::StackLock lock(_mutex);
-
- uint8 h = regAddress & 0xf0;
- uint8 l = (regAddress & 0x0f);
-
- ChanInternal *c = 0;
- TownsPC98_FmSynthOperator **co = 0;
- TownsPC98_FmSynthOperator *o = 0;
-
- if (regAddress > 0x2F) {
- c = &_chanInternal[(l & 3) + 3 * part];
- co = c->opr;
- o = c->opr[oprOrdr[(l - (l & 3)) >> 2]];
- } else if (regAddress == 0x28) {
- c = &_chanInternal[(value & 3) + ((value & 4) ? 3 : 0)];
- co = c->opr;
- }
-
- switch (h) {
- case 0x00:
- // ssg
- if (_ssg)
- _ssg->writeReg(l, value);
- break;
- case 0x10:
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- // pcm rhythm channel
- if (_prc)
- _prc->writeReg(l, value);
-#endif
- break;
- case 0x20:
- if (l == 8) {
- // Key on/off
- for (int i = 0; i < 4; i++) {
- if ((value >> (4 + i)) & 1)
- co[oprOrdr[i]]->keyOn();
- else
- co[oprOrdr[i]]->keyOff();
- }
- } else if (l == 4) {
- // Timer A
- _timers[0].value = (_timers[0].value & 3) | (value << 2);
- } else if (l == 5) {
- // Timer A
- _timers[0].value = (_timers[0].value & 0x3fc) | (value & 3);
- } else if (l == 6) {
- // Timer B
- _timers[1].value = value & 0xff;
- } else if (l == 7) {
- if (value & 1) {
- float spc = (float)(0x400 - _timers[0].value) / _baserate;
- if (spc < 1) {
- warning("TownsPC98_FmSynth: Invalid Timer A setting: %d", _timers[0].value);
- spc = 1;
- }
-
- _timers[0].smpPerCb = (int32) spc;
- _timers[0].smpPerCbRem = (uint32)((spc - (float)_timers[0].smpPerCb) * 1000000.0f);
- _timers[0].smpTillCb = _timers[0].smpPerCb;
- _timers[0].smpTillCbRem = _timers[0].smpPerCbRem;
- _timers[0].enabled = true;
- } else {
- _timers[0].enabled = false;
- }
-
- if (value & 2) {
- float spc = (float)(0x100 - _timers[1].value) * 16.0f / _baserate;
- if (spc < 1) {
- warning("TownsPC98_FmSynth: Invalid Timer B setting: %d", _timers[1].value);
- spc = 1;
- }
-
- _timers[1].smpPerCb = (int32) spc;
- _timers[1].smpPerCbRem = (uint32)((spc - (float)_timers[1].smpPerCb) * 1000000.0f);
- _timers[1].smpTillCb = _timers[1].smpPerCb;
- _timers[1].smpTillCbRem = _timers[1].smpPerCbRem;
- _timers[1].enabled = true;
- } else {
- _timers[1].enabled = false;
- }
-
- if (value & 0x10) {
- _timers[0].smpTillCb = _timers[0].smpPerCb;
- _timers[0].smpTillCbRem = _timers[0].smpTillCbRem;
- }
-
- if (value & 0x20) {
- _timers[1].smpTillCb = _timers[1].smpPerCb;
- _timers[1].smpTillCbRem = _timers[1].smpTillCbRem;
- }
- } else if (l == 2) {
- // LFO
- if (value & 8)
- warning("TownsPC98_FmSynth: TRYING TO USE LFO (NOT SUPPORTED)");
- } else if (l == 10 || l == 11) {
- // DAC
- if (l == 11 && (value & 0x80))
- warning("TownsPC98_FmSynth: TRYING TO USE DAC (NOT SUPPORTED)");
- }
- break;
-
- case 0x30:
- // detune, multiple
- o->detune((value >> 4) & 7);
- o->multiple(value & 0x0f);
- c->updateEnvelopeParameters = true;
- break;
-
- case 0x40:
- // total level
- o->totalLevel(value & 0x7f);
- break;
-
- case 0x50:
- // rate scaling, attack rate
- o->attackRate(value & 0x1f);
- if (o->scaleRate(value >> 6))
- c->updateEnvelopeParameters = true;
- break;
-
- case 0x60:
- // first decay rate, amplitude modulation
- o->decayRate(value & 0x1f);
- o->ampModulation(value & 0x80 ? true : false);
- break;
-
- case 0x70:
- // secondary decay rate
- o->sustainRate(value & 0x1f);
- break;
-
- case 0x80:
- // secondary amplitude, release rate;
- o->sustainLevel(value >> 4);
- o->releaseRate(value & 0x0f);
- break;
-
- case 0x90:
- warning("TownsPC98_FmSynth: TRYING TO USE SSG ENVELOPE SHAPES (NOT SUPPORTED)");
- break;
-
- case 0xa0:
- // frequency
- l &= ~3;
- if (l == 0) {
- c->frqTemp = (c->frqTemp & 0xff00) | value;
- c->updateEnvelopeParameters = true;
- for (int i = 0; i < 4; i++)
- co[i]->frequency(c->frqTemp);
- } else if (l == 4) {
- c->frqTemp = (c->frqTemp & 0xff) | (value << 8);
- } else if (l == 8) {
- // Ch 3/6 special mode frq
- warning("TownsPC98_FmSynth: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
- } else if (l == 12) {
- // Ch 3/6 special mode frq
- warning("TownsPC98_FmSynth: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
- }
- break;
-
- case 0xb0:
- l &= ~3;
- if (l == 0) {
- // feedback, _algorithm
- co[0]->feedbackLevel((value >> 3) & 7);
- c->algorithm = value & 7;
- } else if (l == 4) {
- // stereo, LFO sensitivity
- c->enableLeft = value & 0x80 ? true : false;
- c->enableRight = value & 0x40 ? true : false;
- c->ampModSensitivity((value & 0x30) >> 4);
- c->frqModSensitivity(value & 3);
- }
- break;
-
- default:
- warning("TownsPC98_FmSynth: UNKNOWN ADDRESS %d", regAddress);
- }
-}
-
-int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock lock(_mutex);
-
- memset(buffer, 0, sizeof(int16) * numSamples);
- int32 *tmp = new int32[numSamples];
- int32 *tmpStart = tmp;
- memset(tmp, 0, sizeof(int32) * numSamples);
- int32 samplesLeft = numSamples >> 1;
-
- while (_ready && samplesLeft) {
- int32 render = samplesLeft;
-
- for (int i = 0; i < 2; i++) {
- if (_timers[i].enabled && _timers[i].cb) {
- if (!_timers[i].smpTillCb) {
- (this->*_timers[i].cb)();
- _timers[i].smpTillCb = _timers[i].smpPerCb;
-
- _timers[i].smpTillCbRem += _timers[i].smpPerCbRem;
- if (_timers[i].smpTillCbRem >= _timerbase) {
- _timers[i].smpTillCb++;
- _timers[i].smpTillCbRem -= _timerbase;
- }
- }
- render = MIN(render, _timers[i].smpTillCb);
- }
- }
-
- samplesLeft -= render;
-
- for (int i = 0; i < 2; i++) {
- if (_timers[i].enabled && _timers[i].cb) {
- _timers[i].smpTillCb -= render;
- }
- }
-
- nextTick(tmp, render);
-
- if (_ssg)
- _ssg->nextTick(tmp, render);
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_prc)
- _prc->nextTick(tmp, render);
-#endif
-
- nextTickEx(tmp, render);
-
- for (int i = 0; i < render; ++i) {
- int32 l = CLIP<int32>(tmp[i << 1], -32767, 32767);
- buffer[i << 1] = (int16) l;
- int32 r = CLIP<int32>(tmp[(i << 1) + 1], -32767, 32767);
- buffer[(i << 1) + 1] = (int16) r;
- }
-
- buffer += (render << 1);
- tmp += (render << 1);
- }
-
- delete[] tmpStart;
- return numSamples;
-}
-
-void TownsPC98_FmSynth::deinit() {
- _ready = false;
- _mixer->stopHandle(_soundHandle);
- _timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback;
-}
-
-uint8 TownsPC98_FmSynth::readSSGStatus() {
- return _ssg->chanEnable();
-}
-
-void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) {
- Common::StackLock lock(_mutex);
- _volumeA = CLIP<uint16>(volA, 0, Audio::Mixer::kMaxMixerVolume);
- _volumeB = CLIP<uint16>(volB, 0, Audio::Mixer::kMaxMixerVolume);
- if (_ssg)
- _ssg->setVolumeIntern(_volumeA, _volumeB);
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_prc)
- _prc->setVolumeIntern(_volumeA, _volumeB);
-#endif
-}
-
-void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
- Common::StackLock lock(_mutex);
- _volMaskA = channelMaskA;
- _volMaskB = channelMaskB;
- if (_ssg)
- _ssg->setVolumeChannelMasks(_volMaskA >> _numChan, _volMaskB >> _numChan);
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- if (_prc)
- _prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG));
-#endif
-}
-
-void TownsPC98_FmSynth::generateTables() {
- delete[] _oprRates;
- _oprRates = new uint8[128];
-
- WRITE_BE_UINT32(_oprRates + 32, _numChan == 6 ? 0x90900000 : 0x00081018);
- WRITE_BE_UINT32(_oprRates + 36, _numChan == 6 ? 0x00001010 : 0x00081018);
- memset(_oprRates, 0x90, 32);
- memset(_oprRates + 96, 0x80, 32);
- uint8 *dst = (uint8 *)_oprRates + 40;
- for (int i = 0; i < 40; i += 4)
- WRITE_BE_UINT32(dst + i, 0x00081018);
- for (int i = 0; i < 48; i += 4)
- WRITE_BE_UINT32(dst + i, 0x00081018);
- dst += 40;
- for (uint8 i = 0; i < 16; i ++) {
- uint8 v = (i < 12) ? i : 12;
- *dst++ = ((4 + v) << 3);
- }
-
- delete[] _oprRateshift;
- _oprRateshift = new uint8[128];
- memset(_oprRateshift, 0, 128);
- dst = (uint8 *)_oprRateshift + 32;
- for (int i = 11; i; i--) {
- memset(dst, i, 4);
- dst += 4;
- }
-
- delete[] _oprFrq;
- _oprFrq = new uint32[0x1000];
- for (uint32 i = 0; i < 0x1000; i++)
- _oprFrq[i] = (uint32)(_baserate * (float)(i << 11));
-
- delete[] _oprAttackDecay;
- _oprAttackDecay = new uint8[152];
- memset(_oprAttackDecay, 0, 152);
- for (int i = 0; i < 36; i++)
- WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]);
-
- delete[] _oprSinTbl;
- _oprSinTbl = new uint32[1024];
- for (int i = 0; i < 1024; i++) {
- double val = sin((double)(((i << 1) + 1) * PI / 1024.0));
- double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0;
- int32 i_dcb = (int32)(2.0 * d_dcb);
- i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1);
- _oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1);
- }
-
- delete[] _oprLevelOut;
- _oprLevelOut = new int32[0x1a00];
- for (int i = 0; i < 256; i++) {
- double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i)));
- int32 val_int = ((int32) val) >> 4;
- _oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2;
- _oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1];
- for (int ii = 1; ii < 13; ++ii) {
- _oprLevelOut[(i << 1) + (ii << 9)] = _oprLevelOut[i << 1] >> ii;
- _oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)];
- }
- }
-
- uint8 *dtt = new uint8[128];
- memset(dtt, 0, 36);
- memset(dtt + 36, 1, 8);
- memcpy(dtt + 44, _detSrc, 84);
-
- delete[] _oprDetune;
- _oprDetune = new int32[256];
- for (int i = 0; i < 128; i++) {
- _oprDetune[i] = (int32)((float)dtt[i] * _baserate * 64.0);
- _oprDetune[i + 128] = -_oprDetune[i];
- }
-
- delete[] dtt;
-}
-
-void TownsPC98_FmSynth::nextTick(int32 *buffer, uint32 bufferSize) {
- if (!_ready)
- return;
-
- for (int i = 0; i < _numChan; i++) {
- TownsPC98_FmSynthOperator **o = _chanInternal[i].opr;
-
- if (_chanInternal[i].updateEnvelopeParameters) {
- _chanInternal[i].updateEnvelopeParameters = false;
- for (int ii = 0; ii < 4 ; ii++)
- o[ii]->updatePhaseIncrement();
- }
-
- for (uint32 ii = 0; ii < bufferSize ; ii++) {
- int32 phbuf1, phbuf2, output;
- phbuf1 = phbuf2 = output = 0;
-
- int32 *leftSample = &buffer[ii * 2];
- int32 *rightSample = &buffer[ii * 2 + 1];
- int32 *del = &_chanInternal[i].feedbuf[2];
- int32 *feed = _chanInternal[i].feedbuf;
-
- switch (_chanInternal[i].algorithm) {
- case 0:
- o[0]->generateOutput(0, feed, phbuf1);
- o[2]->generateOutput(*del, 0, phbuf2);
- *del = 0;
- o[1]->generateOutput(phbuf1, 0, *del);
- o[3]->generateOutput(phbuf2, 0, output);
- break;
- case 1:
- o[0]->generateOutput(0, feed, phbuf1);
- o[2]->generateOutput(*del, 0, phbuf2);
- o[1]->generateOutput(0, 0, phbuf1);
- o[3]->generateOutput(phbuf2, 0, output);
- *del = phbuf1;
- break;
- case 2:
- o[0]->generateOutput(0, feed, phbuf2);
- o[2]->generateOutput(*del, 0, phbuf2);
- o[1]->generateOutput(0, 0, phbuf1);
- o[3]->generateOutput(phbuf2, 0, output);
- *del = phbuf1;
- break;
- case 3:
- o[0]->generateOutput(0, feed, phbuf2);
- o[2]->generateOutput(0, 0, *del);
- o[1]->generateOutput(phbuf2, 0, phbuf1);
- o[3]->generateOutput(*del, 0, output);
- *del = phbuf1;
- break;
- case 4:
- o[0]->generateOutput(0, feed, phbuf1);
- o[2]->generateOutput(0, 0, phbuf2);
- o[1]->generateOutput(phbuf1, 0, output);
- o[3]->generateOutput(phbuf2, 0, output);
- *del = 0;
- break;
- case 5:
- o[0]->generateOutput(0, feed, phbuf1);
- o[2]->generateOutput(*del, 0, output);
- o[1]->generateOutput(phbuf1, 0, output);
- o[3]->generateOutput(phbuf1, 0, output);
- *del = phbuf1;
- break;
- case 6:
- o[0]->generateOutput(0, feed, phbuf1);
- o[2]->generateOutput(0, 0, output);
- o[1]->generateOutput(phbuf1, 0, output);
- o[3]->generateOutput(0, 0, output);
- *del = 0;
- break;
- case 7:
- o[0]->generateOutput(0, feed, output);
- o[2]->generateOutput(0, 0, output);
- o[1]->generateOutput(0, 0, output);
- o[3]->generateOutput(0, 0, output);
- *del = 0;
- break;
- };
-
- int32 finOut = (output << 2) / ((_numChan + _numSSG - 3) / 3);
-
- if ((1 << i) & _volMaskA)
- finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
-
- if ((1 << i) & _volMaskB)
- finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
-
- if (_chanInternal[i].enableLeft)
- *leftSample += finOut;
-
- if (_chanInternal[i].enableRight)
- *rightSample += finOut;
- }
- }
-}
-
-const uint32 TownsPC98_FmSynth::_adtStat[] = {
- 0x00010001, 0x00010001, 0x00010001, 0x01010001,
- 0x00010101, 0x00010101, 0x00010101, 0x01010101,
- 0x01010101, 0x01010101, 0x01010102, 0x01010102,
- 0x01020102, 0x01020102, 0x01020202, 0x01020202,
- 0x02020202, 0x02020202, 0x02020204, 0x02020204,
- 0x02040204, 0x02040204, 0x02040404, 0x02040404,
- 0x04040404, 0x04040404, 0x04040408, 0x04040408,
- 0x04080408, 0x04080408, 0x04080808, 0x04080808,
- 0x08080808, 0x08080808, 0x10101010, 0x10101010
-};
-
-const uint8 TownsPC98_FmSynth::_detSrc[] = {
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
- 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07,
- 0x08, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
- 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07,
- 0x08, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
- 0x10, 0x10, 0x10, 0x10, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05,
- 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a,
- 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14,
- 0x16, 0x16, 0x16, 0x16
-};
-
-const int TownsPC98_FmSynth::_ssgTables[] = {
- 0x01202A, 0x0092D2, 0x006B42, 0x0053CB, 0x003DF8, 0x003053, 0x0022DA, 0x001A8C,
- 0x00129B, 0x000DC1, 0x000963, 0x0006C9, 0x000463, 0x0002FA, 0x0001B6, 0x0000FB,
- 0x0193B6, 0x01202A, 0x00CDB1, 0x0092D2, 0x007D7D, 0x006B42, 0x005ECD, 0x0053CB,
- 0x00480F, 0x003DF8, 0x0036B9, 0x003053, 0x00290A, 0x0022DA, 0x001E6B, 0x001A8C,
- 0x001639, 0x00129B, 0x000FFF, 0x000DC1, 0x000B5D, 0x000963, 0x0007FB, 0x0006C9,
- 0x000575, 0x000463, 0x00039D, 0x0002FA, 0x000242, 0x0001B6, 0x00014C, 0x0000FB
-};
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
-const uint8 TownsPC98_FmSynth::_percussionData[] = {
- 0, 24, 1, 192, 1, 216, 2, 128, 4, 88, 23, 64, 27, 152, 1, 128, 29, 24, 2, 128, 31, 152, 0, 128, 136, 128, 128, 128, 0, 136, 97, 103, 153, 139, 34, 163, 72, 195, 27, 69, 1, 154, 137, 35, 8, 51, 169, 122, 164, 75, 133, 203, 81, 146, 168, 121, 185, 68, 202, 8, 33, 237, 49, 177, 12, 133, 140, 17, 160, 42, 161, 10, 0, 137, 176, 57,
- 233, 41, 160, 136, 235, 65, 177, 137, 128, 26, 164, 28, 3, 157, 51, 137, 1, 152, 113, 161, 40, 146, 115, 192, 56, 5, 169, 66, 161, 56, 1, 50, 145, 59, 39, 168, 97, 1, 160, 57, 7, 153, 50, 153, 32, 2, 25, 129, 32, 20, 186, 66, 129, 24, 153, 164, 142, 130, 169, 153, 26, 242, 138, 217, 9, 128, 204, 58, 209, 172, 40, 176, 141,
- 128, 155, 144, 203, 139, 0, 235, 9, 177, 172, 0, 185, 168, 138, 25, 240, 59, 211, 139, 19, 176, 90, 160, 17, 26, 132, 41, 1, 5, 25, 3, 50, 144, 115, 147, 42, 39, 152, 41, 3, 56, 193, 105, 130, 155, 66, 200, 26, 19, 218, 154, 49, 201, 171, 138, 176, 251, 139, 185, 172, 136, 189, 139, 145, 207, 41, 160, 171, 152, 186, 139,
- 186, 141, 128, 218, 171, 51, 217, 170, 56, 163, 12, 4, 155, 81, 147, 42, 37, 152, 32, 54, 136, 49, 50, 48, 37, 32, 69, 0, 17, 50, 50, 83, 2, 16, 68, 20, 8, 66, 4, 154, 84, 145, 24, 33, 24, 32, 17, 18, 145, 32, 22, 168, 49, 163, 1, 33, 50, 184, 115, 129, 25, 66, 1, 24, 67, 2, 80, 35, 40, 53, 2, 65, 51, 19, 67, 37, 0, 52, 35, 49, 37,
- 34, 49, 37, 17, 52, 17, 35, 35, 35, 34, 32, 49, 33, 152, 34, 145, 24, 24, 128, 138, 128, 184, 9, 177, 171, 168, 185, 155, 152, 172, 155, 186, 172, 185, 172, 155, 186, 173, 153, 202, 187, 185, 202, 170, 171, 202, 186, 169, 170, 170, 171, 139, 154, 171, 153, 154, 169, 10, 168, 154, 128, 168, 154, 0, 153, 152, 136, 137,
- 128, 153, 0, 152, 8, 128, 137, 0, 136, 136, 8, 9, 8, 9, 8, 24, 153, 128, 136, 153, 144, 0, 161, 138, 1, 169, 136, 128, 160, 168, 152, 153, 138, 137, 154, 153, 153, 154, 153, 170, 168, 170, 185, 168, 169, 154, 169, 171, 153, 169, 170, 153, 152, 154, 153, 137, 169, 137, 136, 144, 152, 144, 128, 128, 144, 129, 129, 0, 33,
- 0, 17, 17, 17, 33, 33, 18, 18, 34, 34, 34, 34, 34, 34, 35, 19, 35, 19, 35, 35, 18, 19, 18, 35, 18, 33, 0, 8, 8, 8, 8, 8, 8, 8, 160, 205, 65, 176, 171, 203, 16, 240, 95, 242, 120, 145, 156, 66, 177, 26, 19, 153, 9, 35, 35, 239, 56, 132, 138, 154, 50, 145, 203, 25, 32, 20, 237, 24, 130, 138, 160, 27, 39, 173, 50, 203, 64, 145, 139,
- 18, 168, 48, 146, 171, 65, 18, 176, 12, 52, 128, 25, 5, 57, 240, 104, 161, 25, 129, 18, 188, 114, 160, 26, 36, 200, 154, 18, 1, 128, 186, 73, 162, 173, 32, 184, 25, 144, 137, 234, 8, 154, 32, 160, 158, 18, 187, 81, 2, 235, 41, 36, 144, 154, 17, 67, 128, 33, 160, 114, 146, 26, 37, 33, 232, 41, 130, 41, 178, 29, 50, 251, 24,
- 1, 153, 138, 160, 76, 179, 155, 11, 0, 38, 252, 41, 146, 41, 178, 27, 193, 43, 39, 170, 136, 17, 129, 8, 49, 233, 48, 129, 11, 6, 26, 130, 136, 128, 64, 1, 248, 105, 145, 9, 16, 144, 140, 5, 25, 168, 16, 186, 48, 5, 171, 217, 57, 134, 171, 8, 34, 188, 20, 203, 41, 6, 155, 161, 89, 164, 140, 2, 136, 51, 202, 41, 131, 56, 144,
- 8, 97, 144, 146, 13, 69, 200, 42, 130, 25, 152, 57, 6, 220, 88, 177, 26, 148, 9, 168, 8, 67, 192, 156, 65, 145, 137, 10, 4, 154, 18, 157, 67, 160, 154, 1, 50, 188, 82, 170, 82, 185, 49, 220, 97, 144, 10, 8, 16, 145, 9, 136, 18, 202, 51, 184, 141, 114, 179, 139, 24, 19, 8, 250, 121, 160, 40, 160, 10, 18, 152, 168, 42, 35, 216,
- 187, 120, 145, 18, 156, 203, 84, 144, 9, 144, 26, 66, 161, 13, 1, 128, 17, 154, 18, 142, 6, 154, 65, 192, 29, 35, 186, 64, 192, 24, 9, 146, 56, 185, 16, 248, 121, 176, 40, 129, 136, 171, 96, 147, 140, 50, 203, 64, 144, 41, 128, 161, 187, 71, 200, 24, 129, 24, 217, 56, 20, 220, 24, 4, 169, 9, 1, 33, 201, 26, 134, 141, 51, 201,
- 25, 16, 33, 235, 32, 144, 33, 153, 169, 99, 160, 11, 3, 136, 58, 210, 33, 203, 48, 163, 17, 219, 128, 140, 38, 8, 184, 141, 50, 131, 159, 33, 128, 153, 25, 18, 153, 88, 242, 43, 3, 9, 136, 157, 53, 202, 40, 145, 25, 2, 204, 105, 146, 156, 66, 152, 8, 153, 33, 128, 129, 136, 153, 50, 186, 55, 188, 51, 249, 64, 178, 27, 128,
- 48, 177, 156, 18, 35, 175, 51, 189, 32, 51, 234, 155, 69, 184, 26, 2, 152, 9, 17, 136, 144, 137, 50, 235, 115, 216, 24, 2, 170, 67, 187, 49, 129, 155, 4, 27, 129, 56, 232, 43, 39, 203, 40, 3, 154, 169, 66, 184, 114, 224, 25, 2, 9, 128, 11, 35, 155, 18, 11, 202, 84, 169, 26, 5, 154, 8, 160, 98, 185, 17, 187, 50, 23, 188, 33,
- 1, 139, 4, 154, 90, 147, 12, 3, 43, 2, 170, 171, 103, 193, 28, 132, 137, 8, 129, 24, 170, 50, 201, 42, 35, 202, 169, 52, 201, 33, 218, 40, 39, 203, 0, 40, 147, 29, 163, 139, 83, 185, 1, 4, 159, 34, 160, 12, 21, 155, 40, 129, 137, 58, 151, 13, 2, 136, 144, 16, 153, 40, 17, 131, 207, 51, 144, 140, 4, 154, 17, 146, 170, 73, 163,
- 44, 164, 12, 152, 37, 203, 17, 128, 144, 139, 23, 154, 128, 138, 38, 216, 41, 1, 0, 233, 73, 131, 171, 49, 136, 9, 164, 46, 3, 171, 32, 0, 145, 157, 38, 187, 64, 176, 58, 134, 155, 18, 136, 217, 64, 1, 200, 140, 38, 153, 170, 66, 161, 8, 169, 65, 185, 98, 200, 41, 3, 155, 144, 58, 23, 187, 1, 145, 40, 147, 189, 32, 68, 249,
- 1, 112, 255, 199, 195, 19, 108, 76, 187, 247, 247, 183, 40, 168, 212, 245, 199, 227, 68, 45, 59, 10, 145, 177, 198, 24, 130, 76, 26, 193, 180, 129, 0, 162, 42, 160, 199, 162, 0, 16, 152, 137, 132, 168, 195, 130, 162, 181, 227, 163, 161, 179, 211, 180, 179, 164, 128, 162, 161, 194, 164, 179, 40, 153, 195, 213, 146, 178,
- 147, 176, 50, 186, 161, 196, 151, 58, 16, 28, 162, 160, 131, 122, 155, 33, 241, 146, 128, 40, 26, 128, 154, 36, 170, 89, 59, 9, 24, 144, 77, 161, 8, 177, 112, 139, 33, 232, 148, 24, 41, 61, 9, 26, 162, 32, 30, 58, 153, 32, 59, 73, 59, 11, 79, 137, 57, 9, 49, 30, 24, 153, 131, 25, 106, 61, 153, 73, 28, 56, 27, 41, 137, 148,
- 76, 43, 74, 58, 13, 161, 3, 171, 149, 32, 77, 10, 74, 42, 168, 16, 0, 123, 138, 129, 162, 178, 225, 50, 140, 161, 0, 147, 10, 129, 41, 244, 210, 165, 1, 152, 24, 162, 184, 166, 32, 144, 59, 216, 132, 177, 8, 145, 67, 143, 146, 160, 183, 162, 130, 24, 192, 32, 225, 146, 144, 33, 44, 73, 30, 129, 137, 32, 76, 152, 25, 161,
- 2, 154, 32, 177, 132, 232, 2, 136, 210, 128, 149, 177, 32, 58, 27, 168, 225, 133, 8, 44, 107, 136, 25, 136, 17, 26, 58, 46, 16, 11, 145, 17, 144, 79, 136, 144, 136, 145, 152, 33, 31, 162, 130, 200, 82, 153, 74, 137, 147, 26, 0, 13, 133, 170, 149, 16, 192, 0, 178, 0, 128, 152, 182, 150, 9, 16, 9, 137, 33, 59, 63, 10, 152, 32,
- 179, 192, 5, 154, 228, 182, 145, 130, 144, 42, 128, 242, 2, 136, 41, 168, 17, 76, 57, 31, 129, 136, 17, 47, 8, 41, 138, 32, 138, 123, 59, 58, 10, 136, 161, 4, 46, 25, 145, 136, 129, 25, 56, 28, 91, 41, 154, 108, 9, 16, 44, 24, 137, 48, 15, 0, 194, 162, 41, 194, 56, 241, 163, 146, 0, 139, 7, 186, 150, 129, 152, 1, 208, 33, 176,
- 136, 164, 163, 185, 7, 138, 130, 242, 162, 163, 177, 88, 136, 184, 166, 146, 0, 25, 25, 177, 199, 146, 16, 136, 9, 145, 178, 178, 0, 147, 138, 229, 18, 152, 25, 144, 163, 246, 162, 129, 129, 184, 5, 152, 178, 145, 148, 136, 146, 95, 152, 128, 144, 33, 170, 81, 11, 40, 202, 131, 0, 243, 24, 1, 11, 148, 42, 24, 163, 140,
- 120, 9, 76, 58, 153, 145, 56, 30, 72, 46, 42, 9, 8, 57, 91, 76, 59, 26, 160, 129, 41, 76, 10, 57, 192, 163, 129, 16, 225, 2, 27, 40, 200, 48, 91, 226, 40, 145, 43, 177, 177, 182, 196, 145, 33, 184, 165, 17, 192, 163, 194, 129, 211, 128, 162, 197, 129, 0, 136, 211, 146, 8, 162, 144, 0, 167, 160, 1, 176, 150, 137, 1, 24, 243,
- 0, 129, 145, 25, 123, 169, 130, 168, 132, 41, 63, 42, 136, 137, 120, 26, 136, 8, 24, 89, 29, 58, 177, 193, 147, 1, 26, 162, 176, 167, 180, 8, 49, 28, 29, 178, 162, 88, 43, 42, 57, 43, 61, 8, 29, 129, 128, 128, 123, 137, 24, 243, 16, 136, 16, 46, 0, 169, 149, 128, 1, 60, 153, 72, 154, 90, 25, 25, 25, 8, 91, 73, 12, 16, 137, 144,
- 72, 11, 8, 167, 128, 129, 9, 138, 166, 193, 147, 162, 123, 137, 145, 1, 162, 26, 1, 219, 147, 129, 210, 147, 243, 1, 243, 16, 144, 145, 160, 131, 200, 4, 59, 75, 57, 218, 2, 178, 77, 24, 60, 11, 147, 10, 50, 141, 64, 27, 185, 122, 161, 41, 128, 90, 136, 24, 46, 16, 139, 16, 24, 28, 124, 9, 41, 8, 26, 121, 10, 42, 40, 139, 129,
- 0, 201, 135, 137, 56, 176, 176, 35, 215, 145, 1, 26, 145, 144, 160, 135, 138, 1, 177, 146, 146, 161, 65, 242, 136, 164, 177, 1, 1, 186, 151, 208, 148, 129, 10, 32, 241, 145, 163, 178, 17, 168, 136, 151, 168, 2, 148, 185, 133, 176, 130, 129, 154, 163, 215, 0, 146, 136, 40, 211, 161, 131, 171, 81, 144, 170, 21, 184, 56,
- 195, 168, 133, 177, 91, 16, 187, 5, 145, 153, 66, 172, 18, 177, 42, 120, 138, 27, 134, 26, 106, 42, 138, 146, 184, 66, 75, 46, 41, 168, 0, 145, 57, 91, 75, 27, 24, 27, 48, 169, 40, 122, 9, 109, 10, 8, 177, 146, 16, 74, 30, 129, 160, 162, 146, 41, 124, 138, 24, 145, 152, 3, 1, 14, 3, 139, 1, 192, 161, 151, 177, 122, 8, 10, 0,
- 176, 130, 129, 27, 88, 225, 0, 2, 154, 129, 129, 193, 49, 203, 81, 153, 226, 33, 0, 30, 0, 176, 179, 18, 9, 96, 156, 162, 148, 160, 129, 2, 29, 195, 128, 0, 56, 156, 20, 232, 129, 128, 32, 10, 144, 74, 183, 9, 145, 162, 1, 162, 138, 23, 171, 1, 164, 224, 34, 43, 43, 177, 200, 135, 161, 91, 57, 154, 177, 148, 145, 146, 58,
- 108, 136, 170, 35, 208, 177, 34, 128, 44, 129, 155, 151, 243, 16, 1, 154, 72, 193, 144, 18, 11, 122, 160, 153, 5, 192, 24, 130, 184, 132, 226, 0, 128, 153, 131, 181, 136, 65, 154, 128, 17, 170, 39, 28, 59, 144, 168, 80, 25, 47, 24, 26, 144, 32, 47, 41, 153, 161, 148, 8, 92, 9, 9, 129, 144, 33, 26, 47, 24, 137, 108, 25, 10,
- 17, 10, 73, 75, 47, 24, 184, 48, 8, 45, 57, 138, 136, 150, 10, 48, 139, 136, 35, 203, 121, 8, 27, 179, 161, 106, 0, 29, 16, 176, 179, 3, 185, 19, 227, 41, 145, 168, 61, 197, 177, 20, 10, 57, 42, 250, 147, 196, 16, 41, 138, 24, 195, 208, 135, 137, 0, 145, 160, 2, 210, 146, 195, 177, 132, 136, 153, 167, 210, 146, 162, 40, 8,
- 138, 148, 227, 145, 17, 137, 40, 169, 179, 130, 242, 2, 196, 9, 146, 145, 169, 167, 146, 130, 137, 136, 51, 220, 17, 163, 28, 74, 10, 76, 40, 140, 5, 137, 43, 18, 12, 107, 137, 40, 8, 201, 50, 0, 143, 3, 138, 161, 134, 138, 104, 169, 16, 162, 160, 121, 25, 28, 129, 152, 32, 56, 14, 16, 184, 146, 3, 46, 25, 176, 129, 179,
- 193, 17, 130, 202, 135, 8, 57, 25, 154, 148, 184, 120, 9, 153, 211, 165, 24, 128, 26, 17, 242, 161, 18, 185, 81, 42, 11, 17, 12, 25, 181, 137, 66, 42, 47, 41, 184, 166, 129, 24, 91, 27, 136, 196, 0, 0, 74, 28, 178, 161, 149, 160, 32, 8, 225, 32, 128, 59, 8, 169, 50, 139, 47, 72, 186, 16, 132, 9, 122, 9, 160, 146, 144, 89, 153,
- 10, 149, 178, 0, 121, 11, 146, 152, 162, 48, 13, 123, 177, 24, 0, 106, 27, 9, 144, 132, 12, 17, 0, 168, 0, 181, 56, 169, 129, 242, 195, 129, 17, 154, 64, 161, 244, 16, 137, 24, 144, 144, 164, 129, 75, 42, 176, 149, 9, 179, 148, 203, 4, 166, 136, 163, 128, 227, 163, 8, 57, 11, 30, 165, 0, 74, 59, 62, 9, 208, 131, 144, 40, 76,
- 26, 27, 196, 129, 1, 25, 43, 49, 174, 67, 153, 136, 106, 152, 41, 25, 28, 2, 43, 44, 104, 45, 59, 8, 43, 128, 144, 120, 25, 12, 17, 152, 9, 130, 155, 151, 145, 74, 40, 13, 48, 192, 58, 90, 43, 43, 177, 146, 49, 31, 75, 24, 217, 131, 0, 76, 26, 152, 149, 161, 24, 74, 154, 193, 166, 145, 32, 27, 161, 164, 176, 135, 152, 24, 193,
- 162, 146, 164, 58, 227, 193, 148, 161, 128, 18, 234, 130, 180, 145, 2, 200, 1, 163, 186, 98, 184, 129, 149, 153, 49, 42, 186, 151, 242, 129, 1, 43, 8, 177, 212, 165, 8, 40, 137, 24, 8, 144, 90, 9, 25, 48, 44, 46, 24, 138, 40, 144, 108, 58, 27, 128, 181, 128, 80, 29, 42, 152, 162, 130, 25, 106, 136, 11, 148, 8, 144, 128, 136,
- 112, 139, 80, 153, 24, 136, 129, 46, 0, 60, 129, 208, 1, 3, 13, 57, 168, 144, 1, 242, 17, 9, 26, 2, 185, 27, 55, 140, 73, 137, 179, 16, 192, 3, 145, 143, 33, 9, 171, 135, 160, 17, 137, 10, 151, 168, 3, 178, 44, 17, 208, 144, 167, 0, 40, 155, 16, 167, 152, 18, 144, 26, 160, 199, 1, 136, 91, 136, 160, 178, 150, 161, 1, 10, 181,
- 145, 161, 1, 145, 161, 198, 2, 9, 90, 137, 177, 160, 150, 40, 29, 129, 144, 145, 162, 57, 77, 169, 16, 148, 42, 42, 40, 141, 34, 170, 121, 154, 210, 131, 162, 107, 8, 9, 160, 195, 40, 73, 139, 18, 224, 162, 34, 139, 0, 244, 178, 163, 24, 26, 146, 194, 166, 49, 29, 42, 137, 130, 192, 16, 93, 128, 154, 19, 59, 11, 122, 11,
- 146, 177, 120, 42, 26, 43, 164, 152, 17, 60, 63, 137, 128, 48, 10, 58, 92, 9, 59, 91, 75, 139, 32, 25, 25, 61, 74, 28, 177, 40, 130, 74, 29, 73, 168, 130, 128, 48, 14, 8, 77, 9, 25, 26, 179, 211, 32, 78, 26, 41, 152, 161, 180, 89, 59, 9, 153, 166, 160, 3, 26, 57, 106, 154, 88, 184, 40, 1, 27, 58, 73, 143, 131, 169, 3, 161, 184,
- 122, 152, 16, 181, 145, 129, 17, 15, 129, 193, 147, 145, 192, 33, 193, 162, 183, 163, 136, 178, 129, 178, 197, 2, 41, 216, 131, 168, 163, 181, 226, 163, 178, 1, 33, 187, 166, 212, 129, 1, 27, 24, 162, 184, 151, 8, 16, 160, 144, 181, 210, 72, 168, 128, 32, 42, 25, 40, 142, 5, 185, 88, 58, 11, 58, 177, 32, 129, 63, 42, 136,
- 186, 53, 29, 75, 58, 144, 144, 129, 77, 128, 11, 144, 133, 29, 40, 152, 24, 161, 129, 80, 155, 60, 3, 12, 89, 8, 60, 152, 152, 49, 136, 47, 57, 224, 129, 16, 41, 90, 139, 162, 147, 170, 51, 169, 27, 17, 95, 26, 26, 160, 5, 139, 48, 76, 10, 228, 146, 1, 136, 44, 161, 147, 209, 130, 137, 73, 224, 1, 162, 195, 32, 210, 177, 180,
- 179, 148, 145, 154, 132, 242, 146, 1, 152, 32, 192, 1, 144, 155, 7, 177, 168, 5, 138, 178, 148, 152, 150, 136, 89, 152, 9, 41, 196, 145, 40, 28, 16, 8, 10, 178, 167, 24, 1, 44, 123, 137, 136, 145, 194, 48, 27, 74, 26, 192, 179, 135, 136, 88, 27, 10, 177, 163, 164, 128, 73, 24, 31, 8, 0, 192, 149, 144, 129, 9, 106, 41, 200,
- 161, 151, 41, 138, 0, 24, 226, 162, 49, 42, 11, 90, 136, 136, 152, 17, 145, 10, 63, 40, 11, 56, 245, 162, 16, 26, 73, 11, 144, 135, 137, 58, 106, 10, 25, 8, 57, 137, 28, 33, 129, 156, 113, 10, 10, 161, 18, 8, 153, 77, 3, 217, 0, 1, 242, 128, 193, 18, 128, 75, 60, 178, 154, 37, 45, 58, 29, 144, 1, 184, 66, 41, 29, 8, 145, 10,
- 194, 33, 148, 170, 107, 89, 139, 128, 163, 178, 16, 63, 59, 176, 144, 151, 129, 42, 74, 10, 129, 192, 2, 128, 154, 97, 192, 0, 177, 128, 178, 183, 16, 16, 155, 149, 145, 184, 84, 138, 8, 192, 161, 20, 225, 0, 130, 138, 165, 0, 28, 148, 153, 18, 209, 128, 88, 153, 89, 152, 9, 17, 9, 29, 130, 43, 122, 153, 24, 32, 202, 49,
- 24, 43, 106, 154, 130, 193, 27, 51, 29, 28, 133, 138, 65, 11, 123, 25, 10, 40, 152, 44, 130, 26, 43, 148, 45, 73, 140, 33, 8, 153, 88, 128, 61, 144, 42, 59, 225, 128, 18, 155, 50, 75, 186, 20, 202, 120, 144, 42, 92, 176, 162, 165, 25, 2, 169, 152, 135, 185, 19, 152, 8, 146, 160, 123, 195, 137, 132, 209, 0, 16, 11, 2, 242,
- 146, 164, 152, 73, 193, 136, 130, 178, 1, 136, 169, 23, 169, 128, 164, 242, 129, 178, 129, 32, 138, 180, 167, 153, 132, 8, 138, 2, 209, 4, 138, 1, 128, 138, 92, 136, 44, 129, 136, 162, 33, 63, 40, 141, 2, 160, 144, 106, 137, 64, 155, 17, 129, 60, 30, 146, 26, 17, 28, 48, 46, 169, 51, 154, 91, 137, 41, 26, 32, 143, 18, 138,
- 1, 32, 28, 123, 177, 9, 181, 195, 56, 57, 14, 145, 161, 17, 17, 31, 41, 152, 145, 194, 194, 20, 153, 41, 9, 243, 129, 180, 0, 128, 45, 16, 43, 170, 135, 144, 16, 25, 42, 137, 242, 163, 194, 16, 0, 57, 14, 130, 194, 178, 16, 33, 30, 8, 59, 211, 163, 160, 5, 137, 44, 10, 17, 170, 3, 120, 9, 44, 146, 136, 131, 140, 91, 9, 171,
- 7, 161, 32, 73, 13, 8, 161, 40, 106, 11, 25, 129, 59, 0, 49, 31, 42, 28, 40, 11, 0, 81, 176, 61, 32, 138, 25, 178, 241, 148, 136, 106, 8, 136, 128, 177, 90, 8, 155, 96, 176, 9, 18, 217, 132, 129, 10, 81, 156, 40, 178, 161, 36, 169, 76, 147, 203, 150, 0, 10, 146, 200, 147, 149, 128, 144, 148, 154, 182, 24, 0, 137, 11, 134, 211,
- 24, 136, 129, 145, 209, 33, 8, 43, 163, 243, 88, 41, 13, 0, 160, 145, 33, 31, 32, 185, 145, 4, 155, 17, 32, 47, 161, 128, 73, 160, 44, 56, 176, 75, 74, 12, 35, 141, 104, 137, 9, 89, 152, 58, 56, 44, 41, 30, 41, 40, 157, 48, 128, 154, 88, 41, 42, 8, 14, 3, 184, 59, 120, 152, 9, 56, 10, 128, 41, 57, 227, 186, 52, 152, 62, 8, 56,
- 242, 0, 58, 8, 156, 34, 243, 128, 24, 176, 51, 169, 58, 183, 192, 146, 164, 177, 18, 170, 7, 177, 208, 132, 161, 24, 136, 27, 147, 243, 128, 133, 10, 24, 161, 161, 178, 214, 17, 160, 25, 16, 161, 137, 165, 192, 48, 27, 72, 58, 218, 133, 162, 26, 72, 27, 10, 197, 178, 49, 138, 89, 56, 142, 1, 24, 11, 0, 44, 105, 10, 25, 0,
- 194, 9, 3, 47, 8, 138, 147, 18, 28, 48, 202, 147, 199, 146, 25, 161, 0, 145, 194, 163, 57, 11, 146, 248, 130, 32, 57, 63, 154, 16, 48, 14, 128, 144, 209, 133, 26, 56, 154, 182, 162, 195, 18, 152, 44, 194, 180, 168, 5, 24, 137, 138, 35, 192, 232, 66, 176, 161, 24, 41, 26, 244, 129, 163, 160, 75, 129, 226, 147, 40, 145, 61,
- 13, 130, 177, 17, 137, 112, 170, 130, 0, 136, 75, 152, 177, 241, 34, 0, 59, 156, 51, 186, 178, 91, 132, 137, 137, 122, 1, 45, 28, 50, 172, 57, 108, 8, 26, 136, 32, 152, 46, 144, 131, 171, 4, 152, 18, 141, 148, 1, 216, 32, 9, 60, 169, 66, 152, 128, 72, 90, 201, 1, 17, 201, 136, 3, 195, 26, 73, 133, 200, 176, 150, 146, 169,
- 24, 33, 178, 184, 151, 73, 11, 28, 72, 44, 153, 82, 153, 17, 42, 57, 78, 153, 8, 160, 0, 1, 123, 11, 19, 171, 195, 18, 59, 31, 129, 10, 162, 2, 58, 96, 142, 130, 26, 75, 128, 176, 17, 180, 123, 9, 90, 137, 211, 145, 32, 26, 76, 43, 145, 130, 12, 90, 41, 27, 58, 160, 160, 128, 178, 7, 76, 59, 0, 203, 180, 147, 33, 62, 10, 0, 243,
- 129, 146, 73, 29, 145, 144, 0, 26, 56, 153, 185, 83, 8, 76, 27, 166, 161, 193, 146, 131, 224, 145, 165, 161, 40, 168, 149, 162, 226, 2, 136, 138, 163, 131, 211, 0, 59, 146, 218, 148, 1, 192, 16, 16, 58, 248, 88, 144, 177, 136, 1, 58, 45, 9, 195, 197, 147, 48, 29, 10, 0, 162, 176, 64, 122, 9, 10, 17, 9, 153, 56, 75, 27, 31,
- 72, 136, 9, 129, 129, 61, 45, 59, 10, 161, 18, 122, 43, 59, 41, 169, 34, 155, 130, 131, 219, 120, 162, 27, 49, 208, 160, 131, 156, 66, 12, 145, 50, 240, 16, 136, 12, 162, 40, 129, 130, 15, 129, 162, 146, 180, 83, 139, 58, 217, 129, 177, 4, 0, 169, 197, 163, 144, 242, 131, 168, 179, 179, 17, 197, 145, 178, 164, 128, 160,
- 211, 2, 244, 163, 145, 162, 129, 212, 177, 163, 17, 208, 163, 195, 180, 57, 24, 170, 182, 164, 129, 0, 60, 60, 169, 149, 162, 177, 122, 26, 24, 136, 136, 133, 43, 27, 178, 56, 77, 24, 128, 240, 0, 2, 44, 46, 8, 128, 193, 146, 64, 27, 42, 16, 193, 25, 0, 192, 148, 11, 52, 47, 153, 147, 243, 0, 24, 73, 28, 144, 161, 150, 9,
- 8, 73, 170, 2, 162, 25, 27, 147, 167, 131, 29, 1, 168, 200, 165, 16, 91, 137, 8, 162, 176, 35, 41, 31, 24, 169, 50, 168, 58, 123, 144, 48, 128, 13, 73, 169, 144, 16, 57, 123, 44, 200, 163, 56, 153, 80, 10, 176, 146, 57, 94, 8, 152, 131, 9, 168, 125, 26, 145, 177, 132, 137, 41, 60, 26, 144, 243, 32, 192, 34, 60, 43, 26, 16,
- 249, 164, 16, 58, 61, 11, 130, 243, 146, 2, 42, 44, 27, 128, 165, 137, 49, 45, 28, 16, 43, 8, 211, 48, 28, 152, 105, 9, 9, 163, 161, 169, 35, 107, 42, 232, 164, 130, 168, 72, 42, 168, 210, 148, 144, 136, 129, 3, 217, 194, 50, 27, 192, 41, 210, 147, 40, 76, 226, 1, 161, 1, 155, 132, 145, 147, 171, 67, 173, 210, 132, 161, 106,
- 137, 56, 169, 209, 131, 64, 13, 129, 9, 194, 17, 57, 61, 169, 17, 128, 40, 31, 16, 10, 162, 57, 61, 75, 139, 40, 242, 17, 58, 59, 138, 179, 144, 50, 105, 140, 179, 243, 57, 40, 26, 9, 243, 130, 24, 29, 57, 128, 210, 129, 25, 59, 91, 137, 162, 178, 72, 27, 181, 168, 19, 129, 8, 184, 231, 147, 178, 32, 28, 184, 198, 148, 144,
- 1, 26, 128, 16, 192, 2, 26, 144, 244, 129, 0, 16, 10, 197, 177, 181, 1, 41, 9, 178, 165, 211, 129, 25, 145, 137, 210, 147, 152, 210, 163, 132, 194, 17, 91, 169, 145, 181, 130, 9, 89, 137, 152, 178, 4, 128, 9, 63, 160, 128, 106, 8, 25, 43, 10, 32, 47, 26, 123, 152, 24, 40, 25, 27, 18, 186, 35, 158, 64, 42, 216, 33, 25, 58, 58,
- 45, 184, 147, 29, 72, 46, 9, 0, 178, 146, 58, 77, 26, 25, 209, 165, 128, 145, 17, 153, 128, 129, 148, 240, 129, 1, 40, 31, 0, 152, 242, 163, 16, 59, 44, 24, 243, 146, 128, 1, 26, 26, 179, 213, 145, 130, 176, 131, 40, 25, 145, 219, 179, 167, 8, 33, 59, 14, 176, 166, 16, 136, 74, 128, 176, 128, 149, 8, 8, 209, 148, 152, 0, 72,
- 153, 161, 178, 35, 62, 75, 154, 163, 153, 19, 62, 170, 133, 179, 136, 89, 12, 129, 164, 144, 3, 47, 58, 193, 177, 148, 0, 61, 43, 10, 129, 17, 41, 61, 43, 25, 8, 126, 26, 25, 137, 145, 34, 44, 45, 129, 216, 179, 1, 90, 25, 137, 32, 227, 8, 16, 9, 170, 49, 31, 32, 29, 128, 145, 148, 75, 25, 75, 153, 162, 192, 35, 12, 80, 136,
- 176, 8, 194, 24, 1, 176, 21, 154, 145, 80, 251, 130, 2, 30, 9, 8, 130, 145, 128, 98, 27, 26, 129, 136, 162, 15, 33, 168, 59, 65, 177, 77, 141, 1, 128, 168, 113, 10, 137, 178, 163, 146, 132, 74, 153, 224, 164, 33, 184, 19, 184, 228, 161, 17, 91, 152, 25, 146, 152, 44, 121, 9, 160, 145, 17, 25, 28, 93, 128, 152, 2, 25, 27, 161,
- 210, 129, 146, 45, 179, 227, 163, 162, 9, 40, 193, 148, 179, 57, 107, 140, 196, 32, 25, 57, 47, 136, 210, 130, 24, 40, 28, 152, 210, 182, 145, 40, 8, 129, 184, 147, 147, 140, 163, 166, 160, 34, 45, 144, 194, 161, 134, 41, 46, 152, 162, 162, 3, 44, 58, 75, 209, 162, 144, 57, 129, 47, 152, 130, 59, 16, 248, 129, 17, 26, 57,
- 9, 29, 167, 2, 60, 42, 138, 136, 209, 130, 90, 42, 42, 176, 146, 178, 120, 28, 8, 160, 145, 16, 33, 31, 1, 8, 160, 129, 128, 242, 164, 32, 152, 177, 146, 213, 196, 128, 40, 26, 160, 163, 180, 146, 108, 60, 144, 144, 136, 147, 137, 40, 90, 161, 3, 17, 219, 243, 33, 184, 130, 60, 136, 243, 178, 179, 132, 26, 8, 168, 212, 147,
- 16, 57, 42, 31, 145, 145, 160, 32, 43, 184, 66, 45, 180, 33, 140, 226, 1, 91, 152, 16, 144, 193, 162, 48, 77, 25, 137, 153, 17, 178, 78, 0, 0, 16, 14, 90, 152, 153, 19, 129, 13, 123, 137, 129, 160, 1, 73, 44, 9, 129, 0, 153, 120, 10, 9, 162, 195, 32, 139, 28, 151, 161, 2, 128, 26, 45, 193, 146, 48, 29, 146, 153, 194, 5, 59,
- 29, 128, 144, 195, 1, 64, 43, 208, 178, 149, 8, 9, 16, 240, 163, 129, 16, 42, 185, 181, 211, 24, 48, 45, 137, 149, 9, 24, 41, 75, 184, 177, 4, 43, 91, 128, 180, 16, 144, 29, 25, 184, 167, 1, 59, 60, 153, 148, 161, 146, 91, 42, 186, 4, 24, 145, 123, 11, 2, 178, 77, 136, 26, 25, 195, 40, 115, 61, 27, 168, 177, 3, 59, 79, 26, 25,
- 144, 1, 48, 13, 56, 154, 248, 1, 16, 9, 129, 8, 2, 178, 31, 130, 153, 162, 20, 15, 33, 170, 56, 40, 29, 28, 128, 152, 149, 144, 56, 120, 11, 162, 212, 129, 144, 145, 59, 180, 243, 147, 145, 144, 16, 152, 48, 241, 0, 161, 176, 1, 134, 10, 129, 200, 166, 144, 128, 121, 26, 24, 177, 178, 196, 48, 75, 138, 41, 180, 195, 26, 24,
- 89, 138, 24, 33, 187, 41, 84, 155, 57, 79, 136, 160, 210, 130, 0, 58, 58, 168, 243, 132, 27, 41, 75, 138, 3, 8, 61, 8, 29, 145, 179, 76, 24, 28, 146, 208, 2, 49, 140, 75, 196, 144, 0, 40, 44, 179, 208, 3, 176, 33, 15, 177, 2, 160, 106, 8, 160, 164, 164, 8, 73, 27, 226, 179, 161, 1, 57, 1, 196, 211, 128, 40, 156, 145, 166, 178,
- 131, 29, 128, 145, 162, 165, 40, 27, 216, 146, 135, 144, 40, 160, 194, 177, 145, 20, 139, 200, 151, 178, 17, 136, 40, 25, 205, 130, 17, 11, 17, 129, 156, 38, 26, 25, 137, 179, 163, 11, 79, 16, 12, 146, 147, 143, 89, 25, 136, 136, 25, 48, 26, 46, 129, 40, 29, 42, 29, 8, 145, 2, 56, 27, 62, 8, 25, 212, 161, 48, 43, 144, 129,
- 29, 145, 144, 41, 106, 10, 107, 43, 184, 131, 1, 36, 61, 13, 138, 2, 194, 1, 16, 27, 75, 186, 181, 151, 8, 1, 161, 138, 211, 129, 2, 59, 248, 129, 16, 0, 144, 63, 152, 150, 136, 24, 25, 128, 30, 161, 128, 17, 24, 225, 146, 10, 16, 0, 9, 227, 183, 129, 40, 60, 26, 162, 194, 181, 24, 90, 9, 24, 0, 176, 161, 193, 194, 35, 12, 63,
- 8, 210, 162, 1, 32, 78, 28, 152, 164, 144, 16, 48, 45, 137, 162, 147, 168, 152, 98, 27, 43, 33, 12, 160, 165, 129, 137, 63, 41, 153, 153, 151, 16, 91, 26, 8, 8, 9, 56, 10, 46, 24, 146, 57, 168, 160, 166, 241, 129, 32, 140, 16, 145, 179, 164, 137, 113, 138, 208, 131, 26, 25, 1, 42, 178, 196, 106, 24, 171, 18, 196, 8, 18, 29,
- 41, 194, 128, 3, 249, 57, 162, 152, 48, 184, 120, 160, 208, 33, 137, 74, 57, 187, 149, 129, 26, 35, 158, 72, 128, 168, 32, 26, 25, 180, 75, 2, 136, 15, 163, 161, 136, 120, 27, 41, 160, 128, 182, 56, 60, 25, 12, 178, 151, 128, 168, 72, 10, 152, 4, 177, 26, 147, 137, 113, 44, 42, 33, 220, 2, 152, 41, 82, 11, 210, 163, 184,
- 133, 162, 10, 196, 128, 3, 234, 40, 149, 152, 161, 1, 44, 129, 194, 4, 225, 16, 58, 168, 24, 194, 146, 146, 154, 49, 21, 218, 33, 152, 248, 129, 194, 147, 0, 28, 1, 195, 162, 20, 140, 42, 25, 160, 198, 1, 33, 136, 142, 3, 25, 24, 141, 16, 177, 208, 112, 0, 138, 41, 160, 130, 45, 60, 32, 170, 73, 24, 75, 59, 161, 176, 49, 159,
- 97, 26, 168, 149, 145, 32, 28, 25, 184, 211, 129, 179, 74, 73, 8, 153, 136, 193, 151, 160, 32, 48, 143, 9, 147, 181, 145, 32, 60, 9, 187, 133, 166, 144, 32, 152, 25, 136, 161, 150, 168, 145, 81, 10, 42, 0, 169, 182, 148, 136, 58, 41, 187, 182, 211, 131, 16, 137, 25, 243, 144, 129, 2, 9, 8, 202, 7, 25, 185, 21, 144, 136, 153,
- 65, 184, 137, 56, 151, 10, 153, 49, 16, 145, 14, 56, 176, 11, 192, 19, 89, 91, 44, 168, 147, 2, 8, 147, 63, 27, 1, 136, 229, 129, 73, 26, 136, 26, 137, 81, 170, 147, 77, 72, 12, 42, 42, 192, 24, 104, 91, 26, 27, 65, 177, 27, 32, 41, 60, 14, 136, 17, 170, 150, 129, 24, 58, 11, 16, 251, 162, 19, 57, 31, 0, 152, 129, 145, 17, 61,
- 14, 1, 129, 27, 129, 66, 169, 178, 74, 12, 11, 19, 198, 145, 75, 33, 138, 174, 133, 1, 184, 57, 40, 136, 169, 20, 1, 60, 174, 20, 154, 201, 67, 26, 162, 151, 42, 16, 138, 59, 130, 204, 20, 169, 59, 180, 59, 114, 184, 56, 178, 242, 128, 130, 43, 8, 194, 3, 229, 144, 33, 185, 144, 34, 181, 145, 168, 17, 149, 153, 74, 35, 220,
- 129, 128, 1, 88, 59, 75, 225, 136, 130, 168, 17, 144, 12, 151, 8, 25, 179, 8, 1, 240, 16, 8, 25, 145, 211, 41, 130, 138, 115, 169, 160, 163, 168, 84, 154, 74, 0, 170, 144, 211, 149, 2, 30, 128, 137, 9, 149, 1, 144, 58, 60, 57, 153, 178, 150, 17, 29, 27, 74, 25, 195, 152, 56, 15, 1, 25, 26, 152, 149, 80, 153, 57, 73, 140, 128,
- 160, 144, 113, 27, 56, 28, 25, 4, 42, 44, 137, 60, 171, 130, 50, 240, 8, 5, 139, 145, 1, 105, 137, 200, 80, 137, 145, 146, 178, 179, 160, 46, 16, 240, 195, 131, 128, 144, 24, 164, 198, 128, 0, 136, 137, 131, 194, 165, 177, 2, 161, 147, 11, 144, 188, 181, 148, 144, 23, 0, 28, 224, 128, 131, 192, 32, 1, 224, 1, 168, 132, 145,
- 9, 41, 208, 58, 137, 179, 151, 145, 16, 1, 30, 8, 145, 178, 1, 47, 32, 186, 72, 169, 146, 75, 8, 41, 48, 136, 89, 13, 48, 9, 10, 124, 26, 11, 42, 32, 129, 91, 77, 16, 12, 128, 42, 57, 138, 10, 60, 2, 63, 9, 0, 93, 128, 152, 90, 8, 10, 24, 40, 44, 144, 29, 49, 188, 48, 72, 25, 30, 177, 33, 128, 186, 120, 129, 186, 133, 152, 130,
- 24, 156, 51, 154, 8, 226, 2, 56, 155, 2, 179, 233, 167, 128, 24, 129, 176, 136, 151, 8, 184, 0, 33, 224, 152, 21, 177, 24, 10, 163, 16, 250, 17, 130, 171, 83, 137, 136, 37, 12, 56, 242, 154, 17, 160, 145, 82, 13, 3, 201, 128, 18, 137, 24, 162, 63, 162, 8, 107, 178, 128, 57, 158, 32, 24, 200, 18, 0, 106, 154, 73, 16, 248, 8,
- 73, 137, 57, 75, 0, 128, 12, 65, 137, 59, 75, 28, 144, 129, 122, 0, 58, 140, 160, 195, 145, 105, 56, 28, 153, 145, 164, 88, 8, 28, 25, 153, 9, 162, 113, 89, 153, 136, 33, 234, 147, 128, 41, 72, 11, 138, 151, 144, 145, 16, 43, 58, 248, 130, 178, 42, 4, 40, 10, 196, 154, 147, 216, 24, 7, 136, 10, 161, 148, 210, 161, 98, 138,
- 137, 128, 146, 176, 33, 105, 27, 43, 163, 49, 185, 6, 10, 136, 43, 67, 174, 161, 162, 151, 137, 1, 64, 200, 193, 24, 64, 200, 56, 145, 242, 24, 57, 137, 1, 128, 3, 162, 175, 80, 128, 162, 152, 25, 58, 175, 17, 17, 0, 200, 64, 168, 162, 91, 1, 154, 44, 211, 177, 35, 64, 160, 161, 144, 4, 241, 41, 209, 162, 25, 1, 3, 242, 176,
- 134, 153, 42, 41, 136, 135, 154, 2, 130, 46, 41, 161, 153, 180, 145, 34, 26, 46, 18, 242, 137, 146, 129, 25, 128, 11, 151, 161, 40, 179, 27, 122, 168, 59, 137, 181, 50, 172, 36, 56, 15, 9, 129, 137, 128, 75, 2, 58, 12, 52, 141, 8, 24, 58, 153, 157, 122, 145, 9, 1, 80, 27, 184, 32, 74, 219, 50, 57, 168, 153, 180, 48, 28, 143,
- 131, 144, 178, 65, 13, 48, 168, 162, 147, 155, 121, 9, 170, 5, 16, 153, 21, 29, 144, 161, 91, 0, 184, 57, 128, 137, 17, 159, 88, 178, 128, 105, 152, 9, 162, 33, 164, 141, 88, 178, 224, 1, 0, 16, 27, 185, 150, 161, 9, 4, 139, 16, 128, 160, 194, 144, 65, 180, 46, 40, 136, 27, 135, 160, 16, 44, 57, 145, 236, 2, 195, 40, 75, 177,
- 2, 200, 179, 146, 186, 104, 50, 141, 24, 169, 165, 148, 11, 97, 10, 11, 130, 177, 49, 57, 78, 42, 154, 128, 165, 59, 33, 28, 30, 1, 136, 16, 192, 41, 128, 152, 123, 136, 24, 1, 169, 113, 10, 11, 49, 153, 14, 147, 19, 45, 43, 8, 176, 210, 148, 8, 16, 11, 96, 144, 192, 163, 150, 10, 128, 43, 26, 150, 178, 165, 24, 41, 171, 18,
- 27, 215, 1, 8, 128, 136, 40, 35, 208, 11, 161, 193, 18, 73, 154, 133, 155, 165, 164, 10, 49, 154, 8, 199, 0, 2, 168, 64, 192, 0, 40, 162, 43, 202, 180, 150, 10, 106, 24, 185, 145, 131, 184, 113, 43, 24, 162, 187, 73, 146, 42, 81, 171, 121, 58, 155, 151, 16, 43, 32, 31, 9, 160, 146, 17, 136, 94, 10, 24, 145, 25, 9, 130, 59,
- 65, 13, 91, 25, 169, 146, 176, 112, 42, 59, 16, 217, 130, 20, 13, 25, 9, 40, 161, 138, 68, 169, 154, 18, 62, 154, 180, 145, 135, 152, 56, 58, 155, 165, 211, 8, 40, 42, 10, 198, 1, 2, 184, 57, 184, 224, 51, 154, 27, 134, 168, 19, 202, 73, 75, 184, 35, 176, 75, 24, 25, 209, 51, 157, 19, 30, 184, 179, 3, 33, 148, 45, 232, 146,
- 129, 168, 41, 32, 170, 149, 193, 35, 136, 16, 50, 191, 56, 146, 173, 149, 16, 24, 41, 30, 129, 168, 209, 3, 57, 31, 0, 16, 176, 147, 41, 152, 10, 17, 181, 14, 40, 144, 49, 170, 75, 97, 141, 25, 162, 146, 72, 177, 92, 137, 137, 19, 137, 153, 113, 154, 2, 41, 60, 129, 217, 2, 211, 152, 73, 42, 193, 197, 146, 147, 10, 59, 0,
- 192, 196, 132, 41, 160, 25, 88, 169, 16, 40, 241, 1, 153, 81, 28, 10, 147, 161, 209, 88, 75, 9, 161, 162, 180, 16, 43, 57, 235, 33, 56, 156, 129, 144, 2, 135, 31, 128, 145, 136, 163, 56, 59, 154, 57, 167, 160, 105, 137, 0, 138, 163, 3, 41, 47, 185, 211, 131, 41, 41, 60, 139, 182, 146, 16, 16, 43, 242, 144, 145, 129, 16, 179,
- 183, 1, 26, 9, 147, 240, 131, 160, 91, 74, 152, 184, 166, 178, 33, 140, 9, 4, 162, 233, 34, 136, 129, 144, 163, 60, 142, 144, 149, 128, 33, 73, 13, 161, 194, 131, 0, 26, 56, 142, 128, 163, 128, 1, 233, 56, 209, 41, 145, 194, 147, 179, 149, 64, 30, 8, 128, 216, 18, 24, 43, 43, 32, 153, 25, 74, 109, 137, 153, 48, 8, 137, 122,
- 25, 144, 26, 43, 59, 30, 33, 41, 27, 24, 96, 153, 160, 50, 76, 27, 47, 152, 145, 163, 73, 40, 14, 152, 131, 176, 74, 90, 8, 8, 200, 67, 155, 154, 50, 49, 155, 28, 124, 177, 152, 1, 2, 17, 62, 138, 180, 176, 4, 25, 9, 177, 245, 162, 129, 40, 25, 176, 164, 130, 172, 4, 8, 181, 194, 49, 11, 168, 154, 165, 133, 152, 40, 136, 226,
- 179, 19, 26, 185, 16, 167, 194, 16, 25, 57, 243, 136, 147, 1, 31, 25, 184, 132, 160, 33, 62, 138, 129, 130, 41, 121, 137, 153, 145, 26, 17, 107, 136, 179, 1, 61, 60, 26, 162, 168, 148, 64, 31, 25, 32, 168, 152, 64, 31, 137, 8, 129, 33, 62, 24, 137, 8, 16, 59, 47, 153, 33, 162, 91, 59, 41, 170, 145, 5, 43, 60, 41, 13, 178, 134,
- 57, 153, 12, 194, 227, 8, 2, 128, 57, 208, 162, 19, 216, 32, 178, 25, 128, 160, 48, 194, 195, 37, 155, 10, 33, 251, 163, 146, 16, 136, 12, 166, 195, 160, 148, 129, 176, 147, 178, 150, 160, 72, 162, 162, 193, 162, 60, 200, 145, 5, 144, 25, 122, 216, 129, 161, 130, 0, 10, 73, 1, 241, 2, 9, 168, 33, 13, 161, 165, 24, 64, 203,
- 50, 1, 14, 9, 9, 129, 161, 106, 33, 27, 13, 164, 128, 40, 41, 107, 169, 160, 33, 136, 60, 92, 168, 152, 2, 91, 57, 176, 129, 0, 144, 47, 136, 162, 164, 128, 80, 43, 154, 179, 213, 130, 74, 27, 0, 145, 145, 167, 58, 59, 160, 9, 26, 76, 8, 171, 5, 49, 28, 44, 169, 162, 183, 130, 72, 28, 144, 179, 228, 2, 25, 26, 129, 186, 151,
- 1, 75, 128, 169, 17, 178, 15, 57, 170, 16, 166, 16, 57, 8, 139, 162, 181, 1, 8, 152, 164, 181, 41, 81, 43, 10, 242, 145, 57, 139, 89, 8, 193, 18, 154, 32, 176, 10, 165, 129, 137, 147, 177, 134, 0, 25, 25, 201, 147, 227, 129, 72, 59, 185, 167, 128, 129, 160, 91, 25, 176, 130, 147, 145, 9, 160, 5, 202, 17, 16, 186, 136, 37,
- 177, 56, 76, 42, 169, 186, 48, 9, 145, 57, 24, 128, 41, 169, 134, 137, 145, 147, 28, 41, 168, 131, 228, 32, 27, 9, 60, 129, 178, 64, 60, 45, 25, 9, 24, 152, 49, 31, 136, 57, 42, 0, 25, 12, 181, 18, 153, 57, 96, 169, 177, 132, 153, 123, 9, 152, 129, 177, 17, 74, 43, 24, 169, 128, 121, 137, 25, 1, 139, 96, 42, 10, 146, 178, 18,
- 44, 29, 1, 161, 164, 146, 31, 137, 146, 177, 19, 1, 10, 26, 209, 165, 146, 43, 40, 138, 240, 130, 18, 144, 25, 40, 212, 1, 58, 11, 152, 196, 147, 10, 74, 26, 152, 225, 130, 146, 58, 60, 210, 145, 16, 148, 16, 185, 192, 18, 44, 42, 57, 199, 162, 1, 9, 87, 47, 186, 215, 231, 197, 179, 180, 195, 212, 164, 32, 59, 92, 126, 62,
- 41, 59, 76, 59, 60, 168, 179, 213, 197, 163, 72, 44, 25, 74, 126, 127, 127, 79, 26, 177, 148, 90, 27, 225, 247, 165, 0, 152, 147, 123, 138, 211, 164, 72, 126, 127, 46, 210, 196, 163, 228, 215, 64, 11, 210, 180, 1, 8, 58, 153, 1, 224, 149, 57, 76, 27, 24, 76, 42, 43, 136, 128, 243, 179, 130, 106, 60, 42, 42, 92, 28, 243, 231,
- 147, 24, 57, 44, 58, 94, 45, 8, 57, 139, 214, 148, 40, 77, 26, 9, 16, 10, 144, 64, 62, 43, 25, 123, 59, 138, 162, 48, 63, 26, 41, 92, 60, 43, 176, 3, 59, 232, 214, 164, 16, 75, 75, 76, 60, 153, 179, 33, 62, 26, 136, 40, 75, 169, 197, 163, 129, 57, 60, 59, 75, 138, 145, 64, 63, 138, 179, 1, 42, 136, 90, 43, 176, 214, 180, 1, 25,
- 152, 195, 129, 129, 106, 76, 60, 137, 145, 178, 2, 25, 10, 228, 130, 57, 59, 44, 41, 154, 165, 105, 76, 44, 144, 16, 76, 26, 41, 76, 26, 152, 1, 58, 26, 9, 193, 165, 16, 92, 26, 41, 77, 59, 76, 76, 60, 26, 136, 161, 130, 152, 195, 163, 211, 146, 0, 57, 11, 211, 130, 8, 25, 40, 62, 153, 162, 17, 109, 60, 153, 146, 40, 76, 60,
- 26, 160, 179, 211, 163, 32, 60, 42, 153, 179, 194, 199, 130, 24, 58, 43, 58, 27, 128, 161, 195, 129, 226, 196, 147, 90, 59, 75, 44, 136, 128, 145, 160, 148, 123, 59, 42, 26, 41, 26, 57, 27, 192, 215, 147, 57, 59, 27, 161, 145, 213, 130, 106, 76, 43, 9, 144, 162, 129, 177, 181, 130, 136, 194, 146, 40, 10, 129, 25, 210, 146,
- 178, 197, 196, 179, 196, 130, 8, 41, 9, 144, 178, 130, 209, 182, 17, 92, 43, 176, 147, 144, 212, 130, 136, 0, 177, 130, 73, 62, 10, 161, 130, 91, 75, 59, 43, 57, 46, 25, 41, 77, 10, 177, 164, 16, 26, 136, 210, 197, 179, 130, 128, 57, 77, 43, 25, 75, 10, 227, 179, 180, 179, 146, 128, 57, 185, 183, 163, 145, 0, 8, 8, 10, 119,
- 114, 120, 16, 210, 244, 60, 28, 41, 25, 152, 149, 56, 161, 35, 44, 89, 27, 24, 136, 24, 164, 211, 17, 233, 176, 136, 192, 129, 179, 17, 17, 25, 0, 10, 46, 160, 132, 49, 66, 24, 132, 177, 147, 193, 56, 72, 26, 29, 232, 168, 176, 12, 137, 41, 139, 147, 9, 1, 41, 15, 91, 136, 35, 148, 21, 18, 48, 40, 1, 168, 167, 144, 0, 42, 172,
- 177, 204, 193, 155, 232, 152, 152, 26, 152, 41, 146, 17, 6, 4, 65, 34, 35, 135, 4, 16, 32, 9, 24, 186, 176, 0, 250, 153, 204, 186, 173, 154, 153, 177, 3, 65, 41, 34, 145, 134, 35, 65, 98, 49, 50, 50, 2, 33, 169, 138, 155, 175, 170, 172, 204, 192, 138, 234, 136, 155, 136, 10, 32, 18, 5, 52, 48, 24, 162, 17, 67, 54, 66, 51, 34,
- 131, 184, 174, 234, 153, 10, 9, 40, 0, 152, 251, 168, 142, 154, 9, 16, 33, 49, 33, 128, 154, 170, 156, 34, 54, 54, 33, 68, 0, 1, 136, 201, 137, 26, 88, 48, 35, 99, 8, 152, 189, 189, 187, 155, 171, 16, 24, 130, 145, 188, 175, 203, 144, 49, 115, 67, 67, 50, 19, 2, 1, 0, 0, 130, 131, 1, 136, 206, 216, 188, 203, 204, 187, 187,
- 156, 153, 0, 0, 51, 17, 34, 24, 112, 20, 69, 67, 67, 34, 19, 0, 136, 169, 185, 137, 186, 232, 185, 219, 201, 203, 187, 173, 170, 154, 153, 129, 131, 6, 2, 19, 49, 49, 21, 65, 19, 53, 51, 83, 34, 16, 168, 201, 154, 172, 156, 138, 0, 1, 24, 201, 233, 186, 204, 186, 171, 137, 3, 37, 48, 24, 128, 201, 202, 202, 129, 17, 48, 21,
- 22, 20, 19, 19, 32, 16, 2, 66, 52, 68, 4, 3, 1, 203, 235, 188, 189, 186, 171, 153, 137, 153, 170, 219, 170, 140, 9, 17, 53, 115, 50, 52, 67, 51, 51, 51, 17, 130, 0, 145, 154, 169, 188, 236, 187, 190, 203, 187, 172, 171, 138, 136, 17, 33, 18, 2, 34, 98, 98, 50, 50, 52, 66, 34, 35, 2, 19, 24, 169, 203, 203, 188, 219, 169, 154,
- 9, 137, 171, 204, 188, 203, 184, 136, 34, 83, 50, 33, 153, 184, 170, 170, 152, 40, 57, 19, 36, 50, 50, 18, 35, 17, 2, 49, 49, 66, 66, 66, 34, 17, 168, 233, 202, 202, 170, 171, 170, 186, 219, 203, 188, 188, 154, 138, 25, 33, 68, 52, 68, 67, 67, 36, 51, 36, 18, 17, 17, 136, 8, 170, 176, 202, 188, 206, 202, 171, 172, 186, 169,
- 153, 8, 25, 144, 128, 1, 34, 68, 52, 68, 51, 52, 34, 49, 18, 34, 2, 144, 136, 155, 140, 187, 186, 186, 154, 154, 185, 185, 153, 9, 9, 0, 24, 0, 128, 144, 168, 169, 170, 154, 154, 153, 9, 8, 16, 8, 0, 144, 19, 35, 68, 51, 52, 67, 51, 66, 34, 50, 33, 1, 144, 185, 186, 172, 204, 187, 188, 173, 172, 186, 172, 186, 154, 138, 41,
- 33, 52, 53, 83, 50, 51, 52, 52, 37, 34, 34, 18, 16, 144, 152, 154, 187, 219, 203, 188, 173, 186, 186, 186, 170, 154, 153, 138, 144, 16, 17, 67, 82, 50, 51, 21, 34, 19, 33, 2, 18, 33, 1, 8, 153, 169, 153, 153, 136, 128, 0, 136, 154, 153, 153, 8, 8, 1, 16, 0, 169, 170, 187, 171, 171, 154, 153, 153, 152, 153, 153, 0, 16, 51, 83,
- 66, 50, 67, 50, 51, 67, 51, 52, 35, 18, 136, 186, 219, 187, 189, 186, 171, 187, 173, 187, 188, 187, 203, 138, 9, 16, 33, 50, 52, 53, 67, 67, 147, 8, 128, 128, 128, 128, 128, 128, 128, 128, 0, 240, 255, 55, 232, 23, 220, 0, 148, 1, 9, 18, 148, 10, 189, 32, 163, 62, 160, 5, 137, 12, 149, 42, 153, 144, 34, 42, 8, 1, 138, 181,
- 45, 136, 18, 144, 105, 138, 1, 160, 14, 128, 132, 145, 186, 37, 138, 41, 192, 48, 145, 46, 160, 33, 44, 24, 225, 16, 13, 132, 136, 137, 16, 148, 25, 170, 194, 82, 152, 136, 91, 24, 42, 169, 33, 233, 131, 179, 24, 185, 149, 16, 57, 172, 164, 18, 10, 211, 160, 147, 211, 33, 138, 243, 129, 16, 41, 193, 0, 43, 132, 155, 73,
- 58, 145, 244, 145, 43, 35, 9, 171, 16, 110, 25, 8, 28, 74, 162, 128, 26, 27, 82, 45, 136, 153, 18, 8, 136, 8
-};
-#endif // DISABLE_PC98_RHYTHM_CHANNEL
-
-TownsPC98_FmSynth::ChanInternal::ChanInternal() {
- memset(this, 0, sizeof(ChanInternal));
-}
-
-TownsPC98_FmSynth::ChanInternal::~ChanInternal() {
- for (uint i = 0; i < ARRAYSIZE(opr); ++i)
- delete opr[i];
-}
diff --git a/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
deleted file mode 100644
index ddd249b1b8..0000000000
--- a/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
+++ /dev/null
@@ -1,196 +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$
- *
- */
-
-#ifndef TOWNS_PC98_FMSYNTH_H
-#define TOWNS_PC98_FMSYNTH_H
-
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "common/list.h"
-
-#ifdef __DS__
-/* This disables the rhythm channel when emulating the PC-98 type 86 sound card.
- * The only purpose is code size reduction for certain backends.
- * At the moment the only games which make use of the rhythm channel are the
- * (very rare) PC-98 versions of Legend of Kyrandia 2 and Lands of Lore. Music will
- * still be okay, just missing a couple of rhythm instruments.
- */
-#define DISABLE_PC98_RHYTHM_CHANNEL
-#endif
-
-class TownsPC98_FmSynthOperator;
-class TownsPC98_FmSynthSquareSineSource;
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
-class TownsPC98_FmSynthPercussionSource;
-#endif
-
-enum EnvelopeState {
- kEnvReady,
- kEnvAttacking,
- kEnvDecaying,
- kEnvSustaining,
- kEnvReleasing
-};
-
-class TownsPC98_FmSynth : public Audio::AudioStream {
-public:
- enum EmuType {
- kTypeTowns,
- kType26,
- kType86
- };
-
- TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type);
- virtual ~TownsPC98_FmSynth();
-
- virtual bool init();
- virtual void reset();
-
- void writeReg(uint8 part, uint8 regAddress, uint8 value);
-
- // AudioStream interface
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const {
- return true;
- }
- bool endOfData() const {
- return false;
- }
- int getRate() const {
- return _mixer->getOutputRate();
- }
-
-protected:
- void deinit();
-
- // Implement this in your inherited class if your driver generates
- // additional output that has to be inserted into the buffer.
- virtual void nextTickEx(int32 *buffer, uint32 bufferSize) {}
-
- void toggleRegProtection(bool prot) {
- _regProtectionFlag = prot;
- }
- uint8 readSSGStatus();
-
- virtual void timerCallbackA() = 0;
- virtual void timerCallbackB() = 0;
-
- // The audio driver can store and apply two different audio settings
- // (usually for music and sound effects). The channel mask will determine
- // which channels get effected by the setting. The first bits will be
- // the normal fm channels, the next bits the ssg channels and the final
- // bit the rhythm channel.
- void setVolumeIntern(int volA, int volB);
- void setVolumeChannelMasks(int channelMaskA, int channelMaskB);
-
- const int _numChan;
- const int _numSSG;
- const bool _hasPercussion;
-
- Common::Mutex _mutex;
-private:
- void generateTables();
- void nextTick(int32 *buffer, uint32 bufferSize);
- void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed);
-
- struct ChanInternal {
- ChanInternal();
- ~ChanInternal();
-
- void ampModSensitivity(uint32 value) {
- ampModSvty = (1 << (3 - value)) - (((value >> 1) & 1) | (value & 1));
- }
- void frqModSensitivity(uint32 value) {
- frqModSvty = value << 5;
- }
-
- uint16 frqTemp;
- bool enableLeft;
- bool enableRight;
- bool updateEnvelopeParameters;
- int32 feedbuf[3];
- uint8 algorithm;
-
- uint32 ampModSvty;
- uint32 frqModSvty;
-
- TownsPC98_FmSynthOperator *opr[4];
- };
-
- TownsPC98_FmSynthSquareSineSource *_ssg;
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- TownsPC98_FmSynthPercussionSource *_prc;
-#endif
- ChanInternal *_chanInternal;
-
- uint8 *_oprRates;
- uint8 *_oprRateshift;
- uint8 *_oprAttackDecay;
- uint32 *_oprFrq;
- uint32 *_oprSinTbl;
- int32 *_oprLevelOut;
- int32 *_oprDetune;
-
- bool _regProtectionFlag;
-
- typedef void (TownsPC98_FmSynth::*ChipTimerProc)();
- void idleTimerCallback() {}
-
- struct ChipTimer {
- bool enabled;
- uint16 value;
-
- int32 smpTillCb;
- uint32 smpTillCbRem;
- int32 smpPerCb;
- uint32 smpPerCbRem;
-
- ChipTimerProc cb;
- };
-
- ChipTimer _timers[2];
-
- int _volMaskA, _volMaskB;
- uint16 _volumeA, _volumeB;
-
- const float _baserate;
- uint32 _timerbase;
- uint32 _rtt;
-
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
-
-#ifndef DISABLE_PC98_RHYTHM_CHANNEL
- static const uint8 _percussionData[];
-#endif
- static const uint32 _adtStat[];
- static const uint8 _detSrc[];
- static const int _ssgTables[];
-
- bool _ready;
-};
-
-#endif
-
diff --git a/sound/softsynth/mt32.cpp b/sound/softsynth/mt32.cpp
deleted file mode 100644
index 09e7e48151..0000000000
--- a/sound/softsynth/mt32.cpp
+++ /dev/null
@@ -1,573 +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$
- */
-
-#include "common/scummsys.h"
-
-#ifdef USE_MT32EMU
-
-#include "sound/softsynth/mt32/mt32emu.h"
-
-#include "sound/softsynth/emumidi.h"
-#include "sound/musicplugin.h"
-#include "sound/mpu401.h"
-
-#include "common/config-manager.h"
-#include "common/debug.h"
-#include "common/events.h"
-#include "common/file.h"
-#include "common/system.h"
-#include "common/util.h"
-#include "common/archive.h"
-#include "common/translation.h"
-
-#include "graphics/fontman.h"
-#include "graphics/surface.h"
-
-class MidiChannel_MT32 : public MidiChannel_MPU401 {
- void effectLevel(byte value) { }
- void chorusLevel(byte value) { }
-};
-
-class MidiDriver_MT32 : public MidiDriver_Emulated {
-private:
- Audio::SoundHandle _handle;
- MidiChannel_MT32 _midiChannels[16];
- uint16 _channelMask;
- MT32Emu::Synth *_synth;
-
- int _outputRate;
-
-protected:
- void generateSamples(int16 *buf, int len);
-
-public:
- bool _initialising;
-
- MidiDriver_MT32(Audio::Mixer *mixer);
- virtual ~MidiDriver_MT32();
-
- int open();
- void close();
- void send(uint32 b);
- void setPitchBendRange (byte channel, uint range);
- void sysEx(const byte *msg, uint16 length);
-
- uint32 property(int prop, uint32 param);
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel();
-
- // AudioStream API
- bool isStereo() const { return true; }
- int getRate() const { return _outputRate; }
-};
-
-class MT32File : public MT32Emu::File {
- Common::File _in;
- Common::DumpFile _out;
-public:
- bool open(const char *filename, OpenMode mode) {
- if (mode == OpenMode_read)
- return _in.open(filename);
- else
- return _out.open(filename);
- }
- void close() {
- _in.close();
- _out.close();
- }
- size_t read(void *in, size_t size) {
- return _in.read(in, size);
- }
- bool readBit8u(MT32Emu::Bit8u *in) {
- byte b = _in.readByte();
- if (_in.eos())
- return false;
- *in = b;
- return true;
- }
- size_t write(const void *in, size_t size) {
- return _out.write(in, size);
- }
- bool writeBit8u(MT32Emu::Bit8u out) {
- _out.writeByte(out);
- return !_out.err();
- }
- bool isEOF() {
- return _in.isOpen() && _in.eos();
- }
-};
-
-static int eatSystemEvents() {
- Common::Event event;
- Common::EventManager *eventMan = g_system->getEventManager();
- while (eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_QUIT:
- return 1;
- default:
- break;
- }
- }
- return 0;
-}
-
-static void drawProgress(float progress) {
- const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kOSDFont));
- Graphics::Surface *screen = g_system->lockScreen();
-
- assert(screen);
- assert(screen->pixels);
-
- Graphics::PixelFormat screenFormat = g_system->getScreenFormat();
-
- int16 w = g_system->getWidth() / 7 * 5;
- int16 h = font.getFontHeight();
- int16 x = g_system->getWidth() / 7;
- int16 y = g_system->getHeight() / 2 - h / 2;
-
- Common::Rect r(x, y, x + w, y + h);
-
- uint32 col;
-
- if (screenFormat.bytesPerPixel > 1)
- col = screenFormat.RGBToColor(0, 171, 0);
- else
- col = 1;
-
- screen->frameRect(r, col);
-
- r.grow(-1);
- r.setWidth(uint16(progress * w));
-
- if (screenFormat.bytesPerPixel > 1)
- col = screenFormat.RGBToColor(171, 0, 0);
- else
- col = 2;
-
- screen->fillRect(r, col);
-
- g_system->unlockScreen();
- g_system->updateScreen();
-}
-
-static void drawMessage(int offset, const Common::String &text) {
- const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kOSDFont));
- Graphics::Surface *screen = g_system->lockScreen();
-
- assert(screen);
- assert(screen->pixels);
-
- Graphics::PixelFormat screenFormat = g_system->getScreenFormat();
-
- uint16 h = font.getFontHeight();
- uint16 y = g_system->getHeight() / 2 - h / 2 + offset * (h + 1);
-
- uint32 col;
-
- if (screenFormat.bytesPerPixel > 1)
- col = screenFormat.RGBToColor(0, 0, 0);
- else
- col = 0;
-
- Common::Rect r(0, y, screen->w, y + h);
- screen->fillRect(r, col);
-
- if (screenFormat.bytesPerPixel > 1)
- col = screenFormat.RGBToColor(0, 171, 0);
- else
- col = 1;
-
- font.drawString(screen, text, 0, y, screen->w, col, Graphics::kTextAlignCenter);
-
- g_system->unlockScreen();
- g_system->updateScreen();
-}
-
-static MT32Emu::File *MT32_OpenFile(void *userData, const char *filename, MT32Emu::File::OpenMode mode) {
- MT32File *file = new MT32File();
- if (!file->open(filename, mode)) {
- delete file;
- return NULL;
- }
- return file;
-}
-
-static void MT32_PrintDebug(void *userData, const char *fmt, va_list list) {
- if (((MidiDriver_MT32 *)userData)->_initialising) {
- char buf[512];
-
- vsnprintf(buf, 512, fmt, list);
- buf[70] = 0; // Truncate to a reasonable length
-
- drawMessage(1, buf);
- }
-
- //vdebug(0, fmt, list); // FIXME: Use a higher debug level
-}
-
-static int MT32_Report(void *userData, MT32Emu::ReportType type, const void *reportData) {
- switch (type) {
- case MT32Emu::ReportType_lcdMessage:
- g_system->displayMessageOnOSD((const char *)reportData);
- break;
- case MT32Emu::ReportType_errorControlROM:
- error("Failed to load MT32_CONTROL.ROM");
- break;
- case MT32Emu::ReportType_errorPCMROM:
- error("Failed to load MT32_PCM.ROM");
- break;
- case MT32Emu::ReportType_progressInit:
- if (((MidiDriver_MT32 *)userData)->_initialising) {
- drawProgress(*((const float *)reportData));
- return eatSystemEvents();
- }
- break;
- case MT32Emu::ReportType_availableSSE:
- debug(1, "MT32emu: SSE is available");
- break;
- case MT32Emu::ReportType_usingSSE:
- debug(1, "MT32emu: using SSE");
- break;
- case MT32Emu::ReportType_available3DNow:
- debug(1, "MT32emu: 3DNow! is available");
- break;
- case MT32Emu::ReportType_using3DNow:
- debug(1, "MT32emu: using 3DNow!");
- break;
- default:
- break;
- }
- return 0;
-}
-
-////////////////////////////////////////
-//
-// MidiDriver_MT32
-//
-////////////////////////////////////////
-
-MidiDriver_MT32::MidiDriver_MT32(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) {
- _channelMask = 0xFFFF; // Permit all 16 channels by default
- uint i;
- for (i = 0; i < ARRAYSIZE(_midiChannels); ++i) {
- _midiChannels[i].init(this, i);
- }
- _synth = NULL;
- // A higher baseFreq reduces the length used in generateSamples(),
- // and means that the timer callback will be called more often.
- // That results in more accurate timing.
- _baseFreq = 10000;
- // Unfortunately bugs in the emulator cause inaccurate tuning
- // at rates other than 32KHz, thus we produce data at 32KHz and
- // rely on Mixer to convert.
- _outputRate = 32000; //_mixer->getOutputRate();
- _initialising = false;
-}
-
-MidiDriver_MT32::~MidiDriver_MT32() {
- delete _synth;
-}
-
-int MidiDriver_MT32::open() {
- MT32Emu::SynthProperties prop;
-
- if (_isOpen)
- return MERR_ALREADY_OPEN;
-
- MidiDriver_Emulated::open();
-
- memset(&prop, 0, sizeof(prop));
- prop.sampleRate = getRate();
- prop.useReverb = true;
- prop.useDefaultReverb = false;
- prop.reverbType = 0;
- prop.reverbTime = 5;
- prop.reverbLevel = 3;
- prop.userData = this;
- prop.printDebug = MT32_PrintDebug;
- prop.report = MT32_Report;
- prop.openFile = MT32_OpenFile;
-
- _synth = new MT32Emu::Synth();
-
- Graphics::PixelFormat screenFormat = g_system->getScreenFormat();
-
- if (screenFormat.bytesPerPixel == 1) {
- const byte dummy_palette[] = {
- 0, 0, 0, 0, // background
- 0, 171, 0, 0, // border, font
- 171, 0, 0, 0 // fill
- };
-
- g_system->getPaletteManager()->setPalette(dummy_palette, 0, 3);
- }
-
- _initialising = true;
- drawMessage(-1, _s("Initialising MT-32 Emulator"));
- if (!_synth->open(prop))
- return MERR_DEVICE_NOT_AVAILABLE;
- _initialising = false;
-
- if (screenFormat.bytesPerPixel > 1)
- g_system->fillScreen(screenFormat.RGBToColor(0, 0, 0));
- else
- g_system->fillScreen(0);
-
- g_system->updateScreen();
-
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- return 0;
-}
-
-void MidiDriver_MT32::send(uint32 b) {
- _synth->playMsg(b);
-}
-
-void MidiDriver_MT32::setPitchBendRange(byte channel, uint range) {
- if (range > 24) {
- printf("setPitchBendRange() called with range > 24: %d", range);
- }
- byte benderRangeSysex[9];
- benderRangeSysex[0] = 0x41; // Roland
- benderRangeSysex[1] = channel;
- benderRangeSysex[2] = 0x16; // MT-32
- benderRangeSysex[3] = 0x12; // Write
- benderRangeSysex[4] = 0x00;
- benderRangeSysex[5] = 0x00;
- benderRangeSysex[6] = 0x04;
- benderRangeSysex[7] = (byte)range;
- benderRangeSysex[8] = MT32Emu::Synth::calcSysexChecksum(&benderRangeSysex[4], 4, 0);
- sysEx(benderRangeSysex, 9);
-}
-
-void MidiDriver_MT32::sysEx(const byte *msg, uint16 length) {
- if (msg[0] == 0xf0) {
- _synth->playSysex(msg, length);
- } else {
- _synth->playSysexWithoutFraming(msg, length);
- }
-}
-
-void MidiDriver_MT32::close() {
- if (!_isOpen)
- return;
- _isOpen = false;
-
- // Detach the player callback handler
- setTimerCallback(NULL, NULL);
- // Detach the mixer callback handler
- _mixer->stopHandle(_handle);
-
- _synth->close();
- delete _synth;
- _synth = NULL;
-}
-
-void MidiDriver_MT32::generateSamples(int16 *data, int len) {
- _synth->render(data, len);
-}
-
-uint32 MidiDriver_MT32::property(int prop, uint32 param) {
- switch (prop) {
- case PROP_CHANNEL_MASK:
- _channelMask = param & 0xFFFF;
- return 1;
- }
-
- return 0;
-}
-
-MidiChannel *MidiDriver_MT32::allocateChannel() {
- MidiChannel_MT32 *chan;
- uint i;
-
- for (i = 0; i < ARRAYSIZE(_midiChannels); ++i) {
- if (i == 9 || !(_channelMask & (1 << i)))
- continue;
- chan = &_midiChannels[i];
- if (chan->allocate()) {
- return chan;
- }
- }
- return NULL;
-}
-
-MidiChannel *MidiDriver_MT32::getPercussionChannel() {
- return &_midiChannels[9];
-}
-
-// This code should be used when calling the timer callback from the mixer thread is undesirable.
-// Note that it results in less accurate timing.
-#if 0
-class MidiEvent_MT32 {
-public:
- MidiEvent_MT32 *_next;
- uint32 _msg; // 0xFFFFFFFF indicates a sysex message
- byte *_data;
- uint32 _len;
-
- MidiEvent_MT32(uint32 msg, byte *data, uint32 len) {
- _msg = msg;
- if (len > 0) {
- _data = new byte[len];
- memcpy(_data, data, len);
- }
- _len = len;
- _next = NULL;
- }
-
- MidiEvent_MT32() {
- if (_len > 0)
- delete _data;
- }
-};
-
-class MidiDriver_ThreadedMT32 : public MidiDriver_MT32 {
-private:
- OSystem::Mutex _eventMutex;
- MidiEvent_MT32 *_events;
- TimerManager::TimerProc _timer_proc;
-
- void pushMidiEvent(MidiEvent_MT32 *event);
- MidiEvent_MT32 *popMidiEvent();
-
-protected:
- void send(uint32 b);
- void sysEx(const byte *msg, uint16 length);
-
-public:
- MidiDriver_ThreadedMT32(Audio::Mixer *mixer);
-
- void onTimer();
- void close();
- void setTimerCallback(void *timer_param, TimerManager::TimerProc timer_proc);
-};
-
-
-MidiDriver_ThreadedMT32::MidiDriver_ThreadedMT32(Audio::Mixer *mixer) : MidiDriver_MT32(mixer) {
- _events = NULL;
- _timer_proc = NULL;
-}
-
-void MidiDriver_ThreadedMT32::close() {
- MidiDriver_MT32::close();
- while ((popMidiEvent() != NULL)) {
- // Just eat any leftover events
- }
-}
-
-void MidiDriver_ThreadedMT32::setTimerCallback(void *timer_param, TimerManager::TimerProc timer_proc) {
- if (!_timer_proc || !timer_proc) {
- if (_timer_proc)
- _vm->_timer->removeTimerProc(_timer_proc);
- _timer_proc = timer_proc;
- if (timer_proc)
- _vm->_timer->installTimerProc(timer_proc, getBaseTempo(), timer_param);
- }
-}
-
-void MidiDriver_ThreadedMT32::pushMidiEvent(MidiEvent_MT32 *event) {
- Common::StackLock lock(_eventMutex);
- if (_events == NULL) {
- _events = event;
- } else {
- MidiEvent_MT32 *last = _events;
- while (last->_next != NULL)
- last = last->_next;
- last->_next = event;
- }
-}
-
-MidiEvent_MT32 *MidiDriver_ThreadedMT32::popMidiEvent() {
- Common::StackLock lock(_eventMutex);
- MidiEvent_MT32 *event;
- event = _events;
- if (event != NULL)
- _events = event->_next;
- return event;
-}
-
-void MidiDriver_ThreadedMT32::send(uint32 b) {
- MidiEvent_MT32 *event = new MidiEvent_MT32(b, NULL, 0);
- pushMidiEvent(event);
-}
-
-void MidiDriver_ThreadedMT32::sysEx(const byte *msg, uint16 length) {
- MidiEvent_MT32 *event = new MidiEvent_MT32(0xFFFFFFFF, msg, length);
- pushMidiEvent(event);
-}
-
-void MidiDriver_ThreadedMT32::onTimer() {
- MidiEvent_MT32 *event;
- while ((event = popMidiEvent()) != NULL) {
- if (event->_msg == 0xFFFFFFFF) {
- MidiDriver_MT32::sysEx(event->_data, event->_len);
- } else {
- MidiDriver_MT32::send(event->_msg);
- }
- delete event;
- }
-}
-#endif
-
-
-// Plugin interface
-
-class MT32EmuMusicPlugin : public MusicPluginObject {
-public:
- const char *getName() const {
- return _s("MT-32 Emulator");
- }
-
- const char *getId() const {
- return "mt32";
- }
-
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
-};
-
-MusicDevices MT32EmuMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_MT32));
- return devices;
-}
-
-Common::Error MT32EmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- if (ConfMan.hasKey("extrapath"))
- SearchMan.addDirectory("extrapath", ConfMan.get("extrapath"));
-
- *mididriver = new MidiDriver_MT32(g_system->getMixer());
-
- return Common::kNoError;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(MT32)
- //REGISTER_PLUGIN_DYNAMIC(MT32, PLUGIN_TYPE_MUSIC, MT32EmuMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(MT32, PLUGIN_TYPE_MUSIC, MT32EmuMusicPlugin);
-//#endif
-
-#endif
diff --git a/sound/softsynth/mt32/freeverb.cpp b/sound/softsynth/mt32/freeverb.cpp
deleted file mode 100644
index 4ee6e20117..0000000000
--- a/sound/softsynth/mt32/freeverb.cpp
+++ /dev/null
@@ -1,310 +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$
- *
- */
-
-// Comb filter implementation
-//
-// Written by
-// http://www.dreampoint.co.uk
-// This code is public domain
-
-#include "sound/softsynth/mt32/freeverb.h"
-
-comb::comb() {
- filterstore = 0;
- bufidx = 0;
-}
-
-void comb::setbuffer(float *buf, int size) {
- buffer = buf;
- bufsize = size;
-}
-
-void comb::mute() {
- for (int i = 0; i < bufsize; i++)
- buffer[i] = 0;
-}
-
-void comb::setdamp(float val) {
- damp1 = val;
- damp2 = 1 - val;
-}
-
-float comb::getdamp() {
- return damp1;
-}
-
-void comb::setfeedback(float val) {
- feedback = val;
-}
-
-float comb::getfeedback() {
- return feedback;
-}
-
-// Allpass filter implementation
-
-allpass::allpass() {
- bufidx = 0;
-}
-
-void allpass::setbuffer(float *buf, int size) {
- buffer = buf;
- bufsize = size;
-}
-
-void allpass::mute() {
- for (int i = 0; i < bufsize; i++)
- buffer[i] = 0;
-}
-
-void allpass::setfeedback(float val) {
- feedback = val;
-}
-
-float allpass::getfeedback() {
- return feedback;
-}
-
-// Reverb model implementation
-
-revmodel::revmodel() {
- // Tie the components to their buffers
- combL[0].setbuffer(bufcombL1,combtuningL1);
- combR[0].setbuffer(bufcombR1,combtuningR1);
- combL[1].setbuffer(bufcombL2,combtuningL2);
- combR[1].setbuffer(bufcombR2,combtuningR2);
- combL[2].setbuffer(bufcombL3,combtuningL3);
- combR[2].setbuffer(bufcombR3,combtuningR3);
- combL[3].setbuffer(bufcombL4,combtuningL4);
- combR[3].setbuffer(bufcombR4,combtuningR4);
- combL[4].setbuffer(bufcombL5,combtuningL5);
- combR[4].setbuffer(bufcombR5,combtuningR5);
- combL[5].setbuffer(bufcombL6,combtuningL6);
- combR[5].setbuffer(bufcombR6,combtuningR6);
- combL[6].setbuffer(bufcombL7,combtuningL7);
- combR[6].setbuffer(bufcombR7,combtuningR7);
- combL[7].setbuffer(bufcombL8,combtuningL8);
- combR[7].setbuffer(bufcombR8,combtuningR8);
- allpassL[0].setbuffer(bufallpassL1,allpasstuningL1);
- allpassR[0].setbuffer(bufallpassR1,allpasstuningR1);
- allpassL[1].setbuffer(bufallpassL2,allpasstuningL2);
- allpassR[1].setbuffer(bufallpassR2,allpasstuningR2);
- allpassL[2].setbuffer(bufallpassL3,allpasstuningL3);
- allpassR[2].setbuffer(bufallpassR3,allpasstuningR3);
- allpassL[3].setbuffer(bufallpassL4,allpasstuningL4);
- allpassR[3].setbuffer(bufallpassR4,allpasstuningR4);
-
- // Set default values
- allpassL[0].setfeedback(0.5f);
- allpassR[0].setfeedback(0.5f);
- allpassL[1].setfeedback(0.5f);
- allpassR[1].setfeedback(0.5f);
- allpassL[2].setfeedback(0.5f);
- allpassR[2].setfeedback(0.5f);
- allpassL[3].setfeedback(0.5f);
- allpassR[3].setfeedback(0.5f);
- setmode(initialmode);
- setwet(initialwet);
- setroomsize(initialroom);
- setdry(initialdry);
- setdamp(initialdamp);
- setwidth(initialwidth);
-
- // Buffer will be full of rubbish - so we MUST mute them
- mute();
-}
-
-void revmodel::mute() {
- int i;
-
- if (getmode() >= freezemode)
- return;
-
- for (i = 0; i < numcombs; i++) {
- combL[i].mute();
- combR[i].mute();
- }
-
- for (i = 0; i < numallpasses; i++) {
- allpassL[i].mute();
- allpassR[i].mute();
- }
-}
-
-void revmodel::processreplace(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip) {
- float outL, outR, input;
-
- while (numsamples-- > 0) {
- int i;
-
- outL = outR = 0;
- input = (*inputL + *inputR) * gain;
-
- // Accumulate comb filters in parallel
- for (i = 0; i < numcombs; i++) {
- outL += combL[i].process(input);
- outR += combR[i].process(input);
- }
-
- // Feed through allpasses in series
- for (i = 0; i < numallpasses; i++) {
- outL = allpassL[i].process(outL);
- outR = allpassR[i].process(outR);
- }
-
- // Calculate output REPLACING anything already there
- *outputL = outL * wet1 + outR * wet2 + *inputL * dry;
- *outputR = outR * wet1 + outL * wet2 + *inputR * dry;
-
- // Increment sample pointers, allowing for interleave (if any)
- inputL += skip;
- inputR += skip;
- outputL += skip;
- outputR += skip;
- }
-}
-
-void revmodel::processmix(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip) {
- float outL, outR, input;
-
- while (numsamples-- > 0) {
- int i;
-
- outL = outR = 0;
- input = (*inputL + *inputR) * gain;
-
- // Accumulate comb filters in parallel
- for (i = 0; i < numcombs; i++) {
- outL += combL[i].process(input);
- outR += combR[i].process(input);
- }
-
- // Feed through allpasses in series
- for (i = 0; i < numallpasses; i++) {
- outL = allpassL[i].process(outL);
- outR = allpassR[i].process(outR);
- }
-
- // Calculate output MIXING with anything already there
- *outputL += outL * wet1 + outR * wet2 + *inputL * dry;
- *outputR += outR * wet1 + outL * wet2 + *inputR * dry;
-
- // Increment sample pointers, allowing for interleave (if any)
- inputL += skip;
- inputR += skip;
- outputL += skip;
- outputR += skip;
- }
-}
-
-void revmodel::update() {
- // Recalculate internal values after parameter change
-
- int i;
-
- wet1 = wet * (width / 2 + 0.5f);
- wet2 = wet * ((1 - width) / 2);
-
- if (mode >= freezemode) {
- roomsize1 = 1;
- damp1 = 0;
- gain = muted;
- } else {
- roomsize1 = roomsize;
- damp1 = damp;
- gain = fixedgain;
- }
-
- for (i = 0; i < numcombs; i++) {
- combL[i].setfeedback(roomsize1);
- combR[i].setfeedback(roomsize1);
- }
-
- for (i = 0; i < numcombs; i++) {
- combL[i].setdamp(damp1);
- combR[i].setdamp(damp1);
- }
-}
-
-// The following get/set functions are not inlined, because
-// speed is never an issue when calling them, and also
-// because as you develop the reverb model, you may
-// wish to take dynamic action when they are called.
-
-void revmodel::setroomsize(float value) {
- roomsize = (value * scaleroom) + offsetroom;
- update();
-}
-
-float revmodel::getroomsize() {
- return (roomsize - offsetroom) / scaleroom;
-}
-
-void revmodel::setdamp(float value) {
- damp = value * scaledamp;
- update();
-}
-
-float revmodel::getdamp() {
- return damp / scaledamp;
-}
-
-void revmodel::setwet(float value) {
- wet = value * scalewet;
- update();
-}
-
-float revmodel::getwet() {
- return wet / scalewet;
-}
-
-void revmodel::setdry(float value) {
- dry = value * scaledry;
-}
-
-float revmodel::getdry() {
- return dry / scaledry;
-}
-
-void revmodel::setwidth(float value) {
- width = value;
- update();
-}
-
-float revmodel::getwidth() {
- return width;
-}
-
-void revmodel::setmode(float value) {
- mode = value;
- update();
-}
-
-float revmodel::getmode() {
- if (mode >= freezemode)
- return 1;
- else
- return 0;
-}
diff --git a/sound/softsynth/mt32/freeverb.h b/sound/softsynth/mt32/freeverb.h
deleted file mode 100644
index 8310aca3e3..0000000000
--- a/sound/softsynth/mt32/freeverb.h
+++ /dev/null
@@ -1,244 +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$
- *
- */
-
-// Macro for killing denormalled numbers
-//
-// Written by Jezar at Dreampoint, June 2000
-// http://www.dreampoint.co.uk
-// Based on IS_DENORMAL macro by Jon Watte
-// This code is public domain
-
-#ifndef FREEVERB_H
-#define FREEVERB_H
-
-// FIXME: Fix this really ugly hack
-inline float undenormalise(void *sample) {
- if (((*(unsigned int*)sample) & 0x7f800000) == 0)
- return 0.0f;
- return *(float*)sample;
-}
-
-// Comb filter class declaration
-
-class comb {
-public:
- comb();
- void setbuffer(float *buf, int size);
- inline float process(float inp);
- void mute();
- void setdamp(float val);
- float getdamp();
- void setfeedback(float val);
- float getfeedback();
-private:
- float feedback;
- float filterstore;
- float damp1;
- float damp2;
- float *buffer;
- int bufsize;
- int bufidx;
-};
-
-
-// Big to inline - but crucial for speed
-
-inline float comb::process(float input) {
- float output;
-
- output = buffer[bufidx];
- undenormalise(&output);
-
- filterstore = (output * damp2) + (filterstore * damp1);
- undenormalise(&filterstore);
-
- buffer[bufidx] = input + (filterstore * feedback);
-
- if (++bufidx >= bufsize)
- bufidx = 0;
-
- return output;
-}
-
-// Allpass filter declaration
-
-class allpass {
-public:
- allpass();
- void setbuffer(float *buf, int size);
- inline float process(float inp);
- void mute();
- void setfeedback(float val);
- float getfeedback();
-private:
- float feedback;
- float *buffer;
- int bufsize;
- int bufidx;
-};
-
-
-// Big to inline - but crucial for speed
-
-inline float allpass::process(float input) {
- float output;
- float bufout;
-
- bufout = buffer[bufidx];
- undenormalise(&bufout);
-
- output = -input + bufout;
- buffer[bufidx] = input + (bufout * feedback);
-
- if (++bufidx >= bufsize)
- bufidx = 0;
-
- return output;
-}
-
-
-// Reverb model tuning values
-
-const int numcombs = 8;
-const int numallpasses = 4;
-const float muted = 0;
-const float fixedgain = 0.015f;
-const float scalewet = 3;
-const float scaledry = 2;
-const float scaledamp = 0.4f;
-const float scaleroom = 0.28f;
-const float offsetroom = 0.7f;
-const float initialroom = 0.5f;
-const float initialdamp = 0.5f;
-const float initialwet = 1 / scalewet;
-const float initialdry = 0;
-const float initialwidth = 1;
-const float initialmode = 0;
-const float freezemode = 0.5f;
-const int stereospread = 23;
-
-// These values assume 44.1KHz sample rate
-// they will probably be OK for 48KHz sample rate
-// but would need scaling for 96KHz (or other) sample rates.
-// The values were obtained by listening tests.
-const int combtuningL1 = 1116;
-const int combtuningR1 = 1116 + stereospread;
-const int combtuningL2 = 1188;
-const int combtuningR2 = 1188 + stereospread;
-const int combtuningL3 = 1277;
-const int combtuningR3 = 1277 + stereospread;
-const int combtuningL4 = 1356;
-const int combtuningR4 = 1356 + stereospread;
-const int combtuningL5 = 1422;
-const int combtuningR5 = 1422 + stereospread;
-const int combtuningL6 = 1491;
-const int combtuningR6 = 1491 + stereospread;
-const int combtuningL7 = 1557;
-const int combtuningR7 = 1557 + stereospread;
-const int combtuningL8 = 1617;
-const int combtuningR8 = 1617 + stereospread;
-const int allpasstuningL1 = 556;
-const int allpasstuningR1 = 556 + stereospread;
-const int allpasstuningL2 = 441;
-const int allpasstuningR2 = 441 + stereospread;
-const int allpasstuningL3 = 341;
-const int allpasstuningR3 = 341 + stereospread;
-const int allpasstuningL4 = 225;
-const int allpasstuningR4 = 225 + stereospread;
-
-
-// Reverb model declaration
-
-class revmodel {
-public:
- revmodel();
- void mute();
- void processmix(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip);
- void processreplace(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip);
- void setroomsize(float value);
- float getroomsize();
- void setdamp(float value);
- float getdamp();
- void setwet(float value);
- float getwet();
- void setdry(float value);
- float getdry();
- void setwidth(float value);
- float getwidth();
- void setmode(float value);
- float getmode();
-private:
- void update();
-
- float gain;
- float roomsize, roomsize1;
- float damp, damp1;
- float wet, wet1, wet2;
- float dry;
- float width;
- float mode;
-
- // The following are all declared inline
- // to remove the need for dynamic allocation
- // with its subsequent error-checking messiness
-
- // Comb filters
- comb combL[numcombs];
- comb combR[numcombs];
-
- // Allpass filters
- allpass allpassL[numallpasses];
- allpass allpassR[numallpasses];
-
- // Buffers for the combs
- float bufcombL1[combtuningL1];
- float bufcombR1[combtuningR1];
- float bufcombL2[combtuningL2];
- float bufcombR2[combtuningR2];
- float bufcombL3[combtuningL3];
- float bufcombR3[combtuningR3];
- float bufcombL4[combtuningL4];
- float bufcombR4[combtuningR4];
- float bufcombL5[combtuningL5];
- float bufcombR5[combtuningR5];
- float bufcombL6[combtuningL6];
- float bufcombR6[combtuningR6];
- float bufcombL7[combtuningL7];
- float bufcombR7[combtuningR7];
- float bufcombL8[combtuningL8];
- float bufcombR8[combtuningR8];
-
- // Buffers for the allpasses
- float bufallpassL1[allpasstuningL1];
- float bufallpassR1[allpasstuningR1];
- float bufallpassL2[allpasstuningL2];
- float bufallpassR2[allpasstuningR2];
- float bufallpassL3[allpasstuningL3];
- float bufallpassR3[allpasstuningR3];
- float bufallpassL4[allpasstuningL4];
- float bufallpassR4[allpasstuningR4];
-};
-
-#endif
diff --git a/sound/softsynth/mt32/i386.cpp b/sound/softsynth/mt32/i386.cpp
deleted file mode 100644
index f092189d76..0000000000
--- a/sound/softsynth/mt32/i386.cpp
+++ /dev/null
@@ -1,849 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "mt32emu.h"
-
-#ifdef MT32EMU_HAVE_X86
-
-namespace MT32Emu {
-
-#ifndef _MSC_VER
-
-#define eflag(value) __asm__ __volatile__("pushfl \n popfl \n" : : "a"(value))
-#define cpuid_flag (1 << 21)
-
-static inline bool atti386_DetectCPUID() {
- unsigned int result;
-
- // Is there a cpuid?
- result = cpuid_flag; // set test
- eflag(result);
- if (!(result & cpuid_flag))
- return false;
-
- result = 0; // clear test
- eflag(result);
- if (result & cpuid_flag)
- return false;
-
- return true;
-}
-
-static inline bool atti386_DetectSIMD() {
- unsigned int result;
-
- if (atti386_DetectCPUID() == false)
- return false;
-
- /* check cpuid */
- __asm__ __volatile__(
- "pushl %%ebx \n" \
- "movl $1, %%eax \n" \
- "cpuid \n" \
- "movl %%edx, %0 \n" \
- "popl %%ebx \n" \
- : "=r"(result) : : "eax", "ecx", "edx");
-
- if (result & (1 << 25))
- return true;
-
- return false;
-}
-
-static inline bool atti386_Detect3DNow() {
- unsigned int result;
-
- if (atti386_DetectCPUID() == false)
- return false;
-
- // get cpuid
- __asm__ __volatile__(
- "pushl %%ebx \n" \
- "movl $0x80000001, %%eax \n" \
- "cpuid \n" \
- "movl %%edx, %0 \n" \
- "popl %%ebx \n" \
- : "=r"(result) : : "eax", "ecx", "edx");
-
- if (result & 0x80000000)
- return true;
-
- return false;
-}
-
-
-static inline float atti386_iir_filter_sse(float *output, float *hist1_ptr, float *coef_ptr) {
- __asm__ __volatile__ (
- "pushl %1 \n" \
- "pushl %2 \n" \
- "movss 0(%0), %%xmm1 \n" \
- "movups 0(%1), %%xmm2 \n" \
- "movlps 0(%2), %%xmm3 \n" \
- " \n" \
- "shufps $0x44, %%xmm3, %%xmm3 \n" \
- " \n" \
- "mulps %%xmm3, %%xmm2 \n" \
- " \n" \
- "subss %%xmm2, %%xmm1 \n" \
- "shufps $0x39, %%xmm2, %%xmm2 \n" \
- "subss %%xmm2, %%xmm1 \n" \
- " \n" \
- "movss %%xmm1, 0(%2) \n" \
- " \n" \
- "shufps $0x39, %%xmm2, %%xmm2 \n" \
- "addss %%xmm2, %%xmm1 \n" \
- " \n" \
- "shufps $0x39, %%xmm2, %%xmm2 \n" \
- "addss %%xmm2, %%xmm1 \n" \
- " \n" \
- "movss %%xmm3, 4(%2) \n" \
- " \n" \
- "addl $16, %1 \n" \
- "addl $8, %2 \n" \
- " \n" \
- "movups 0(%1), %%xmm2 \n" \
- " \n" \
- "movlps 0(%2), %%xmm3 \n" \
- "shufps $0x44, %%xmm3, %%xmm3 \n" \
- " \n" \
- "mulps %%xmm3, %%xmm2 \n" \
- " \n" \
- "subss %%xmm2, %%xmm1 \n" \
- "shufps $0x39, %%xmm2, %%xmm2 \n" \
- "subss %%xmm2, %%xmm1 \n" \
- " \n" \
- "movss %%xmm1, 0(%2) \n" \
- " \n" \
- "shufps $0x39, %%xmm2, %%xmm2 \n" \
- "addss %%xmm2, %%xmm1 \n" \
- " \n" \
- "shufps $0x39, %%xmm2, %%xmm2 \n" \
- "addss %%xmm2, %%xmm1 \n" \
- " \n" \
- "movss %%xmm3, 4(%2) \n" \
- "movss %%xmm1, 0(%0) \n" \
- "popl %2 \n" \
- "popl %1 \n" \
- : : "r"(output), "r"(coef_ptr), "r"(hist1_ptr)
- : "memory"
-#ifdef __SSE__
- , "xmm1", "xmm2", "xmm3"
-#endif
- );
-
- return *output;
-}
-
-static inline float atti386_iir_filter_3DNow(float output, float *hist1_ptr, float *coef_ptr) {
- float tmp;
-
- __asm__ __volatile__ (
- "movq %0, %%mm1 \n" \
- " \n" \
- "movl %1, %%edi \n" \
- "movq 0(%%edi), %%mm2 \n" \
- " \n" \
- "movl %2, %%eax; \n" \
- "movq 0(%%eax), %%mm3 \n" \
- " \n" \
- "pfmul %%mm3, %%mm2 \n" \
- "pfsub %%mm2, %%mm1 \n" \
- " \n" \
- "psrlq $32, %%mm2 \n" \
- "pfsub %%mm2, %%mm1 \n" \
- " \n" \
- "movd %%mm1, %3 \n" \
- " \n" \
- "addl $8, %%edi \n" \
- "movq 0(%%edi), %%mm2 \n" \
- "movq 0(%%eax), %%mm3 \n" \
- " \n" \
- "pfmul %%mm3, %%mm2 \n" \
- "pfadd %%mm2, %%mm1 \n" \
- " \n" \
- "psrlq $32, %%mm2 \n" \
- "pfadd %%mm2, %%mm1 \n" \
- " \n" \
- "pushl %3 \n" \
- "popl 0(%%eax) \n" \
- " \n" \
- "movd %%mm3, 4(%%eax) \n" \
- " \n" \
- "addl $8, %%edi \n" \
- "addl $8, %%eax \n" \
- " \n" \
- "movq 0(%%edi), %%mm2 \n" \
- "movq 0(%%eax), %%mm3 \n" \
- " \n" \
- "pfmul %%mm3, %%mm2 \n" \
- "pfsub %%mm2, %%mm1 \n" \
- " \n" \
- "psrlq $32, %%mm2 \n" \
- "pfsub %%mm2, %%mm1 \n" \
- " \n" \
- "movd %%mm1, %3 \n" \
- " \n" \
- "addl $8, %%edi \n" \
- "movq 0(%%edi), %%mm2 \n" \
- "movq 0(%%eax), %%mm3 \n" \
- " \n" \
- "pfmul %%mm3, %%mm2 \n" \
- "pfadd %%mm2, %%mm1 \n" \
- " \n" \
- "psrlq $32, %%mm2 \n" \
- "pfadd %%mm2, %%mm1 \n" \
- " \n" \
- "pushl %3 \n" \
- "popl 0(%%eax) \n" \
- "movd %%mm3, 4(%%eax) \n" \
- " \n" \
- "movd %%mm1, %0 \n" \
- "femms \n" \
- : "=m"(output) : "g"(coef_ptr), "g"(hist1_ptr), "m"(tmp)
- : "eax", "edi", "memory"
-#ifdef __MMX__
- , "mm1", "mm2", "mm3"
-#endif
- );
-
- return output;
-}
-
-static inline void atti386_produceOutput1(int tmplen, Bit16s myvolume, Bit16s *useBuf, Bit16s *snd) {
- __asm__ __volatile__(
- "movl %0, %%ecx \n" \
- "movw %1, %%ax \n" \
- "shll $16, %%eax \n" \
- "movw %1, %%ax \n" \
- "movd %%eax, %%mm3 \n" \
- "movd %%eax, %%mm2 \n" \
- "psllq $32, %%mm3 \n" \
- "por %%mm2, %%mm3 \n" \
- "movl %2, %%esi \n" \
- "movl %3, %%edi \n" \
- "1: \n" \
- "movq 0(%%esi), %%mm1 \n" \
- "movq 0(%%edi), %%mm2 \n" \
- "pmulhw %%mm3, %%mm1 \n" \
- "paddw %%mm2, %%mm1 \n" \
- "movq %%mm1, 0(%%edi) \n" \
- " \n" \
- "addl $8, %%esi \n" \
- "addl $8, %%edi \n" \
- " \n" \
- "decl %%ecx \n" \
- "cmpl $0, %%ecx \n" \
- "jg 1b \n" \
- "emms \n" \
- : : "g"(tmplen), "g"(myvolume), "g"(useBuf), "g"(snd)
- : "eax", "ecx", "edi", "esi", "memory"
-#ifdef __MMX__
- , "mm1", "mm2", "mm3"
-#endif
- );
-}
-
-static inline void atti386_produceOutput2(Bit32u len, Bit16s *snd, float *sndbufl, float *sndbufr, float *multFactor) {
- __asm__ __volatile__(
- "movl %4, %%ecx \n" \
- "shrl $1, %%ecx \n" \
- "addl $4, %%ecx \n" \
- "pushl %%ecx \n" \
- " \n" \
- "movl %0, %%esi \n" \
- "movups 0(%%esi), %%xmm1 \n" \
- " \n" \
- "movl %1, %%esi \n" \
- "movl %2, %%edi \n" \
- "1: \n" \
- "xorl %%eax, %%eax \n" \
- "movw 0(%1), %%ax \n" \
- "cwde \n" \
- "incl %1 \n" \
- "incl %1 \n" \
- "movd %%eax, %%mm1 \n" \
- "psrlq $32, %%mm1 \n" \
- "movw 0(%1), %%ax \n" \
- "incl %1 \n" \
- "incl %1 \n" \
- "movd %%eax, %%mm2 \n" \
- "por %%mm2, %%mm1 \n" \
- " \n" \
- "decl %%ecx \n" \
- "jnz 1b \n" \
- " \n" \
- "popl %%ecx \n" \
- "movl %1, %%esi \n" \
- "movl %3, %%edi \n" \
- "incl %%esi \n" \
- "2: \n" \
- "decl %%ecx \n" \
- "jnz 2b \n" \
- : : "g"(multFactor), "r"(snd), "g"(sndbufl), "g"(sndbufr), "g"(len)
- : "eax", "ecx", "edi", "esi", "mm1", "mm2", "xmm1", "memory");
-}
-
-static inline void atti386_mixBuffers(Bit16s * buf1, Bit16s *buf2, int len) {
- __asm__ __volatile__(
- "movl %0, %%ecx \n" \
- "movl %1, %%esi \n" \
- "movl %2, %%edi \n" \
- "1: \n" \
- "movq 0(%%edi), %%mm1 \n" \
- "movq 0(%%esi), %%mm2 \n" \
- "paddw %%mm2, %%mm1 \n" \
- "movq %%mm1, 0(%%esi) \n" \
- "addl $8, %%edi \n" \
- "addl $8, %%esi \n" \
- "decl %%ecx \n" \
- "cmpl $0, %%ecx \n" \
- "jg 1b \n" \
- "emms \n" \
- : : "g"(len), "g"(buf1), "g"(buf2)
- : "ecx", "edi", "esi", "memory"
-#ifdef __MMX__
- , "mm1", "mm2"
-#endif
- );
-}
-
-static inline void atti386_mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len) {
- __asm__ __volatile__(
- "movl %0, %%ecx \n" \
- "movl %1, %%esi \n" \
- "movl %2, %%edi \n" \
- "1: \n" \
- "movq 0(%%esi), %%mm1 \n" \
- "movq 0(%%edi), %%mm2 \n" \
- "movq %%mm1, %%mm3 \n" \
- "pmulhw %%mm2, %%mm1 \n" \
- "paddw %%mm3, %%mm1 \n" \
- "movq %%mm1, 0(%%esi) \n" \
- "addl $8, %%edi \n" \
- "addl $8, %%esi \n" \
- "decl %%ecx \n" \
- "cmpl $0, %%ecx \n" \
- "jg 1b \n" \
- "emms \n" \
- : : "g"(len), "g"(buf1), "g"(buf2)
- : "ecx", "edi", "esi", "memory"
-#ifdef __MMX__
- , "mm1", "mm2", "mm3"
-#endif
- );
-}
-
-static inline void atti386_mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len) {
- __asm__ __volatile__(
- "movl %0, %%ecx \n" \
- "movl %1, %%esi \n" \
- "movl %2, %%edi \n" \
- "1: \n" \
- "movq 0(%%esi), %%mm1 \n" \
- "movq 0(%%edi), %%mm2 \n" \
- "pmulhw %%mm2, %%mm1 \n" \
- "movq %%mm1, 0(%%esi) \n" \
- "addl $8, %%edi \n" \
- "addl $8, %%esi \n" \
- "decl %%ecx \n" \
- "cmpl $0, %%ecx \n" \
- "jg 1b \n" \
- "emms \n" \
- : : "g"(len), "g"(buf1), "g"(buf2)
- : "ecx", "edi", "esi", "memory"
-#ifdef __MMX__
- , "mm1", "mm2"
-#endif
- );
-}
-
-static inline void atti386_partialProductOutput(int quadlen, Bit16s leftvol, Bit16s rightvol, Bit16s *partialBuf, Bit16s *p1buf) {
- __asm__ __volatile__(
- "movl %0, %%ecx \n" \
- "movw %1, %%ax \n" \
- "shll $16, %%eax \n" \
- "movw %2, %%ax \n" \
- "movd %%eax, %%mm1 \n" \
- "movd %%eax, %%mm2 \n" \
- "psllq $32, %%mm1 \n" \
- "por %%mm2, %%mm1 \n" \
- "movl %3, %%edi \n" \
- "movl %4, %%esi \n" \
- "pushl %%ebx \n" \
- "1: \n" \
- "movw 0(%%esi), %%bx \n" \
- "addl $2, %%esi \n" \
- "movw 0(%%esi), %%dx \n" \
- "addl $2, %%esi \n" \
- "" \
- "movw %%dx, %%ax \n" \
- "shll $16, %%eax \n" \
- "movw %%dx, %%ax \n" \
- "movd %%eax, %%mm2 \n" \
- "psllq $32, %%mm2 \n" \
- "movw %%bx, %%ax \n" \
- "shll $16, %%eax \n" \
- "movw %%bx, %%ax \n" \
- "movd %%eax, %%mm3 \n" \
- "por %%mm3, %%mm2 \n" \
- "" \
- "pmulhw %%mm1, %%mm2 \n" \
- "movq %%mm2, 0(%%edi) \n" \
- "addl $8, %%edi \n" \
- "" \
- "decl %%ecx \n" \
- "cmpl $0, %%ecx \n" \
- "jg 1b \n" \
- "emms \n" \
- "popl %%ebx \n" \
- : : "g"(quadlen), "g"(leftvol), "g"(rightvol), "g"(partialBuf), "g"(p1buf)
- : "eax", "ecx", "edx", "edi", "esi", "memory"
-#ifdef __MMX__
- , "mm1", "mm2", "mm3"
-#endif
- );
-}
-
-#endif
-
-bool DetectSIMD() {
-#ifdef _MSC_VER
- bool found_simd;
- __asm {
- pushfd
- pop eax // get EFLAGS into eax
- mov ebx,eax // keep a copy
- xor eax,0x200000
- // toggle CPUID bit
-
- push eax
- popfd // set new EFLAGS
- pushfd
- pop eax // EFLAGS back into eax
-
- xor eax,ebx
- // have we changed the ID bit?
-
- je NO_SIMD
- // No, no CPUID instruction
-
- // we could toggle the
- // ID bit so CPUID is present
- mov eax,1
-
- cpuid // get processor features
- test edx,1<<25 // check the SIMD bit
- jz NO_SIMD
- mov found_simd,1
- jmp DONE
- NO_SIMD:
- mov found_simd,0
- DONE:
- }
- return found_simd;
-#else
- return atti386_DetectSIMD();
-#endif
-}
-
-bool Detect3DNow() {
-#ifdef _MSC_VER
- bool found3D = false;
- __asm {
- pushfd
- pop eax
- mov edx, eax
- xor eax, 00200000h
- push eax
- popfd
- pushfd
- pop eax
- xor eax, edx
- jz NO_3DNOW
-
- mov eax, 80000000h
- cpuid
-
- cmp eax, 80000000h
- jbe NO_3DNOW
-
- mov eax, 80000001h
- cpuid
- test edx, 80000000h
- jz NO_3DNOW
- mov found3D, 1
-NO_3DNOW:
-
- }
- return found3D;
-#else
- return atti386_Detect3DNow();
-#endif
-}
-
-float iir_filter_sse(float input,float *hist1_ptr, float *coef_ptr) {
- float output;
-
- // 1st number of coefficients array is overall input scale factor, or filter gain
- output = input * (*coef_ptr++);
-
-#ifdef _MSC_VER
- __asm {
-
- movss xmm1, output
-
- mov eax, coef_ptr
- movups xmm2, [eax]
-
- mov eax, hist1_ptr
- movlps xmm3, [eax]
- shufps xmm3, xmm3, 44h
- // hist1_ptr+1, hist1_ptr, hist1_ptr+1, hist1_ptr
-
- mulps xmm2, xmm3
-
- subss xmm1, xmm2
- // Rotate elements right
- shufps xmm2, xmm2, 39h
- subss xmm1, xmm2
-
- // Store new_hist
- movss DWORD PTR [eax], xmm1
-
- // Rotate elements right
- shufps xmm2, xmm2, 39h
- addss xmm1, xmm2
-
- // Rotate elements right
- shufps xmm2, xmm2, 39h
- addss xmm1, xmm2
-
- // Store previous hist
- movss DWORD PTR [eax+4], xmm3
-
- add coef_ptr, 16
- add hist1_ptr, 8
-
- mov eax, coef_ptr
- movups xmm2, [eax]
-
- mov eax, hist1_ptr
- movlps xmm3, [eax]
- shufps xmm3, xmm3, 44h
- // hist1_ptr+1, hist1_ptr, hist1_ptr+1, hist1_ptr
-
- mulps xmm2, xmm3
-
- subss xmm1, xmm2
- // Rotate elements right
- shufps xmm2, xmm2, 39h
- subss xmm1, xmm2
-
- // Store new_hist
- movss DWORD PTR [eax], xmm1
-
- // Rotate elements right
- shufps xmm2, xmm2, 39h
- addss xmm1, xmm2
-
- // Rotate elements right
- shufps xmm2, xmm2, 39h
- addss xmm1, xmm2
-
- // Store previous hist
- movss DWORD PTR [eax+4], xmm3
-
- movss output, xmm1
- }
-#else
- output = atti386_iir_filter_sse(&output, hist1_ptr, coef_ptr);
-#endif
- return output;
-}
-
-float iir_filter_3dnow(float input,float *hist1_ptr, float *coef_ptr) {
- float output;
-
- // 1st number of coefficients array is overall input scale factor, or filter gain
- output = input * (*coef_ptr++);
-
- // I find it very sad that 3DNow requires twice as many instructions as Intel's SSE
- // Intel does have the upper hand here.
-#ifdef _MSC_VER
- float tmp;
- __asm {
- movq mm1, output
- mov ebx, coef_ptr
- movq mm2, [ebx]
-
- mov eax, hist1_ptr;
- movq mm3, [eax]
-
- pfmul mm2, mm3
- pfsub mm1, mm2
-
- psrlq mm2, 32
- pfsub mm1, mm2
-
- // Store new hist
- movd tmp, mm1
-
- add ebx, 8
- movq mm2, [ebx]
- movq mm3, [eax]
-
- pfmul mm2, mm3
- pfadd mm1, mm2
-
- psrlq mm2, 32
- pfadd mm1, mm2
-
- push tmp
- pop DWORD PTR [eax]
-
- movd DWORD PTR [eax+4], mm3
-
- add ebx, 8
- add eax, 8
-
- movq mm2, [ebx]
- movq mm3, [eax]
-
- pfmul mm2, mm3
- pfsub mm1, mm2
-
- psrlq mm2, 32
- pfsub mm1, mm2
-
- // Store new hist
- movd tmp, mm1
-
- add ebx, 8
- movq mm2, [ebx]
- movq mm3, [eax]
-
- pfmul mm2, mm3
- pfadd mm1, mm2
-
- psrlq mm2, 32
- pfadd mm1, mm2
-
- push tmp
- pop DWORD PTR [eax]
- movd DWORD PTR [eax+4], mm3
-
- movd output, mm1
-
- femms
- }
-#else
- output = atti386_iir_filter_3DNow(output, hist1_ptr, coef_ptr);
-#endif
- return output;
-}
-
-#if MT32EMU_USE_MMX > 0
-
-int i386_partialProductOutput(int len, Bit16s leftvol, Bit16s rightvol, Bit16s *partialBuf, Bit16s *mixedBuf) {
- int tmplen = len >> 1;
- if (tmplen == 0) {
- return 0;
- }
-#ifdef _MSC_VER
- __asm {
- mov ecx,tmplen
- mov ax, leftvol
- shl eax,16
- mov ax, rightvol
- movd mm1, eax
- movd mm2, eax
- psllq mm1, 32
- por mm1, mm2
- mov edi, partialBuf
- mov esi, mixedBuf
-mmxloop1:
- mov bx, [esi]
- add esi,2
- mov dx, [esi]
- add esi,2
-
- mov ax, dx
- shl eax, 16
- mov ax, dx
- movd mm2,eax
- psllq mm2, 32
- mov ax, bx
- shl eax, 16
- mov ax, bx
- movd mm3,eax
- por mm2,mm3
-
- pmulhw mm2, mm1
- movq [edi], mm2
- add edi, 8
-
- dec ecx
- cmp ecx,0
- jg mmxloop1
- emms
- }
-#else
- atti386_partialProductOutput(tmplen, leftvol, rightvol, partialBuf, mixedBuf);
-#endif
- return tmplen << 1;
-}
-
-int i386_mixBuffers(Bit16s * buf1, Bit16s *buf2, int len) {
- int tmplen = len >> 2;
- if (tmplen == 0) {
- return 0;
- }
-#ifdef _MSC_VER
- __asm {
- mov ecx, tmplen
- mov esi, buf1
- mov edi, buf2
-
-mixloop1:
- movq mm1, [edi]
- movq mm2, [esi]
- paddw mm1,mm2
- movq [esi],mm1
- add edi,8
- add esi,8
-
- dec ecx
- cmp ecx,0
- jg mixloop1
- emms
- }
-#else
- atti386_mixBuffers(buf1, buf2, tmplen);
-#endif
- return tmplen << 2;
-}
-
-
-int i386_mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len) {
- int tmplen = len >> 2;
- if (tmplen == 0) {
- return 0;
- }
-#ifdef _MSC_VER
- __asm {
- mov ecx, tmplen
- mov esi, buf1
- mov edi, buf2
-
-mixloop2:
- movq mm1, [esi]
- movq mm2, [edi]
- movq mm3, mm1
- pmulhw mm1, mm2
- paddw mm1,mm3
- movq [esi],mm1
- add edi,8
- add esi,8
-
- dec ecx
- cmp ecx,0
- jg mixloop2
- emms
- }
-#else
- atti386_mixBuffersRingMix(buf1, buf2, tmplen);
-#endif
- return tmplen << 2;
-}
-
-int i386_mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len) {
- int tmplen = len >> 2;
- if (tmplen == 0) {
- return 0;
- }
-#ifdef _MSC_VER
- __asm {
- mov ecx, tmplen
- mov esi, buf1
- mov edi, buf2
-
-mixloop3:
- movq mm1, [esi]
- movq mm2, [edi]
- pmulhw mm1, mm2
- movq [esi],mm1
- add edi,8
- add esi,8
-
- dec ecx
- cmp ecx,0
- jg mixloop3
- emms
- }
-#else
- atti386_mixBuffersRing(buf1, buf2, tmplen);
-#endif
- return tmplen << 2;
-}
-
-int i386_produceOutput1(Bit16s *useBuf, Bit16s *stream, Bit32u len, Bit16s volume) {
- int tmplen = (len >> 1);
- if (tmplen == 0) {
- return 0;
- }
-#ifdef _MSC_VER
- __asm {
- mov ecx, tmplen
- mov ax,volume
- shl eax,16
- mov ax,volume
- movd mm3,eax
- movd mm2,eax
- psllq mm3, 32
- por mm3,mm2
- mov esi, useBuf
- mov edi, stream
-mixloop4:
- movq mm1, [esi]
- movq mm2, [edi]
- pmulhw mm1, mm3
- paddw mm1,mm2
- movq [edi], mm1
-
- add esi,8
- add edi,8
-
- dec ecx
- cmp ecx,0
- jg mixloop4
- emms
- }
-#else
- atti386_produceOutput1(tmplen, volume, useBuf, stream);
-#endif
- return tmplen << 1;
-}
-
-#endif
-
-}
-
-#endif
diff --git a/sound/softsynth/mt32/i386.h b/sound/softsynth/mt32/i386.h
deleted file mode 100644
index e8644411cd..0000000000
--- a/sound/softsynth/mt32/i386.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_I386_H
-#define MT32EMU_I386_H
-
-namespace MT32Emu {
-#ifdef MT32EMU_HAVE_X86
-
-// Function that detects the availablity of SSE SIMD instructions
-bool DetectSIMD();
-// Function that detects the availablity of 3DNow instructions
-bool Detect3DNow();
-
-float iir_filter_sse(float input,float *hist1_ptr, float *coef_ptr);
-float iir_filter_3dnow(float input,float *hist1_ptr, float *coef_ptr);
-float iir_filter_normal(float input,float *hist1_ptr, float *coef_ptr);
-
-#if MT32EMU_USE_MMX > 0
-int i386_partialProductOutput(int len, Bit16s leftvol, Bit16s rightvol, Bit16s *partialBuf, Bit16s *mixedBuf);
-int i386_mixBuffers(Bit16s * buf1, Bit16s *buf2, int len);
-int i386_mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len);
-int i386_mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len);
-int i386_produceOutput1(Bit16s *useBuf, Bit16s *stream, Bit32u len, Bit16s volume);
-#endif
-
-#endif
-
-}
-
-#endif
diff --git a/sound/softsynth/mt32/module.mk b/sound/softsynth/mt32/module.mk
deleted file mode 100644
index 4d5d899ac3..0000000000
--- a/sound/softsynth/mt32/module.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-MODULE := sound/softsynth/mt32
-
-MODULE_OBJS := \
- mt32_file.o \
- i386.o \
- part.o \
- partial.o \
- partialManager.o \
- synth.o \
- tables.o \
- freeverb.o
-
-# Include common rules
-include $(srcdir)/rules.mk
diff --git a/sound/softsynth/mt32/mt32_file.cpp b/sound/softsynth/mt32/mt32_file.cpp
deleted file mode 100644
index cdf9fa13f6..0000000000
--- a/sound/softsynth/mt32/mt32_file.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-
-#include "mt32emu.h"
-
-namespace MT32Emu {
-
-bool File::readBit16u(Bit16u *in) {
- Bit8u b[2];
- if (read(&b[0], 2) != 2)
- return false;
- *in = ((b[0] << 8) | b[1]);
- return true;
-}
-
-bool File::readBit32u(Bit32u *in) {
- Bit8u b[4];
- if (read(&b[0], 4) != 4)
- return false;
- *in = ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]);
- return true;
-}
-
-bool File::writeBit16u(Bit16u out) {
- if (!writeBit8u((Bit8u)((out & 0xFF00) >> 8))) {
- return false;
- }
- if (!writeBit8u((Bit8u)(out & 0x00FF))) {
- return false;
- }
- return true;
-}
-
-bool File::writeBit32u(Bit32u out) {
- if (!writeBit8u((Bit8u)((out & 0xFF000000) >> 24))) {
- return false;
- }
- if (!writeBit8u((Bit8u)((out & 0x00FF0000) >> 16))) {
- return false;
- }
- if (!writeBit8u((Bit8u)((out & 0x0000FF00) >> 8))) {
- return false;
- }
- if (!writeBit8u((Bit8u)(out & 0x000000FF))) {
- return false;
- }
- return true;
-}
-
-} // End of namespace MT32Emu
-
diff --git a/sound/softsynth/mt32/mt32_file.h b/sound/softsynth/mt32/mt32_file.h
deleted file mode 100644
index e6641660ee..0000000000
--- a/sound/softsynth/mt32/mt32_file.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_FILE_H
-#define MT32EMU_FILE_H
-
-#include "common/scummsys.h"
-
-namespace MT32Emu {
-
-class File {
-public:
- enum OpenMode {
- OpenMode_read = 0,
- OpenMode_write = 1
- };
- virtual ~File() {}
- virtual void close() = 0;
- virtual size_t read(void *in, size_t size) = 0;
- virtual bool readBit8u(Bit8u *in) = 0;
- virtual bool readBit16u(Bit16u *in);
- virtual bool readBit32u(Bit32u *in);
- virtual size_t write(const void *out, size_t size) = 0;
- virtual bool writeBit8u(Bit8u out) = 0;
- // Note: May write a single byte to the file before failing
- virtual bool writeBit16u(Bit16u out);
- // Note: May write some (<4) bytes to the file before failing
- virtual bool writeBit32u(Bit32u out);
- virtual bool isEOF() = 0;
-};
-
-} // End of namespace MT32Emu
-
-#endif
diff --git a/sound/softsynth/mt32/mt32emu.h b/sound/softsynth/mt32/mt32emu.h
deleted file mode 100644
index 6eedf04bc0..0000000000
--- a/sound/softsynth/mt32/mt32emu.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_MT32EMU_H
-#define MT32EMU_MT32EMU_H
-
-// Debugging
-// Show the instruments played
-#define MT32EMU_MONITOR_INSTRUMENTS 1
-// Shows number of partials MT-32 is playing, and on which parts
-#define MT32EMU_MONITOR_PARTIALS 0
-// Determines how the waveform cache file is handled (must be regenerated after sampling rate change)
-#define MT32EMU_WAVECACHEMODE 0 // Load existing cache if possible, otherwise generate and save cache
-//#define MT32EMU_WAVECACHEMODE 1 // Load existing cache if possible, otherwise generate but don't save cache
-//#define MT32EMU_WAVECACHEMODE 2 // Ignore existing cache, generate and save cache
-//#define MT32EMU_WAVECACHEMODE 3 // Ignore existing cache, generate but don't save cache
-
-// Configuration
-// The maximum number of partials playing simultaneously
-#define MT32EMU_MAX_PARTIALS 32
-// The maximum number of notes playing simultaneously per part.
-// No point making it more than MT32EMU_MAX_PARTIALS, since each note needs at least one partial.
-#define MT32EMU_MAX_POLY 32
-// This calculates the exact frequencies of notes as they are played, instead of offsetting from pre-cached semitones. Potentially very slow.
-#define MT32EMU_ACCURATENOTES 0
-
-#if (defined (_MSC_VER) && defined(_M_IX86))
-#define MT32EMU_HAVE_X86
-#elif defined(__GNUC__)
-#if __GNUC__ >= 3 && defined(__i386__)
-#define MT32EMU_HAVE_X86
-#endif
-#endif
-
-#ifdef MT32EMU_HAVE_X86
-#define MT32EMU_USE_MMX 1
-#else
-#define MT32EMU_USE_MMX 0
-#endif
-
-#include "freeverb.h"
-
-#include "structures.h"
-#include "i386.h"
-#include "mt32_file.h"
-#include "tables.h"
-#include "partial.h"
-#include "partialManager.h"
-#include "part.h"
-#include "synth.h"
-
-#endif
diff --git a/sound/softsynth/mt32/part.cpp b/sound/softsynth/mt32/part.cpp
deleted file mode 100644
index eb087f7ea0..0000000000
--- a/sound/softsynth/mt32/part.cpp
+++ /dev/null
@@ -1,633 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <string.h>
-#include <math.h>
-
-#include "mt32emu.h"
-
-namespace MT32Emu {
-
-static const Bit8u PartialStruct[13] = {
- 0, 0, 2, 2, 1, 3,
- 3, 0, 3, 0, 2, 1, 3 };
-
-static const Bit8u PartialMixStruct[13] = {
- 0, 1, 0, 1, 1, 0,
- 1, 3, 3, 2, 2, 2, 2 };
-
-static const float floatKeyfollow[17] = {
- -1.0f, -1.0f/2.0f, -1.0f/4.0f, 0.0f,
- 1.0f/8.0f, 1.0f/4.0f, 3.0f/8.0f, 1.0f/2.0f, 5.0f/8.0f, 3.0f/4.0f, 7.0f/8.0f, 1.0f,
- 5.0f/4.0f, 3.0f/2.0f, 2.0f,
- 1.0009765625f, 1.0048828125f
-};
-
-//FIXME:KG: Put this dpoly stuff somewhere better
-bool dpoly::isActive() const {
- return partials[0] != NULL || partials[1] != NULL || partials[2] != NULL || partials[3] != NULL;
-}
-
-Bit32u dpoly::getAge() const {
- for (int i = 0; i < 4; i++) {
- if (partials[i] != NULL) {
- return partials[i]->age;
- }
- }
- return 0;
-}
-
-RhythmPart::RhythmPart(Synth *useSynth, unsigned int usePartNum): Part(useSynth, usePartNum) {
- strcpy(name, "Rhythm");
- rhythmTemp = &synth->mt32ram.rhythmSettings[0];
- refresh();
-}
-
-Part::Part(Synth *useSynth, unsigned int usePartNum) {
- this->synth = useSynth;
- this->partNum = usePartNum;
- patchCache[0].dirty = true;
- holdpedal = false;
- patchTemp = &synth->mt32ram.patchSettings[partNum];
- if (usePartNum == 8) {
- // Nasty hack for rhythm
- timbreTemp = NULL;
- } else {
- sprintf(name, "Part %d", partNum + 1);
- timbreTemp = &synth->mt32ram.timbreSettings[partNum];
- }
- currentInstr[0] = 0;
- currentInstr[10] = 0;
- expression = 127;
- volumeMult = 0;
- volumesetting.leftvol = 32767;
- volumesetting.rightvol = 32767;
- bend = 0.0f;
- memset(polyTable,0,sizeof(polyTable));
- memset(patchCache, 0, sizeof(patchCache));
-}
-
-void Part::setHoldPedal(bool pedalval) {
- if (holdpedal && !pedalval) {
- holdpedal = false;
- stopPedalHold();
- } else {
- holdpedal = pedalval;
- }
-}
-
-void RhythmPart::setBend(unsigned int midiBend) {
- synth->printDebug("%s: Setting bend (%d) not supported on rhythm", name, midiBend);
- return;
-}
-
-void Part::setBend(unsigned int midiBend) {
- // FIXME:KG: Slightly unbalanced increments, but I wanted min -1.0, centre 0.0 and max 1.0
- if (midiBend <= 0x2000) {
- bend = ((signed int)midiBend - 0x2000) / (float)0x2000;
- } else {
- bend = ((signed int)midiBend - 0x2000) / (float)0x1FFF;
- }
- // Loop through all partials to update their bend
- for (int i = 0; i < MT32EMU_MAX_POLY; i++) {
- for (int j = 0; j < 4; j++) {
- if (polyTable[i].partials[j] != NULL) {
- polyTable[i].partials[j]->setBend(bend);
- }
- }
- }
-}
-
-void RhythmPart::setModulation(unsigned int midiModulation) {
- synth->printDebug("%s: Setting modulation (%d) not supported on rhythm", name, midiModulation);
-}
-
-void Part::setModulation(unsigned int midiModulation) {
- // Just a bloody guess, as always, before I get things figured out
- for (int t = 0; t < 4; t++) {
- if (patchCache[t].playPartial) {
- int newrate = (patchCache[t].modsense * midiModulation) >> 7;
- //patchCache[t].lfoperiod = lfotable[newrate];
- patchCache[t].lfodepth = newrate;
- //FIXME:KG: timbreTemp->partial[t].lfo.depth =
- }
- }
-}
-
-void RhythmPart::refresh() {
- updateVolume();
- // (Re-)cache all the mapped timbres ahead of time
- for (unsigned int drumNum = 0; drumNum < synth->controlROMMap->rhythmSettingsCount; drumNum++) {
- int drumTimbreNum = rhythmTemp[drumNum].timbre;
- if (drumTimbreNum >= 127) // 94 on MT-32
- continue;
- Bit16s pan = rhythmTemp[drumNum].panpot; // They use R-L 0-14...
- // FIXME:KG: Panning cache should be backed up to partials using it, too
- if (pan < 7) {
- drumPan[drumNum].leftvol = pan * 4681;
- drumPan[drumNum].rightvol = 32767;
- } else {
- drumPan[drumNum].rightvol = (14 - pan) * 4681;
- drumPan[drumNum].leftvol = 32767;
- }
- PatchCache *cache = drumCache[drumNum];
- backupCacheToPartials(cache);
- for (int t = 0; t < 4; t++) {
- // Common parameters, stored redundantly
- cache[t].dirty = true;
- cache[t].pitchShift = 0.0f;
- cache[t].benderRange = 0.0f;
- cache[t].pansetptr = &drumPan[drumNum];
- cache[t].reverb = rhythmTemp[drumNum].reverbSwitch > 0;
- }
- }
-}
-
-void Part::refresh() {
- updateVolume();
- backupCacheToPartials(patchCache);
- for (int t = 0; t < 4; t++) {
- // Common parameters, stored redundantly
- patchCache[t].dirty = true;
- patchCache[t].pitchShift = (patchTemp->patch.keyShift - 24) + (patchTemp->patch.fineTune - 50) / 100.0f;
- patchCache[t].benderRange = patchTemp->patch.benderRange;
- patchCache[t].pansetptr = &volumesetting;
- patchCache[t].reverb = patchTemp->patch.reverbSwitch > 0;
- }
- memcpy(currentInstr, timbreTemp->common.name, 10);
-}
-
-const char *Part::getCurrentInstr() const {
- return &currentInstr[0];
-}
-
-void RhythmPart::refreshTimbre(unsigned int absTimbreNum) {
- for (int m = 0; m < 85; m++) {
- if (rhythmTemp[m].timbre == absTimbreNum - 128)
- drumCache[m][0].dirty = true;
- }
-}
-
-void Part::refreshTimbre(unsigned int absTimbreNum) {
- if (getAbsTimbreNum() == absTimbreNum) {
- memcpy(currentInstr, timbreTemp->common.name, 10);
- patchCache[0].dirty = true;
- }
-}
-
-int Part::fixBiaslevel(int srcpnt, int *dir) {
- int noteat = srcpnt & 0x3F;
- int outnote;
- if (srcpnt < 64)
- *dir = 0;
- else
- *dir = 1;
- outnote = 33 + noteat;
- //synth->printDebug("Bias note %d, dir %d", outnote, *dir);
-
- return outnote;
-}
-
-int Part::fixKeyfollow(int srckey) {
- if (srckey>=0 && srckey<=16) {
- int keyfix[17] = { -256*16, -128*16, -64*16, 0, 32*16, 64*16, 96*16, 128*16, (128+32)*16, 192*16, (192+32)*16, 256*16, (256+64)*16, (256+128)*16, (512)*16, 4100, 4116};
- return keyfix[srckey];
- } else {
- //LOG(LOG_ERROR|LOG_MISC,"Missed key: %d", srckey);
- return 256;
- }
-}
-
-void Part::abortPoly(dpoly *poly) {
- if (!poly->isPlaying) {
- return;
- }
- for (int i = 0; i < 4; i++) {
- Partial *partial = poly->partials[i];
- if (partial != NULL) {
- partial->deactivate();
- }
- }
- poly->isPlaying = false;
-}
-
-void Part::setPatch(const PatchParam *patch) {
- patchTemp->patch = *patch;
-}
-
-void RhythmPart::setTimbre(TimbreParam * /*timbre*/) {
- synth->printDebug("%s: Attempted to call setTimbre() - doesn't make sense for rhythm", name);
-}
-
-void Part::setTimbre(TimbreParam *timbre) {
- *timbreTemp = *timbre;
-}
-
-unsigned int RhythmPart::getAbsTimbreNum() const {
- synth->printDebug("%s: Attempted to call getAbsTimbreNum() - doesn't make sense for rhythm", name);
- return 0;
-}
-
-unsigned int Part::getAbsTimbreNum() const {
- return (patchTemp->patch.timbreGroup * 64) + patchTemp->patch.timbreNum;
-}
-
-void RhythmPart::setProgram(unsigned int patchNum) {
- synth->printDebug("%s: Attempt to set program (%d) on rhythm is invalid", name, patchNum);
-}
-
-void Part::setProgram(unsigned int patchNum) {
- setPatch(&synth->mt32ram.patches[patchNum]);
- setTimbre(&synth->mt32ram.timbres[getAbsTimbreNum()].timbre);
-
- refresh();
-
- allSoundOff(); //FIXME:KG: Is this correct?
-}
-
-void Part::backupCacheToPartials(PatchCache cache[4]) {
- // check if any partials are still playing with the old patch cache
- // if so then duplicate the cached data from the part to the partial so that
- // we can change the part's cache without affecting the partial.
- // We delay this until now to avoid a copy operation with every note played
- for (int m = 0; m < MT32EMU_MAX_POLY; m++) {
- for (int i = 0; i < 4; i++) {
- Partial *partial = polyTable[m].partials[i];
- if (partial != NULL && partial->patchCache == &cache[i]) {
- partial->cachebackup = cache[i];
- partial->patchCache = &partial->cachebackup;
- }
- }
- }
-}
-
-void Part::cacheTimbre(PatchCache cache[4], const TimbreParam *timbre) {
- backupCacheToPartials(cache);
- int partialCount = 0;
- for (int t = 0; t < 4; t++) {
- cache[t].PCMPartial = false;
- if (((timbre->common.pmute >> t) & 0x1) == 1) {
- cache[t].playPartial = true;
- partialCount++;
- } else {
- cache[t].playPartial = false;
- continue;
- }
-
- // Calculate and cache common parameters
-
- cache[t].pcm = timbre->partial[t].wg.pcmwave;
- cache[t].useBender = (timbre->partial[t].wg.bender == 1);
-
- switch (t) {
- case 0:
- cache[t].PCMPartial = (PartialStruct[(int)timbre->common.pstruct12] & 0x2) ? true : false;
- cache[t].structureMix = PartialMixStruct[(int)timbre->common.pstruct12];
- cache[t].structurePosition = 0;
- cache[t].structurePair = 1;
- break;
- case 1:
- cache[t].PCMPartial = (PartialStruct[(int)timbre->common.pstruct12] & 0x1) ? true : false;
- cache[t].structureMix = PartialMixStruct[(int)timbre->common.pstruct12];
- cache[t].structurePosition = 1;
- cache[t].structurePair = 0;
- break;
- case 2:
- cache[t].PCMPartial = (PartialStruct[(int)timbre->common.pstruct34] & 0x2) ? true : false;
- cache[t].structureMix = PartialMixStruct[(int)timbre->common.pstruct34];
- cache[t].structurePosition = 0;
- cache[t].structurePair = 3;
- break;
- case 3:
- cache[t].PCMPartial = (PartialStruct[(int)timbre->common.pstruct34] & 0x1) ? true : false;
- cache[t].structureMix = PartialMixStruct[(int)timbre->common.pstruct34];
- cache[t].structurePosition = 1;
- cache[t].structurePair = 2;
- break;
- default:
- break;
- }
-
- cache[t].waveform = timbre->partial[t].wg.waveform;
- cache[t].pulsewidth = timbre->partial[t].wg.pulsewid;
- cache[t].pwsens = timbre->partial[t].wg.pwvelo;
- if (timbre->partial[t].wg.keyfollow > 16) {
- synth->printDebug("Bad keyfollow value in timbre!");
- cache[t].pitchKeyfollow = 1.0f;
- } else {
- cache[t].pitchKeyfollow = floatKeyfollow[timbre->partial[t].wg.keyfollow];
- }
-
- cache[t].pitch = timbre->partial[t].wg.coarse + (timbre->partial[t].wg.fine - 50) / 100.0f + 24.0f;
- cache[t].pitchEnv = timbre->partial[t].env;
- cache[t].pitchEnv.sensitivity = (char)((float)cache[t].pitchEnv.sensitivity * 1.27f);
- cache[t].pitchsustain = cache[t].pitchEnv.level[3];
-
- // Calculate and cache TVA envelope stuff
- cache[t].ampEnv = timbre->partial[t].tva;
- cache[t].ampEnv.level = (char)((float)cache[t].ampEnv.level * 1.27f);
-
- cache[t].ampbias[0] = fixBiaslevel(cache[t].ampEnv.biaspoint1, &cache[t].ampdir[0]);
- cache[t].ampblevel[0] = 12 - cache[t].ampEnv.biaslevel1;
- cache[t].ampbias[1] = fixBiaslevel(cache[t].ampEnv.biaspoint2, &cache[t].ampdir[1]);
- cache[t].ampblevel[1] = 12 - cache[t].ampEnv.biaslevel2;
- cache[t].ampdepth = cache[t].ampEnv.envvkf * cache[t].ampEnv.envvkf;
-
- // Calculate and cache filter stuff
- cache[t].filtEnv = timbre->partial[t].tvf;
- cache[t].filtkeyfollow = fixKeyfollow(cache[t].filtEnv.keyfollow);
- cache[t].filtEnv.envdepth = (char)((float)cache[t].filtEnv.envdepth * 1.27);
- cache[t].tvfbias = fixBiaslevel(cache[t].filtEnv.biaspoint, &cache[t].tvfdir);
- cache[t].tvfblevel = cache[t].filtEnv.biaslevel;
- cache[t].filtsustain = cache[t].filtEnv.envlevel[3];
-
- // Calculate and cache LFO stuff
- cache[t].lfodepth = timbre->partial[t].lfo.depth;
- cache[t].lfoperiod = synth->tables.lfoPeriod[(int)timbre->partial[t].lfo.rate];
- cache[t].lforate = timbre->partial[t].lfo.rate;
- cache[t].modsense = timbre->partial[t].lfo.modsense;
- }
- for (int t = 0; t < 4; t++) {
- // Common parameters, stored redundantly
- cache[t].dirty = false;
- cache[t].partialCount = partialCount;
- cache[t].sustain = (timbre->common.nosustain == 0);
- }
- //synth->printDebug("Res 1: %d 2: %d 3: %d 4: %d", cache[0].waveform, cache[1].waveform, cache[2].waveform, cache[3].waveform);
-
-#if MT32EMU_MONITOR_INSTRUMENTS == 1
- synth->printDebug("%s (%s): Recached timbre", name, currentInstr);
- for (int i = 0; i < 4; i++) {
- synth->printDebug(" %d: play=%s, pcm=%s (%d), wave=%d", i, cache[i].playPartial ? "YES" : "NO", cache[i].PCMPartial ? "YES" : "NO", timbre->partial[i].wg.pcmwave, timbre->partial[i].wg.waveform);
- }
-#endif
-}
-
-const char *Part::getName() const {
- return name;
-}
-
-void Part::updateVolume() {
- volumeMult = synth->tables.volumeMult[patchTemp->outlevel * expression / 127];
-}
-
-int Part::getVolume() const {
- // FIXME: Use the mappings for this in the control ROM
- return patchTemp->outlevel * 127 / 100;
-}
-
-void Part::setVolume(int midiVolume) {
- // FIXME: Use the mappings for this in the control ROM
- patchTemp->outlevel = (Bit8u)(midiVolume * 100 / 127);
- updateVolume();
- synth->printDebug("%s (%s): Set volume to %d", name, currentInstr, midiVolume);
-}
-
-void Part::setExpression(int midiExpression) {
- expression = midiExpression;
- updateVolume();
-}
-
-void RhythmPart::setPan(unsigned int midiPan)
-{
- // FIXME:KG: This is unchangeable for drums (they always use drumPan), is that correct?
- synth->printDebug("%s: Setting pan (%d) not supported on rhythm", name, midiPan);
-}
-
-void Part::setPan(unsigned int midiPan) {
- // FIXME:KG: Tweaked this a bit so that we have a left 100%, centre and right 100%
- // (But this makes the range somewhat skewed)
- // Check against the real thing
- // NOTE: Panning is inverted compared to GM.
- if (midiPan < 64) {
- volumesetting.leftvol = (Bit16s)(midiPan * 512);
- volumesetting.rightvol = 32767;
- } else if (midiPan == 64) {
- volumesetting.leftvol = 32767;
- volumesetting.rightvol = 32767;
- } else {
- volumesetting.rightvol = (Bit16s)((127 - midiPan) * 520);
- volumesetting.leftvol = 32767;
- }
- patchTemp->panpot = (Bit8u)(midiPan * 14 / 127);
- //synth->printDebug("%s (%s): Set pan to %d", name, currentInstr, panpot);
-}
-
-void RhythmPart::playNote(unsigned int key, int vel) {
- if (key < 24 || key > 108)/*> 87 on MT-32)*/ {
- synth->printDebug("%s: Attempted to play invalid key %d", name, key);
- return;
- }
- int drumNum = key - 24;
- int drumTimbreNum = rhythmTemp[drumNum].timbre;
- if (drumTimbreNum >= 127) { // 94 on MT-32
- synth->printDebug("%s: Attempted to play unmapped key %d", name, key);
- return;
- }
- int absTimbreNum = drumTimbreNum + 128;
- TimbreParam *timbre = &synth->mt32ram.timbres[absTimbreNum].timbre;
- memcpy(currentInstr, timbre->common.name, 10);
-#if MT32EMU_MONITOR_INSTRUMENTS == 1
- synth->printDebug("%s (%s): starting poly (drum %d, timbre %d) - Vel %d Key %d", name, currentInstr, drumNum, absTimbreNum, vel, key);
-#endif
- if (drumCache[drumNum][0].dirty) {
- cacheTimbre(drumCache[drumNum], timbre);
- }
- playPoly(drumCache[drumNum], key, MIDDLEC, vel);
-}
-
-void Part::playNote(unsigned int key, int vel) {
- int freqNum = key;
- if (freqNum < 12) {
- synth->printDebug("%s (%s): Attempted to play invalid key %d < 12; moving up by octave", name, currentInstr, key);
- freqNum += 12;
- } else if (freqNum > 108) {
- synth->printDebug("%s (%s): Attempted to play invalid key %d > 108; moving down by octave", name, currentInstr, key);
- while (freqNum > 108) {
- freqNum -= 12;
- }
- }
- // POLY1 mode, Single Assign
- // Haven't found any software that uses any of the other poly modes
- // FIXME:KG: Should this also apply to rhythm?
- for (unsigned int i = 0; i < MT32EMU_MAX_POLY; i++) {
- if (polyTable[i].isActive() && (polyTable[i].key == key)) {
- //AbortPoly(&polyTable[i]);
- stopNote(key);
- break;
- }
- }
-#if MT32EMU_MONITOR_INSTRUMENTS == 1
- synth->printDebug("%s (%s): starting poly - Vel %d Key %d", name, currentInstr, vel, key);
-#endif
- if (patchCache[0].dirty) {
- cacheTimbre(patchCache, timbreTemp);
- }
- playPoly(patchCache, key, freqNum, vel);
-}
-
-void Part::playPoly(const PatchCache cache[4], unsigned int key, int freqNum, int vel) {
- unsigned int needPartials = cache[0].partialCount;
- unsigned int freePartials = synth->partialManager->getFreePartialCount();
-
- if (freePartials < needPartials) {
- if (!synth->partialManager->freePartials(needPartials - freePartials, partNum)) {
- synth->printDebug("%s (%s): Insufficient free partials to play key %d (vel=%d); needed=%d, free=%d", name, currentInstr, key, vel, needPartials, synth->partialManager->getFreePartialCount());
- return;
- }
- }
- // Find free poly
- int m;
- for (m = 0; m < MT32EMU_MAX_POLY; m++) {
- if (!polyTable[m].isActive()) {
- break;
- }
- }
- if (m == MT32EMU_MAX_POLY) {
- synth->printDebug("%s (%s): No free poly to play key %d (vel %d)", name, currentInstr, key, vel);
- return;
- }
-
- dpoly *tpoly = &polyTable[m];
-
- tpoly->isPlaying = true;
- tpoly->key = key;
- tpoly->isDecay = false;
- tpoly->freqnum = freqNum;
- tpoly->vel = vel;
- tpoly->pedalhold = false;
-
- bool allnull = true;
- for (int x = 0; x < 4; x++) {
- if (cache[x].playPartial) {
- tpoly->partials[x] = synth->partialManager->allocPartial(partNum);
- allnull = false;
- } else {
- tpoly->partials[x] = NULL;
- }
- }
-
- if (allnull)
- synth->printDebug("%s (%s): No partials to play for this instrument", name, this->currentInstr);
-
- tpoly->sustain = cache[0].sustain;
- tpoly->volumeptr = &volumeMult;
-
- for (int x = 0; x < 4; x++) {
- if (tpoly->partials[x] != NULL) {
- tpoly->partials[x]->startPartial(tpoly, &cache[x], tpoly->partials[cache[x].structurePair]);
- tpoly->partials[x]->setBend(bend);
- }
- }
-}
-
-static void startDecayPoly(dpoly *tpoly) {
- if (tpoly->isDecay) {
- return;
- }
- tpoly->isDecay = true;
-
- for (int t = 0; t < 4; t++) {
- Partial *partial = tpoly->partials[t];
- if (partial == NULL)
- continue;
- partial->startDecayAll();
- }
- tpoly->isPlaying = false;
-}
-
-void Part::allNotesOff() {
- // Note: Unchecked on real MT-32, but the MIDI specification states that all notes off (0x7B)
- // should treat the hold pedal as usual.
- // All *sound* off (0x78) should stop notes immediately regardless of the hold pedal.
- // The latter controller is not implemented on the MT-32 (according to the docs).
- for (int q = 0; q < MT32EMU_MAX_POLY; q++) {
- dpoly *tpoly = &polyTable[q];
- if (tpoly->isPlaying) {
- if (holdpedal)
- tpoly->pedalhold = true;
- else if (tpoly->sustain)
- startDecayPoly(tpoly);
- }
- }
-}
-
-void Part::allSoundOff() {
- for (int q = 0; q < MT32EMU_MAX_POLY; q++) {
- dpoly *tpoly = &polyTable[q];
- if (tpoly->isPlaying) {
- startDecayPoly(tpoly);
- }
- }
-}
-
-void Part::stopPedalHold() {
- for (int q = 0; q < MT32EMU_MAX_POLY; q++) {
- dpoly *tpoly;
- tpoly = &polyTable[q];
- if (tpoly->isActive() && tpoly->pedalhold)
- stopNote(tpoly->key);
- }
-}
-
-void Part::stopNote(unsigned int key) {
- // Non-sustaining instruments ignore stop commands.
- // They die away eventually anyway
-
-#if MT32EMU_MONITOR_INSTRUMENTS == 1
- synth->printDebug("%s (%s): stopping key %d", name, currentInstr, key);
-#endif
-
- if (key != 255) {
- for (int q = 0; q < MT32EMU_MAX_POLY; q++) {
- dpoly *tpoly = &polyTable[q];
- if (tpoly->isPlaying && tpoly->key == key) {
- if (holdpedal)
- tpoly->pedalhold = true;
- else if (tpoly->sustain)
- startDecayPoly(tpoly);
- }
- }
- return;
- }
-
- // Find oldest poly... yes, the MT-32 can be reconfigured to kill different poly first
- // This is simplest
- int oldest = -1;
- Bit32u oldage = 0;
-
- for (int q = 0; q < MT32EMU_MAX_POLY; q++) {
- dpoly *tpoly = &polyTable[q];
-
- if (tpoly->isPlaying && !tpoly->isDecay) {
- if (tpoly->getAge() >= oldage) {
- oldage = tpoly->getAge();
- oldest = q;
- }
- }
- }
-
- if (oldest != -1) {
- startDecayPoly(&polyTable[oldest]);
- }
-}
-
-}
diff --git a/sound/softsynth/mt32/part.h b/sound/softsynth/mt32/part.h
deleted file mode 100644
index 54c4999653..0000000000
--- a/sound/softsynth/mt32/part.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_PART_H
-#define MT32EMU_PART_H
-
-namespace MT32Emu {
-
-class PartialManager;
-class Synth;
-
-class Part {
-private:
- // Pointers to the areas of the MT-32's memory dedicated to this part (for parts 1-8)
- MemParams::PatchTemp *patchTemp;
- TimbreParam *timbreTemp;
-
- // 0=Part 1, .. 7=Part 8, 8=Rhythm
- unsigned int partNum;
-
- bool holdpedal;
-
- StereoVolume volumesetting;
-
- PatchCache patchCache[4];
-
- float bend; // -1.0 .. +1.0
-
- dpoly polyTable[MT32EMU_MAX_POLY];
-
- void abortPoly(dpoly *poly);
-
- static int fixKeyfollow(int srckey);
- static int fixBiaslevel(int srcpnt, int *dir);
-
- void setPatch(const PatchParam *patch);
-
-protected:
- Synth *synth;
- char name[8]; // "Part 1".."Part 8", "Rhythm"
- char currentInstr[11];
- int expression;
- Bit32u volumeMult;
-
- void updateVolume();
- void backupCacheToPartials(PatchCache cache[4]);
- void cacheTimbre(PatchCache cache[4], const TimbreParam *timbre);
- void playPoly(const PatchCache cache[4], unsigned int key, int freqNum, int vel);
- const char *getName() const;
-
-public:
- Part(Synth *synth, unsigned int usePartNum);
- virtual ~Part() {}
- virtual void playNote(unsigned int key, int vel);
- void stopNote(unsigned int key);
- void allNotesOff();
- void allSoundOff();
- int getVolume() const;
- void setVolume(int midiVolume);
- void setExpression(int midiExpression);
- virtual void setPan(unsigned int midiPan);
- virtual void setBend(unsigned int midiBend);
- virtual void setModulation(unsigned int midiModulation);
- virtual void setProgram(unsigned int midiProgram);
- void setHoldPedal(bool pedalval);
- void stopPedalHold();
- virtual void refresh();
- virtual void refreshTimbre(unsigned int absTimbreNum);
- virtual void setTimbre(TimbreParam *timbre);
- virtual unsigned int getAbsTimbreNum() const;
- const char *getCurrentInstr() const;
-};
-
-class RhythmPart: public Part {
- // Pointer to the area of the MT-32's memory dedicated to rhythm
- const MemParams::RhythmTemp *rhythmTemp;
-
- // This caches the timbres/settings in use by the rhythm part
- PatchCache drumCache[85][4];
- StereoVolume drumPan[85];
-public:
- RhythmPart(Synth *synth, unsigned int usePartNum);
- void refresh();
- void refreshTimbre(unsigned int timbreNum);
- void setTimbre(TimbreParam *timbre);
- void playNote(unsigned int key, int vel);
- unsigned int getAbsTimbreNum() const;
- void setPan(unsigned int midiPan);
- void setBend(unsigned int midiBend);
- void setModulation(unsigned int midiModulation);
- void setProgram(unsigned int patchNum);
-};
-
-}
-#endif
diff --git a/sound/softsynth/mt32/partial.cpp b/sound/softsynth/mt32/partial.cpp
deleted file mode 100644
index 5ba9ef6145..0000000000
--- a/sound/softsynth/mt32/partial.cpp
+++ /dev/null
@@ -1,968 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#include "mt32emu.h"
-
-#if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__)
-// Older versions of Mac OS X didn't supply a powf function, so using it
-// will cause a binary incompatibility when trying to run a binary built
-// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide
-// powf, floorf, fabsf etc. at all.
-// Cross-compiled MinGW32 toolchains suffer from a cross-compile bug in
-// libstdc++. math/stubs.o should be empty, but it comes with a symbol for
-// powf, resulting in a linker error because of multiple definitions.
-// Hence we re-define them here. The only potential drawback is that it
-// might be a little bit slower this way.
-#define powf(x,y) ((float)pow(x,y))
-#define floorf(x) ((float)floor(x))
-#define fabsf(x) ((float)fabs(x))
-#endif
-
-#define FIXEDPOINT_UDIV(x, y, point) (((x) << (point)) / ((y)))
-#define FIXEDPOINT_SDIV(x, y, point) (((x) * (1 << point)) / ((y)))
-#define FIXEDPOINT_UMULT(x, y, point) (((x) * (y)) >> point)
-#define FIXEDPOINT_SMULT(x, y, point) (((x) * (y)) / (1 << point))
-
-using namespace MT32Emu;
-
-Partial::Partial(Synth *useSynth) {
- this->synth = useSynth;
- ownerPart = -1;
- poly = NULL;
- pair = NULL;
-#if MT32EMU_ACCURATENOTES == 1
- for (int i = 0; i < 3; i++) {
- noteLookupStorage.waveforms[i] = new Bit16s[65536];
- }
- noteLookup = &noteLookupStorage;
-#endif
-}
-
-Partial::~Partial() {
-#if MT32EMU_ACCURATENOTES == 1
- for (int i = 0; i < 3; i++) {
- delete[] noteLookupStorage.waveforms[i];
- }
- delete[] noteLookupStorage.wavTable;
-#endif
-}
-
-int Partial::getOwnerPart() const {
- return ownerPart;
-}
-
-bool Partial::isActive() {
- return ownerPart > -1;
-}
-
-const dpoly *Partial::getDpoly() const {
- return this->poly;
-}
-
-void Partial::activate(int part) {
- // This just marks the partial as being assigned to a part
- ownerPart = part;
-}
-
-void Partial::deactivate() {
- ownerPart = -1;
- if (poly != NULL) {
- for (int i = 0; i < 4; i++) {
- if (poly->partials[i] == this) {
- poly->partials[i] = NULL;
- break;
- }
- }
- if (pair != NULL) {
- pair->pair = NULL;
- }
- }
-}
-
-void Partial::initKeyFollow(int key) {
- // Setup partial keyfollow
- // Note follow relative to middle C
-
- // Calculate keyfollow for pitch
-#if 1
- float rel = key == -1 ? 0.0f : (key - MIDDLEC);
- float newPitch = rel * patchCache->pitchKeyfollow + patchCache->pitch + patchCache->pitchShift;
- //FIXME:KG: Does it truncate the keyfollowed pitch to a semitone (towards MIDDLEC)?
- //int newKey = (int)(rel * patchCache->pitchKeyfollow);
- //float newPitch = newKey + patchCache->pitch + patchCache->pitchShift;
-#else
- float rel = key == -1 ? 0.0f : (key + patchCache->pitchShift - MIDDLEC);
- float newPitch = rel * patchCache->pitchKeyfollow + patchCache->pitch;
-#endif
-#if MT32EMU_ACCURATENOTES == 1
- noteVal = newPitch;
- synth->printDebug("key=%d, pitch=%f, pitchKeyfollow=%f, pitchShift=%f, newPitch=%f", key, (double)patchCache->pitch, (double)patchCache->pitchKeyfollow, (double)patchCache->pitchShift, (double)newPitch);
-#else
- float newPitchInt;
- float newPitchFract = modff(newPitch, &newPitchInt);
- if (newPitchFract > 0.5f) {
- newPitchInt += 1.0f;
- newPitchFract -= 1.0f;
- }
- noteVal = (int)newPitchInt;
- fineShift = (int)(powf(2.0f, newPitchFract / 12.0f) * 4096.0f);
- synth->printDebug("key=%d, pitch=%f, pitchKeyfollow=%f, pitchShift=%f, newPitch=%f, noteVal=%d, fineShift=%d", key, (double)patchCache->pitch, (double)patchCache->pitchKeyfollow, (double)patchCache->pitchShift, (double)newPitch, noteVal, fineShift);
-#endif
- // FIXME:KG: Raise/lower by octaves until in the supported range.
- while (noteVal > HIGHEST_NOTE) // FIXME:KG: see tables.cpp: >108?
- noteVal -= 12;
- while (noteVal < LOWEST_NOTE) // FIXME:KG: see tables.cpp: <12?
- noteVal += 12;
- // Calculate keyfollow for filter
- int keyfollow = ((key - MIDDLEC) * patchCache->filtkeyfollow) / 4096;
- if (keyfollow > 108)
- keyfollow = 108;
- else if (keyfollow < -108)
- keyfollow = -108;
- filtVal = synth->tables.tvfKeyfollowMult[keyfollow + 108];
- realVal = synth->tables.tvfKeyfollowMult[(noteVal - MIDDLEC) + 108];
-}
-
-int Partial::getKey() const {
- if (poly == NULL) {
- return -1;
- } else {
- return poly->key;
- }
-}
-
-void Partial::startPartial(dpoly *usePoly, const PatchCache *useCache, Partial *pairPartial) {
- if (usePoly == NULL || useCache == NULL) {
- synth->printDebug("*** Error: Starting partial for owner %d, usePoly=%s, useCache=%s", ownerPart, usePoly == NULL ? "*** NULL ***" : "OK", useCache == NULL ? "*** NULL ***" : "OK");
- return;
- }
- patchCache = useCache;
- poly = usePoly;
- mixType = patchCache->structureMix;
- structurePosition = patchCache->structurePosition;
-
- play = true;
- initKeyFollow(poly->freqnum); // Initialises noteVal, filtVal and realVal
-#if MT32EMU_ACCURATENOTES == 0
- noteLookup = &synth->tables.noteLookups[noteVal - LOWEST_NOTE];
-#else
- Tables::initNote(synth, &noteLookupStorage, noteVal, (float)synth->myProp.sampleRate, synth->masterTune, synth->pcmWaves, NULL);
-#endif
- keyLookup = &synth->tables.keyLookups[poly->freqnum - 12];
-
- if (patchCache->PCMPartial) {
- pcmNum = patchCache->pcm;
- if (synth->controlROMMap->pcmCount > 128) {
- // CM-32L, etc. support two "banks" of PCMs, selectable by waveform type parameter.
- if (patchCache->waveform > 1) {
- pcmNum += 128;
- }
- }
- pcmWave = &synth->pcmWaves[pcmNum];
- } else {
- pcmWave = NULL;
- }
-
- lfoPos = 0;
- pulsewidth = patchCache->pulsewidth + synth->tables.pwVelfollowAdd[patchCache->pwsens][poly->vel];
- if (pulsewidth > 100) {
- pulsewidth = 100;
- } else if (pulsewidth < 0) {
- pulsewidth = 0;
- }
-
- for (int e = 0; e < 3; e++) {
- envs[e].envpos = 0;
- envs[e].envstat = -1;
- envs[e].envbase = 0;
- envs[e].envdist = 0;
- envs[e].envsize = 0;
- envs[e].sustaining = false;
- envs[e].decaying = false;
- envs[e].prevlevel = 0;
- envs[e].counter = 0;
- envs[e].count = 0;
- }
- ampEnvVal = 0;
- pitchEnvVal = 0;
- pitchSustain = false;
- loopPos = 0;
- partialOff.pcmoffset = partialOff.pcmplace = 0;
- pair = pairPartial;
- useNoisePair = pairPartial == NULL && (mixType == 1 || mixType == 2);
- age = 0;
- alreadyOutputed = false;
- memset(history,0,sizeof(history));
-}
-
-Bit16s *Partial::generateSamples(long length) {
- if (!isActive() || alreadyOutputed) {
- return NULL;
- }
- if (poly == NULL) {
- synth->printDebug("*** ERROR: poly is NULL at Partial::generateSamples()!");
- return NULL;
- }
-
- alreadyOutputed = true;
-
- // Generate samples
-
- Bit16s *partialBuf = &myBuffer[0];
- Bit32u volume = *poly->volumeptr;
- while (length--) {
- Bit32s envval;
- Bit32s sample = 0;
- if (!envs[EnvelopeType_amp].sustaining) {
- if (envs[EnvelopeType_amp].count <= 0) {
- Bit32u ampval = getAmpEnvelope();
- if (!play) {
- deactivate();
- break;
- }
- if (ampval > 100) {
- ampval = 100;
- }
-
- ampval = synth->tables.volumeMult[ampval];
- ampval = FIXEDPOINT_UMULT(ampval, synth->tables.tvaVelfollowMult[poly->vel][(int)patchCache->ampEnv.velosens], 8);
- //if (envs[EnvelopeType_amp].sustaining)
- ampEnvVal = ampval;
- }
- --envs[EnvelopeType_amp].count;
- }
-
- unsigned int lfoShift = 0x1000;
- if (pitchSustain) {
- // Calculate LFO position
- // LFO does not kick in completely until pitch envelope sustains
- if (patchCache->lfodepth > 0) {
- lfoPos++;
- if (lfoPos >= patchCache->lfoperiod)
- lfoPos = 0;
- int lfoatm = FIXEDPOINT_UDIV(lfoPos, patchCache->lfoperiod, 16);
- int lfoatr = synth->tables.sintable[lfoatm];
- lfoShift = synth->tables.lfoShift[patchCache->lfodepth][lfoatr];
- }
- } else {
- // Calculate Pitch envelope
- envval = getPitchEnvelope();
- int pd = patchCache->pitchEnv.depth;
- pitchEnvVal = synth->tables.pitchEnvVal[pd][envval];
- }
-
- int delta;
-
- // Wrap positions or end if necessary
- if (patchCache->PCMPartial) {
- // PCM partial
-
- delta = noteLookup->wavTable[pcmNum];
- int len = pcmWave->len;
- if (partialOff.pcmplace >= len) {
- if (pcmWave->loop) {
- //partialOff.pcmplace = partialOff.pcmoffset = 0;
- partialOff.pcmplace %= len;
- } else {
- play = false;
- deactivate();
- break;
- }
- }
- } else {
- // Synthesis partial
- delta = 0x10000;
- partialOff.pcmplace %= (Bit16u)noteLookup->div2;
- }
-
- // Build delta for position of next sample
- // Fix delta code
- Bit32u tdelta = delta;
-#if MT32EMU_ACCURATENOTES == 0
- tdelta = FIXEDPOINT_UMULT(tdelta, fineShift, 12);
-#endif
- tdelta = FIXEDPOINT_UMULT(tdelta, pitchEnvVal, 12);
- tdelta = FIXEDPOINT_UMULT(tdelta, lfoShift, 12);
- tdelta = FIXEDPOINT_UMULT(tdelta, bendShift, 12);
- delta = (int)tdelta;
-
- // Get waveform - either PCM or synthesized sawtooth or square
- if (ampEnvVal > 0) {
- if (patchCache->PCMPartial) {
- // Render PCM sample
- int ra, rb, dist;
- Bit32u taddr;
- Bit32u pcmAddr = pcmWave->addr;
- if (delta < 0x10000) {
- // Linear sound interpolation
- taddr = pcmAddr + partialOff.pcmplace;
- ra = synth->pcmROMData[taddr];
- taddr++;
- if (taddr == pcmAddr + pcmWave->len) {
- // Past end of PCM
- if (pcmWave->loop) {
- rb = synth->pcmROMData[pcmAddr];
- } else {
- rb = 0;
- }
- } else {
- rb = synth->pcmROMData[taddr];
- }
- dist = rb - ra;
- sample = (ra + ((dist * (Bit32s)(partialOff.pcmoffset >> 8)) >> 8));
- } else {
- // Sound decimation
- // The right way to do it is to use a lowpass filter on the waveform before selecting
- // a point. This is too slow. The following approximates this as fast as possible
- int idelta = delta >> 16;
- taddr = pcmAddr + partialOff.pcmplace;
- ra = synth->pcmROMData[taddr++];
- for (int ix = 0; ix < idelta - 1; ix++) {
- if (taddr == pcmAddr + pcmWave->len) {
- // Past end of PCM
- if (pcmWave->loop) {
- taddr = pcmAddr;
- } else {
- // Behave as if all subsequent samples were 0
- break;
- }
- }
- ra += synth->pcmROMData[taddr++];
- }
- sample = ra / idelta;
- }
- } else {
- // Render synthesised sample
- int toff = partialOff.pcmplace;
- int minorplace = partialOff.pcmoffset >> 14;
- Bit32s filterInput;
- Bit32s filtval = getFiltEnvelope();
-
- //synth->printDebug("Filtval: %d", filtval);
-
- if ((patchCache->waveform & 1) == 0) {
- // Square waveform. Made by combining two pregenerated bandlimited
- // sawtooth waveforms
- Bit32u ofsA = ((toff << 2) + minorplace) % noteLookup->waveformSize[0];
- int width = FIXEDPOINT_UMULT(noteLookup->div2, synth->tables.pwFactor[pulsewidth], 7);
- Bit32u ofsB = (ofsA + width) % noteLookup->waveformSize[0];
- Bit16s pa = noteLookup->waveforms[0][ofsA];
- Bit16s pb = noteLookup->waveforms[0][ofsB];
- filterInput = pa - pb;
- // Non-bandlimited squarewave
- /*
- ofs = FIXEDPOINT_UMULT(noteLookup->div2, synth->tables.pwFactor[patchCache->pulsewidth], 8);
- if (toff < ofs)
- sample = 1 * WGAMP;
- else
- sample = -1 * WGAMP;
- */
- } else {
- // Sawtooth. Made by combining the full cosine and half cosine according
- // to how it looks on the MT-32. What it really does it takes the
- // square wave and multiplies it by a full cosine
- int waveoff = (toff << 2) + minorplace;
- if (toff < noteLookup->sawTable[pulsewidth])
- filterInput = noteLookup->waveforms[1][waveoff % noteLookup->waveformSize[1]];
- else
- filterInput = noteLookup->waveforms[2][waveoff % noteLookup->waveformSize[2]];
- // This is the correct way
- // Seems slow to me (though bandlimited) -- doesn't seem to
- // sound any better though
- /*
- //int pw = (patchCache->pulsewidth * pulsemod[filtval]) >> 8;
-
- Bit32u ofs = toff % (noteLookup->div2 >> 1);
-
- Bit32u ofs3 = toff + FIXEDPOINT_UMULT(noteLookup->div2, synth->tables.pwFactor[patchCache->pulsewidth], 9);
- ofs3 = ofs3 % (noteLookup->div2 >> 1);
-
- pa = noteLookup->waveforms[0][ofs];
- pb = noteLookup->waveforms[0][ofs3];
- sample = ((pa - pb) * noteLookup->waveforms[2][toff]) / 2;
- */
- }
-
- //Very exact filter
- if (filtval > ((FILTERGRAN * 15) / 16))
- filtval = ((FILTERGRAN * 15) / 16);
- sample = (Bit32s)(floorf((synth->iirFilter)((float)filterInput, &history[0], synth->tables.filtCoeff[filtval][(int)patchCache->filtEnv.resonance])) / synth->tables.resonanceFactor[patchCache->filtEnv.resonance]);
- if (sample < -32768) {
- synth->printDebug("Overdriven amplitude for %d: %d:=%d < -32768", patchCache->waveform, filterInput, sample);
- sample = -32768;
- }
- else if (sample > 32767) {
- synth->printDebug("Overdriven amplitude for %d: %d:=%d > 32767", patchCache->waveform, filterInput, sample);
- sample = 32767;
- }
- }
- }
-
- // Add calculated delta to our waveform offset
- Bit32u absOff = ((partialOff.pcmplace << 16) | partialOff.pcmoffset);
- absOff += delta;
- partialOff.pcmplace = (Bit16u)((absOff & 0xFFFF0000) >> 16);
- partialOff.pcmoffset = (Bit16u)(absOff & 0xFFFF);
-
- // Put volume envelope over generated sample
- sample = FIXEDPOINT_SMULT(sample, ampEnvVal, 9);
- sample = FIXEDPOINT_SMULT(sample, volume, 7);
- envs[EnvelopeType_amp].envpos++;
- envs[EnvelopeType_pitch].envpos++;
- envs[EnvelopeType_filt].envpos++;
-
- *partialBuf++ = (Bit16s)sample;
- }
- // We may have deactivated and broken out of the loop before the end of the buffer,
- // if so then fill the remainder with 0s.
- if (++length > 0)
- memset(partialBuf, 0, length * 2);
- return &myBuffer[0];
-}
-
-void Partial::setBend(float factor) {
- if (!patchCache->useBender || factor == 0.0f) {
- bendShift = 4096;
- return;
- }
- // NOTE:KG: We can't do this smoothly with lookup tables, unless we use several MB.
- // FIXME:KG: Bend should be influenced by pitch key-follow too, according to docs.
- float bendSemitones = factor * patchCache->benderRange; // -24 .. 24
- float mult = powf(2.0f, bendSemitones / 12.0f);
- synth->printDebug("setBend(): factor=%f, benderRange=%f, semitones=%f, mult=%f\n", (double)factor, (double)patchCache->benderRange, (double)bendSemitones, (double)mult);
- bendShift = (int)(mult * 4096.0f);
-}
-
-Bit16s *Partial::mixBuffers(Bit16s * buf1, Bit16s *buf2, int len) {
- if (buf1 == NULL)
- return buf2;
- if (buf2 == NULL)
- return buf1;
-
- Bit16s *outBuf = buf1;
-#if MT32EMU_USE_MMX >= 1
- // KG: This seems to be fine
- int donelen = i386_mixBuffers(buf1, buf2, len);
- len -= donelen;
- buf1 += donelen;
- buf2 += donelen;
-#endif
- while (len--) {
- *buf1 = *buf1 + *buf2;
- buf1++, buf2++;
- }
- return outBuf;
-}
-
-Bit16s *Partial::mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len) {
- if (buf1 == NULL)
- return NULL;
- if (buf2 == NULL) {
- Bit16s *outBuf = buf1;
- while (len--) {
- if (*buf1 < -8192)
- *buf1 = -8192;
- else if (*buf1 > 8192)
- *buf1 = 8192;
- buf1++;
- }
- return outBuf;
- }
-
- Bit16s *outBuf = buf1;
-#if MT32EMU_USE_MMX >= 1
- // KG: This seems to be fine
- int donelen = i386_mixBuffersRingMix(buf1, buf2, len);
- len -= donelen;
- buf1 += donelen;
- buf2 += donelen;
-#endif
- while (len--) {
- float a, b;
- a = ((float)*buf1) / 8192.0f;
- b = ((float)*buf2) / 8192.0f;
- a = (a * b) + a;
- if (a > 1.0f)
- a = 1.0f;
- if (a < -1.0f)
- a = -1.0f;
- *buf1 = (Bit16s)(a * 8192.0f);
- buf1++;
- buf2++;
- //buf1[i] = (Bit16s)(((Bit32s)buf1[i] * (Bit32s)buf2[i]) >> 10) + buf1[i];
- }
- return outBuf;
-}
-
-Bit16s *Partial::mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len) {
- if (buf1 == NULL) {
- return NULL;
- }
- if (buf2 == NULL) {
- return NULL;
- }
-
- Bit16s *outBuf = buf1;
-#if MT32EMU_USE_MMX >= 1
- // FIXME:KG: Not really checked as working
- int donelen = i386_mixBuffersRing(buf1, buf2, len);
- len -= donelen;
- buf1 += donelen;
- buf2 += donelen;
-#endif
- while (len--) {
- float a, b;
- a = ((float)*buf1) / 8192.0f;
- b = ((float)*buf2) / 8192.0f;
- a *= b;
- if (a > 1.0f)
- a = 1.0f;
- if (a < -1.0f)
- a = -1.0f;
- *buf1 = (Bit16s)(a * 8192.0f);
- buf1++;
- buf2++;
- }
- return outBuf;
-}
-
-void Partial::mixBuffersStereo(Bit16s *buf1, Bit16s *buf2, Bit16s *outBuf, int len) {
- if (buf2 == NULL) {
- while (len--) {
- *outBuf++ = *buf1++;
- *outBuf++ = 0;
- }
- } else if (buf1 == NULL) {
- while (len--) {
- *outBuf++ = 0;
- *outBuf++ = *buf2++;
- }
- } else {
- while (len--) {
- *outBuf++ = *buf1++;
- *outBuf++ = *buf2++;
- }
- }
-}
-
-bool Partial::produceOutput(Bit16s *partialBuf, long length) {
- if (!isActive() || alreadyOutputed)
- return false;
- if (poly == NULL) {
- synth->printDebug("*** ERROR: poly is NULL at Partial::produceOutput()!");
- return false;
- }
-
- Bit16s *pairBuf = NULL;
- // Check for dependant partial
- if (pair != NULL) {
- if (!pair->alreadyOutputed) {
- // Note: pair may have become NULL after this
- pairBuf = pair->generateSamples(length);
- }
- } else if (useNoisePair) {
- // Generate noise for pairless ring mix
- pairBuf = synth->tables.noiseBuf;
- }
-
- Bit16s *myBuf = generateSamples(length);
-
- if (myBuf == NULL && pairBuf == NULL)
- return false;
-
- Bit16s *p1buf, *p2buf;
-
- if (structurePosition == 0 || pairBuf == NULL) {
- p1buf = myBuf;
- p2buf = pairBuf;
- } else {
- p2buf = myBuf;
- p1buf = pairBuf;
- }
-
- //synth->printDebug("mixType: %d", mixType);
-
- Bit16s *mixedBuf;
- switch (mixType) {
- case 0:
- // Standard sound mix
- mixedBuf = mixBuffers(p1buf, p2buf, length);
- break;
-
- case 1:
- // Ring modulation with sound mix
- mixedBuf = mixBuffersRingMix(p1buf, p2buf, length);
- break;
-
- case 2:
- // Ring modulation alone
- mixedBuf = mixBuffersRing(p1buf, p2buf, length);
- break;
-
- case 3:
- // Stereo mixing. One partial to one speaker channel, one to another.
- // FIXME:KG: Surely we should be multiplying by the left/right volumes here?
- mixBuffersStereo(p1buf, p2buf, partialBuf, length);
- return true;
-
- default:
- mixedBuf = mixBuffers(p1buf, p2buf, length);
- break;
- }
-
- if (mixedBuf == NULL)
- return false;
-
- Bit16s leftvol, rightvol;
- leftvol = patchCache->pansetptr->leftvol;
- rightvol = patchCache->pansetptr->rightvol;
-
-#if MT32EMU_USE_MMX >= 2
- // FIXME:KG: This appears to introduce crackle
- int donelen = i386_partialProductOutput(length, leftvol, rightvol, partialBuf, mixedBuf);
- length -= donelen;
- mixedBuf += donelen;
- partialBuf += donelen * 2;
-#endif
- while (length--) {
- *partialBuf++ = (Bit16s)(((Bit32s)*mixedBuf * (Bit32s)leftvol) >> 15);
- *partialBuf++ = (Bit16s)(((Bit32s)*mixedBuf * (Bit32s)rightvol) >> 15);
- mixedBuf++;
- }
- return true;
-}
-
-Bit32s Partial::getFiltEnvelope() {
- int reshigh;
-
- int cutoff, depth;
-
- EnvelopeStatus *tStat = &envs[EnvelopeType_filt];
-
- if (tStat->decaying) {
- reshigh = tStat->envbase;
- reshigh = (reshigh + ((tStat->envdist * tStat->envpos) / tStat->envsize));
- if (tStat->envpos >= tStat->envsize)
- reshigh = 0;
- } else {
- if (tStat->envstat==4) {
- reshigh = patchCache->filtsustain;
- if (!poly->sustain) {
- startDecay(EnvelopeType_filt, reshigh);
- }
- } else {
- if ((tStat->envstat==-1) || (tStat->envpos >= tStat->envsize)) {
- if (tStat->envstat==-1)
- tStat->envbase = 0;
- else
- tStat->envbase = patchCache->filtEnv.envlevel[tStat->envstat];
- tStat->envstat++;
- tStat->envpos = 0;
- if (tStat->envstat == 3) {
- tStat->envsize = synth->tables.envTime[(int)patchCache->filtEnv.envtime[tStat->envstat]];
- } else {
- Bit32u envTime = (int)patchCache->filtEnv.envtime[tStat->envstat];
- if (tStat->envstat > 1) {
- int envDiff = abs(patchCache->filtEnv.envlevel[tStat->envstat] - patchCache->filtEnv.envlevel[tStat->envstat - 1]);
- if (envTime > synth->tables.envDeltaMaxTime[envDiff]) {
- envTime = synth->tables.envDeltaMaxTime[envDiff];
- }
- }
-
- tStat->envsize = (synth->tables.envTime[envTime] * keyLookup->envTimeMult[(int)patchCache->filtEnv.envtkf]) >> 8;
- }
-
- tStat->envsize++;
- tStat->envdist = patchCache->filtEnv.envlevel[tStat->envstat] - tStat->envbase;
- }
-
- reshigh = tStat->envbase;
- reshigh = (reshigh + ((tStat->envdist * tStat->envpos) / tStat->envsize));
-
- }
- tStat->prevlevel = reshigh;
- }
-
- cutoff = patchCache->filtEnv.cutoff;
-
- //if (patchCache->waveform==1) reshigh = (reshigh * 3) >> 2;
-
- depth = patchCache->filtEnv.envdepth;
-
- //int sensedep = (depth * 127-patchCache->filtEnv.envsense) >> 7;
- depth = FIXEDPOINT_UMULT(depth, synth->tables.tvfVelfollowMult[poly->vel][(int)patchCache->filtEnv.envsense], 8);
-
- int bias = patchCache->tvfbias;
- int dist;
-
- if (bias != 0) {
- //FIXME:KG: Is this really based on pitch (as now), or key pressed?
- //synth->printDebug("Cutoff before %d", cutoff);
- if (patchCache->tvfdir == 0) {
- if (noteVal < bias) {
- dist = bias - noteVal;
- cutoff = FIXEDPOINT_UMULT(cutoff, synth->tables.tvfBiasMult[patchCache->tvfblevel][dist], 8);
- }
- } else {
- // > Bias
- if (noteVal > bias) {
- dist = noteVal - bias;
- cutoff = FIXEDPOINT_UMULT(cutoff, synth->tables.tvfBiasMult[patchCache->tvfblevel][dist], 8);
- }
-
- }
- //synth->printDebug("Cutoff after %d", cutoff);
- }
-
- depth = (depth * keyLookup->envDepthMult[patchCache->filtEnv.envdkf]) >> 8;
- reshigh = (reshigh * depth) >> 7;
-
- Bit32s tmp;
-
- cutoff *= filtVal;
- cutoff /= realVal; //FIXME:KG: With filter keyfollow 0, this makes no sense. What's correct?
-
- reshigh *= filtVal;
- reshigh /= realVal; //FIXME:KG: As above for cutoff
-
- if (patchCache->waveform == 1) {
- reshigh = (reshigh * 65) / 100;
- }
-
- if (cutoff > 100)
- cutoff = 100;
- else if (cutoff < 0)
- cutoff = 0;
- if (reshigh > 100)
- reshigh = 100;
- else if (reshigh < 0)
- reshigh = 0;
- tmp = noteLookup->nfiltTable[cutoff][reshigh];
- //tmp *= keyfollow;
- //tmp /= realfollow;
-
- //synth->printDebug("Cutoff %d, tmp %d, freq %d", cutoff, tmp, tmp * 256);
- return tmp;
-}
-
-bool Partial::shouldReverb() {
- if (!isActive())
- return false;
- return patchCache->reverb;
-}
-
-Bit32u Partial::getAmpEnvelope() {
- Bit32s tc;
-
- EnvelopeStatus *tStat = &envs[EnvelopeType_amp];
-
- if (!play)
- return 0;
-
- if (tStat->decaying) {
- tc = tStat->envbase;
- tc += (tStat->envdist * tStat->envpos) / tStat->envsize;
- if (tc < 0)
- tc = 0;
- if ((tStat->envpos >= tStat->envsize) || (tc == 0)) {
- play = false;
- // Don't have to worry about prevlevel storage or anything, this partial's about to die
- return 0;
- }
- } else {
- if ((tStat->envstat == -1) || (tStat->envpos >= tStat->envsize)) {
- if (tStat->envstat == -1)
- tStat->envbase = 0;
- else
- tStat->envbase = patchCache->ampEnv.envlevel[tStat->envstat];
- tStat->envstat++;
- tStat->envpos = 0;
- if (tStat->envstat == 4) {
- //synth->printDebug("Envstat %d, size %d", tStat->envstat, tStat->envsize);
- tc = patchCache->ampEnv.envlevel[3];
- if (!poly->sustain)
- startDecay(EnvelopeType_amp, tc);
- else
- tStat->sustaining = true;
- goto PastCalc;
- }
- Bit8u targetLevel = patchCache->ampEnv.envlevel[tStat->envstat];
- tStat->envdist = targetLevel - tStat->envbase;
- Bit32u envTime = patchCache->ampEnv.envtime[tStat->envstat];
- if (targetLevel == 0) {
- tStat->envsize = synth->tables.envDecayTime[envTime];
- } else {
- int envLevelDelta = abs(tStat->envdist);
- if (envTime > synth->tables.envDeltaMaxTime[envLevelDelta]) {
- envTime = synth->tables.envDeltaMaxTime[envLevelDelta];
- }
- tStat->envsize = synth->tables.envTime[envTime];
- }
-
- // Time keyfollow is used by all sections of the envelope (confirmed on CM-32L)
- tStat->envsize = FIXEDPOINT_UMULT(tStat->envsize, keyLookup->envTimeMult[(int)patchCache->ampEnv.envtkf], 8);
-
- switch (tStat->envstat) {
- case 0:
- //Spot for velocity time follow
- //Only used for first attack
- tStat->envsize = FIXEDPOINT_UMULT(tStat->envsize, synth->tables.envTimeVelfollowMult[(int)patchCache->ampEnv.envvkf][poly->vel], 8);
- //synth->printDebug("Envstat %d, size %d", tStat->envstat, tStat->envsize);
- break;
- case 1:
- case 2:
- case 3:
- //synth->printDebug("Envstat %d, size %d", tStat->envstat, tStat->envsize);
- break;
- default:
- synth->printDebug("Invalid TVA envelope number %d hit!", tStat->envstat);
- break;
- }
-
- tStat->envsize++;
-
- if (tStat->envdist != 0) {
- tStat->counter = abs(tStat->envsize / tStat->envdist);
- //synth->printDebug("Pos %d, envsize %d envdist %d", tStat->envstat, tStat->envsize, tStat->envdist);
- } else {
- tStat->counter = 0;
- //synth->printDebug("Pos %d, envsize %d envdist %d", tStat->envstat, tStat->envsize, tStat->envdist);
- }
- }
- tc = tStat->envbase;
- tc = (tc + ((tStat->envdist * tStat->envpos) / tStat->envsize));
- tStat->count = tStat->counter;
-PastCalc:
- tc = (tc * (Bit32s)patchCache->ampEnv.level) / 100;
- }
-
- // Prevlevel storage is bottle neck
- tStat->prevlevel = tc;
-
- //Bias level crap stuff now
-
- for (int i = 0; i < 2; i++) {
- if (patchCache->ampblevel[i]!=0) {
- int bias = patchCache->ampbias[i];
- if (patchCache->ampdir[i]==0) {
- // < Bias
- if (noteVal < bias) {
- int dist = bias - noteVal;
- tc = FIXEDPOINT_UMULT(tc, synth->tables.tvaBiasMult[patchCache->ampblevel[i]][dist], 8);
- }
- } else {
- // > Bias
- if (noteVal > bias) {
- int dist = noteVal - bias;
- tc = FIXEDPOINT_UMULT(tc, synth->tables.tvaBiasMult[patchCache->ampblevel[i]][dist], 8);
- }
- }
- }
- }
- if (tc < 0) {
- synth->printDebug("*** ERROR: tc < 0 (%d) at getAmpEnvelope()", tc);
- tc = 0;
- }
- return (Bit32u)tc;
-}
-
-Bit32s Partial::getPitchEnvelope() {
- EnvelopeStatus *tStat = &envs[EnvelopeType_pitch];
-
- Bit32s tc;
- pitchSustain = false;
- if (tStat->decaying) {
- if (tStat->envpos >= tStat->envsize)
- tc = patchCache->pitchEnv.level[4];
- else {
- tc = tStat->envbase;
- tc = (tc + ((tStat->envdist * tStat->envpos) / tStat->envsize));
- }
- } else {
- if (tStat->envstat==3) {
- tc = patchCache->pitchsustain;
- if (poly->sustain)
- pitchSustain = true;
- else
- startDecay(EnvelopeType_pitch, tc);
- } else {
- if ((tStat->envstat==-1) || (tStat->envpos >= tStat->envsize)) {
- tStat->envstat++;
-
- tStat->envbase = patchCache->pitchEnv.level[tStat->envstat];
-
- Bit32u envTime = patchCache->pitchEnv.time[tStat->envstat];
- int envDiff = abs(patchCache->pitchEnv.level[tStat->envstat] - patchCache->pitchEnv.level[tStat->envstat + 1]);
- if (envTime > synth->tables.envDeltaMaxTime[envDiff]) {
- envTime = synth->tables.envDeltaMaxTime[envDiff];
- }
-
- tStat->envsize = (synth->tables.envTime[envTime] * keyLookup->envTimeMult[(int)patchCache->pitchEnv.timekeyfollow]) >> 8;
-
- tStat->envpos = 0;
- tStat->envsize++;
- tStat->envdist = patchCache->pitchEnv.level[tStat->envstat + 1] - tStat->envbase;
- }
- tc = tStat->envbase;
- tc = (tc + ((tStat->envdist * tStat->envpos) / tStat->envsize));
- }
- tStat->prevlevel = tc;
- }
- return tc;
-}
-
-void Partial::startDecayAll() {
- startDecay(EnvelopeType_amp, envs[EnvelopeType_amp].prevlevel);
- startDecay(EnvelopeType_filt, envs[EnvelopeType_filt].prevlevel);
- startDecay(EnvelopeType_pitch, envs[EnvelopeType_pitch].prevlevel);
- pitchSustain = false;
-}
-
-void Partial::startDecay(EnvelopeType envnum, Bit32s startval) {
- EnvelopeStatus *tStat = &envs[envnum];
-
- tStat->sustaining = false;
- tStat->decaying = true;
- tStat->envpos = 0;
- tStat->envbase = startval;
-
- switch (envnum) {
- case EnvelopeType_amp:
- tStat->envsize = FIXEDPOINT_UMULT(synth->tables.envDecayTime[(int)patchCache->ampEnv.envtime[4]], keyLookup->envTimeMult[(int)patchCache->ampEnv.envtkf], 8);
- tStat->envdist = -startval;
- break;
- case EnvelopeType_filt:
- tStat->envsize = FIXEDPOINT_UMULT(synth->tables.envDecayTime[(int)patchCache->filtEnv.envtime[4]], keyLookup->envTimeMult[(int)patchCache->filtEnv.envtkf], 8);
- tStat->envdist = -startval;
- break;
- case EnvelopeType_pitch:
- tStat->envsize = FIXEDPOINT_UMULT(synth->tables.envDecayTime[(int)patchCache->pitchEnv.time[3]], keyLookup->envTimeMult[(int)patchCache->pitchEnv.timekeyfollow], 8);
- tStat->envdist = patchCache->pitchEnv.level[4] - startval;
- break;
- default:
- break;
- }
- tStat->envsize++;
-}
diff --git a/sound/softsynth/mt32/partial.h b/sound/softsynth/mt32/partial.h
deleted file mode 100644
index 93d8bcd985..0000000000
--- a/sound/softsynth/mt32/partial.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_PARTIAL_H
-#define MT32EMU_PARTIAL_H
-
-namespace MT32Emu {
-
-class Synth;
-struct NoteLookup;
-
-enum EnvelopeType {
- EnvelopeType_amp = 0,
- EnvelopeType_filt = 1,
- EnvelopeType_pitch = 2
-};
-
-struct EnvelopeStatus {
- Bit32s envpos;
- Bit32s envstat;
- Bit32s envbase;
- Bit32s envdist;
- Bit32s envsize;
-
- bool sustaining;
- bool decaying;
- Bit32s prevlevel;
-
- Bit32s counter;
- Bit32s count;
-};
-
-// Class definition of MT-32 partials. 32 in all.
-class Partial {
-private:
- Synth *synth;
-
- int ownerPart; // -1 if unassigned
- int mixType;
- int structurePosition; // 0 or 1 of a structure pair
- bool useNoisePair;
-
- Bit16s myBuffer[MAX_SAMPLE_OUTPUT];
-
- // Keyfollowed note value
-#if MT32EMU_ACCURATENOTES == 1
- NoteLookup noteLookupStorage;
- float noteVal;
-#else
- int noteVal;
- int fineShift;
-#endif
- const NoteLookup *noteLookup; // LUTs for this noteVal
- const KeyLookup *keyLookup; // LUTs for the clamped (12..108) key
-
- // Keyfollowed filter values
- int realVal;
- int filtVal;
-
- // Only used for PCM partials
- int pcmNum;
- PCMWaveEntry *pcmWave;
-
- int pulsewidth;
-
- Bit32u lfoPos;
- soundaddr partialOff;
-
- Bit32u ampEnvVal;
- Bit32u pitchEnvVal;
-
- float history[32];
-
- bool pitchSustain;
-
- int loopPos;
-
- dpoly *poly;
-
- int bendShift;
-
- Bit16s *mixBuffers(Bit16s *buf1, Bit16s *buf2, int len);
- Bit16s *mixBuffersRingMix(Bit16s *buf1, Bit16s *buf2, int len);
- Bit16s *mixBuffersRing(Bit16s *buf1, Bit16s *buf2, int len);
- void mixBuffersStereo(Bit16s *buf1, Bit16s *buf2, Bit16s *outBuf, int len);
-
- Bit32s getFiltEnvelope();
- Bit32u getAmpEnvelope();
- Bit32s getPitchEnvelope();
-
- void initKeyFollow(int freqNum);
-
-public:
- const PatchCache *patchCache;
- EnvelopeStatus envs[3];
- bool play;
-
- PatchCache cachebackup;
-
- Partial *pair;
- bool alreadyOutputed;
- Bit32u age;
-
- Partial(Synth *synth);
- ~Partial();
-
- int getOwnerPart() const;
- int getKey() const;
- const dpoly *getDpoly() const;
- bool isActive();
- void activate(int part);
- void deactivate(void);
- void startPartial(dpoly *usePoly, const PatchCache *useCache, Partial *pairPartial);
- void startDecay(EnvelopeType envnum, Bit32s startval);
- void startDecayAll();
- void setBend(float factor);
- bool shouldReverb();
-
- // Returns true only if data written to buffer
- // This function (unlike the one below it) returns processed stereo samples
- // made from combining this single partial with its pair, if it has one.
- bool produceOutput(Bit16s * partialBuf, long length);
-
- // This function produces mono sample output using the partial's private internal buffer
- Bit16s *generateSamples(long length);
-};
-
-}
-
-#endif
diff --git a/sound/softsynth/mt32/partialManager.cpp b/sound/softsynth/mt32/partialManager.cpp
deleted file mode 100644
index 3d3b6302db..0000000000
--- a/sound/softsynth/mt32/partialManager.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <string.h>
-
-#include "mt32emu.h"
-
-using namespace MT32Emu;
-
-PartialManager::PartialManager(Synth *useSynth) {
- this->synth = useSynth;
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++)
- partialTable[i] = new Partial(synth);
-}
-
-PartialManager::~PartialManager(void) {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++)
- delete partialTable[i];
-}
-
-void PartialManager::getPerPartPartialUsage(int usage[9]) {
- memset(usage, 0, 9 * sizeof (int));
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialTable[i]->isActive())
- usage[partialTable[i]->getOwnerPart()]++;
- }
-}
-
-void PartialManager::clearAlreadyOutputed() {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++)
- partialTable[i]->alreadyOutputed = false;
-}
-
-void PartialManager::ageAll() {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++)
- partialTable[i]->age++;
-}
-
-bool PartialManager::shouldReverb(int i) {
- return partialTable[i]->shouldReverb();
-}
-
-bool PartialManager::produceOutput(int i, Bit16s *buffer, Bit32u bufferLength) {
- return partialTable[i]->produceOutput(buffer, bufferLength);
-}
-
-void PartialManager::deactivateAll() {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- partialTable[i]->deactivate();
- }
-}
-
-unsigned int PartialManager::setReserve(Bit8u *rset) {
- unsigned int pr = 0;
- for (int x = 0; x < 9; x++) {
- for (int y = 0; y < rset[x]; y++) {
- partialReserveTable[pr] = x;
- pr++;
- }
- }
- return pr;
-}
-
-Partial *PartialManager::allocPartial(int partNum) {
- Partial *outPartial = NULL;
-
- // Use the first inactive partial reserved for the specified part (if there are any)
- // Otherwise, use the last inactive partial, if any
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (!partialTable[i]->isActive()) {
- outPartial = partialTable[i];
- if (partialReserveTable[i] == partNum)
- break;
- }
- }
- if (outPartial != NULL) {
- outPartial->activate(partNum);
- outPartial->age = 0;
- }
- return outPartial;
-}
-
-unsigned int PartialManager::getFreePartialCount(void) {
- int count = 0;
- memset(partialPart, 0, sizeof(partialPart));
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (!partialTable[i]->isActive())
- count++;
- else
- partialPart[partialTable[i]->getOwnerPart()]++;
- }
- return count;
-}
-
-/*
-bool PartialManager::freePartials(unsigned int needed, int partNum) {
- int i;
- int myPartPrior = (int)mt32ram.system.reserveSettings[partNum];
- if (myPartPrior<partialPart[partNum]) {
- //This can have more parts, must kill off those with less priority
- int most, mostPart;
- while (needed > 0) {
- int selectPart = -1;
- //Find the worst offender with more partials than allocated and kill them
- most = -1;
- mostPart = -1;
- int diff;
-
- for (i=0;i<9;i++) {
- diff = partialPart[i] - (int)mt32ram.system.reserveSettings[i];
-
- if (diff>0) {
- if (diff>most) {
- most = diff;
- mostPart = i;
- }
- }
- }
- selectPart = mostPart;
- if (selectPart == -1) {
- // All parts are within the allocated limits, you suck
- // Look for first partial not of this part that's decaying perhaps?
- return false;
- }
- bool found;
- int oldest;
- int oldnum;
- while (partialPart[selectPart] > (int)mt32ram.system.reserveSettings[selectPart]) {
- oldest = -1;
- oldnum = -1;
- found = false;
- for (i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialTable[i]->isActive) {
- if (partialTable[i]->ownerPart == selectPart) {
- found = true;
- if (partialTable[i]->age > oldest) {
- oldest = partialTable[i]->age;
- oldnum = i;
- }
- }
- }
- }
- if (!found) break;
- partialTable[oldnum]->deactivate();
- --partialPart[selectPart];
- --needed;
- }
-
- }
- return true;
-
- } else {
- //This part has reached its max, must kill off its own
- bool found;
- int oldest;
- int oldnum;
- while (needed > 0) {
- oldest = -1;
- oldnum = -1;
- found = false;
- for (i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialTable[i]->isActive) {
- if (partialTable[i]->ownerPart == partNum) {
- found = true;
- if (partialTable[i]->age > oldest) {
- oldest = partialTable[i]->age;
- oldnum = i;
- }
- }
- }
- }
- if (!found) break;
- partialTable[oldnum]->deactivate();
- --needed;
- }
- // Couldn't free enough partials, sorry
- if (needed>0) return false;
- return true;
- }
-
-}
-*/
-bool PartialManager::freePartials(unsigned int needed, int partNum) {
- if (needed == 0) {
- return true;
- }
- // Reclaim partials reserved for this part
- // Kill those that are already decaying first
- /*
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialReserveTable[i] == partNum) {
- if (partialTable[i]->ownerPart != partNum) {
- if (partialTable[i]->partCache->envs[AMPENV].decaying) {
- partialTable[i]->isActive = false;
- --needed;
- if (needed == 0)
- return true;
- }
- }
- }
- }*/
- // Then kill those with the lowest part priority -- oldest at the moment
- while (needed > 0) {
- Bit32u prior = 0;
- int priornum = -1;
-
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialReserveTable[i] == partNum && partialTable[i]->isActive() && partialTable[i]->getOwnerPart() != partNum) {
- /*
- if (mt32ram.system.reserveSettings[partialTable[i]->ownerPart] < prior) {
- prior = mt32ram.system.reserveSettings[partialTable[i]->ownerPart];
- priornum = i;
- }*/
- if (partialTable[i]->age >= prior) {
- prior = partialTable[i]->age;
- priornum = i;
- }
- }
- }
- if (priornum != -1) {
- partialTable[priornum]->deactivate();
- --needed;
- } else {
- break;
- }
- }
-
- // Kill off the oldest partials within this part
- while (needed > 0) {
- Bit32u oldest = 0;
- int oldlist = -1;
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialTable[i]->getOwnerPart() == partNum && partialTable[i]->isActive()) {
- if (partialTable[i]->age >= oldest) {
- oldest = partialTable[i]->age;
- oldlist = i;
- }
- }
- }
- if (oldlist != -1) {
- partialTable[oldlist]->deactivate();
- --needed;
- } else {
- break;
- }
- }
- return needed == 0;
-}
-
-const Partial *PartialManager::getPartial(unsigned int partialNum) const {
- if (partialNum > MT32EMU_MAX_PARTIALS - 1)
- return NULL;
- return partialTable[partialNum];
-}
diff --git a/sound/softsynth/mt32/partialManager.h b/sound/softsynth/mt32/partialManager.h
deleted file mode 100644
index b10f93ff02..0000000000
--- a/sound/softsynth/mt32/partialManager.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_PARTIALMANAGER_H
-#define MT32EMU_PARTIALMANAGER_H
-
-namespace MT32Emu {
-
-class Synth;
-
-class PartialManager {
-private:
- Synth *synth; // Only used for sending debug output
-
- Partial *partialTable[MT32EMU_MAX_PARTIALS];
- Bit32s partialReserveTable[MT32EMU_MAX_PARTIALS];
- Bit32s partialPart[9]; // The count of partials played per part
-
-public:
-
- PartialManager(Synth *synth);
- ~PartialManager();
- Partial *allocPartial(int partNum);
- unsigned int getFreePartialCount(void);
- bool freePartials(unsigned int needed, int partNum);
- unsigned int setReserve(Bit8u *rset);
- void deactivateAll();
- void ageAll();
- bool produceOutput(int i, Bit16s *buffer, Bit32u bufferLength);
- bool shouldReverb(int i);
- void clearAlreadyOutputed();
- void getPerPartPartialUsage(int usage[9]);
- const Partial *getPartial(unsigned int partialNum) const;
-};
-
-}
-
-#endif
diff --git a/sound/softsynth/mt32/structures.h b/sound/softsynth/mt32/structures.h
deleted file mode 100644
index ef58c1d20f..0000000000
--- a/sound/softsynth/mt32/structures.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_STRUCTURES_H
-#define MT32EMU_STRUCTURES_H
-
-namespace MT32Emu {
-
-const unsigned int MAX_SAMPLE_OUTPUT = 4096;
-
-// MT32EMU_MEMADDR() converts from sysex-padded, MT32EMU_SYSEXMEMADDR converts to it
-// Roland provides documentation using the sysex-padded addresses, so we tend to use that in code and output
-#define MT32EMU_MEMADDR(x) ((((x) & 0x7f0000) >> 2) | (((x) & 0x7f00) >> 1) | ((x) & 0x7f))
-#define MT32EMU_SYSEXMEMADDR(x) ((((x) & 0x1FC000) << 2) | (((x) & 0x3F80) << 1) | ((x) & 0x7f))
-
-#ifdef _MSC_VER
-#define MT32EMU_ALIGN_PACKED __declspec(align(1))
-typedef unsigned __int64 Bit64u;
-typedef signed __int64 Bit64s;
-#else
-#define MT32EMU_ALIGN_PACKED __attribute__((packed))
-typedef unsigned long long Bit64u;
-typedef signed long long Bit64s;
-#endif
-
-typedef unsigned int Bit32u;
-typedef signed int Bit32s;
-typedef unsigned short int Bit16u;
-typedef signed short int Bit16s;
-typedef unsigned char Bit8u;
-typedef signed char Bit8s;
-
-// The following structures represent the MT-32's memory
-// Since sysex allows this memory to be written to in blocks of bytes,
-// we keep this packed so that we can copy data into the various
-// banks directly
-#if defined(_MSC_VER) || defined (__MINGW32__)
-#pragma pack(push, 1)
-#else
-#pragma pack(1)
-#endif
-
-struct TimbreParam {
- struct commonParam {
- char name[10];
- Bit8u pstruct12; // 1&2 0-12 (1-13)
- Bit8u pstruct34; // #3&4 0-12 (1-13)
- Bit8u pmute; // 0-15 (0000-1111)
- Bit8u nosustain; // 0-1(Normal, No sustain)
- } MT32EMU_ALIGN_PACKED common;
-
- struct partialParam {
- struct wgParam {
- Bit8u coarse; // 0-96 (C1,C#1-C9)
- Bit8u fine; // 0-100 (-50 to +50 (cents?))
- Bit8u keyfollow; // 0-16 (-1,-1/2,0,1,1/8,1/4,3/8,1/2,5/8,3/4,7/8,1,5/4,3/2,2.s1,s2)
- Bit8u bender; // 0,1 (ON/OFF)
- Bit8u waveform; // MT-32: 0-1 (SQU/SAW); LAPC-I: WG WAVEFORM/PCM BANK 0 - 3 (SQU/1, SAW/1, SQU/2, SAW/2)
- Bit8u pcmwave; // 0-127 (1-128)
- Bit8u pulsewid; // 0-100
- Bit8u pwvelo; // 0-14 (-7 - +7)
- } MT32EMU_ALIGN_PACKED wg;
-
- struct envParam {
- Bit8u depth; // 0-10
- Bit8u sensitivity; // 1-100
- Bit8u timekeyfollow; // 0-4
- Bit8u time[4]; // 1-100
- Bit8u level[5]; // 1-100 (-50 - +50)
- } MT32EMU_ALIGN_PACKED env;
-
- struct lfoParam {
- Bit8u rate; // 0-100
- Bit8u depth; // 0-100
- Bit8u modsense; // 0-100
- } MT32EMU_ALIGN_PACKED lfo;
-
- struct tvfParam {
- Bit8u cutoff; // 0-100
- Bit8u resonance; // 0-30
- Bit8u keyfollow; // 0-16 (-1,-1/2,1/4,0,1,1/8,1/4,3/8,1/2,5/8,3/2,7/8,1,5/4,3/2,2,s1,s2)
- Bit8u biaspoint; // 0-127 (<1A-<7C >1A-7C)
- Bit8u biaslevel; // 0-14 (-7 - +7)
- Bit8u envdepth; // 0-100
- Bit8u envsense; // 0-100
- Bit8u envdkf; // DEPTH KEY FOLL0W 0-4
- Bit8u envtkf; // TIME KEY FOLLOW 0-4
- Bit8u envtime[5]; // 1-100
- Bit8u envlevel[4]; // 1-100
- } MT32EMU_ALIGN_PACKED tvf;
-
- struct tvaParam {
- Bit8u level; // 0-100
- Bit8u velosens; // 0-100
- Bit8u biaspoint1; // 0-127 (<1A-<7C >1A-7C)
- Bit8u biaslevel1; // 0-12 (-12 - 0)
- Bit8u biaspoint2; // 0-127 (<1A-<7C >1A-7C)
- Bit8u biaslevel2; // 0-12 (-12 - 0)
- Bit8u envtkf; // TIME KEY FOLLOW 0-4
- Bit8u envvkf; // VELOS KEY FOLL0W 0-4
- Bit8u envtime[5]; // 1-100
- Bit8u envlevel[4]; // 1-100
- } MT32EMU_ALIGN_PACKED tva;
- } MT32EMU_ALIGN_PACKED partial[4];
-} MT32EMU_ALIGN_PACKED;
-
-struct PatchParam {
- Bit8u timbreGroup; // TIMBRE GROUP 0-3 (group A, group B, Memory, Rhythm)
- Bit8u timbreNum; // TIMBRE NUMBER 0-63
- Bit8u keyShift; // KEY SHIFT 0-48 (-24 - +24 semitones)
- Bit8u fineTune; // FINE TUNE 0-100 (-50 - +50 cents)
- Bit8u benderRange; // BENDER RANGE 0-24
- Bit8u assignMode; // ASSIGN MODE 0-3 (POLY1, POLY2, POLY3, POLY4)
- Bit8u reverbSwitch; // REVERB SWITCH 0-1 (OFF,ON)
- Bit8u dummy; // (DUMMY)
-} MT32EMU_ALIGN_PACKED;
-
-struct MemParams {
- // NOTE: The MT-32 documentation only specifies PatchTemp areas for parts 1-8.
- // The LAPC-I documentation specified an additional area for rhythm at the end,
- // where all parameters but fine tune, assign mode and output level are ignored
- struct PatchTemp {
- PatchParam patch;
- Bit8u outlevel; // OUTPUT LEVEL 0-100
- Bit8u panpot; // PANPOT 0-14 (R-L)
- Bit8u dummyv[6];
- } MT32EMU_ALIGN_PACKED;
-
- PatchTemp patchSettings[9];
-
- struct RhythmTemp {
- Bit8u timbre; // TIMBRE 0-94 (M1-M64,R1-30,OFF)
- Bit8u outlevel; // OUTPUT LEVEL 0-100
- Bit8u panpot; // PANPOT 0-14 (R-L)
- Bit8u reverbSwitch; // REVERB SWITCH 0-1 (OFF,ON)
- } MT32EMU_ALIGN_PACKED;
-
- RhythmTemp rhythmSettings[85];
-
- TimbreParam timbreSettings[8];
-
- PatchParam patches[128];
-
- // NOTE: There are only 30 timbres in the "rhythm" bank for MT-32; the additional 34 are for LAPC-I and above
- struct PaddedTimbre {
- TimbreParam timbre;
- Bit8u padding[10];
- } MT32EMU_ALIGN_PACKED;
-
- PaddedTimbre timbres[64 + 64 + 64 + 64]; // Group A, Group B, Memory, Rhythm
-
- struct SystemArea {
- Bit8u masterTune; // MASTER TUNE 0-127 432.1-457.6Hz
- Bit8u reverbMode; // REVERB MODE 0-3 (room, hall, plate, tap delay)
- Bit8u reverbTime; // REVERB TIME 0-7 (1-8)
- Bit8u reverbLevel; // REVERB LEVEL 0-7 (1-8)
- Bit8u reserveSettings[9]; // PARTIAL RESERVE (PART 1) 0-32
- Bit8u chanAssign[9]; // MIDI CHANNEL (PART1) 0-16 (1-16,OFF)
- Bit8u masterVol; // MASTER VOLUME 0-100
- } MT32EMU_ALIGN_PACKED;
-
- SystemArea system;
-};
-
-#if defined(_MSC_VER) || defined (__MINGW32__)
-#pragma pack(pop)
-#else
-#pragma pack()
-#endif
-
-struct PCMWaveEntry {
- Bit32u addr;
- Bit32u len;
- double tune;
- bool loop;
-};
-
-struct soundaddr {
- Bit16u pcmplace;
- Bit16u pcmoffset;
-};
-
-struct StereoVolume {
- Bit16s leftvol;
- Bit16s rightvol;
-};
-
-// This is basically a per-partial, pre-processed combination of timbre and patch/rhythm settings
-struct PatchCache {
- bool playPartial;
- bool PCMPartial;
- int pcm;
- char waveform;
- int pulsewidth;
- int pwsens;
-
- float pitch;
-
- int lfodepth;
- int lforate;
- Bit32u lfoperiod;
- int modsense;
-
- float pitchKeyfollow;
-
- int filtkeyfollow;
-
- int tvfbias;
- int tvfblevel;
- int tvfdir;
-
- int ampbias[2];
- int ampblevel[2];
- int ampdir[2];
-
- int ampdepth;
- int amplevel;
-
- bool useBender;
- float benderRange; // 0.0, 1.0, .., 24.0 (semitones)
-
- TimbreParam::partialParam::envParam pitchEnv;
- TimbreParam::partialParam::tvaParam ampEnv;
- TimbreParam::partialParam::tvfParam filtEnv;
-
- Bit32s pitchsustain;
- Bit32s filtsustain;
-
- Bit32u structureMix;
- int structurePosition;
- int structurePair;
-
- // The following fields are actually common to all partials in the timbre
- bool dirty;
- Bit32u partialCount;
- bool sustain;
- float pitchShift;
- bool reverb;
- const StereoVolume *pansetptr;
-};
-
-class Partial; // Forward reference for class defined in partial.h
-
-struct dpoly {
- bool isPlaying;
-
- unsigned int key;
- int freqnum;
- int vel;
-
- bool isDecay;
-
- const Bit32u *volumeptr;
-
- Partial *partials[4];
-
- bool pedalhold; // This marks keys that have been released on the keyboard, but are being held by the pedal
- bool sustain;
-
- bool isActive() const;
- Bit32u getAge() const;
-};
-
-}
-
-#endif
diff --git a/sound/softsynth/mt32/synth.cpp b/sound/softsynth/mt32/synth.cpp
deleted file mode 100644
index 16460795a5..0000000000
--- a/sound/softsynth/mt32/synth.cpp
+++ /dev/null
@@ -1,1198 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <math.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "mt32emu.h"
-
-#include "common/str.h"
-
-#if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__)
-// Older versions of Mac OS X didn't supply a powf function, so using it
-// will cause a binary incompatibility when trying to run a binary built
-// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide
-// powf, floorf, fabsf etc. at all.
-// Cross-compiled MinGW32 toolchains suffer from a cross-compile bug in
-// libstdc++. math/stubs.o should be empty, but it comes with a symbol for
-// powf, resulting in a linker error because of multiple definitions.
-// Hence we re-define them here. The only potential drawback is that it
-// might be a little bit slower this way.
-#define powf(x,y) ((float)pow(x,y))
-#define floorf(x) ((float)floor(x))
-#define fabsf(x) ((float)fabs(x))
-#endif
-
-namespace MT32Emu {
-
-const int MAX_SYSEX_SIZE = 512;
-
-const ControlROMMap ControlROMMaps[5] = {
- // ID IDc IDbytes PCMmap PCMc tmbrA tmbrAO, tmbrB tmbrBO, tmbrR trC rhythm rhyC rsrv panpot prog
- {0x4014, 22, "\000 ver1.04 14 July 87 ", 0x3000, 128, 0x8000, 0x0000, 0xC000, 0x4000, 0x3200, 30, 0x73A6, 85, 0x57C7, 0x57D0, 0x57E2}, // MT-32 revision 0
- {0x4014, 22, "\000 ver1.06 31 Aug, 87 ", 0x3000, 128, 0x8000, 0x0000, 0xC000, 0x4000, 0x3200, 30, 0x7414, 85, 0x57D9, 0x57E2, 0x57F4}, // MT-32 revision 0
- {0x4010, 22, "\000 ver1.07 10 Oct, 87 ", 0x3000, 128, 0x8000, 0x0000, 0xC000, 0x4000, 0x3200, 30, 0x73fe, 85, 0x57B1, 0x57BA, 0x57CC}, // MT-32 revision 1
- {0x4010, 22, "\000verX.XX 30 Sep, 88 ", 0x3000, 128, 0x8000, 0x0000, 0xC000, 0x4000, 0x3200, 30, 0x741C, 85, 0x57E5, 0x57EE, 0x5800}, // MT-32 Blue Ridge mod
- {0x2205, 22, "\000CM32/LAPC1.02 891205", 0x8100, 256, 0x8000, 0x8000, 0x8080, 0x8000, 0x8500, 64, 0x8580, 85, 0x4F93, 0x4F9C, 0x4FAE} // CM-32L
- // (Note that all but CM-32L ROM actually have 86 entries for rhythmTemp)
-};
-
-float iir_filter_normal(float input, float *hist1_ptr, float *coef_ptr) {
- float *hist2_ptr;
- float output,new_hist;
-
- hist2_ptr = hist1_ptr + 1; // next history
-
- // 1st number of coefficients array is overall input scale factor, or filter gain
- output = input * (*coef_ptr++);
-
- output = output - *hist1_ptr * (*coef_ptr++);
- new_hist = output - *hist2_ptr * (*coef_ptr++); // poles
-
- output = new_hist + *hist1_ptr * (*coef_ptr++);
- output = output + *hist2_ptr * (*coef_ptr++); // zeros
-
- *hist2_ptr++ = *hist1_ptr;
- *hist1_ptr++ = new_hist;
- hist1_ptr++;
- hist2_ptr++;
-
- // i = 1
- output = output - *hist1_ptr * (*coef_ptr++);
- new_hist = output - *hist2_ptr * (*coef_ptr++); // poles
-
- output = new_hist + *hist1_ptr * (*coef_ptr++);
- output = output + *hist2_ptr * (*coef_ptr++); // zeros
-
- *hist2_ptr++ = *hist1_ptr;
- *hist1_ptr++ = new_hist;
-
- return(output);
-}
-
-Bit8u Synth::calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum) {
- for (unsigned int i = 0; i < len; i++) {
- checksum = checksum + data[i];
- }
- checksum = checksum & 0x7f;
- if (checksum)
- checksum = 0x80 - checksum;
- return checksum;
-}
-
-Synth::Synth() {
- isOpen = false;
- reverbModel = NULL;
- partialManager = NULL;
- memset(parts, 0, sizeof(parts));
-}
-
-Synth::~Synth() {
- close(); // Make sure we're closed and everything is freed
-}
-
-int Synth::report(ReportType type, const void *data) {
- if (myProp.report != NULL) {
- return myProp.report(myProp.userData, type, data);
- }
- return 0;
-}
-
-void Synth::printDebug(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- if (myProp.printDebug != NULL) {
- myProp.printDebug(myProp.userData, fmt, ap);
- } else {
- vprintf(fmt, ap);
- printf("\n");
- }
- va_end(ap);
-}
-
-void Synth::initReverb(Bit8u newRevMode, Bit8u newRevTime, Bit8u newRevLevel) {
- // FIXME:KG: I don't think it's necessary to recreate the reverbModel... Just set the parameters
- delete reverbModel;
- reverbModel = new revmodel();
-
- switch (newRevMode) {
- case 0:
- reverbModel->setroomsize(.1f);
- reverbModel->setdamp(.75f);
- break;
- case 1:
- reverbModel->setroomsize(.5f);
- reverbModel->setdamp(.5f);
- break;
- case 2:
- reverbModel->setroomsize(.5f);
- reverbModel->setdamp(.1f);
- break;
- case 3:
- reverbModel->setroomsize(1.0f);
- reverbModel->setdamp(.75f);
- break;
- default:
- reverbModel->setroomsize(.1f);
- reverbModel->setdamp(.5f);
- break;
- }
- reverbModel->setdry(1);
- reverbModel->setwet((float)newRevLevel / 8.0f);
- reverbModel->setwidth((float)newRevTime / 8.0f);
-}
-
-File *Synth::openFile(const char *filename, File::OpenMode mode) {
- // It should never happen that openFile is NULL in our use case.
- // Just to cover the case where something is horrible wrong we
- // use an assert here.
- assert(myProp.openFile != NULL);
- return myProp.openFile(myProp.userData, filename, mode);
-}
-
-void Synth::closeFile(File *file) {
- if (myProp.closeFile != NULL) {
- myProp.closeFile(myProp.userData, file);
- } else {
- file->close();
- delete file;
- }
-}
-
-bool Synth::loadPreset(File *file) {
- bool inSys = false;
- Bit8u sysexBuf[MAX_SYSEX_SIZE];
- Bit16u syslen = 0;
- bool rc = true;
- for (;;) {
- Bit8u c;
- if (!file->readBit8u(&c)) {
- if (!file->isEOF()) {
- rc = false;
- }
- break;
- }
- sysexBuf[syslen] = c;
- if (inSys) {
- syslen++;
- if (c == 0xF7) {
- playSysex(&sysexBuf[0], syslen);
- inSys = false;
- syslen = 0;
- } else if (syslen == MAX_SYSEX_SIZE) {
- printDebug("MAX_SYSEX_SIZE (%d) exceeded while processing preset, ignoring message", MAX_SYSEX_SIZE);
- inSys = false;
- syslen = 0;
- }
- } else if (c == 0xF0) {
- syslen++;
- inSys = true;
- }
- }
- return rc;
-}
-
-bool Synth::loadControlROM(const char *filename) {
- File *file = openFile(filename, File::OpenMode_read); // ROM File
- if (file == NULL) {
- return false;
- }
- bool rc = (file->read(controlROMData, CONTROL_ROM_SIZE) == CONTROL_ROM_SIZE);
-
- closeFile(file);
- if (!rc)
- return rc;
-
- // Control ROM successfully loaded, now check whether it's a known type
- controlROMMap = NULL;
- for (unsigned int i = 0; i < sizeof (ControlROMMaps) / sizeof (ControlROMMaps[0]); i++) {
- if (memcmp(&controlROMData[ControlROMMaps[i].idPos], ControlROMMaps[i].idBytes, ControlROMMaps[i].idLen) == 0) {
- controlROMMap = &ControlROMMaps[i];
- return true;
- }
- }
- return false;
-}
-
-bool Synth::loadPCMROM(const char *filename) {
- File *file = openFile(filename, File::OpenMode_read); // ROM File
- if (file == NULL) {
- return false;
- }
- bool rc = true;
- int i;
- for (i = 0; i < pcmROMSize; i++) {
- Bit8u s;
- if (!file->readBit8u(&s)) {
- if (!file->isEOF()) {
- rc = false;
- }
- break;
- }
- Bit8u c;
- if (!file->readBit8u(&c)) {
- if (!file->isEOF()) {
- rc = false;
- } else {
- printDebug("PCM ROM file has an odd number of bytes! Ignoring last");
- }
- break;
- }
-
- short e;
- int bit;
- int u;
- int order[16] = {0, 9, 1 ,2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8};
-
- e = 0;
- for (u = 0; u < 15; u++) {
- if (order[u] < 8)
- bit = (s >> (7 - order[u])) & 0x1;
- else
- bit = (c >> (7 - (order[u] - 8))) & 0x1;
- e = e | (short)(bit << (15 - u));
- }
-
- /*
- //Bit16s e = ( ((s & 0x7f) << 4) | ((c & 0x40) << 6) | ((s & 0x80) << 6) | ((c & 0x3f))) << 2;
- if (e<0)
- e = -32767 - e;
- int ut = abs(e);
- int dif = 0x7fff - ut;
- x = exp(((float)((float)0x8000-(float)dif) / (float)0x1000));
- e = (int)((float)e * (x/3200));
- */
-
- // File is companded (dB?), convert to linear PCM
- // MINDB = -96
- // MAXDB = -15
- float testval;
- testval = (float)((~e) & 0x7fff);
- testval = -(testval / 400.00f);
- //testval = -(testval / 341.32291666666666666666666666667);
- float vol = powf(8, testval / 20) * 32767.0f;
-
- if (e > 0)
- vol = -vol;
-
- pcmROMData[i] = (Bit16s)vol;
- }
- if (i != pcmROMSize) {
- printDebug("PCM ROM file is too short (expected %d, got %d)", pcmROMSize, i);
- rc = false;
- }
- closeFile(file);
- return rc;
-}
-
-bool Synth::initPCMList(Bit16u mapAddress, Bit16u count) {
- ControlROMPCMStruct *tps = (ControlROMPCMStruct *)&controlROMData[mapAddress];
- for (int i = 0; i < count; i++) {
- int rAddr = tps[i].pos * 0x800;
- int rLenExp = (tps[i].len & 0x70) >> 4;
- int rLen = 0x800 << rLenExp;
- bool rLoop = (tps[i].len & 0x80) != 0;
- //Bit8u rFlag = tps[i].len & 0x0F;
- Bit16u rTuneOffset = (tps[i].pitchMSB << 8) | tps[i].pitchLSB;
- // The number below is confirmed to a reasonable degree of accuracy on CM-32L
- double STANDARDFREQ = 442.0;
- float rTune = (float)(STANDARDFREQ * pow(2.0, (0x5000 - rTuneOffset) / 4056.0 - 9.0 / 12.0));
- //printDebug("%f,%d,%d", (double)pTune, tps[i].pitchCoarse, tps[i].pitchFine);
- if (rAddr + rLen > pcmROMSize) {
- printDebug("Control ROM error: Wave map entry %d points to invalid PCM address 0x%04X, length 0x%04X", i, rAddr, rLen);
- return false;
- }
- pcmWaves[i].addr = rAddr;
- pcmWaves[i].len = rLen;
- pcmWaves[i].loop = rLoop;
- pcmWaves[i].tune = rTune;
- }
- return false;
-}
-
-bool Synth::initRhythmTimbre(int timbreNum, const Bit8u *mem, unsigned int memLen) {
- if (memLen < sizeof(TimbreParam::commonParam)) {
- return false;
- }
- TimbreParam *timbre = &mt32ram.timbres[timbreNum].timbre;
- memcpy(&timbre->common, mem, 14);
- unsigned int memPos = 14;
- char drumname[11];
- memset(drumname, 0, 11);
- memcpy(drumname, timbre->common.name, 10);
- for (int t = 0; t < 4; t++) {
- if (((timbre->common.pmute >> t) & 0x1) == 0x1) {
- if (memPos + 58 >= memLen) {
- return false;
- }
- memcpy(&timbre->partial[t], mem + memPos, 58);
- memPos += 58;
- }
- }
- return true;
-}
-
-bool Synth::initRhythmTimbres(Bit16u mapAddress, Bit16u count) {
- const Bit8u *drumMap = &controlROMData[mapAddress];
- int timbreNum = 192;
- for (Bit16u i = 0; i < count * 2; i += 2) {
- Bit16u address = (drumMap[i + 1] << 8) | drumMap[i];
- /*
- // This check is nonsensical when the control ROM is the full 64KB addressable by 16-bit absolute pointers (which it is)
- if (address >= CONTROL_ROM_SIZE) {
- printDebug("Control ROM error: Timbre map entry 0x%04x points to invalid timbre address 0x%04x", i, address);
- return false;
- }
- */
- if (!initRhythmTimbre(timbreNum++, &controlROMData[address], CONTROL_ROM_SIZE - address)) {
- printDebug("Control ROM error: Timbre map entry 0x%04x points to invalid timbre 0x%04x", i, address);
- return false;
- }
- }
- return true;
-}
-
-bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, int startTimbre) {
- for (Bit16u i = mapAddress; i < mapAddress + 0x80; i += 2) {
- Bit16u address = (controlROMData[i + 1] << 8) | controlROMData[i];
- if (address + sizeof(TimbreParam) > CONTROL_ROM_SIZE) {
- printDebug("Control ROM error: Timbre map entry 0x%04x points to invalid timbre address 0x%04x", i, address);
- return false;
- }
- address = address + offset;
- TimbreParam *timbre = &mt32ram.timbres[startTimbre++].timbre;
- memcpy(timbre, &controlROMData[address], sizeof(TimbreParam));
- }
- return true;
-}
-
-bool Synth::open(SynthProperties &useProp) {
- if (isOpen)
- return false;
-
- myProp = useProp;
- if (useProp.baseDir != NULL) {
- myProp.baseDir = new char[strlen(useProp.baseDir) + 1];
- strcpy(myProp.baseDir, useProp.baseDir);
- }
-
- // This is to help detect bugs
- memset(&mt32ram, '?', sizeof(mt32ram));
-
- printDebug("Loading Control ROM");
- if (!loadControlROM("CM32L_CONTROL.ROM")) {
- if (!loadControlROM("MT32_CONTROL.ROM")) {
- printDebug("Init Error - Missing or invalid MT32_CONTROL.ROM");
- report(ReportType_errorControlROM, NULL);
- return false;
- }
- }
-
- // 512KB PCM ROM for MT-32, etc.
- // 1MB PCM ROM for CM-32L, LAPC-I, CM-64, CM-500
- // Note that the size below is given in samples (16-bit), not bytes
- pcmROMSize = controlROMMap->pcmCount == 256 ? 512 * 1024 : 256 * 1024;
- pcmROMData = new Bit16s[pcmROMSize];
-
- printDebug("Loading PCM ROM");
- if (!loadPCMROM("CM32L_PCM.ROM")) {
- if (!loadPCMROM("MT32_PCM.ROM")) {
- printDebug("Init Error - Missing MT32_PCM.ROM");
- report(ReportType_errorPCMROM, NULL);
- return false;
- }
- }
-
- printDebug("Initialising Timbre Bank A");
- if (!initTimbres(controlROMMap->timbreAMap, controlROMMap->timbreAOffset, 0)) {
- return false;
- }
-
- printDebug("Initialising Timbre Bank B");
- if (!initTimbres(controlROMMap->timbreBMap, controlROMMap->timbreBOffset, 64)) {
- return false;
- }
-
- printDebug("Initialising Timbre Bank R");
- if (!initRhythmTimbres(controlROMMap->timbreRMap, controlROMMap->timbreRCount)) {
- return false;
- }
-
- printDebug("Initialising Timbre Bank M");
- // CM-64 seems to initialise all bytes in this bank to 0.
- memset(&mt32ram.timbres[128], 0, sizeof (mt32ram.timbres[128]) * 64);
-
- partialManager = new PartialManager(this);
-
- pcmWaves = new PCMWaveEntry[controlROMMap->pcmCount];
-
- printDebug("Initialising PCM List");
- initPCMList(controlROMMap->pcmTable, controlROMMap->pcmCount);
-
- printDebug("Initialising Rhythm Temp");
- memcpy(mt32ram.rhythmSettings, &controlROMData[controlROMMap->rhythmSettings], controlROMMap->rhythmSettingsCount * 4);
-
- printDebug("Initialising Patches");
- for (Bit8u i = 0; i < 128; i++) {
- PatchParam *patch = &mt32ram.patches[i];
- patch->timbreGroup = i / 64;
- patch->timbreNum = i % 64;
- patch->keyShift = 24;
- patch->fineTune = 50;
- patch->benderRange = 12;
- patch->assignMode = 0;
- patch->reverbSwitch = 1;
- patch->dummy = 0;
- }
-
- printDebug("Initialising System");
- // The MT-32 manual claims that "Standard pitch" is 442Hz.
- mt32ram.system.masterTune = 0x40; // Confirmed on CM-64 as 0x4A, but SCUMM games use 0x40 and we don't want to initialise twice
- mt32ram.system.reverbMode = 0; // Confirmed
- mt32ram.system.reverbTime = 5; // Confirmed
- mt32ram.system.reverbLevel = 3; // Confirmed
- memcpy(mt32ram.system.reserveSettings, &controlROMData[controlROMMap->reserveSettings], 9); // Confirmed
- for (Bit8u i = 0; i < 9; i++) {
- // This is the default: {1, 2, 3, 4, 5, 6, 7, 8, 9}
- // An alternative configuration can be selected by holding "Master Volume"
- // and pressing "PART button 1" on the real MT-32's frontpanel.
- // The channel assignment is then {0, 1, 2, 3, 4, 5, 6, 7, 9}
- mt32ram.system.chanAssign[i] = i + 1;
- }
- mt32ram.system.masterVol = 100; // Confirmed
- if (!refreshSystem())
- return false;
-
- for (int i = 0; i < 8; i++) {
- mt32ram.patchSettings[i].outlevel = 80;
- mt32ram.patchSettings[i].panpot = controlROMData[controlROMMap->panSettings + i];
- memset(mt32ram.patchSettings[i].dummyv, 0, sizeof(mt32ram.patchSettings[i].dummyv));
- parts[i] = new Part(this, i);
- parts[i]->setProgram(controlROMData[controlROMMap->programSettings + i]);
- }
- parts[8] = new RhythmPart(this, 8);
-
- // For resetting mt32 mid-execution
- mt32default = mt32ram;
-
- iirFilter = &iir_filter_normal;
-
-#ifdef MT32EMU_HAVE_X86
- bool availableSSE = DetectSIMD();
- bool available3DNow = Detect3DNow();
-
- if (availableSSE)
- report(ReportType_availableSSE, NULL);
- if (available3DNow)
- report(ReportType_available3DNow, NULL);
-
- if (available3DNow) {
- printDebug("Detected and using SIMD (AMD 3DNow) extensions");
- iirFilter = &iir_filter_3dnow;
- report(ReportType_using3DNow, NULL);
- } else if (availableSSE) {
- printDebug("Detected and using SIMD (Intel SSE) extensions");
- iirFilter = &iir_filter_sse;
- report(ReportType_usingSSE, NULL);
- }
-#endif
-
- isOpen = true;
- isEnabled = false;
-
- printDebug("*** Initialisation complete ***");
- return true;
-}
-
-void Synth::close(void) {
- if (!isOpen)
- return;
-
- tables.freeNotes();
- if (partialManager != NULL) {
- delete partialManager;
- partialManager = NULL;
- }
-
- if (reverbModel != NULL) {
- delete reverbModel;
- reverbModel = NULL;
- }
-
- for (int i = 0; i < 9; i++) {
- if (parts[i] != NULL) {
- delete parts[i];
- parts[i] = NULL;
- }
- }
- if (myProp.baseDir != NULL) {
- delete myProp.baseDir;
- myProp.baseDir = NULL;
- }
-
- delete[] pcmWaves;
- delete[] pcmROMData;
- isOpen = false;
-}
-
-void Synth::playMsg(Bit32u msg) {
- // FIXME: Implement active sensing
- unsigned char code = (unsigned char)((msg & 0x0000F0) >> 4);
- unsigned char chan = (unsigned char) (msg & 0x00000F);
- unsigned char note = (unsigned char)((msg & 0x00FF00) >> 8);
- unsigned char velocity = (unsigned char)((msg & 0xFF0000) >> 16);
- isEnabled = true;
-
- //printDebug("Playing chan %d, code 0x%01x note: 0x%02x", chan, code, note);
-
- signed char part = chantable[chan];
- if (part < 0 || part > 8) {
- printDebug("Play msg on unreg chan %d (%d): code=0x%01x, vel=%d", chan, part, code, velocity);
- return;
- }
- playMsgOnPart(part, code, note, velocity);
-}
-
-void Synth::playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity) {
- Bit32u bend;
-
- //printDebug("Synth::playMsg(0x%02x)",msg);
- switch (code) {
- case 0x8:
- //printDebug("Note OFF - Part %d", part);
- // The MT-32 ignores velocity for note off
- parts[part]->stopNote(note);
- break;
- case 0x9:
- //printDebug("Note ON - Part %d, Note %d Vel %d", part, note, velocity);
- if (velocity == 0) {
- // MIDI defines note-on with velocity 0 as being the same as note-off with velocity 40
- parts[part]->stopNote(note);
- } else {
- parts[part]->playNote(note, velocity);
- }
- break;
- case 0xB: // Control change
- switch (note) {
- case 0x01: // Modulation
- //printDebug("Modulation: %d", velocity);
- parts[part]->setModulation(velocity);
- break;
- case 0x07: // Set volume
- //printDebug("Volume set: %d", velocity);
- parts[part]->setVolume(velocity);
- break;
- case 0x0A: // Pan
- //printDebug("Pan set: %d", velocity);
- parts[part]->setPan(velocity);
- break;
- case 0x0B:
- //printDebug("Expression set: %d", velocity);
- parts[part]->setExpression(velocity);
- break;
- case 0x40: // Hold (sustain) pedal
- //printDebug("Hold pedal set: %d", velocity);
- parts[part]->setHoldPedal(velocity>=64);
- break;
-
- case 0x79: // Reset all controllers
- //printDebug("Reset all controllers");
- //FIXME: Check for accuracy against real thing
- parts[part]->setVolume(100);
- parts[part]->setExpression(127);
- parts[part]->setPan(64);
- parts[part]->setBend(0x2000);
- parts[part]->setHoldPedal(false);
- break;
-
- case 0x7B: // All notes off
- //printDebug("All notes off");
- parts[part]->allNotesOff();
- break;
-
- default:
- printDebug("Unknown MIDI Control code: 0x%02x - vel 0x%02x", note, velocity);
- break;
- }
-
- break;
- case 0xC: // Program change
- //printDebug("Program change %01x", note);
- parts[part]->setProgram(note);
- break;
- case 0xE: // Pitch bender
- bend = (velocity << 7) | (note);
- //printDebug("Pitch bender %02x", bend);
- parts[part]->setBend(bend);
- break;
- default:
- printDebug("Unknown Midi code: 0x%01x - %02x - %02x", code, note, velocity);
- break;
- }
-
- //midiOutShortMsg(m_out, msg);
-}
-
-void Synth::playSysex(const Bit8u *sysex, Bit32u len) {
- if (len < 2) {
- printDebug("playSysex: Message is too short for sysex (%d bytes)", len);
- }
- if (sysex[0] != 0xF0) {
- printDebug("playSysex: Message lacks start-of-sysex (0xF0)");
- return;
- }
- // Due to some programs (e.g. Java) sending buffers with junk at the end, we have to go through and find the end marker rather than relying on len.
- Bit32u endPos;
- for (endPos = 1; endPos < len; endPos++)
- {
- if (sysex[endPos] == 0xF7)
- break;
- }
- if (endPos == len) {
- printDebug("playSysex: Message lacks end-of-sysex (0xf7)");
- return;
- }
- playSysexWithoutFraming(sysex + 1, endPos - 1);
-}
-
-void Synth::playSysexWithoutFraming(const Bit8u *sysex, Bit32u len) {
- if (len < 4) {
- printDebug("playSysexWithoutFraming: Message is too short (%d bytes)!", len);
- return;
- }
- if (sysex[0] != SYSEX_MANUFACTURER_ROLAND) {
- printDebug("playSysexWithoutFraming: Header not intended for this device manufacturer: %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]);
- return;
- }
- if (sysex[2] == SYSEX_MDL_D50) {
- printDebug("playSysexWithoutFraming: Header is intended for model D-50 (not yet supported): %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]);
- return;
- }
- else if (sysex[2] != SYSEX_MDL_MT32) {
- printDebug("playSysexWithoutFraming: Header not intended for model MT-32: %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]);
- return;
- }
- playSysexWithoutHeader(sysex[1], sysex[3], sysex + 4, len - 4);
-}
-
-void Synth::playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len) {
- if (device > 0x10) {
- // We have device ID 0x10 (default, but changeable, on real MT-32), < 0x10 is for channels
- printDebug("playSysexWithoutHeader: Message is not intended for this device ID (provided: %02x, expected: 0x10 or channel)", (int)device);
- return;
- }
- if (len < 4) {
- printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len);
- return;
- }
- unsigned char checksum = calcSysexChecksum(sysex, len - 1, 0);
- if (checksum != sysex[len - 1]) {
- printDebug("playSysexWithoutHeader: Message checksum is incorrect (provided: %02x, expected: %02x)!", sysex[len - 1], checksum);
- return;
- }
- len -= 1; // Exclude checksum
- switch (command) {
- case SYSEX_CMD_DT1:
- writeSysex(device, sysex, len);
- break;
- case SYSEX_CMD_RQ1:
- readSysex(device, sysex, len);
- break;
- default:
- printDebug("playSysexWithoutFraming: Unsupported command %02x", command);
- return;
- }
-}
-
-void Synth::readSysex(unsigned char /*device*/, const Bit8u * /*sysex*/, Bit32u /*len*/) {
-}
-
-const MemoryRegion memoryRegions[8] = {
- {MR_PatchTemp, MT32EMU_MEMADDR(0x030000), sizeof(MemParams::PatchTemp), 9},
- {MR_RhythmTemp, MT32EMU_MEMADDR(0x030110), sizeof(MemParams::RhythmTemp), 85},
- {MR_TimbreTemp, MT32EMU_MEMADDR(0x040000), sizeof(TimbreParam), 8},
- {MR_Patches, MT32EMU_MEMADDR(0x050000), sizeof(PatchParam), 128},
- {MR_Timbres, MT32EMU_MEMADDR(0x080000), sizeof(MemParams::PaddedTimbre), 64 + 64 + 64 + 64},
- {MR_System, MT32EMU_MEMADDR(0x100000), sizeof(MemParams::SystemArea), 1},
- {MR_Display, MT32EMU_MEMADDR(0x200000), MAX_SYSEX_SIZE - 1, 1},
- {MR_Reset, MT32EMU_MEMADDR(0x7F0000), 0x3FFF, 1}
-};
-
-const int NUM_REGIONS = sizeof(memoryRegions) / sizeof(MemoryRegion);
-
-void Synth::writeSysex(unsigned char device, const Bit8u *sysex, Bit32u len) {
- Bit32u addr = (sysex[0] << 16) | (sysex[1] << 8) | (sysex[2]);
- addr = MT32EMU_MEMADDR(addr);
- sysex += 3;
- len -= 3;
- //printDebug("Sysex addr: 0x%06x", MT32EMU_SYSEXMEMADDR(addr));
- // NOTE: Please keep both lower and upper bounds in each check, for ease of reading
-
- // Process channel-specific sysex by converting it to device-global
- if (device < 0x10) {
- printDebug("WRITE-CHANNEL: Channel %d temp area 0x%06x", device, MT32EMU_SYSEXMEMADDR(addr));
- if (/*addr >= MT32EMU_MEMADDR(0x000000) && */addr < MT32EMU_MEMADDR(0x010000)) {
- int offset;
- if (chantable[device] == -1) {
- printDebug(" (Channel not mapped to a partial... 0 offset)");
- offset = 0;
- } else if (chantable[device] == 8) {
- printDebug(" (Channel mapped to rhythm... 0 offset)");
- offset = 0;
- } else {
- offset = chantable[device] * sizeof(MemParams::PatchTemp);
- printDebug(" (Setting extra offset to %d)", offset);
- }
- addr += MT32EMU_MEMADDR(0x030000) + offset;
- } else if (/*addr >= 0x010000 && */ addr < MT32EMU_MEMADDR(0x020000)) {
- addr += MT32EMU_MEMADDR(0x030110) - MT32EMU_MEMADDR(0x010000);
- } else if (/*addr >= 0x020000 && */ addr < MT32EMU_MEMADDR(0x030000)) {
- int offset;
- if (chantable[device] == -1) {
- printDebug(" (Channel not mapped to a partial... 0 offset)");
- offset = 0;
- } else if (chantable[device] == 8) {
- printDebug(" (Channel mapped to rhythm... 0 offset)");
- offset = 0;
- } else {
- offset = chantable[device] * sizeof(TimbreParam);
- printDebug(" (Setting extra offset to %d)", offset);
- }
- addr += MT32EMU_MEMADDR(0x040000) - MT32EMU_MEMADDR(0x020000) + offset;
- } else {
- printDebug("PlaySysexWithoutHeader: Invalid channel %d address 0x%06x", device, MT32EMU_SYSEXMEMADDR(addr));
- return;
- }
- }
-
- // Process device-global sysex (possibly converted from channel-specific sysex above)
- for (;;) {
- // Find the appropriate memory region
- int regionNum;
- const MemoryRegion *region = NULL; // Initialised to please compiler
- for (regionNum = 0; regionNum < NUM_REGIONS; regionNum++) {
- region = &memoryRegions[regionNum];
- if (region->contains(addr)) {
- writeMemoryRegion(region, addr, region->getClampedLen(addr, len), sysex);
- break;
- }
- }
- if (regionNum == NUM_REGIONS) {
- printDebug("Sysex write to unrecognised address %06x, len %d", MT32EMU_SYSEXMEMADDR(addr), len);
- break;
- }
- Bit32u next = region->next(addr, len);
- if (next == 0) {
- break;
- }
- addr += next;
- sysex += next;
- len -= next;
- }
-}
-
-void Synth::readMemory(Bit32u addr, Bit32u len, Bit8u *data) {
- int regionNum;
- const MemoryRegion *region = NULL;
- for (regionNum = 0; regionNum < NUM_REGIONS; regionNum++) {
- region = &memoryRegions[regionNum];
- if (region->contains(addr)) {
- readMemoryRegion(region, addr, len, data);
- break;
- }
- }
-}
-
-void Synth::readMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, Bit8u *data) {
- unsigned int first = region->firstTouched(addr);
- //unsigned int last = region->lastTouched(addr, len);
- unsigned int off = region->firstTouchedOffset(addr);
- len = region->getClampedLen(addr, len);
-
- unsigned int m;
-
- switch (region->type) {
- case MR_PatchTemp:
- for (m = 0; m < len; m++)
- data[m] = ((Bit8u *)&mt32ram.patchSettings[first])[off + m];
- break;
- case MR_RhythmTemp:
- for (m = 0; m < len; m++)
- data[m] = ((Bit8u *)&mt32ram.rhythmSettings[first])[off + m];
- break;
- case MR_TimbreTemp:
- for (m = 0; m < len; m++)
- data[m] = ((Bit8u *)&mt32ram.timbreSettings[first])[off + m];
- break;
- case MR_Patches:
- for (m = 0; m < len; m++)
- data[m] = ((Bit8u *)&mt32ram.patches[first])[off + m];
- break;
- case MR_Timbres:
- for (m = 0; m < len; m++)
- data[m] = ((Bit8u *)&mt32ram.timbres[first])[off + m];
- break;
- case MR_System:
- for (m = 0; m < len; m++)
- data[m] = ((Bit8u *)&mt32ram.system)[m + off];
- break;
- default:
- for (m = 0; m < len; m += 2) {
- data[m] = 0xff;
- if (m + 1 < len) {
- data[m+1] = (Bit8u)region->type;
- }
- }
- // TODO: Don't care about the others ATM
- break;
- }
-
-}
-
-void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, const Bit8u *data) {
- unsigned int first = region->firstTouched(addr);
- unsigned int last = region->lastTouched(addr, len);
- unsigned int off = region->firstTouchedOffset(addr);
- switch (region->type) {
- case MR_PatchTemp:
- for (unsigned int m = 0; m < len; m++) {
- ((Bit8u *)&mt32ram.patchSettings[first])[off + m] = data[m];
- }
- //printDebug("Patch temp: Patch %d, offset %x, len %d", off/16, off % 16, len);
-
- for (unsigned int i = first; i <= last; i++) {
- int absTimbreNum = mt32ram.patchSettings[i].patch.timbreGroup * 64 + mt32ram.patchSettings[i].patch.timbreNum;
- char timbreName[11];
- memcpy(timbreName, mt32ram.timbres[absTimbreNum].timbre.common.name, 10);
- timbreName[10] = 0;
- printDebug("WRITE-PARTPATCH (%d-%d@%d..%d): %d; timbre=%d (%s), outlevel=%d", first, last, off, off + len, i, absTimbreNum, timbreName, mt32ram.patchSettings[i].outlevel);
- if (parts[i] != NULL) {
- if (i != 8) {
- // Note: Confirmed on CM-64 that we definitely *should* update the timbre here,
- // but only in the case that the sysex actually writes to those values
- if (i == first && off > 2) {
- printDebug(" (Not updating timbre, since those values weren't touched)");
- } else {
- parts[i]->setTimbre(&mt32ram.timbres[parts[i]->getAbsTimbreNum()].timbre);
- }
- }
- parts[i]->refresh();
- }
- }
- break;
- case MR_RhythmTemp:
- for (unsigned int m = 0; m < len; m++)
- ((Bit8u *)&mt32ram.rhythmSettings[first])[off + m] = data[m];
- for (unsigned int i = first; i <= last; i++) {
- int timbreNum = mt32ram.rhythmSettings[i].timbre;
- char timbreName[11];
- if (timbreNum < 94) {
- memcpy(timbreName, mt32ram.timbres[128 + timbreNum].timbre.common.name, 10);
- timbreName[10] = 0;
- } else {
- strcpy(timbreName, "[None]");
- }
- printDebug("WRITE-RHYTHM (%d-%d@%d..%d): %d; level=%02x, panpot=%02x, reverb=%02x, timbre=%d (%s)", first, last, off, off + len, i, mt32ram.rhythmSettings[i].outlevel, mt32ram.rhythmSettings[i].panpot, mt32ram.rhythmSettings[i].reverbSwitch, mt32ram.rhythmSettings[i].timbre, timbreName);
- }
- if (parts[8] != NULL) {
- parts[8]->refresh();
- }
- break;
- case MR_TimbreTemp:
- for (unsigned int m = 0; m < len; m++)
- ((Bit8u *)&mt32ram.timbreSettings[first])[off + m] = data[m];
- for (unsigned int i = first; i <= last; i++) {
- char instrumentName[11];
- memcpy(instrumentName, mt32ram.timbreSettings[i].common.name, 10);
- instrumentName[10] = 0;
- printDebug("WRITE-PARTTIMBRE (%d-%d@%d..%d): timbre=%d (%s)", first, last, off, off + len, i, instrumentName);
- if (parts[i] != NULL) {
- parts[i]->refresh();
- }
- }
- break;
- case MR_Patches:
- for (unsigned int m = 0; m < len; m++)
- ((Bit8u *)&mt32ram.patches[first])[off + m] = data[m];
- for (unsigned int i = first; i <= last; i++) {
- PatchParam *patch = &mt32ram.patches[i];
- int patchAbsTimbreNum = patch->timbreGroup * 64 + patch->timbreNum;
- char instrumentName[11];
- memcpy(instrumentName, mt32ram.timbres[patchAbsTimbreNum].timbre.common.name, 10);
- instrumentName[10] = 0;
- Bit8u *n = (Bit8u *)patch;
- printDebug("WRITE-PATCH (%d-%d@%d..%d): %d; timbre=%d (%s) %02X%02X%02X%02X%02X%02X%02X%02X", first, last, off, off + len, i, patchAbsTimbreNum, instrumentName, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]);
- // FIXME:KG: The below is definitely dodgy. We just guess that this is the patch that the part was using
- // based on a timbre match (but many patches could have the same timbre!)
- // If this refresh is really correct, we should store the patch number in use by each part.
- /*
- for (int part = 0; part < 8; part++) {
- if (parts[part] != NULL) {
- int partPatchAbsTimbreNum = mt32ram.patchSettings[part].patch.timbreGroup * 64 + mt32ram.patchSettings[part].patch.timbreNum;
- if (parts[part]->getAbsTimbreNum() == patchAbsTimbreNum) {
- parts[part]->setPatch(patch);
- parts[part]->RefreshPatch();
- }
- }
- }
- */
- }
- break;
- case MR_Timbres:
- // Timbres
- first += 128;
- last += 128;
- for (unsigned int m = 0; m < len; m++)
- ((Bit8u *)&mt32ram.timbres[first])[off + m] = data[m];
- for (unsigned int i = first; i <= last; i++) {
- char instrumentName[11];
- memcpy(instrumentName, mt32ram.timbres[i].timbre.common.name, 10);
- instrumentName[10] = 0;
- printDebug("WRITE-TIMBRE (%d-%d@%d..%d): %d; name=\"%s\"", first, last, off, off + len, i, instrumentName);
- // FIXME:KG: Not sure if the stuff below should be done (for rhythm and/or parts)...
- // Does the real MT-32 automatically do this?
- for (unsigned int part = 0; part < 9; part++) {
- if (parts[part] != NULL) {
- parts[part]->refreshTimbre(i);
- }
- }
- }
- break;
- case MR_System:
- for (unsigned int m = 0; m < len; m++)
- ((Bit8u *)&mt32ram.system)[m + off] = data[m];
-
- report(ReportType_devReconfig, NULL);
-
- printDebug("WRITE-SYSTEM:");
- refreshSystem();
- break;
- case MR_Display:
- char buf[MAX_SYSEX_SIZE];
- memcpy(&buf, &data[0], len);
- buf[len] = 0;
- printDebug("WRITE-LCD: %s", buf);
- report(ReportType_lcdMessage, buf);
- break;
- case MR_Reset:
- printDebug("RESET");
- report(ReportType_devReset, NULL);
- partialManager->deactivateAll();
- mt32ram = mt32default;
- for (int i = 0; i < 9; i++) {
- parts[i]->refresh();
- }
- isEnabled = false;
- break;
- }
-}
-
-bool Synth::refreshSystem() {
- memset(chantable, -1, sizeof(chantable));
-
- for (unsigned int i = 0; i < 9; i++) {
- //LOG(LOG_MISC|LOG_ERROR,"Part %d set to MIDI channel %d",i,mt32ram.system.chanAssign[i]);
- if (mt32ram.system.chanAssign[i] == 16 && parts[i] != NULL) {
- parts[i]->allSoundOff();
- } else {
- chantable[(int)mt32ram.system.chanAssign[i]] = (char)i;
- }
- }
- //FIXME:KG: This is just an educated guess.
- // The LAPC-I documentation claims a range of 427.5Hz-452.6Hz (similar to what we have here)
- // The MT-32 documentation claims a range of 432.1Hz-457.6Hz
- masterTune = 440.0f * powf(2.0f, (mt32ram.system.masterTune - 64.0f) / (128.0f * 12.0f));
- printDebug(" Master Tune: %f", (double)masterTune);
- printDebug(" Reverb: mode=%d, time=%d, level=%d", mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel);
- report(ReportType_newReverbMode, &mt32ram.system.reverbMode);
- report(ReportType_newReverbTime, &mt32ram.system.reverbTime);
- report(ReportType_newReverbLevel, &mt32ram.system.reverbLevel);
-
- if (myProp.useDefaultReverb) {
- initReverb(mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel);
- } else {
- initReverb(myProp.reverbType, myProp.reverbTime, mt32ram.system.reverbLevel);
- }
-
- Bit8u *rset = mt32ram.system.reserveSettings;
- printDebug(" Partial reserve: 1=%02d 2=%02d 3=%02d 4=%02d 5=%02d 6=%02d 7=%02d 8=%02d Rhythm=%02d", rset[0], rset[1], rset[2], rset[3], rset[4], rset[5], rset[6], rset[7], rset[8]);
- int pr = partialManager->setReserve(rset);
- if (pr != 32)
- printDebug(" (Partial Reserve Table with less than 32 partials reserved!)");
- rset = mt32ram.system.chanAssign;
- printDebug(" Part assign: 1=%02d 2=%02d 3=%02d 4=%02d 5=%02d 6=%02d 7=%02d 8=%02d Rhythm=%02d", rset[0], rset[1], rset[2], rset[3], rset[4], rset[5], rset[6], rset[7], rset[8]);
- printDebug(" Master volume: %d", mt32ram.system.masterVol);
- masterVolume = (Bit16u)(mt32ram.system.masterVol * 32767 / 100);
- if (!tables.init(this, pcmWaves, (float)myProp.sampleRate, masterTune)) {
- report(ReportType_errorSampleRate, NULL);
- return false;
- }
- return true;
-}
-
-bool Synth::dumpTimbre(File *file, const TimbreParam *timbre, Bit32u address) {
- // Sysex header
- if (!file->writeBit8u(0xF0))
- return false;
- if (!file->writeBit8u(0x41))
- return false;
- if (!file->writeBit8u(0x10))
- return false;
- if (!file->writeBit8u(0x16))
- return false;
- if (!file->writeBit8u(0x12))
- return false;
-
- char lsb = (char)(address & 0x7f);
- char isb = (char)((address >> 7) & 0x7f);
- char msb = (char)(((address >> 14) & 0x7f) | 0x08);
-
- //Address
- if (!file->writeBit8u(msb))
- return false;
- if (!file->writeBit8u(isb))
- return false;
- if (!file->writeBit8u(lsb))
- return false;
-
- //Data
- if (file->write(timbre, 246) != 246)
- return false;
-
- //Checksum
- unsigned char checksum = calcSysexChecksum((const Bit8u *)timbre, 246, msb + isb + lsb);
- if (!file->writeBit8u(checksum))
- return false;
-
- //End of sysex
- if (!file->writeBit8u(0xF7))
- return false;
- return true;
-}
-
-int Synth::dumpTimbres(const char *filename, int start, int len) {
- File *file = openFile(filename, File::OpenMode_write);
- if (file == NULL)
- return -1;
-
- for (int timbreNum = start; timbreNum < start + len; timbreNum++) {
- int useaddr = (timbreNum - start) * 256;
- TimbreParam *timbre = &mt32ram.timbres[timbreNum].timbre;
- if (!dumpTimbre(file, timbre, useaddr))
- break;
- }
- closeFile(file);
- return 0;
-}
-
-void ProduceOutput1(Bit16s *useBuf, Bit16s *stream, Bit32u len, Bit16s volume) {
-#if MT32EMU_USE_MMX > 2
- //FIXME:KG: This appears to introduce crackle
- int donelen = i386_produceOutput1(useBuf, stream, len, volume);
- len -= donelen;
- stream += donelen * 2;
- useBuf += donelen * 2;
-#endif
- int end = len * 2;
- while (end--) {
- *stream = *stream + (Bit16s)(((Bit32s)*useBuf++ * (Bit32s)volume)>>15);
- stream++;
- }
-}
-
-void Synth::render(Bit16s *stream, Bit32u len) {
- memset(stream, 0, len * sizeof (Bit16s) * 2);
- if (!isEnabled)
- return;
- while (len > 0) {
- Bit32u thisLen = len > MAX_SAMPLE_OUTPUT ? MAX_SAMPLE_OUTPUT : len;
- doRender(stream, thisLen);
- len -= thisLen;
- stream += 2 * thisLen;
- }
-}
-
-void Synth::doRender(Bit16s *stream, Bit32u len) {
- partialManager->ageAll();
-
- if (myProp.useReverb) {
- for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialManager->shouldReverb(i)) {
- if (partialManager->produceOutput(i, &tmpBuffer[0], len)) {
- ProduceOutput1(&tmpBuffer[0], stream, len, masterVolume);
- }
- }
- }
- Bit32u m = 0;
- for (unsigned int i = 0; i < len; i++) {
- sndbufl[i] = (float)stream[m] / 32767.0f;
- m++;
- sndbufr[i] = (float)stream[m] / 32767.0f;
- m++;
- }
- reverbModel->processreplace(sndbufl, sndbufr, outbufl, outbufr, len, 1);
- m=0;
- for (unsigned int i = 0; i < len; i++) {
- stream[m] = (Bit16s)(outbufl[i] * 32767.0f);
- m++;
- stream[m] = (Bit16s)(outbufr[i] * 32767.0f);
- m++;
- }
- for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (!partialManager->shouldReverb(i)) {
- if (partialManager->produceOutput(i, &tmpBuffer[0], len)) {
- ProduceOutput1(&tmpBuffer[0], stream, len, masterVolume);
- }
- }
- }
- } else {
- for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (partialManager->produceOutput(i, &tmpBuffer[0], len))
- ProduceOutput1(&tmpBuffer[0], stream, len, masterVolume);
- }
- }
-
- partialManager->clearAlreadyOutputed();
-
-#if MT32EMU_MONITOR_PARTIALS == 1
- samplepos += len;
- if (samplepos > myProp.SampleRate * 5) {
- samplepos = 0;
- int partialUsage[9];
- partialManager->GetPerPartPartialUsage(partialUsage);
- printDebug("1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d", partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7]);
- printDebug("Rhythm: %02d TOTAL: %02d", partialUsage[8], MT32EMU_MAX_PARTIALS - partialManager->GetFreePartialCount());
- }
-#endif
-}
-
-const Partial *Synth::getPartial(unsigned int partialNum) const {
- return partialManager->getPartial(partialNum);
-}
-
-const Part *Synth::getPart(unsigned int partNum) const {
- if (partNum > 8)
- return NULL;
- return parts[partNum];
-}
-
-}
diff --git a/sound/softsynth/mt32/synth.h b/sound/softsynth/mt32/synth.h
deleted file mode 100644
index 3fc303d322..0000000000
--- a/sound/softsynth/mt32/synth.h
+++ /dev/null
@@ -1,300 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_SYNTH_H
-#define MT32EMU_SYNTH_H
-
-#include "common/scummsys.h"
-
-class revmodel;
-
-namespace MT32Emu {
-
-class File;
-class TableInitialiser;
-class Partial;
-class PartialManager;
-class Part;
-
-enum ReportType {
- // Errors
- ReportType_errorControlROM = 1,
- ReportType_errorPCMROM,
- ReportType_errorSampleRate,
-
- // Progress
- ReportType_progressInit,
-
- // HW spec
- ReportType_availableSSE,
- ReportType_available3DNow,
- ReportType_usingSSE,
- ReportType_using3DNow,
-
- // General info
- ReportType_lcdMessage,
- ReportType_devReset,
- ReportType_devReconfig,
- ReportType_newReverbMode,
- ReportType_newReverbTime,
- ReportType_newReverbLevel
-};
-
-struct SynthProperties {
- // Sample rate to use in mixing
- int sampleRate;
-
- // Flag to activate reverb. True = use reverb, False = no reverb
- bool useReverb;
- // True to use software set reverb settings, False to set reverb settings in
- // following parameters
- bool useDefaultReverb;
- // When not using the default settings, this specifies one of the 4 reverb types
- // 1 = Room 2 = Hall 3 = Plate 4 = Tap
- unsigned char reverbType;
- // This specifies the delay time, from 0-7 (not sure of the actual MT-32's measurement)
- unsigned char reverbTime;
- // This specifies the reverb level, from 0-7 (not sure of the actual MT-32's measurement)
- unsigned char reverbLevel;
- // The name of the directory in which the ROM and data files are stored (with trailing slash/backslash)
- // Not used if "openFile" is set. May be NULL in any case.
- char *baseDir;
- // This is used as the first argument to all callbacks
- void *userData;
- // Callback for reporting various errors and information. May be NULL
- int (*report)(void *userData, ReportType type, const void *reportData);
- // Callback for debug messages, in vprintf() format
- void (*printDebug)(void *userData, const char *fmt, va_list list);
- // Callback for providing an implementation of File, opened and ready for use
- // May be NULL, in which case a default implementation will be used.
- File *(*openFile)(void *userData, const char *filename, File::OpenMode mode);
- // Callback for closing a File. May be NULL, in which case the File will automatically be close()d/deleted.
- void (*closeFile)(void *userData, File *file);
-};
-
-// This is the specification of the Callback routine used when calling the RecalcWaveforms
-// function
-typedef void (*recalcStatusCallback)(int percDone);
-
-// This external function recreates the base waveform file (waveforms.raw) using a specifed
-// sampling rate. The callback routine provides interactivity to let the user know what
-// percentage is complete in regenerating the waveforms. When a NULL pointer is used as the
-// callback routine, no status is reported.
-bool RecalcWaveforms(char * baseDir, int sampRate, recalcStatusCallback callBack);
-
-typedef float (*iir_filter_type)(float input,float *hist1_ptr, float *coef_ptr);
-
-const Bit8u SYSEX_MANUFACTURER_ROLAND = 0x41;
-
-const Bit8u SYSEX_MDL_MT32 = 0x16;
-const Bit8u SYSEX_MDL_D50 = 0x14;
-
-const Bit8u SYSEX_CMD_RQ1 = 0x11; // Request data #1
-const Bit8u SYSEX_CMD_DT1 = 0x12; // Data set 1
-const Bit8u SYSEX_CMD_WSD = 0x40; // Want to send data
-const Bit8u SYSEX_CMD_RQD = 0x41; // Request data
-const Bit8u SYSEX_CMD_DAT = 0x42; // Data set
-const Bit8u SYSEX_CMD_ACK = 0x43; // Acknowledge
-const Bit8u SYSEX_CMD_EOD = 0x45; // End of data
-const Bit8u SYSEX_CMD_ERR = 0x4E; // Communications error
-const Bit8u SYSEX_CMD_RJC = 0x4F; // Rejection
-
-const unsigned int CONTROL_ROM_SIZE = 64 * 1024;
-
-struct ControlROMPCMStruct
-{
- Bit8u pos;
- Bit8u len;
- Bit8u pitchLSB;
- Bit8u pitchMSB;
-};
-
-struct ControlROMMap {
- Bit16u idPos;
- Bit16u idLen;
- const char *idBytes;
- Bit16u pcmTable;
- Bit16u pcmCount;
- Bit16u timbreAMap;
- Bit16u timbreAOffset;
- Bit16u timbreBMap;
- Bit16u timbreBOffset;
- Bit16u timbreRMap;
- Bit16u timbreRCount;
- Bit16u rhythmSettings;
- Bit16u rhythmSettingsCount;
- Bit16u reserveSettings;
- Bit16u panSettings;
- Bit16u programSettings;
-};
-
-enum MemoryRegionType {
- MR_PatchTemp, MR_RhythmTemp, MR_TimbreTemp, MR_Patches, MR_Timbres, MR_System, MR_Display, MR_Reset
-};
-
-class MemoryRegion {
-public:
- MemoryRegionType type;
- Bit32u startAddr, entrySize, entries;
-
- int lastTouched(Bit32u addr, Bit32u len) const {
- return (offset(addr) + len - 1) / entrySize;
- }
- int firstTouchedOffset(Bit32u addr) const {
- return offset(addr) % entrySize;
- }
- int firstTouched(Bit32u addr) const {
- return offset(addr) / entrySize;
- }
- Bit32u regionEnd() const {
- return startAddr + entrySize * entries;
- }
- bool contains(Bit32u addr) const {
- return addr >= startAddr && addr < regionEnd();
- }
- int offset(Bit32u addr) const {
- return addr - startAddr;
- }
- Bit32u getClampedLen(Bit32u addr, Bit32u len) const {
- if (addr + len > regionEnd())
- return regionEnd() - addr;
- return len;
- }
- Bit32u next(Bit32u addr, Bit32u len) const {
- if (addr + len > regionEnd()) {
- return regionEnd() - addr;
- }
- return 0;
- }
-};
-
-
-class Synth {
-friend class Part;
-friend class RhythmPart;
-friend class Partial;
-friend class Tables;
-private:
- bool isEnabled;
-
- iir_filter_type iirFilter;
-
- PCMWaveEntry *pcmWaves; // Array
-
- const ControlROMMap *controlROMMap;
- Bit8u controlROMData[CONTROL_ROM_SIZE];
- Bit16s *pcmROMData;
- int pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM
-
- Bit8s chantable[32];
-
- #if MT32EMU_MONITOR_PARTIALS == 1
- static Bit32s samplepos = 0;
- #endif
-
- Tables tables;
-
- MemParams mt32ram, mt32default;
-
- revmodel *reverbModel;
-
- float masterTune;
- Bit16u masterVolume;
-
- bool isOpen;
-
- PartialManager *partialManager;
- Part *parts[9];
-
- Bit16s tmpBuffer[MAX_SAMPLE_OUTPUT * 2];
- float sndbufl[MAX_SAMPLE_OUTPUT];
- float sndbufr[MAX_SAMPLE_OUTPUT];
- float outbufl[MAX_SAMPLE_OUTPUT];
- float outbufr[MAX_SAMPLE_OUTPUT];
-
- SynthProperties myProp;
-
- bool loadPreset(File *file);
- void initReverb(Bit8u newRevMode, Bit8u newRevTime, Bit8u newRevLevel);
- void doRender(Bit16s * stream, Bit32u len);
-
- void playAddressedSysex(unsigned char channel, const Bit8u *sysex, Bit32u len);
- void readSysex(unsigned char channel, const Bit8u *sysex, Bit32u len);
- void writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, const Bit8u *data);
- void readMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, Bit8u *data);
-
- bool loadControlROM(const char *filename);
- bool loadPCMROM(const char *filename);
- bool dumpTimbre(File *file, const TimbreParam *timbre, Bit32u addr);
- int dumpTimbres(const char *filename, int start, int len);
-
- bool initPCMList(Bit16u mapAddress, Bit16u count);
- bool initRhythmTimbres(Bit16u mapAddress, Bit16u count);
- bool initTimbres(Bit16u mapAddress, Bit16u offset, int startTimbre);
- bool initRhythmTimbre(int drumNum, const Bit8u *mem, unsigned int memLen);
- bool refreshSystem();
-
-protected:
- int report(ReportType type, const void *reportData);
- File *openFile(const char *filename, File::OpenMode mode);
- void closeFile(File *file);
- void printDebug(const char *fmt, ...) GCC_PRINTF(2, 3);
-
-public:
- static Bit8u calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum);
-
- Synth();
- ~Synth();
-
- // Used to initialise the MT-32. Must be called before any other function.
- // Returns true if initialization was sucessful, otherwise returns false.
- bool open(SynthProperties &useProp);
-
- // Closes the MT-32 and deallocates any memory used by the synthesizer
- void close(void);
-
- // Sends a 4-byte MIDI message to the MT-32 for immediate playback
- void playMsg(Bit32u msg);
- void playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity);
-
- // Sends a string of Sysex commands to the MT-32 for immediate interpretation
- // The length is in bytes
- void playSysex(const Bit8u *sysex, Bit32u len);
- void playSysexWithoutFraming(const Bit8u *sysex, Bit32u len);
- void playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len);
- void writeSysex(unsigned char channel, const Bit8u *sysex, Bit32u len);
-
- // This callback routine is used to have the MT-32 generate samples to the specified
- // output stream. The length is in whole samples, not bytes. (I.E. in 16-bit stereo,
- // one sample is 4 bytes)
- void render(Bit16s * stream, Bit32u len);
-
- const Partial *getPartial(unsigned int partialNum) const;
-
- void readMemory(Bit32u addr, Bit32u len, Bit8u *data);
-
- // partNum should be 0..7 for Part 1..8, or 8 for Rhythm
- const Part *getPart(unsigned int partNum) const;
-};
-
-}
-
-#endif
diff --git a/sound/softsynth/mt32/tables.cpp b/sound/softsynth/mt32/tables.cpp
deleted file mode 100644
index eba4d2a520..0000000000
--- a/sound/softsynth/mt32/tables.cpp
+++ /dev/null
@@ -1,757 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "mt32emu.h"
-
-#if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__)
-// Older versions of Mac OS X didn't supply a powf function, so using it
-// will cause a binary incompatibility when trying to run a binary built
-// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide
-// powf, floorf, fabsf etc. at all.
-// Cross-compiled MinGW32 toolchains suffer from a cross-compile bug in
-// libstdc++. math/stubs.o should be empty, but it comes with a symbol for
-// powf, resulting in a linker error because of multiple definitions.
-// Hence we re-define them here. The only potential drawback is that it
-// might be a little bit slower this way.
-#define powf(x,y) ((float)pow(x,y))
-#define floorf(x) ((float)floor(x))
-#define fabsf(x) ((float)fabs(x))
-#endif
-
-#define FIXEDPOINT_MAKE(x, point) ((Bit32u)((1 << point) * x))
-
-namespace MT32Emu {
-
-//Amplitude time velocity follow exponential coefficients
-static const double tvcatconst[5] = {0.0, 0.002791309, 0.005942882, 0.012652792, 0.026938637};
-static const double tvcatmult[5] = {1.0, 1.072662811, 1.169129367, 1.288579123, 1.229630539};
-
-// These are division constants for the TVF depth key follow
-static const Bit32u depexp[5] = {3000, 950, 485, 255, 138};
-
-//Envelope time keyfollow exponential coefficients
-static const double tkcatconst[5] = {0.0, 0.005853144, 0.011148054, 0.019086143, 0.043333215};
-static const double tkcatmult[5] = {1.0, 1.058245688, 1.048488989, 1.016049301, 1.097538067};
-
-// Begin filter stuff
-
-// Pre-warp the coefficients of a numerator or denominator.
-// Note that a0 is assumed to be 1, so there is no wrapping
-// of it.
-static void prewarp(double *a1, double *a2, double fc, double fs) {
- double wp;
-
- wp = 2.0 * fs * tan(DOUBLE_PI * fc / fs);
-
- *a2 = *a2 / (wp * wp);
- *a1 = *a1 / wp;
-}
-
-// Transform the numerator and denominator coefficients
-// of s-domain biquad section into corresponding
-// z-domain coefficients.
-//
-// Store the 4 IIR coefficients in array pointed by coef
-// in following order:
-// beta1, beta2 (denominator)
-// alpha1, alpha2 (numerator)
-//
-// Arguments:
-// a0-a2 - s-domain numerator coefficients
-// b0-b2 - s-domain denominator coefficients
-// k - filter gain factor. initially set to 1
-// and modified by each biquad section in such
-// a way, as to make it the coefficient by
-// which to multiply the overall filter gain
-// in order to achieve a desired overall filter gain,
-// specified in initial value of k.
-// fs - sampling rate (Hz)
-// coef - array of z-domain coefficients to be filled in.
-//
-// Return:
-// On return, set coef z-domain coefficients
-static void bilinear(double a0, double a1, double a2, double b0, double b1, double b2, double *k, double fs, float *coef) {
- double ad, bd;
-
- // alpha (Numerator in s-domain)
- ad = 4. * a2 * fs * fs + 2. * a1 * fs + a0;
- // beta (Denominator in s-domain)
- bd = 4. * b2 * fs * fs + 2. * b1* fs + b0;
-
- // update gain constant for this section
- *k *= ad/bd;
-
- // Denominator
- *coef++ = (float)((2. * b0 - 8. * b2 * fs * fs) / bd); // beta1
- *coef++ = (float)((4. * b2 * fs * fs - 2. * b1 * fs + b0) / bd); // beta2
-
- // Nominator
- *coef++ = (float)((2. * a0 - 8. * a2 * fs * fs) / ad); // alpha1
- *coef = (float)((4. * a2 * fs * fs - 2. * a1 * fs + a0) / ad); // alpha2
-}
-
-// a0-a2: numerator coefficients
-// b0-b2: denominator coefficients
-// fc: Filter cutoff frequency
-// fs: sampling rate
-// k: overall gain factor
-// coef: pointer to 4 iir coefficients
-static void szxform(double *a0, double *a1, double *a2, double *b0, double *b1, double *b2, double fc, double fs, double *k, float *coef) {
- // Calculate a1 and a2 and overwrite the original values
- prewarp(a1, a2, fc, fs);
- prewarp(b1, b2, fc, fs);
- bilinear(*a0, *a1, *a2, *b0, *b1, *b2, k, fs, coef);
-}
-
-static void initFilter(float fs, float fc, float *icoeff, float Q) {
- float *coef;
- double a0, a1, a2, b0, b1, b2;
-
- double k = 1.5; // Set overall filter gain factor
- coef = icoeff + 1; // Skip k, or gain
-
- // Section 1
- a0 = 1.0;
- a1 = 0;
- a2 = 0;
- b0 = 1.0;
- b1 = 0.765367 / Q; // Divide by resonance or Q
- b2 = 1.0;
- szxform(&a0, &a1, &a2, &b0, &b1, &b2, fc, fs, &k, coef);
- coef += 4; // Point to next filter section
-
- // Section 2
- a0 = 1.0;
- a1 = 0;
- a2 = 0;
- b0 = 1.0;
- b1 = 1.847759 / Q;
- b2 = 1.0;
- szxform(&a0, &a1, &a2, &b0, &b1, &b2, fc, fs, &k, coef);
-
- icoeff[0] = (float)k;
-}
-
-void Tables::initFiltCoeff(float samplerate) {
- for (int j = 0; j < FILTERGRAN; j++) {
- for (int res = 0; res < 31; res++) {
- float tres = resonanceFactor[res];
- initFilter((float)samplerate, (((float)(j+1.0)/FILTERGRAN)) * ((float)samplerate/2), filtCoeff[j][res], tres);
- }
- }
-}
-
-void Tables::initEnvelopes(float samplerate) {
- for (int lf = 0; lf <= 100; lf++) {
- float elf = (float)lf;
-
- // General envelope
- // This formula fits observation of the CM-32L by +/- 0.03s or so for the second time value in the filter,
- // when all other times were 0 and all levels were 100. Note that variations occur depending on the level
- // delta of the section, which we're not fully emulating.
- float seconds = powf(2.0f, (elf / 8.0f) + 7.0f) / 32768.0f;
- int samples = (int)(seconds * samplerate);
- envTime[lf] = samples;
-
- // Cap on envelope times depending on the level delta
- if (elf == 0) {
- envDeltaMaxTime[lf] = 63;
- } else {
- float cap = 11.0f * (float)log(elf) + 64;
- if (cap > 100.0f) {
- cap = 100.0f;
- }
- envDeltaMaxTime[lf] = (int)cap;
- }
-
-
- // This (approximately) represents the time durations when the target level is 0.
- // Not sure why this is a special case, but it's seen to be from the real thing.
- seconds = powf(2, (elf / 8.0f) + 6) / 32768.0f;
- envDecayTime[lf] = (int)(seconds * samplerate);
-
- // I am certain of this: Verified by hand LFO log
- lfoPeriod[lf] = (Bit32u)(((float)samplerate) / (powf(1.088883372f, (float)lf) * 0.021236044f));
- }
-}
-
-void Tables::initMT32ConstantTables(Synth *synth) {
- int lf;
- synth->printDebug("Initialising Pitch Tables");
- for (lf = -108; lf <= 108; lf++) {
- tvfKeyfollowMult[lf + 108] = (int)(256 * powf(2.0f, (float)(lf / 24.0f)));
- //synth->printDebug("KT %d = %d", f, keytable[f+108]);
- }
-
- for (int res = 0; res < 31; res++) {
- resonanceFactor[res] = powf((float)res / 30.0f, 5.0f) + 1.0f;
- }
-
- int period = 65536;
-
- for (int ang = 0; ang < period; ang++) {
- int halfang = (period / 2);
- int angval = ang % halfang;
- float tval = (((float)angval / (float)halfang) - 0.5f) * 2;
- if (ang >= halfang)
- tval = -tval;
- sintable[ang] = (Bit16s)(tval * 50.0f) + 50;
- }
-
- int velt, dep;
- float tempdep;
- for (velt = 0; velt < 128; velt++) {
- for (dep = 0; dep < 5; dep++) {
- if (dep > 0) {
- float ff = (float)(exp(3.5f * tvcatconst[dep] * (59.0f - (float)velt)) * tvcatmult[dep]);
- tempdep = 256.0f * ff;
- envTimeVelfollowMult[dep][velt] = (int)tempdep;
- //if ((velt % 16) == 0) {
- // synth->printDebug("Key %d, depth %d, factor %d", velt, dep, (int)tempdep);
- //}
- } else
- envTimeVelfollowMult[dep][velt] = 256;
- }
-
- for (dep = -7; dep < 8; dep++) {
- float fldep = (float)abs(dep) / 7.0f;
- fldep = powf(fldep,2.5f);
- if (dep < 0)
- fldep = fldep * -1.0f;
- pwVelfollowAdd[dep+7][velt] = Bit32s((fldep * (float)velt * 100) / 128.0);
- }
- }
-
- for (dep = 0; dep <= 100; dep++) {
- for (velt = 0; velt < 128; velt++) {
- float fdep = (float)dep * 0.000347013f; // Another MT-32 constant
- float fv = ((float)velt - 64.0f)/7.26f;
- float flogdep = powf(10, fdep * fv);
- float fbase;
-
- if (velt > 64)
- synth->tables.tvfVelfollowMult[velt][dep] = (int)(flogdep * 256.0);
- else {
- //lff = 1 - (pow(((128.0 - (float)lf) / 64.0),.25) * ((float)velt / 96));
- fbase = 1 - (powf(((float)dep / 100.0f),.25f) * ((float)(64-velt) / 96.0f));
- synth->tables.tvfVelfollowMult[velt][dep] = (int)(fbase * 256.0);
- }
- //synth->printDebug("Filvel dep %d velt %d = %x", dep, velt, filveltable[velt][dep]);
- }
- }
-
- for (lf = 0; lf < 128; lf++) {
- float veloFract = lf / 127.0f;
- for (int velsens = 0; velsens <= 100; velsens++) {
- float sensFract = (velsens - 50) / 50.0f;
- if (velsens < 50) {
- tvaVelfollowMult[lf][velsens] = FIXEDPOINT_MAKE(1.0f / powf(2.0f, veloFract * -sensFract * 127.0f / 20.0f), 8);
- } else {
- tvaVelfollowMult[lf][velsens] = FIXEDPOINT_MAKE(1.0f / powf(2.0f, (1.0f - veloFract) * sensFract * 127.0f / 20.0f), 8);
- }
- }
- }
-
- for (lf = 0; lf <= 100; lf++) {
- // Converts the 0-100 range used by the MT-32 to volume multiplier
- volumeMult[lf] = FIXEDPOINT_MAKE(powf((float)lf / 100.0f, FLOAT_LN), 7);
- }
-
- for (lf = 0; lf <= 100; lf++) {
- float mv = lf / 100.0f;
- float pt = mv - 0.5f;
- if (pt < 0)
- pt = 0;
-
- // Original (CC version)
- //pwFactor[lf] = (int)(pt * 210.04f) + 128;
-
- // Approximation from sample comparison
- pwFactor[lf] = (int)(pt * 179.0f) + 128;
- }
-
- for (unsigned int i = 0; i < MAX_SAMPLE_OUTPUT; i++) {
- int myRand;
- myRand = rand();
- //myRand = ((myRand - 16383) * 7168) >> 16;
- // This one is slower but works with all values of RAND_MAX
- myRand = (int)((myRand - RAND_MAX / 2) / (float)RAND_MAX * (7168 / 2));
- //FIXME:KG: Original ultimately set the lowest two bits to 0, for no obvious reason
- noiseBuf[i] = (Bit16s)myRand;
- }
-
- float tdist;
- float padjtable[51];
- for (lf = 0; lf <= 50; lf++) {
- if (lf == 0)
- padjtable[lf] = 7;
- else if (lf == 1)
- padjtable[lf] = 6;
- else if (lf == 2)
- padjtable[lf] = 5;
- else if (lf == 3)
- padjtable[lf] = 4;
- else if (lf == 4)
- padjtable[lf] = 4 - (0.333333f);
- else if (lf == 5)
- padjtable[lf] = 4 - (0.333333f * 2);
- else if (lf == 6)
- padjtable[lf] = 3;
- else if ((lf > 6) && (lf <= 12)) {
- tdist = (lf-6.0f) / 6.0f;
- padjtable[lf] = 3.0f - tdist;
- } else if ((lf > 12) && (lf <= 25)) {
- tdist = (lf - 12.0f) / 13.0f;
- padjtable[lf] = 2.0f - tdist;
- } else {
- tdist = (lf - 25.0f) / 25.0f;
- padjtable[lf] = 1.0f - tdist;
- }
- //synth->printDebug("lf %d = padj %f", lf, (double)padjtable[lf]);
- }
-
- float lfp, depf, finalval, tlf;
- int depat, pval, depti;
- for (lf = 0; lf <= 10; lf++) {
- // I believe the depth is cubed or something
-
- for (depat = 0; depat <= 100; depat++) {
- if (lf > 0) {
- depti = abs(depat - 50);
- tlf = (float)lf - padjtable[depti];
- if (tlf < 0)
- tlf = 0;
- lfp = (float)exp(0.713619942f * tlf) / 407.4945111f;
-
- if (depat < 50)
- finalval = 4096.0f * powf(2, -lfp);
- else
- finalval = 4096.0f * powf(2, lfp);
- pval = (int)finalval;
-
- pitchEnvVal[lf][depat] = pval;
- //synth->printDebug("lf %d depat %d pval %d tlf %f lfp %f", lf,depat,pval, (double)tlf, (double)lfp);
- } else {
- pitchEnvVal[lf][depat] = 4096;
- //synth->printDebug("lf %d depat %d pval 4096", lf, depat);
- }
- }
- }
- for (lf = 0; lf <= 100; lf++) {
- // It's linear - verified on MT-32 - one of the few things linear
- lfp = ((float)lf * 0.1904f) / 310.55f;
-
- for (depat = 0; depat <= 100; depat++) {
- depf = ((float)depat - 50.0f) / 50.0f;
- //finalval = pow(2, lfp * depf * .5);
- finalval = 4096.0f + (4096.0f * lfp * depf);
-
- pval = (int)finalval;
-
- lfoShift[lf][depat] = pval;
-
- //synth->printDebug("lf %d depat %d pval %x", lf,depat,pval);
- }
- }
-
- for (lf = 0; lf <= 12; lf++) {
- for (int distval = 0; distval < 128; distval++) {
- float amplog, dval;
- if (lf == 0) {
- amplog = 0;
- dval = 1;
- tvaBiasMult[lf][distval] = 256;
- } else {
- /*
- amplog = powf(1.431817011f, (float)lf) / FLOAT_PI;
- dval = ((128.0f - (float)distval) / 128.0f);
- amplog = exp(amplog);
- dval = powf(amplog, dval) / amplog;
- tvaBiasMult[lf][distval] = (int)(dval * 256.0);
- */
- // Lets assume for a second it's linear
-
- // Distance of full volume reduction
- amplog = (float)(12.0f / (float)lf) * 24.0f;
- if (distval > amplog) {
- tvaBiasMult[lf][distval] = 0;
- } else {
- dval = (amplog - (float)distval) / amplog;
- tvaBiasMult[lf][distval] = (int)(dval * 256.0f);
- }
- }
- //synth->printDebug("Ampbias lf %d distval %d = %f (%x) %f", lf, distval, (double)dval, tvaBiasMult[lf][distval],(double)amplog);
- }
- }
-
- for (lf = 0; lf <= 14; lf++) {
- for (int distval = 0; distval < 128; distval++) {
- float filval = fabsf((float)((lf - 7) * 12) / 7.0f);
- float amplog, dval;
- if (lf == 7) {
- amplog = 0;
- dval = 1;
- tvfBiasMult[lf][distval] = 256;
- } else {
- //amplog = pow(1.431817011, filval) / FLOAT_PI;
- amplog = powf(1.531817011f, filval) / FLOAT_PI;
- dval = (128.0f - (float)distval) / 128.0f;
- amplog = (float)exp(amplog);
- dval = powf(amplog,dval)/amplog;
- if (lf < 8) {
- tvfBiasMult[lf][distval] = (int)(dval * 256.0f);
- } else {
- dval = powf(dval, 0.3333333f);
- if (dval < 0.01f)
- dval = 0.01f;
- dval = 1 / dval;
- tvfBiasMult[lf][distval] = (int)(dval * 256.0f);
- }
- }
- //synth->printDebug("Fbias lf %d distval %d = %f (%x) %f", lf, distval, (double)dval, tvfBiasMult[lf][distval],(double)amplog);
- }
- }
-}
-
-// Per-note table initialisation follows
-
-static void initSaw(NoteLookup *noteLookup, Bit32s div2) {
- int tmpdiv = div2 << 16;
- for (int rsaw = 0; rsaw <= 100; rsaw++) {
- float fsaw;
- if (rsaw < 50)
- fsaw = 50.0f;
- else
- fsaw = (float)rsaw;
-
- //(66 - (((A8 - 50) / 50) ^ 0.63) * 50) / 132
- float sawfact = (66.0f - (powf((fsaw - 50.0f) / 50.0f, 0.63f) * 50.0f)) / 132.0f;
- noteLookup->sawTable[rsaw] = (int)(sawfact * (float)tmpdiv) >> 16;
- //synth->printDebug("F %d divtable %d saw %d sawtable %d", f, div, rsaw, sawtable[f][rsaw]);
- }
-}
-
-static void initDep(KeyLookup *keyLookup, float f) {
- for (int dep = 0; dep < 5; dep++) {
- if (dep == 0) {
- keyLookup->envDepthMult[dep] = 256;
- keyLookup->envTimeMult[dep] = 256;
- } else {
- float depfac = 3000.0f;
- float ff, tempdep;
- depfac = (float)depexp[dep];
-
- ff = (f - (float)MIDDLEC) / depfac;
- tempdep = powf(2, ff) * 256.0f;
- keyLookup->envDepthMult[dep] = (int)tempdep;
-
- ff = (float)(exp(tkcatconst[dep] * ((float)MIDDLEC - f)) * tkcatmult[dep]);
- keyLookup->envTimeMult[dep] = (int)(ff * 256.0f);
- }
- }
- //synth->printDebug("F %f d1 %x d2 %x d3 %x d4 %x d5 %x", (double)f, noteLookup->fildepTable[0], noteLookup->fildepTable[1], noteLookup->fildepTable[2], noteLookup->fildepTable[3], noteLookup->fildepTable[4]);
-}
-
-Bit16s Tables::clampWF(Synth *synth, const char *n, float ampVal, double input) {
- Bit32s x = (Bit32s)(input * ampVal);
- if (x < -ampVal - 1) {
- synth->printDebug("%s==%d<-WGAMP-1!", n, x);
- x = (Bit32s)(-ampVal - 1);
- } else if (x > ampVal) {
- synth->printDebug("%s==%d>WGAMP!", n, x);
- x = (Bit32s)ampVal;
- }
- return (Bit16s)x;
-}
-
-File *Tables::initWave(Synth *synth, NoteLookup *noteLookup, float ampVal, float div2, File *file) {
- int iDiv2 = (int)div2;
- noteLookup->waveformSize[0] = iDiv2 << 1;
- noteLookup->waveformSize[1] = iDiv2 << 1;
- noteLookup->waveformSize[2] = iDiv2 << 2;
- for (int i = 0; i < 3; i++) {
- if (noteLookup->waveforms[i] == NULL) {
- noteLookup->waveforms[i] = new Bit16s[noteLookup->waveformSize[i]];
- }
- }
- if (file != NULL) {
- for (int i = 0; i < 3 && file != NULL; i++) {
- size_t len = noteLookup->waveformSize[i];
- for (unsigned int j = 0; j < len; j++) {
- if (!file->readBit16u((Bit16u *)&noteLookup->waveforms[i][j])) {
- synth->printDebug("Error reading wave file cache!");
- file->close();
- file = NULL;
- break;
- }
- }
- }
- }
- if (file == NULL) {
- double sd = DOUBLE_PI / div2;
-
- for (int fa = 0; fa < (iDiv2 << 1); fa++) {
- // sa ranges from 0 to 2PI
- double sa = fa * sd;
-
- // Calculate a sample for the bandlimited sawtooth wave
- double saw = 0.0;
- int sincs = iDiv2 >> 1;
- double sinus = 1.0;
- for (int sincNum = 1; sincNum <= sincs; sincNum++) {
- saw += sin(sinus * sa) / sinus;
- sinus++;
- }
-
- // This works pretty well
- // Multiplied by 0.84 so that the spikes caused by bandlimiting don't overdrive the amplitude
- noteLookup->waveforms[0][fa] = clampWF(synth, "saw", ampVal, -saw / (0.5 * DOUBLE_PI) * 0.84);
- noteLookup->waveforms[1][fa] = clampWF(synth, "cos", ampVal, -cos(sa / 2.0));
- noteLookup->waveforms[2][fa * 2] = clampWF(synth, "cosoff_0", ampVal, -cos(sa - DOUBLE_PI));
- noteLookup->waveforms[2][fa * 2 + 1] = clampWF(synth, "cosoff_1", ampVal, -cos((sa + (sd / 2)) - DOUBLE_PI));
- }
- }
- return file;
-}
-
-static void initFiltTable(NoteLookup *noteLookup, float freq, float rate) {
- for (int tr = 0; tr <= 200; tr++) {
- float ftr = (float)tr;
-
- // Verified exact on MT-32
- if (tr > 100)
- ftr = 100.0f + (powf((ftr - 100.0f) / 100.0f, 3.0f) * 100.0f);
-
- // I think this is the one
- float brsq = powf(10.0f, (tr / 50.0f) - 1.0f);
- noteLookup->filtTable[0][tr] = (int)((freq * brsq) / (rate / 2) * FILTERGRAN);
- if (noteLookup->filtTable[0][tr]>=((FILTERGRAN*15)/16))
- noteLookup->filtTable[0][tr] = ((FILTERGRAN*15)/16);
-
- float brsa = powf(10.0f, ((tr / 55.0f) - 1.0f)) / 2.0f;
- noteLookup->filtTable[1][tr] = (int)((freq * brsa) / (rate / 2) * FILTERGRAN);
- if (noteLookup->filtTable[1][tr]>=((FILTERGRAN*15)/16))
- noteLookup->filtTable[1][tr] = ((FILTERGRAN*15)/16);
- }
-}
-
-static void initNFiltTable(NoteLookup *noteLookup, float freq, float rate) {
- for (int cf = 0; cf <= 100; cf++) {
- float cfmult = (float)cf;
-
- for (int tf = 0;tf <= 100; tf++) {
- float tfadd = (float)tf;
-
- //float freqsum = exp((cfmult + tfadd) / 30.0f) / 4.0f;
- //float freqsum = 0.15f * exp(0.45f * ((cfmult + tfadd) / 10.0f));
-
- float freqsum = powf(2.0f, ((cfmult + tfadd) - 40.0f) / 16.0f);
-
- noteLookup->nfiltTable[cf][tf] = (int)((freq * freqsum) / (rate / 2) * FILTERGRAN);
- if (noteLookup->nfiltTable[cf][tf] >= ((FILTERGRAN * 15) / 16))
- noteLookup->nfiltTable[cf][tf] = ((FILTERGRAN * 15) / 16);
- }
- }
-}
-
-File *Tables::initNote(Synth *synth, NoteLookup *noteLookup, float note, float rate, float masterTune, PCMWaveEntry *pcmWaves, File *file) {
- float freq = (float)(masterTune * pow(2.0, ((double)note - MIDDLEA) / 12.0));
- float div2 = rate * 2.0f / freq;
- noteLookup->div2 = (int)div2;
-
- if (noteLookup->div2 == 0)
- noteLookup->div2 = 1;
-
- initSaw(noteLookup, noteLookup->div2);
-
- //synth->printDebug("Note %f; freq=%f, div=%f", (double)note, (double)freq, (double) rate / freq);
- file = initWave(synth, noteLookup, WGAMP, div2, file);
-
- // Create the pitch tables
- if (noteLookup->wavTable == NULL)
- noteLookup->wavTable = new Bit32u[synth->controlROMMap->pcmCount];
- double rateMult = 32000.0 / rate;
- double tuner = freq * 65536.0f;
- for (int pc = 0; pc < synth->controlROMMap->pcmCount; pc++) {
- noteLookup->wavTable[pc] = (int)(tuner / pcmWaves[pc].tune * rateMult);
- }
-
- initFiltTable(noteLookup, freq, rate);
- initNFiltTable(noteLookup, freq, rate);
- return file;
-}
-
-bool Tables::initNotes(Synth *synth, PCMWaveEntry *pcmWaves, float rate, float masterTune) {
- const char *NoteNames[12] = {
- "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B "
- };
- char filename[64];
- int intRate = (int)rate;
- char version[4] = {0, 0, 0, 5};
- sprintf(filename, "waveformcache-%d-%.2f.raw", intRate, (double)masterTune);
-
- File *file = NULL;
- char header[20];
- memcpy(header, "MT32WAVE", 8);
- int pos = 8;
- // Version...
- for (int i = 0; i < 4; i++)
- header[pos++] = version[i];
- header[pos++] = (char)((intRate >> 24) & 0xFF);
- header[pos++] = (char)((intRate >> 16) & 0xFF);
- header[pos++] = (char)((intRate >> 8) & 0xFF);
- header[pos++] = (char)(intRate & 0xFF);
- int intTuning = (int)masterTune;
- header[pos++] = (char)((intTuning >> 8) & 0xFF);
- header[pos++] = (char)(intTuning & 0xFF);
- header[pos++] = 0;
- header[pos] = (char)((masterTune - intTuning) * 10);
-#if MT32EMU_WAVECACHEMODE < 2
- bool reading = false;
- file = synth->openFile(filename, File::OpenMode_read);
- if (file != NULL) {
- char fileHeader[20];
- if (file->read(fileHeader, 20) == 20) {
- if (memcmp(fileHeader, header, 20) == 0) {
- Bit16u endianCheck;
- if (file->readBit16u(&endianCheck)) {
- if (endianCheck == 1) {
- reading = true;
- } else {
- synth->printDebug("Endian check in %s does not match expected", filename);
- }
- } else {
- synth->printDebug("Unable to read endian check in %s", filename);
- }
- } else {
- synth->printDebug("Header of %s does not match expected", filename);
- }
- } else {
- synth->printDebug("Error reading 16 bytes of %s", filename);
- }
- if (!reading) {
- file->close();
- file = NULL;
- }
- } else {
- synth->printDebug("Unable to open %s for reading", filename);
- }
-#endif
-
- float progress = 0.0f;
- bool abort = false;
- synth->report(ReportType_progressInit, &progress);
- for (int f = LOWEST_NOTE; f <= HIGHEST_NOTE; f++) {
- synth->printDebug("Initialising note %s%d", NoteNames[f % 12], (f / 12) - 2);
- NoteLookup *noteLookup = &noteLookups[f - LOWEST_NOTE];
- file = initNote(synth, noteLookup, (float)f, rate, masterTune, pcmWaves, file);
- progress = (f - LOWEST_NOTE + 1) / (float)NUM_NOTES;
- abort = synth->report(ReportType_progressInit, &progress) != 0;
- if (abort)
- break;
- }
-
-#if MT32EMU_WAVECACHEMODE == 0 || MT32EMU_WAVECACHEMODE == 2
- if (file == NULL) {
- file = synth->openFile(filename, File::OpenMode_write);
- if (file != NULL) {
- if (file->write(header, 20) == 20 && file->writeBit16u(1)) {
- for (int f = 0; f < NUM_NOTES; f++) {
- for (int i = 0; i < 3 && file != NULL; i++) {
- int len = noteLookups[f].waveformSize[i];
- for (int j = 0; j < len; j++) {
- if (!file->writeBit16u(noteLookups[f].waveforms[i][j])) {
- synth->printDebug("Error writing waveform cache file");
- file->close();
- file = NULL;
- break;
- }
- }
- }
- }
- } else {
- synth->printDebug("Error writing 16-byte header to %s - won't continue saving", filename);
- }
- } else {
- synth->printDebug("Unable to open %s for writing - won't be created", filename);
- }
- }
-#endif
-
- if (file != NULL)
- synth->closeFile(file);
- return !abort;
-}
-
-void Tables::freeNotes() {
- for (int t = 0; t < 3; t++) {
- for (int m = 0; m < NUM_NOTES; m++) {
- if (noteLookups[m].waveforms[t] != NULL) {
- delete[] noteLookups[m].waveforms[t];
- noteLookups[m].waveforms[t] = NULL;
- noteLookups[m].waveformSize[t] = 0;
- }
- if (noteLookups[m].wavTable != NULL) {
- delete[] noteLookups[m].wavTable;
- noteLookups[m].wavTable = NULL;
- }
- }
- }
- initialisedMasterTune = 0.0f;
-}
-
-Tables::Tables() {
- initialisedSampleRate = 0.0f;
- initialisedMasterTune = 0.0f;
- memset(&noteLookups, 0, sizeof(noteLookups));
-}
-
-bool Tables::init(Synth *synth, PCMWaveEntry *pcmWaves, float sampleRate, float masterTune) {
- if (sampleRate <= 0.0f) {
- synth->printDebug("Bad sampleRate (%f <= 0.0f)", (double)sampleRate);
- return false;
- }
- if (initialisedSampleRate == 0.0f) {
- initMT32ConstantTables(synth);
- }
- if (initialisedSampleRate != sampleRate) {
- initFiltCoeff(sampleRate);
- initEnvelopes(sampleRate);
- for (int key = 12; key <= 108; key++) {
- initDep(&keyLookups[key - 12], (float)key);
- }
- }
- if (initialisedSampleRate != sampleRate || initialisedMasterTune != masterTune) {
- freeNotes();
- if (!initNotes(synth, pcmWaves, sampleRate, masterTune)) {
- return false;
- }
- initialisedSampleRate = sampleRate;
- initialisedMasterTune = masterTune;
- }
- return true;
-}
-
-}
diff --git a/sound/softsynth/mt32/tables.h b/sound/softsynth/mt32/tables.h
deleted file mode 100644
index d9af5114b2..0000000000
--- a/sound/softsynth/mt32/tables.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (c) 2003-2005 Various contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef MT32EMU_TABLES_H
-#define MT32EMU_TABLES_H
-
-namespace MT32Emu {
-
-// Mathematical constants
-const double DOUBLE_PI = 3.1415926535897932384626433832795;
-const double DOUBLE_LN = 2.3025850929940456840179914546844;
-const float FLOAT_PI = 3.1415926535897932384626433832795f;
-const float FLOAT_LN = 2.3025850929940456840179914546844f;
-
-// Filter settings
-const int FILTERGRAN = 512;
-
-// Amplitude of waveform generator
-// FIXME: This value is the amplitude possible whilst avoiding
-// overdriven values immediately after filtering when playing
-// back SQ3MT.MID. Needs to be checked.
-const int WGAMP = 12382;
-
-const int MIDDLEC = 60;
-const int MIDDLEA = 69; // By this I mean "A above middle C"
-
-// FIXME:KG: may only need to do 12 to 108
-// 12..108 is the range allowed by note on commands, but the key can be modified by pitch keyfollow
-// and adjustment for timbre pitch, so the results can be outside that range.
-// Should we move it (by octave) into the 12..108 range, or keep it in 0..127 range,
-// or something else altogether?
-const int LOWEST_NOTE = 12;
-const int HIGHEST_NOTE = 127;
-const int NUM_NOTES = HIGHEST_NOTE - LOWEST_NOTE + 1; // Number of slots for note LUT
-
-class Synth;
-
-struct NoteLookup {
- Bit32u div2;
- Bit32u *wavTable;
- Bit32s sawTable[101];
- int filtTable[2][201];
- int nfiltTable[101][101];
- Bit16s *waveforms[3];
- Bit32u waveformSize[3];
-};
-
-struct KeyLookup {
- Bit32s envTimeMult[5]; // For envelope time adjustment for key pressed
- Bit32s envDepthMult[5];
-};
-
-class Tables {
- float initialisedSampleRate;
- float initialisedMasterTune;
- void initMT32ConstantTables(Synth *synth);
- static Bit16s clampWF(Synth *synth, const char *n, float ampVal, double input);
- static File *initWave(Synth *synth, NoteLookup *noteLookup, float ampsize, float div2, File *file);
- bool initNotes(Synth *synth, PCMWaveEntry *pcmWaves, float rate, float tuning);
- void initEnvelopes(float sampleRate);
- void initFiltCoeff(float samplerate);
-public:
- // Constant LUTs
- Bit32s tvfKeyfollowMult[217];
- Bit32s tvfVelfollowMult[128][101];
- Bit32s tvfBiasMult[15][128];
- Bit32u tvaVelfollowMult[128][101];
- Bit32s tvaBiasMult[13][128];
- Bit16s noiseBuf[MAX_SAMPLE_OUTPUT];
- Bit16s sintable[65536];
- Bit32s pitchEnvVal[16][101];
- Bit32s envTimeVelfollowMult[5][128];
- Bit32s pwVelfollowAdd[15][128];
- float resonanceFactor[31];
- Bit32u lfoShift[101][101];
- Bit32s pwFactor[101];
- Bit32s volumeMult[101];
-
- // LUTs varying with sample rate
- Bit32u envTime[101];
- Bit32u envDeltaMaxTime[101];
- Bit32u envDecayTime[101];
- Bit32u lfoPeriod[101];
- float filtCoeff[FILTERGRAN][31][8];
-
- // Various LUTs for each note and key
- NoteLookup noteLookups[NUM_NOTES];
- KeyLookup keyLookups[97];
-
- Tables();
- bool init(Synth *synth, PCMWaveEntry *pcmWaves, float sampleRate, float masterTune);
- File *initNote(Synth *synth, NoteLookup *noteLookup, float note, float rate, float tuning, PCMWaveEntry *pcmWaves, File *file);
- void freeNotes();
-};
-
-}
-
-#endif
diff --git a/sound/softsynth/opl/dbopl.cpp b/sound/softsynth/opl/dbopl.cpp
deleted file mode 100644
index 47e263b6b9..0000000000
--- a/sound/softsynth/opl/dbopl.cpp
+++ /dev/null
@@ -1,1536 +0,0 @@
-/*
- * Copyright (C) 2002-2010 The DOSBox Team
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator.
- Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2
- Except for the table generation it's all integer math
- Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms
- The generation was based on the MAME implementation but tried to have it use less memory and be faster in general
- MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times
-
- //TODO Don't delay first operator 1 sample in opl3 mode
- //TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter
- //TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though?
- //TODO Check if having the same accuracy in all frequency multipliers sounds better or not
-
- //DUNNO Keyon in 4op, switch to 2op without keyoff.
-*/
-
-// Last synch with DOSBox SVN trunk r3556
-
-#include "dbopl.h"
-
-#ifndef DISABLE_DOSBOX_OPL
-
-namespace OPL {
-namespace DOSBox {
-
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-namespace DBOPL {
-
-#define OPLRATE ((double)(14318180.0 / 288.0))
-#define TREMOLO_TABLE 52
-
-//Try to use most precision for frequencies
-//Else try to keep different waves in synch
-//#define WAVE_PRECISION 1
-#ifndef WAVE_PRECISION
-//Wave bits available in the top of the 32bit range
-//Original adlib uses 10.10, we use 10.22
-#define WAVE_BITS 10
-#else
-//Need some extra bits at the top to have room for octaves and frequency multiplier
-//We support to 8 times lower rate
-//128 * 15 * 8 = 15350, 2^13.9, so need 14 bits
-#define WAVE_BITS 14
-#endif
-#define WAVE_SH ( 32 - WAVE_BITS )
-#define WAVE_MASK ( ( 1 << WAVE_SH ) - 1 )
-
-//Use the same accuracy as the waves
-#define LFO_SH ( WAVE_SH - 10 )
-//LFO is controlled by our tremolo 256 sample limit
-#define LFO_MAX ( 256 << ( LFO_SH ) )
-
-
-//Maximum amount of attenuation bits
-//Envelope goes to 511, 9 bits
-#if (DBOPL_WAVE == WAVE_TABLEMUL )
-//Uses the value directly
-#define ENV_BITS ( 9 )
-#else
-//Add 3 bits here for more accuracy and would have to be shifted up either way
-#define ENV_BITS ( 9 )
-#endif
-//Limits of the envelope with those bits and when the envelope goes silent
-#define ENV_MIN 0
-#define ENV_EXTRA ( ENV_BITS - 9 )
-#define ENV_MAX ( 511 << ENV_EXTRA )
-#define ENV_LIMIT ( ( 12 * 256) >> ( 3 - ENV_EXTRA ) )
-#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT )
-
-//Attack/decay/release rate counter shift
-#define RATE_SH 24
-#define RATE_MASK ( ( 1 << RATE_SH ) - 1 )
-//Has to fit within 16bit lookuptable
-#define MUL_SH 16
-
-//Check some ranges
-#if ENV_EXTRA > 3
-#error Too many envelope bits
-#endif
-
-
-//How much to substract from the base value for the final attenuation
-static const Bit8u KslCreateTable[16] = {
- //0 will always be be lower than 7 * 8
- 64, 32, 24, 19,
- 16, 12, 11, 10,
- 8, 6, 5, 4,
- 3, 2, 1, 0,
-};
-
-#define M(_X_) ((Bit8u)( (_X_) * 2))
-static const Bit8u FreqCreateTable[16] = {
- M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ),
- M(8 ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15)
-};
-#undef M
-
-//We're not including the highest attack rate, that gets a special value
-static const Bit8u AttackSamplesTable[13] = {
- 69, 55, 46, 40,
- 35, 29, 23, 20,
- 19, 15, 11, 10,
- 9
-};
-//On a real opl these values take 8 samples to reach and are based upon larger tables
-static const Bit8u EnvelopeIncreaseTable[13] = {
- 4, 5, 6, 7,
- 8, 10, 12, 14,
- 16, 20, 24, 28,
- 32,
-};
-
-#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
-static Bit16u ExpTable[ 256 ];
-#endif
-
-#if ( DBOPL_WAVE == WAVE_HANDLER )
-//PI table used by WAVEHANDLER
-static Bit16u SinTable[ 512 ];
-#endif
-
-#if ( DBOPL_WAVE > WAVE_HANDLER )
-//Layout of the waveform table in 512 entry intervals
-//With overlapping waves we reduce the table to half it's size
-
-// | |//\\|____|WAV7|//__|/\ |____|/\/\|
-// |\\//| | |WAV7| | \/| | |
-// |06 |0126|17 |7 |3 |4 |4 5 |5 |
-
-//6 is just 0 shifted and masked
-
-static Bit16s WaveTable[ 8 * 512 ];
-//Distance into WaveTable the wave starts
-static const Bit16u WaveBaseTable[8] = {
- 0x000, 0x200, 0x200, 0x800,
- 0xa00, 0xc00, 0x100, 0x400,
-
-};
-//Mask the counter with this
-static const Bit16u WaveMaskTable[8] = {
- 1023, 1023, 511, 511,
- 1023, 1023, 512, 1023,
-};
-
-//Where to start the counter on at keyon
-static const Bit16u WaveStartTable[8] = {
- 512, 0, 0, 0,
- 0, 512, 512, 256,
-};
-#endif
-
-#if ( DBOPL_WAVE == WAVE_TABLEMUL )
-static Bit16u MulTable[ 384 ];
-#endif
-
-static Bit8u KslTable[ 8 * 16 ];
-static Bit8u TremoloTable[ TREMOLO_TABLE ];
-//Start of a channel behind the chip struct start
-static Bit16u ChanOffsetTable[32];
-//Start of an operator behind the chip struct start
-static Bit16u OpOffsetTable[64];
-
-//The lower bits are the shift of the operator vibrato value
-//The highest bit is right shifted to generate -1 or 0 for negation
-//So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0
-static const Bit8s VibratoTable[ 8 ] = {
- 1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00,
- 1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80
-};
-
-//Shift strength for the ksl value determined by ksl strength
-static const Bit8u KslShiftTable[4] = {
- 31,1,2,0
-};
-
-//Generate a table index and table shift value using input value from a selected rate
-static void EnvelopeSelect( Bit8u val, Bit8u& index, Bit8u& shift ) {
- if ( val < 13 * 4 ) { //Rate 0 - 12
- shift = 12 - ( val >> 2 );
- index = val & 3;
- } else if ( val < 15 * 4 ) { //rate 13 - 14
- shift = 0;
- index = val - 12 * 4;
- } else { //rate 15 and up
- shift = 0;
- index = 12;
- }
-}
-
-#if ( DBOPL_WAVE == WAVE_HANDLER )
-/*
- Generate the different waveforms out of the sine/exponetial table using handlers
-*/
-static inline Bits MakeVolume( Bitu wave, Bitu volume ) {
- Bitu total = wave + volume;
- Bitu index = total & 0xff;
- Bitu sig = ExpTable[ index ];
- Bitu exp = total >> 8;
-#if 0
- //Check if we overflow the 31 shift limit
- if ( exp >= 32 ) {
- LOG_MSG( "WTF %d %d", total, exp );
- }
-#endif
- return (sig >> exp);
-}
-
-static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) {
- Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
- Bitu wave = SinTable[i & 511];
- return (MakeVolume( wave, volume ) ^ neg) - neg;
-}
-static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) {
- Bit32u wave = SinTable[i & 511];
- wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
- return MakeVolume( wave, volume );
-}
-static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) {
- Bitu wave = SinTable[i & 511];
- return MakeVolume( wave, volume );
-}
-static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) {
- Bitu wave = SinTable[i & 255];
- wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 );
- return MakeVolume( wave, volume );
-}
-static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) {
- //Twice as fast
- i <<= 1;
- Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
- Bitu wave = SinTable[i & 511];
- wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
- return (MakeVolume( wave, volume ) ^ neg) - neg;
-}
-static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) {
- //Twice as fast
- i <<= 1;
- Bitu wave = SinTable[i & 511];
- wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
- return MakeVolume( wave, volume );
-}
-static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) {
- Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
- return (MakeVolume( 0, volume ) ^ neg) - neg;
-}
-static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) {
- //Negative is reversed here
- Bits neg = (( i >> 9) & 1) - 1;
- Bitu wave = (i << 3);
- //When negative the volume also runs backwards
- wave = ((wave ^ neg) - neg) & 4095;
- return (MakeVolume( wave, volume ) ^ neg) - neg;
-}
-
-static const WaveHandler WaveHandlerTable[8] = {
- WaveForm0, WaveForm1, WaveForm2, WaveForm3,
- WaveForm4, WaveForm5, WaveForm6, WaveForm7
-};
-
-#endif
-
-/*
- Operator
-*/
-
-//We zero out when rate == 0
-inline void Operator::UpdateAttack( const Chip* chip ) {
- Bit8u rate = reg60 >> 4;
- if ( rate ) {
- Bit8u val = (rate << 2) + ksr;
- attackAdd = chip->attackRates[ val ];
- rateZero &= ~(1 << ATTACK);
- } else {
- attackAdd = 0;
- rateZero |= (1 << ATTACK);
- }
-}
-inline void Operator::UpdateDecay( const Chip* chip ) {
- Bit8u rate = reg60 & 0xf;
- if ( rate ) {
- Bit8u val = (rate << 2) + ksr;
- decayAdd = chip->linearRates[ val ];
- rateZero &= ~(1 << DECAY);
- } else {
- decayAdd = 0;
- rateZero |= (1 << DECAY);
- }
-}
-inline void Operator::UpdateRelease( const Chip* chip ) {
- Bit8u rate = reg80 & 0xf;
- if ( rate ) {
- Bit8u val = (rate << 2) + ksr;
- releaseAdd = chip->linearRates[ val ];
- rateZero &= ~(1 << RELEASE);
- if ( !(reg20 & MASK_SUSTAIN ) ) {
- rateZero &= ~( 1 << SUSTAIN );
- }
- } else {
- rateZero |= (1 << RELEASE);
- releaseAdd = 0;
- if ( !(reg20 & MASK_SUSTAIN ) ) {
- rateZero |= ( 1 << SUSTAIN );
- }
- }
-}
-
-inline void Operator::UpdateAttenuation( ) {
- Bit8u kslBase = (Bit8u)((chanData >> SHIFT_KSLBASE) & 0xff);
- Bit32u tl = reg40 & 0x3f;
- Bit8u kslShift = KslShiftTable[ reg40 >> 6 ];
- //Make sure the attenuation goes to the right bits
- totalLevel = tl << ( ENV_BITS - 7 ); //Total level goes 2 bits below max
- totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift;
-}
-
-void Operator::UpdateFrequency( ) {
- Bit32u freq = chanData & (( 1 << 10 ) - 1);
- Bit32u block = (chanData >> 10) & 0xff;
-#ifdef WAVE_PRECISION
- block = 7 - block;
- waveAdd = ( freq * freqMul ) >> block;
-#else
- waveAdd = ( freq << block ) * freqMul;
-#endif
- if ( reg20 & MASK_VIBRATO ) {
- vibStrength = (Bit8u)(freq >> 7);
-
-#ifdef WAVE_PRECISION
- vibrato = ( vibStrength * freqMul ) >> block;
-#else
- vibrato = ( vibStrength << block ) * freqMul;
-#endif
- } else {
- vibStrength = 0;
- vibrato = 0;
- }
-}
-
-void Operator::UpdateRates( const Chip* chip ) {
- //Mame seems to reverse this where enabling ksr actually lowers
- //the rate, but pdf manuals says otherwise?
- Bit8u newKsr = (Bit8u)((chanData >> SHIFT_KEYCODE) & 0xff);
- if ( !( reg20 & MASK_KSR ) ) {
- newKsr >>= 2;
- }
- if ( ksr == newKsr )
- return;
- ksr = newKsr;
- UpdateAttack( chip );
- UpdateDecay( chip );
- UpdateRelease( chip );
-}
-
-INLINE Bit32s Operator::RateForward( Bit32u add ) {
- rateIndex += add;
- Bit32s ret = rateIndex >> RATE_SH;
- rateIndex = rateIndex & RATE_MASK;
- return ret;
-}
-
-template< Operator::State yes>
-Bits Operator::TemplateVolume( ) {
- Bit32s vol = volume;
- Bit32s change;
- switch ( yes ) {
- case OFF:
- return ENV_MAX;
- case ATTACK:
- change = RateForward( attackAdd );
- if ( !change )
- return vol;
- vol += ( (~vol) * change ) >> 3;
- if ( vol < ENV_MIN ) {
- volume = ENV_MIN;
- rateIndex = 0;
- SetState( DECAY );
- return ENV_MIN;
- }
- break;
- case DECAY:
- vol += RateForward( decayAdd );
- if ( GCC_UNLIKELY(vol >= sustainLevel) ) {
- //Check if we didn't overshoot max attenuation, then just go off
- if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
- volume = ENV_MAX;
- SetState( OFF );
- return ENV_MAX;
- }
- //Continue as sustain
- rateIndex = 0;
- SetState( SUSTAIN );
- }
- break;
- case SUSTAIN:
- if ( reg20 & MASK_SUSTAIN ) {
- return vol;
- }
- //In sustain phase, but not sustaining, do regular release
- case RELEASE:
- vol += RateForward( releaseAdd );
- if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
- volume = ENV_MAX;
- SetState( OFF );
- return ENV_MAX;
- }
- break;
- }
- volume = vol;
- return vol;
-}
-
-static const VolumeHandler VolumeHandlerTable[5] = {
- &Operator::TemplateVolume< Operator::OFF >,
- &Operator::TemplateVolume< Operator::RELEASE >,
- &Operator::TemplateVolume< Operator::SUSTAIN >,
- &Operator::TemplateVolume< Operator::DECAY >,
- &Operator::TemplateVolume< Operator::ATTACK >
-};
-
-INLINE Bitu Operator::ForwardVolume() {
- return currentLevel + (this->*volHandler)();
-}
-
-
-INLINE Bitu Operator::ForwardWave() {
- waveIndex += waveCurrent;
- return waveIndex >> WAVE_SH;
-}
-
-void Operator::Write20( const Chip* chip, Bit8u val ) {
- Bit8u change = (reg20 ^ val );
- if ( !change )
- return;
- reg20 = val;
- //Shift the tremolo bit over the entire register, saved a branch, YES!
- tremoloMask = (Bit8s)(val) >> 7;
- tremoloMask &= ~(( 1 << ENV_EXTRA ) -1);
- //Update specific features based on changes
- if ( change & MASK_KSR ) {
- UpdateRates( chip );
- }
- //With sustain enable the volume doesn't change
- if ( reg20 & MASK_SUSTAIN || ( !releaseAdd ) ) {
- rateZero |= ( 1 << SUSTAIN );
- } else {
- rateZero &= ~( 1 << SUSTAIN );
- }
- //Frequency multiplier or vibrato changed
- if ( change & (0xf | MASK_VIBRATO) ) {
- freqMul = chip->freqMul[ val & 0xf ];
- UpdateFrequency();
- }
-}
-
-void Operator::Write40( const Chip* /*chip*/, Bit8u val ) {
- if (!(reg40 ^ val ))
- return;
- reg40 = val;
- UpdateAttenuation( );
-}
-
-void Operator::Write60( const Chip* chip, Bit8u val ) {
- Bit8u change = reg60 ^ val;
- reg60 = val;
- if ( change & 0x0f ) {
- UpdateDecay( chip );
- }
- if ( change & 0xf0 ) {
- UpdateAttack( chip );
- }
-}
-
-void Operator::Write80( const Chip* chip, Bit8u val ) {
- Bit8u change = (reg80 ^ val );
- if ( !change )
- return;
- reg80 = val;
- Bit8u sustain = val >> 4;
- //Turn 0xf into 0x1f
- sustain |= ( sustain + 1) & 0x10;
- sustainLevel = sustain << ( ENV_BITS - 5 );
- if ( change & 0x0f ) {
- UpdateRelease( chip );
- }
-}
-
-void Operator::WriteE0( const Chip* chip, Bit8u val ) {
- if ( !(regE0 ^ val) )
- return;
- //in opl3 mode you can always selet 7 waveforms regardless of waveformselect
- Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) );
- regE0 = val;
-#if ( DBOPL_WAVE == WAVE_HANDLER )
- waveHandler = WaveHandlerTable[ waveForm ];
-#else
- waveBase = WaveTable + WaveBaseTable[ waveForm ];
- waveStart = WaveStartTable[ waveForm ] << WAVE_SH;
- waveMask = WaveMaskTable[ waveForm ];
-#endif
-}
-
-INLINE void Operator::SetState( Bit8u s ) {
- state = s;
- volHandler = VolumeHandlerTable[ s ];
-}
-
-INLINE bool Operator::Silent() const {
- if ( !ENV_SILENT( totalLevel + volume ) )
- return false;
- if ( !(rateZero & ( 1 << state ) ) )
- return false;
- return true;
-}
-
-INLINE void Operator::Prepare( const Chip* chip ) {
- currentLevel = totalLevel + (chip->tremoloValue & tremoloMask);
- waveCurrent = waveAdd;
- if ( vibStrength >> chip->vibratoShift ) {
- Bit32s add = vibrato >> chip->vibratoShift;
- //Sign extend over the shift value
- Bit32s neg = chip->vibratoSign;
- //Negate the add with -1 or 0
- add = ( add ^ neg ) - neg;
- waveCurrent += add;
- }
-}
-
-void Operator::KeyOn( Bit8u mask ) {
- if ( !keyOn ) {
- //Restart the frequency generator
-#if ( DBOPL_WAVE > WAVE_HANDLER )
- waveIndex = waveStart;
-#else
- waveIndex = 0;
-#endif
- rateIndex = 0;
- SetState( ATTACK );
- }
- keyOn |= mask;
-}
-
-void Operator::KeyOff( Bit8u mask ) {
- keyOn &= ~mask;
- if ( !keyOn ) {
- if ( state != OFF ) {
- SetState( RELEASE );
- }
- }
-}
-
-INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) {
-#if ( DBOPL_WAVE == WAVE_HANDLER )
- return waveHandler( index, vol << ( 3 - ENV_EXTRA ) );
-#elif ( DBOPL_WAVE == WAVE_TABLEMUL )
- return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH;
-#elif ( DBOPL_WAVE == WAVE_TABLELOG )
- Bit32s wave = waveBase[ index & waveMask ];
- Bit32u total = ( wave & 0x7fff ) + ( vol << ( 3 - ENV_EXTRA ) );
- Bit32s sig = ExpTable[ total & 0xff ];
- Bit32u exp = total >> 8;
- Bit32s neg = wave >> 16;
- return ((sig ^ neg) - neg) >> exp;
-#else
-#error "No valid wave routine"
-#endif
-}
-
-INLINE Bits Operator::GetSample( Bits modulation ) {
- Bitu vol = ForwardVolume();
- if ( ENV_SILENT( vol ) ) {
- //Simply forward the wave
- waveIndex += waveCurrent;
- return 0;
- } else {
- Bitu index = ForwardWave();
- index += modulation;
- return GetWave( index, vol );
- }
-}
-
-Operator::Operator() {
- chanData = 0;
- freqMul = 0;
- waveIndex = 0;
- waveAdd = 0;
- waveCurrent = 0;
- keyOn = 0;
- ksr = 0;
- reg20 = 0;
- reg40 = 0;
- reg60 = 0;
- reg80 = 0;
- regE0 = 0;
- SetState( OFF );
- rateZero = (1 << OFF);
- sustainLevel = ENV_MAX;
- currentLevel = ENV_MAX;
- totalLevel = ENV_MAX;
- volume = ENV_MAX;
- releaseAdd = 0;
-}
-
-/*
- Channel
-*/
-
-Channel::Channel() {
- old[0] = old[1] = 0;
- chanData = 0;
- regB0 = 0;
- regC0 = 0;
- maskLeft = -1;
- maskRight = -1;
- feedback = 31;
- fourMask = 0;
- synthHandler = &Channel::BlockTemplate< sm2FM >;
-}
-
-void Channel::SetChanData( const Chip* chip, Bit32u data ) {
- Bit32u change = chanData ^ data;
- chanData = data;
- Op( 0 )->chanData = data;
- Op( 1 )->chanData = data;
- //Since a frequency update triggered this, always update frequency
- Op( 0 )->UpdateFrequency();
- Op( 1 )->UpdateFrequency();
- if ( change & ( 0xff << SHIFT_KSLBASE ) ) {
- Op( 0 )->UpdateAttenuation();
- Op( 1 )->UpdateAttenuation();
- }
- if ( change & ( 0xff << SHIFT_KEYCODE ) ) {
- Op( 0 )->UpdateRates( chip );
- Op( 1 )->UpdateRates( chip );
- }
-}
-
-void Channel::UpdateFrequency( const Chip* chip, Bit8u fourOp ) {
- //Extrace the frequency bits
- Bit32u data = chanData & 0xffff;
- Bit32u kslBase = KslTable[ data >> 6 ];
- Bit32u keyCode = ( data & 0x1c00) >> 9;
- if ( chip->reg08 & 0x40 ) {
- keyCode |= ( data & 0x100)>>8; /* notesel == 1 */
- } else {
- keyCode |= ( data & 0x200)>>9; /* notesel == 0 */
- }
- //Add the keycode and ksl into the highest bits of chanData
- data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE );
- ( this + 0 )->SetChanData( chip, data );
- if ( fourOp & 0x3f ) {
- ( this + 1 )->SetChanData( chip, data );
- }
-}
-
-void Channel::WriteA0( const Chip* chip, Bit8u val ) {
- Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
- //Don't handle writes to silent fourop channels
- if ( fourOp > 0x80 )
- return;
- Bit32u change = (chanData ^ val ) & 0xff;
- if ( change ) {
- chanData ^= change;
- UpdateFrequency( chip, fourOp );
- }
-}
-
-void Channel::WriteB0( const Chip* chip, Bit8u val ) {
- Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
- //Don't handle writes to silent fourop channels
- if ( fourOp > 0x80 )
- return;
- Bitu change = (chanData ^ ( val << 8 ) ) & 0x1f00;
- if ( change ) {
- chanData ^= change;
- UpdateFrequency( chip, fourOp );
- }
- //Check for a change in the keyon/off state
- if ( !(( val ^ regB0) & 0x20))
- return;
- regB0 = val;
- if ( val & 0x20 ) {
- Op(0)->KeyOn( 0x1 );
- Op(1)->KeyOn( 0x1 );
- if ( fourOp & 0x3f ) {
- ( this + 1 )->Op(0)->KeyOn( 1 );
- ( this + 1 )->Op(1)->KeyOn( 1 );
- }
- } else {
- Op(0)->KeyOff( 0x1 );
- Op(1)->KeyOff( 0x1 );
- if ( fourOp & 0x3f ) {
- ( this + 1 )->Op(0)->KeyOff( 1 );
- ( this + 1 )->Op(1)->KeyOff( 1 );
- }
- }
-}
-
-void Channel::WriteC0( const Chip* chip, Bit8u val ) {
- Bit8u change = val ^ regC0;
- if ( !change )
- return;
- regC0 = val;
- feedback = ( val >> 1 ) & 7;
- if ( feedback ) {
- //We shift the input to the right 10 bit wave index value
- feedback = 9 - feedback;
- } else {
- feedback = 31;
- }
- //Select the new synth mode
- if ( chip->opl3Active ) {
- //4-op mode enabled for this channel
- if ( (chip->reg104 & fourMask) & 0x3f ) {
- Channel* chan0, *chan1;
- //Check if it's the 2nd channel in a 4-op
- if ( !(fourMask & 0x80 ) ) {
- chan0 = this;
- chan1 = this + 1;
- } else {
- chan0 = this - 1;
- chan1 = this;
- }
-
- Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
- switch ( synth ) {
- case 0:
- chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >;
- break;
- case 1:
- chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >;
- break;
- case 2:
- chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >;
- break;
- case 3:
- chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >;
- break;
- }
- //Disable updating percussion channels
- } else if ((fourMask & 0x40) && ( chip->regBD & 0x20) ) {
-
- //Regular dual op, am or fm
- } else if ( val & 1 ) {
- synthHandler = &Channel::BlockTemplate< sm3AM >;
- } else {
- synthHandler = &Channel::BlockTemplate< sm3FM >;
- }
- maskLeft = ( val & 0x10 ) ? -1 : 0;
- maskRight = ( val & 0x20 ) ? -1 : 0;
- //opl2 active
- } else {
- //Disable updating percussion channels
- if ( (fourMask & 0x40) && ( chip->regBD & 0x20 ) ) {
-
- //Regular dual op, am or fm
- } else if ( val & 1 ) {
- synthHandler = &Channel::BlockTemplate< sm2AM >;
- } else {
- synthHandler = &Channel::BlockTemplate< sm2FM >;
- }
- }
-}
-
-void Channel::ResetC0( const Chip* chip ) {
- Bit8u val = regC0;
- regC0 ^= 0xff;
- WriteC0( chip, val );
-}
-
-template< bool opl3Mode>
-INLINE void Channel::GeneratePercussion( Chip* chip, Bit32s* output ) {
- Channel* chan = this;
-
- //BassDrum
- Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
- old[0] = old[1];
- old[1] = Op(0)->GetSample( mod );
-
- //When bassdrum is in AM mode first operator is ignoed
- if ( chan->regC0 & 1 ) {
- mod = 0;
- } else {
- mod = old[0];
- }
- Bit32s sample = Op(1)->GetSample( mod );
-
-
- //Precalculate stuff used by other outputs
- Bit32u noiseBit = chip->ForwardNoise() & 0x1;
- Bit32u c2 = Op(2)->ForwardWave();
- Bit32u c5 = Op(5)->ForwardWave();
- Bit32u phaseBit = (((c2 & 0x88) ^ ((c2<<5) & 0x80)) | ((c5 ^ (c5<<2)) & 0x20)) ? 0x02 : 0x00;
-
- //Hi-Hat
- Bit32u hhVol = Op(2)->ForwardVolume();
- if ( !ENV_SILENT( hhVol ) ) {
- Bit32u hhIndex = (phaseBit<<8) | (0x34 << ( phaseBit ^ (noiseBit << 1 )));
- sample += Op(2)->GetWave( hhIndex, hhVol );
- }
- //Snare Drum
- Bit32u sdVol = Op(3)->ForwardVolume();
- if ( !ENV_SILENT( sdVol ) ) {
- Bit32u sdIndex = ( 0x100 + (c2 & 0x100) ) ^ ( noiseBit << 8 );
- sample += Op(3)->GetWave( sdIndex, sdVol );
- }
- //Tom-tom
- sample += Op(4)->GetSample( 0 );
-
- //Top-Cymbal
- Bit32u tcVol = Op(5)->ForwardVolume();
- if ( !ENV_SILENT( tcVol ) ) {
- Bit32u tcIndex = (1 + phaseBit) << 8;
- sample += Op(5)->GetWave( tcIndex, tcVol );
- }
- sample <<= 1;
- if ( opl3Mode ) {
- output[0] += sample;
- output[1] += sample;
- } else {
- output[0] += sample;
- }
-}
-
-template<SynthMode mode>
-Channel* Channel::BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output ) {
- switch( mode ) {
- case sm2AM:
- case sm3AM:
- if ( Op(0)->Silent() && Op(1)->Silent() ) {
- old[0] = old[1] = 0;
- return (this + 1);
- }
- break;
- case sm2FM:
- case sm3FM:
- if ( Op(1)->Silent() ) {
- old[0] = old[1] = 0;
- return (this + 1);
- }
- break;
- case sm3FMFM:
- if ( Op(3)->Silent() ) {
- old[0] = old[1] = 0;
- return (this + 2);
- }
- break;
- case sm3AMFM:
- if ( Op(0)->Silent() && Op(3)->Silent() ) {
- old[0] = old[1] = 0;
- return (this + 2);
- }
- break;
- case sm3FMAM:
- if ( Op(1)->Silent() && Op(3)->Silent() ) {
- old[0] = old[1] = 0;
- return (this + 2);
- }
- break;
- case sm3AMAM:
- if ( Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent() ) {
- old[0] = old[1] = 0;
- return (this + 2);
- }
- break;
- case sm2Percussion:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- case sm3Percussion:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- case sm4Start:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- case sm6Start:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- }
- //Init the operators with the the current vibrato and tremolo values
- Op( 0 )->Prepare( chip );
- Op( 1 )->Prepare( chip );
- if ( mode > sm4Start ) {
- Op( 2 )->Prepare( chip );
- Op( 3 )->Prepare( chip );
- }
- if ( mode > sm6Start ) {
- Op( 4 )->Prepare( chip );
- Op( 5 )->Prepare( chip );
- }
- for ( Bitu i = 0; i < samples; i++ ) {
- //Early out for percussion handlers
- if ( mode == sm2Percussion ) {
- GeneratePercussion<false>( chip, output + i );
- continue; //Prevent some unitialized value bitching
- } else if ( mode == sm3Percussion ) {
- GeneratePercussion<true>( chip, output + i * 2 );
- continue; //Prevent some unitialized value bitching
- }
-
- //Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
- Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
- old[0] = old[1];
- old[1] = Op(0)->GetSample( mod );
- Bit32s sample;
- Bit32s out0 = old[0];
- if ( mode == sm2AM || mode == sm3AM ) {
- sample = out0 + Op(1)->GetSample( 0 );
- } else if ( mode == sm2FM || mode == sm3FM ) {
- sample = Op(1)->GetSample( out0 );
- } else if ( mode == sm3FMFM ) {
- Bits next = Op(1)->GetSample( out0 );
- next = Op(2)->GetSample( next );
- sample = Op(3)->GetSample( next );
- } else if ( mode == sm3AMFM ) {
- sample = out0;
- Bits next = Op(1)->GetSample( 0 );
- next = Op(2)->GetSample( next );
- sample += Op(3)->GetSample( next );
- } else if ( mode == sm3FMAM ) {
- sample = Op(1)->GetSample( out0 );
- Bits next = Op(2)->GetSample( 0 );
- sample += Op(3)->GetSample( next );
- } else if ( mode == sm3AMAM ) {
- sample = out0;
- Bits next = Op(1)->GetSample( 0 );
- sample += Op(2)->GetSample( next );
- sample += Op(3)->GetSample( 0 );
- }
- switch( mode ) {
- case sm2AM:
- case sm2FM:
- output[ i ] += sample;
- break;
- case sm3AM:
- case sm3FM:
- case sm3FMFM:
- case sm3AMFM:
- case sm3FMAM:
- case sm3AMAM:
- output[ i * 2 + 0 ] += sample & maskLeft;
- output[ i * 2 + 1 ] += sample & maskRight;
- break;
- case sm2Percussion:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- case sm3Percussion:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- case sm4Start:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- case sm6Start:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- }
- }
- switch( mode ) {
- case sm2AM:
- case sm2FM:
- case sm3AM:
- case sm3FM:
- return ( this + 1 );
- case sm3FMFM:
- case sm3AMFM:
- case sm3FMAM:
- case sm3AMAM:
- return( this + 2 );
- case sm2Percussion:
- case sm3Percussion:
- return( this + 3 );
- case sm4Start:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- case sm6Start:
- // This case was not handled in the DOSBox code either
- // thus we leave this blank.
- // TODO: Consider checking this.
- break;
- }
- return 0;
-}
-
-/*
- Chip
-*/
-
-Chip::Chip() {
- reg08 = 0;
- reg04 = 0;
- regBD = 0;
- reg104 = 0;
- opl3Active = 0;
-}
-
-INLINE Bit32u Chip::ForwardNoise() {
- noiseCounter += noiseAdd;
- Bitu count = noiseCounter >> LFO_SH;
- noiseCounter &= WAVE_MASK;
- for ( ; count > 0; --count ) {
- //Noise calculation from mame
- noiseValue ^= ( 0x800302 ) & ( 0 - (noiseValue & 1 ) );
- noiseValue >>= 1;
- }
- return noiseValue;
-}
-
-INLINE Bit32u Chip::ForwardLFO( Bit32u samples ) {
- //Current vibrato value, runs 4x slower than tremolo
- vibratoSign = ( VibratoTable[ vibratoIndex >> 2] ) >> 7;
- vibratoShift = ( VibratoTable[ vibratoIndex >> 2] & 7) + vibratoStrength;
- tremoloValue = TremoloTable[ tremoloIndex ] >> tremoloStrength;
-
- //Check hom many samples there can be done before the value changes
- Bit32u todo = LFO_MAX - lfoCounter;
- Bit32u count = (todo + lfoAdd - 1) / lfoAdd;
- if ( count > samples ) {
- count = samples;
- lfoCounter += count * lfoAdd;
- } else {
- lfoCounter += count * lfoAdd;
- lfoCounter &= (LFO_MAX - 1);
- //Maximum of 7 vibrato value * 4
- vibratoIndex = ( vibratoIndex + 1 ) & 31;
- //Clip tremolo to the the table size
- if ( tremoloIndex + 1 < TREMOLO_TABLE )
- ++tremoloIndex;
- else
- tremoloIndex = 0;
- }
- return count;
-}
-
-
-void Chip::WriteBD( Bit8u val ) {
- Bit8u change = regBD ^ val;
- if ( !change )
- return;
- regBD = val;
- //TODO could do this with shift and xor?
- vibratoStrength = (val & 0x40) ? 0x00 : 0x01;
- tremoloStrength = (val & 0x80) ? 0x00 : 0x02;
- if ( val & 0x20 ) {
- //Drum was just enabled, make sure channel 6 has the right synth
- if ( change & 0x20 ) {
- if ( opl3Active ) {
- chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >;
- } else {
- chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >;
- }
- }
- //Bass Drum
- if ( val & 0x10 ) {
- chan[6].op[0].KeyOn( 0x2 );
- chan[6].op[1].KeyOn( 0x2 );
- } else {
- chan[6].op[0].KeyOff( 0x2 );
- chan[6].op[1].KeyOff( 0x2 );
- }
- //Hi-Hat
- if ( val & 0x1 ) {
- chan[7].op[0].KeyOn( 0x2 );
- } else {
- chan[7].op[0].KeyOff( 0x2 );
- }
- //Snare
- if ( val & 0x8 ) {
- chan[7].op[1].KeyOn( 0x2 );
- } else {
- chan[7].op[1].KeyOff( 0x2 );
- }
- //Tom-Tom
- if ( val & 0x4 ) {
- chan[8].op[0].KeyOn( 0x2 );
- } else {
- chan[8].op[0].KeyOff( 0x2 );
- }
- //Top Cymbal
- if ( val & 0x2 ) {
- chan[8].op[1].KeyOn( 0x2 );
- } else {
- chan[8].op[1].KeyOff( 0x2 );
- }
- //Toggle keyoffs when we turn off the percussion
- } else if ( change & 0x20 ) {
- //Trigger a reset to setup the original synth handler
- chan[6].ResetC0( this );
- chan[6].op[0].KeyOff( 0x2 );
- chan[6].op[1].KeyOff( 0x2 );
- chan[7].op[0].KeyOff( 0x2 );
- chan[7].op[1].KeyOff( 0x2 );
- chan[8].op[0].KeyOff( 0x2 );
- chan[8].op[1].KeyOff( 0x2 );
- }
-}
-
-
-#define REGOP( _FUNC_ ) \
- index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f ); \
- if ( OpOffsetTable[ index ] ) { \
- Operator* regOp = (Operator*)( ((char *)this ) + OpOffsetTable[ index ] ); \
- regOp->_FUNC_( this, val ); \
- }
-
-#define REGCHAN( _FUNC_ ) \
- index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf ); \
- if ( ChanOffsetTable[ index ] ) { \
- Channel* regChan = (Channel*)( ((char *)this ) + ChanOffsetTable[ index ] ); \
- regChan->_FUNC_( this, val ); \
- }
-
-void Chip::WriteReg( Bit32u reg, Bit8u val ) {
- Bitu index;
- switch ( (reg & 0xf0) >> 4 ) {
- case 0x00 >> 4:
- if ( reg == 0x01 ) {
- waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0;
- } else if ( reg == 0x104 ) {
- //Only detect changes in lowest 6 bits
- if ( !((reg104 ^ val) & 0x3f) )
- return;
- //Always keep the highest bit enabled, for checking > 0x80
- reg104 = 0x80 | ( val & 0x3f );
- } else if ( reg == 0x105 ) {
- //MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register
- if ( !((opl3Active ^ val) & 1 ) )
- return;
- opl3Active = ( val & 1 ) ? 0xff : 0;
- //Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers
- for ( int i = 0; i < 18;i++ ) {
- chan[i].ResetC0( this );
- }
- } else if ( reg == 0x08 ) {
- reg08 = val;
- }
- case 0x10 >> 4:
- break;
- case 0x20 >> 4:
- case 0x30 >> 4:
- REGOP( Write20 );
- break;
- case 0x40 >> 4:
- case 0x50 >> 4:
- REGOP( Write40 );
- break;
- case 0x60 >> 4:
- case 0x70 >> 4:
- REGOP( Write60 );
- break;
- case 0x80 >> 4:
- case 0x90 >> 4:
- REGOP( Write80 );
- break;
- case 0xa0 >> 4:
- REGCHAN( WriteA0 );
- break;
- case 0xb0 >> 4:
- if ( reg == 0xbd ) {
- WriteBD( val );
- } else {
- REGCHAN( WriteB0 );
- }
- break;
- case 0xc0 >> 4:
- REGCHAN( WriteC0 );
- case 0xd0 >> 4:
- break;
- case 0xe0 >> 4:
- case 0xf0 >> 4:
- REGOP( WriteE0 );
- break;
- }
-}
-
-
-Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) {
- switch ( port & 3 ) {
- case 0:
- return val;
- case 2:
- if ( opl3Active || (val == 0x05) )
- return 0x100 | val;
- else
- return val;
- }
- return 0;
-}
-
-void Chip::GenerateBlock2( Bitu total, Bit32s* output ) {
- while ( total > 0 ) {
- Bit32u samples = ForwardLFO( total );
- memset(output, 0, sizeof(Bit32s) * samples);
- int count = 0;
- for( Channel* ch = chan; ch < chan + 9; ) {
- count++;
- ch = (ch->*(ch->synthHandler))( this, samples, output );
- }
- total -= samples;
- output += samples;
- }
-}
-
-void Chip::GenerateBlock3( Bitu total, Bit32s* output ) {
- while ( total > 0 ) {
- Bit32u samples = ForwardLFO( total );
- memset(output, 0, sizeof(Bit32s) * 2 * samples);
- int count = 0;
- for( Channel* ch = chan; ch < chan + 18; ) {
- count++;
- ch = (ch->*(ch->synthHandler))( this, samples, output );
- }
- total -= samples;
- output += samples * 2;
- }
-}
-
-void Chip::Setup( Bit32u rate ) {
- double scale = OPLRATE / (double)rate;
-
- //Noise counter is run at the same precision as general waves
- noiseAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
- noiseCounter = 0;
- noiseValue = 1; //Make sure it triggers the noise xor the first time
- //The low frequency oscillation counter
- //Every time his overflows vibrato and tremoloindex are increased
- lfoAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
- lfoCounter = 0;
- vibratoIndex = 0;
- tremoloIndex = 0;
-
- //With higher octave this gets shifted up
- //-1 since the freqCreateTable = *2
-#ifdef WAVE_PRECISION
- double freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10));
- for ( int i = 0; i < 16; i++ ) {
- freqMul[i] = (Bit32u)( 0.5 + freqScale * FreqCreateTable[ i ] );
- }
-#else
- Bit32u freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10)));
- for ( int i = 0; i < 16; i++ ) {
- freqMul[i] = freqScale * FreqCreateTable[ i ];
- }
-#endif
-
- //-3 since the real envelope takes 8 steps to reach the single value we supply
- for ( Bit8u i = 0; i < 76; i++ ) {
- Bit8u index, shift;
- EnvelopeSelect( i, index, shift );
- linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
- }
- //Generate the best matching attack rate
- for ( Bit8u i = 0; i < 62; i++ ) {
- Bit8u index, shift;
- EnvelopeSelect( i, index, shift );
- //Original amount of samples the attack would take
- Bit32s original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale);
-
- Bit32s guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 )));
- Bit32s bestAdd = guessAdd;
- Bit32u bestDiff = 1 << 30;
- for( Bit32u passes = 0; passes < 16; passes ++ ) {
- Bit32s volume = ENV_MAX;
- Bit32s samples = 0;
- Bit32u count = 0;
- while ( volume > 0 && samples < original * 2 ) {
- count += guessAdd;
- Bit32s change = count >> RATE_SH;
- count &= RATE_MASK;
- if ( GCC_UNLIKELY(change) ) { // less than 1 %
- volume += ( ~volume * change ) >> 3;
- }
- samples++;
-
- }
- Bit32s diff = original - samples;
- Bit32u lDiff = labs( diff );
- //Init last on first pass
- if ( lDiff < bestDiff ) {
- bestDiff = lDiff;
- bestAdd = guessAdd;
- if ( !bestDiff )
- break;
- }
- //Below our target
- if ( diff < 0 ) {
- //Better than the last time
- Bit32s mul = ((original - diff) << 12) / original;
- guessAdd = ((guessAdd * mul) >> 12);
- guessAdd++;
- } else if ( diff > 0 ) {
- Bit32s mul = ((original - diff) << 12) / original;
- guessAdd = (guessAdd * mul) >> 12;
- guessAdd--;
- }
- }
- attackRates[i] = bestAdd;
- }
- for ( Bit8u i = 62; i < 76; i++ ) {
- //This should provide instant volume maximizing
- attackRates[i] = 8 << RATE_SH;
- }
- //Setup the channels with the correct four op flags
- //Channels are accessed through a table so they appear linear here
- chan[ 0].fourMask = 0x00 | ( 1 << 0 );
- chan[ 1].fourMask = 0x80 | ( 1 << 0 );
- chan[ 2].fourMask = 0x00 | ( 1 << 1 );
- chan[ 3].fourMask = 0x80 | ( 1 << 1 );
- chan[ 4].fourMask = 0x00 | ( 1 << 2 );
- chan[ 5].fourMask = 0x80 | ( 1 << 2 );
-
- chan[ 9].fourMask = 0x00 | ( 1 << 3 );
- chan[10].fourMask = 0x80 | ( 1 << 3 );
- chan[11].fourMask = 0x00 | ( 1 << 4 );
- chan[12].fourMask = 0x80 | ( 1 << 4 );
- chan[13].fourMask = 0x00 | ( 1 << 5 );
- chan[14].fourMask = 0x80 | ( 1 << 5 );
-
- //mark the percussion channels
- chan[ 6].fourMask = 0x40;
- chan[ 7].fourMask = 0x40;
- chan[ 8].fourMask = 0x40;
-
- //Clear Everything in opl3 mode
- WriteReg( 0x105, 0x1 );
- for ( int i = 0; i < 512; i++ ) {
- if ( i == 0x105 )
- continue;
- WriteReg( i, 0xff );
- WriteReg( i, 0x0 );
- }
- WriteReg( 0x105, 0x0 );
- //Clear everything in opl2 mode
- for ( int i = 0; i < 255; i++ ) {
- WriteReg( i, 0xff );
- WriteReg( i, 0x0 );
- }
-}
-
-static bool doneTables = false;
-void InitTables( void ) {
- if ( doneTables )
- return;
- doneTables = true;
-#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
- //Exponential volume table, same as the real adlib
- for ( int i = 0; i < 256; i++ ) {
- //Save them in reverse
- ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 );
- ExpTable[i] += 1024; //or remove the -1 oh well :)
- //Preshift to the left once so the final volume can shift to the right
- ExpTable[i] *= 2;
- }
-#endif
-#if ( DBOPL_WAVE == WAVE_HANDLER )
- //Add 0.5 for the trunc rounding of the integer cast
- //Do a PI sinetable instead of the original 0.5 PI
- for ( int i = 0; i < 512; i++ ) {
- SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
- }
-#endif
-#if ( DBOPL_WAVE == WAVE_TABLEMUL )
- //Multiplication based tables
- for ( int i = 0; i < 384; i++ ) {
- int s = i * 8;
- //TODO maybe keep some of the precision errors of the original table?
- double val = ( 0.5 + ( pow(2.0, -1.0 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH ));
- MulTable[i] = (Bit16u)(val);
- }
-
- //Sine Wave Base
- for ( int i = 0; i < 512; i++ ) {
- WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
- WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
- }
- //Exponential wave
- for ( int i = 0; i < 256; i++ ) {
- WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2.0, -1.0 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 );
- WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ];
- }
-#endif
-#if ( DBOPL_WAVE == WAVE_TABLELOG )
- //Sine Wave Base
- for ( int i = 0; i < 512; i++ ) {
- WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
- WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
- }
- //Exponential wave
- for ( int i = 0; i < 256; i++ ) {
- WaveTable[ 0x700 + i ] = i * 8;
- WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8;
- }
-#endif
-
- // | |//\\|____|WAV7|//__|/\ |____|/\/\|
- // |\\//| | |WAV7| | \/| | |
- // |06 |0126|27 |7 |3 |4 |4 5 |5 |
-
-#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL ))
- for ( int i = 0; i < 256; i++ ) {
- //Fill silence gaps
- WaveTable[ 0x400 + i ] = WaveTable[0];
- WaveTable[ 0x500 + i ] = WaveTable[0];
- WaveTable[ 0x900 + i ] = WaveTable[0];
- WaveTable[ 0xc00 + i ] = WaveTable[0];
- WaveTable[ 0xd00 + i ] = WaveTable[0];
- //Replicate sines in other pieces
- WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ];
- //double speed sines
- WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ];
- WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ];
- WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ];
- WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ];
- }
-#endif
-
- //Create the ksl table
- for ( int oct = 0; oct < 8; oct++ ) {
- int base = oct * 8;
- for ( int i = 0; i < 16; i++ ) {
- int val = base - KslCreateTable[i];
- if ( val < 0 )
- val = 0;
- //*4 for the final range to match attenuation range
- KslTable[ oct * 16 + i ] = val * 4;
- }
- }
- //Create the Tremolo table, just increase and decrease a triangle wave
- for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) {
- Bit8u val = i << ENV_EXTRA;
- TremoloTable[i] = val;
- TremoloTable[TREMOLO_TABLE - 1 - i] = val;
- }
- //Create a table with offsets of the channels from the start of the chip
- DBOPL::Chip* chip = 0;
- for ( Bitu i = 0; i < 32; i++ ) {
- Bitu index = i & 0xf;
- if ( index >= 9 ) {
- ChanOffsetTable[i] = 0;
- continue;
- }
- //Make sure the four op channels follow eachother
- if ( index < 6 ) {
- index = (index % 3) * 2 + ( index / 3 );
- }
- //Add back the bits for highest ones
- if ( i >= 16 )
- index += 9;
- Bitu blah = reinterpret_cast<size_t>( &(chip->chan[ index ]) );
- ChanOffsetTable[i] = blah;
- }
- //Same for operators
- for ( Bitu i = 0; i < 64; i++ ) {
- if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) {
- OpOffsetTable[i] = 0;
- continue;
- }
- Bitu chNum = (i / 8) * 3 + (i % 8) % 3;
- //Make sure we use 16 and up for the 2nd range to match the chanoffset gap
- if ( chNum >= 12 )
- chNum += 16 - 12;
- Bitu opNum = ( i % 8 ) / 3;
- DBOPL::Channel* chan = 0;
- Bitu blah = reinterpret_cast<size_t>( &(chan->op[opNum]) );
- OpOffsetTable[i] = ChanOffsetTable[ chNum ] + blah;
- }
-#if 0
- //Stupid checks if table's are correct
- for ( Bitu i = 0; i < 18; i++ ) {
- Bit32u find = (Bit16u)( &(chip->chan[ i ]) );
- for ( Bitu c = 0; c < 32; c++ ) {
- if ( ChanOffsetTable[c] == find ) {
- find = 0;
- break;
- }
- }
- if ( find ) {
- find = find;
- }
- }
- for ( Bitu i = 0; i < 36; i++ ) {
- Bit32u find = (Bit16u)( &(chip->chan[ i / 2 ].op[i % 2]) );
- for ( Bitu c = 0; c < 64; c++ ) {
- if ( OpOffsetTable[c] == find ) {
- find = 0;
- break;
- }
- }
- if ( find ) {
- find = find;
- }
- }
-#endif
-}
-
-} //Namespace DBOPL
-} // End of namespace DOSBox
-} // End of namespace OPL
-
-#endif // !DISABLE_DOSBOX_OPL
diff --git a/sound/softsynth/opl/dbopl.h b/sound/softsynth/opl/dbopl.h
deleted file mode 100644
index 87d1045fab..0000000000
--- a/sound/softsynth/opl/dbopl.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2002-2010 The DOSBox Team
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-// Last synch with DOSBox SVN trunk r3556
-
-#ifndef SOUND_SOFTSYNTH_OPL_DBOPL_H
-#define SOUND_SOFTSYNTH_OPL_DBOPL_H
-
-#include "common/scummsys.h"
-
-#ifndef DISABLE_DOSBOX_OPL
-
-namespace OPL {
-namespace DOSBox {
-
-//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
-#define WAVE_HANDLER 10
-//Use a logarithmic wavetable with an exponential table for volume
-#define WAVE_TABLELOG 11
-//Use a linear wavetable with a multiply table for volume
-#define WAVE_TABLEMUL 12
-
-//Select the type of wave generator routine
-#define DBOPL_WAVE WAVE_TABLEMUL
-
-namespace DBOPL {
-
-// Type aliases for the DBOPL code
-typedef int Bits;
-typedef uint Bitu;
-
-typedef int8 Bit8s;
-typedef uint8 Bit8u;
-
-typedef int16 Bit16s;
-typedef uint16 Bit16u;
-
-typedef int32 Bit32s;
-typedef uint32 Bit32u;
-
-#define DB_FASTCALL
-#define GCC_UNLIKELY(x) (x)
-#define INLINE inline
-// -------------------------------
-
-struct Chip;
-struct Operator;
-struct Channel;
-
-#if (DBOPL_WAVE == WAVE_HANDLER)
-typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
-#endif
-
-typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
-typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output );
-
-//Different synth modes that can generate blocks of data
-typedef enum {
- sm2AM,
- sm2FM,
- sm3AM,
- sm3FM,
- sm4Start,
- sm3FMFM,
- sm3AMFM,
- sm3FMAM,
- sm3AMAM,
- sm6Start,
- sm2Percussion,
- sm3Percussion
-} SynthMode;
-
-//Shifts for the values contained in chandata variable
-enum {
- SHIFT_KSLBASE = 16,
- SHIFT_KEYCODE = 24
-};
-
-struct Operator {
-public:
- //Masks for operator 20 values
- enum {
- MASK_KSR = 0x10,
- MASK_SUSTAIN = 0x20,
- MASK_VIBRATO = 0x40,
- MASK_TREMOLO = 0x80
- };
-
- typedef enum {
- OFF,
- RELEASE,
- SUSTAIN,
- DECAY,
- ATTACK
- } State;
-
- VolumeHandler volHandler;
-
-#if (DBOPL_WAVE == WAVE_HANDLER)
- WaveHandler waveHandler; //Routine that generate a wave
-#else
- Bit16s* waveBase;
- Bit32u waveMask;
- Bit32u waveStart;
-#endif
- Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index
- Bit32u waveAdd; //The base frequency without vibrato
- Bit32u waveCurrent; //waveAdd + vibratao
-
- Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this
- Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove?
- Bit32u vibrato; //Scaled up vibrato strength
- Bit32s sustainLevel; //When stopping at sustain level stop here
- Bit32s totalLevel; //totalLevel is added to every generated volume
- Bit32u currentLevel; //totalLevel + tremolo
- Bit32s volume; //The currently active volume
-
- Bit32u attackAdd; //Timers for the different states of the envelope
- Bit32u decayAdd;
- Bit32u releaseAdd;
- Bit32u rateIndex; //Current position of the evenlope
-
- Bit8u rateZero; //Bits for the different states of the envelope having no changes
- Bit8u keyOn; //Bitmask of different values that can generate keyon
- //Registers, also used to check for changes
- Bit8u reg20, reg40, reg60, reg80, regE0;
- //Active part of the envelope we're in
- Bit8u state;
- //0xff when tremolo is enabled
- Bit8u tremoloMask;
- //Strength of the vibrato
- Bit8u vibStrength;
- //Keep track of the calculated KSR so we can check for changes
- Bit8u ksr;
-private:
- void SetState( Bit8u s );
- void UpdateAttack( const Chip* chip );
- void UpdateRelease( const Chip* chip );
- void UpdateDecay( const Chip* chip );
-public:
- void UpdateAttenuation();
- void UpdateRates( const Chip* chip );
- void UpdateFrequency( );
-
- void Write20( const Chip* chip, Bit8u val );
- void Write40( const Chip* chip, Bit8u val );
- void Write60( const Chip* chip, Bit8u val );
- void Write80( const Chip* chip, Bit8u val );
- void WriteE0( const Chip* chip, Bit8u val );
-
- bool Silent() const;
- void Prepare( const Chip* chip );
-
- void KeyOn( Bit8u mask);
- void KeyOff( Bit8u mask);
-
- template< State state>
- Bits TemplateVolume( );
-
- Bit32s RateForward( Bit32u add );
- Bitu ForwardWave();
- Bitu ForwardVolume();
-
- Bits GetSample( Bits modulation );
- Bits GetWave( Bitu index, Bitu vol );
-public:
- Operator();
-};
-
-struct Channel {
- Operator op[2];
- inline Operator* Op( Bitu index ) {
- return &( ( this + (index >> 1) )->op[ index & 1 ]);
- }
- SynthHandler synthHandler;
- Bit32u chanData; //Frequency/octave and derived values
- Bit32s old[2]; //Old data for feedback
-
- Bit8u feedback; //Feedback shift
- Bit8u regB0; //Register values to check for changes
- Bit8u regC0;
- //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
- Bit8u fourMask;
- Bit8s maskLeft; //Sign extended values for both channel's panning
- Bit8s maskRight;
-
- //Forward the channel data to the operators of the channel
- void SetChanData( const Chip* chip, Bit32u data );
- //Change in the chandata, check for new values and if we have to forward to operators
- void UpdateFrequency( const Chip* chip, Bit8u fourOp );
- void WriteA0( const Chip* chip, Bit8u val );
- void WriteB0( const Chip* chip, Bit8u val );
- void WriteC0( const Chip* chip, Bit8u val );
- void ResetC0( const Chip* chip );
-
- //call this for the first channel
- template< bool opl3Mode >
- void GeneratePercussion( Chip* chip, Bit32s* output );
-
- //Generate blocks of data in specific modes
- template<SynthMode mode>
- Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
- Channel();
-};
-
-struct Chip {
- //This is used as the base counter for vibrato and tremolo
- Bit32u lfoCounter;
- Bit32u lfoAdd;
-
-
- Bit32u noiseCounter;
- Bit32u noiseAdd;
- Bit32u noiseValue;
-
- //Frequency scales for the different multiplications
- Bit32u freqMul[16];
- //Rates for decay and release for rate of this chip
- Bit32u linearRates[76];
- //Best match attack rates for the rate of this chip
- Bit32u attackRates[76];
-
- //18 channels with 2 operators each
- Channel chan[18];
-
- Bit8u reg104;
- Bit8u reg08;
- Bit8u reg04;
- Bit8u regBD;
- Bit8u vibratoIndex;
- Bit8u tremoloIndex;
- Bit8s vibratoSign;
- Bit8u vibratoShift;
- Bit8u tremoloValue;
- Bit8u vibratoStrength;
- Bit8u tremoloStrength;
- //Mask for allowed wave forms
- Bit8u waveFormMask;
- //0 or -1 when enabled
- Bit8s opl3Active;
-
- //Return the maximum amount of samples before and LFO change
- Bit32u ForwardLFO( Bit32u samples );
- Bit32u ForwardNoise();
-
- void WriteBD( Bit8u val );
- void WriteReg(Bit32u reg, Bit8u val );
-
- Bit32u WriteAddr( Bit32u port, Bit8u val );
-
- void GenerateBlock2( Bitu samples, Bit32s* output );
- void GenerateBlock3( Bitu samples, Bit32s* output );
-
- void Generate( Bit32u samples );
- void Setup( Bit32u r );
-
- Chip();
-};
-
-void InitTables();
-
-} //Namespace
-} // End of namespace DOSBox
-} // End of namespace OPL
-
-#endif // !DISABLE_DOSBOX_OPL
-
-#endif
diff --git a/sound/softsynth/opl/dosbox.cpp b/sound/softsynth/opl/dosbox.cpp
deleted file mode 100644
index 29993ce3d8..0000000000
--- a/sound/softsynth/opl/dosbox.cpp
+++ /dev/null
@@ -1,335 +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$
- */
-
-/*
- * Based on AdLib emulation code of DOSBox
- * Copyright (C) 2002-2009 The DOSBox Team
- * Licensed under GPLv2+
- * http://www.dosbox.com
- */
-
-#ifndef DISABLE_DOSBOX_OPL
-
-#include "dosbox.h"
-#include "dbopl.h"
-
-#include "common/system.h"
-#include "common/scummsys.h"
-
-#include <math.h>
-#include <string.h>
-
-namespace OPL {
-namespace DOSBox {
-
-Timer::Timer() {
- masked = false;
- overflow = false;
- enabled = false;
- counter = 0;
- delay = 0;
-}
-
-void Timer::update(double time) {
- if (!enabled || !delay)
- return;
- double deltaStart = time - startTime;
- // Only set the overflow flag when not masked
- if (deltaStart >= 0 && !masked)
- overflow = 1;
-}
-
-void Timer::reset(double time) {
- overflow = false;
- if (!delay || !enabled)
- return;
- double delta = (time - startTime);
- double rem = fmod(delta, delay);
- double next = delay - rem;
- startTime = time + next;
-}
-
-void Timer::stop() {
- enabled = false;
-}
-
-void Timer::start(double time, int scale) {
- //Don't enable again
- if (enabled)
- return;
- enabled = true;
- delay = 0.001 * (256 - counter) * scale;
- startTime = time + delay;
-}
-
-bool Chip::write(uint32 reg, uint8 val) {
- switch (reg) {
- case 0x02:
- timer[0].counter = val;
- return true;
- case 0x03:
- timer[1].counter = val;
- return true;
- case 0x04:
- double time = g_system->getMillis() / 1000.0;
-
- if (val & 0x80) {
- timer[0].reset(time);
- timer[1].reset(time);
- } else {
- timer[0].update(time);
- timer[1].update(time);
-
- if (val & 0x1)
- timer[0].start(time, 80);
- else
- timer[0].stop();
-
- timer[0].masked = (val & 0x40) > 0;
-
- if (timer[0].masked)
- timer[0].overflow = false;
-
- if (val & 0x2)
- timer[1].start(time, 320);
- else
- timer[1].stop();
-
- timer[1].masked = (val & 0x20) > 0;
-
- if (timer[1].masked)
- timer[1].overflow = false;
- }
- return true;
- }
- return false;
-}
-
-uint8 Chip::read() {
- double time = g_system->getMillis() / 1000.0;
-
- timer[0].update(time);
- timer[1].update(time);
-
- uint8 ret = 0;
- // Overflow won't be set if a channel is masked
- if (timer[0].overflow) {
- ret |= 0x40;
- ret |= 0x80;
- }
- if (timer[1].overflow) {
- ret |= 0x20;
- ret |= 0x80;
- }
- return ret;
-}
-
-OPL::OPL(Config::OplType type) : _type(type), _rate(0), _emulator(0) {
-}
-
-OPL::~OPL() {
- free();
-}
-
-void OPL::free() {
- delete _emulator;
- _emulator = 0;
-}
-
-bool OPL::init(int rate) {
- free();
-
- memset(&_reg, 0, sizeof(_reg));
- memset(_chip, 0, sizeof(_chip));
-
- _emulator = new DBOPL::Chip();
- if (!_emulator)
- return false;
-
- DBOPL::InitTables();
- _emulator->Setup(rate);
-
- if (_type == Config::kDualOpl2) {
- // Setup opl3 mode in the hander
- _emulator->WriteReg(0x105, 1);
- }
-
- _rate = rate;
- return true;
-}
-
-void OPL::reset() {
- init(_rate);
-}
-
-void OPL::write(int port, int val) {
- if (port&1) {
- switch (_type) {
- case Config::kOpl2:
- case Config::kOpl3:
- if (!_chip[0].write(_reg.normal, val))
- _emulator->WriteReg(_reg.normal, val);
- break;
- case Config::kDualOpl2:
- // Not a 0x??8 port, then write to a specific port
- if (!(port & 0x8)) {
- byte index = (port & 2) >> 1;
- dualWrite(index, _reg.dual[index], val);
- } else {
- //Write to both ports
- dualWrite(0, _reg.dual[0], val);
- dualWrite(1, _reg.dual[1], val);
- }
- break;
- }
- } else {
- // Ask the handler to write the address
- // Make sure to clip them in the right range
- switch (_type) {
- case Config::kOpl2:
- _reg.normal = _emulator->WriteAddr(port, val) & 0xff;
- break;
- case Config::kOpl3:
- _reg.normal = _emulator->WriteAddr(port, val) & 0x1ff;
- break;
- case Config::kDualOpl2:
- // Not a 0x?88 port, when write to a specific side
- if (!(port & 0x8)) {
- byte index = (port & 2) >> 1;
- _reg.dual[index] = val & 0xff;
- } else {
- _reg.dual[0] = val & 0xff;
- _reg.dual[1] = val & 0xff;
- }
- break;
- }
- }
-}
-
-byte OPL::read(int port) {
- switch (_type) {
- case Config::kOpl2:
- if (!(port & 1))
- //Make sure the low bits are 6 on opl2
- return _chip[0].read() | 0x6;
- break;
- case Config::kOpl3:
- if (!(port & 1))
- return _chip[0].read();
- break;
- case Config::kDualOpl2:
- // Only return for the lower ports
- if (port & 1)
- return 0xff;
- // Make sure the low bits are 6 on opl2
- return _chip[(port >> 1) & 1].read() | 0x6;
- }
- return 0;
-}
-
-void OPL::writeReg(int r, int v) {
- byte tempReg = 0;
- switch (_type) {
- case Config::kOpl2:
- case Config::kDualOpl2:
- case Config::kOpl3:
- // We can't use _handler->writeReg here directly, since it would miss timer changes.
-
- // Backup old setup register
- tempReg = _reg.normal;
-
- // We need to set the register we want to write to via port 0x388
- write(0x388, r);
- // Do the real writing to the register
- write(0x389, v);
- // Restore the old register
- write(0x388, tempReg);
- break;
- };
-}
-
-void OPL::dualWrite(uint8 index, uint8 reg, uint8 val) {
- // Make sure you don't use opl3 features
- // Don't allow write to disable opl3
- if (reg == 5)
- return;
-
- // Only allow 4 waveforms
- if (reg >= 0xE0 && reg <= 0xE8)
- val &= 3;
-
- // Write to the timer?
- if (_chip[index].write(reg, val))
- return;
-
- // Enabling panning
- if (reg >= 0xC0 && reg <= 0xC8) {
- val &= 15;
- val |= index ? 0xA0 : 0x50;
- }
-
- uint32 fullReg = reg + (index ? 0x100 : 0);
- _emulator->WriteReg(fullReg, val);
-}
-
-void OPL::readBuffer(int16 *buffer, int length) {
- // For stereo OPL cards, we divide the sample count by 2,
- // to match stereo AudioStream behavior.
- if (_type != Config::kOpl2)
- length >>= 1;
-
- const uint bufferLength = 512;
- int32 tempBuffer[bufferLength * 2];
-
- if (_emulator->opl3Active) {
- while (length > 0) {
- const uint readSamples = MIN<uint>(length, bufferLength);
-
- _emulator->GenerateBlock3(readSamples, tempBuffer);
-
- for (uint i = 0; i < (readSamples << 1); ++i)
- buffer[i] = tempBuffer[i];
-
- buffer += (readSamples << 1);
- length -= readSamples;
- }
- } else {
- while (length > 0) {
- const uint readSamples = MIN<uint>(length, bufferLength << 1);
-
- _emulator->GenerateBlock2(readSamples, tempBuffer);
-
- for (uint i = 0; i < readSamples; ++i)
- buffer[i] = tempBuffer[i];
-
- buffer += readSamples;
- length -= readSamples;
- }
- }
-}
-
-} // End of namespace DOSBox
-} // End of namespace OPL
-
-#endif // !DISABLE_DOSBOX_ADLIB
diff --git a/sound/softsynth/opl/dosbox.h b/sound/softsynth/opl/dosbox.h
deleted file mode 100644
index 958310611d..0000000000
--- a/sound/softsynth/opl/dosbox.h
+++ /dev/null
@@ -1,110 +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$
- */
-
-/*
- * Based on OPL emulation code of DOSBox
- * Copyright (C) 2002-2009 The DOSBox Team
- * Licensed under GPLv2+
- * http://www.dosbox.com
- */
-
-#ifndef SOUND_SOFTSYNTH_OPL_DOSBOX_H
-#define SOUND_SOFTSYNTH_OPL_DOSBOX_H
-
-#ifndef DISABLE_DOSBOX_OPL
-
-#include "sound/fmopl.h"
-
-namespace OPL {
-namespace DOSBox {
-
-struct Timer {
- double startTime;
- double delay;
- bool enabled, overflow, masked;
- uint8 counter;
-
- Timer();
-
- //Call update before making any further changes
- void update(double time);
-
- //On a reset make sure the start is in sync with the next cycle
- void reset(double time);
-
- void stop();
-
- void start(double time, int scale);
-};
-
-struct Chip {
- //Last selected register
- Timer timer[2];
- //Check for it being a write to the timer
- bool write(uint32 addr, uint8 val);
- //Read the current timer state, will use current double
- uint8 read();
-};
-
-namespace DBOPL {
-struct Chip;
-} // end of namespace DBOPL
-
-class OPL : public ::OPL::OPL {
-private:
- Config::OplType _type;
- uint _rate;
-
- DBOPL::Chip *_emulator;
- Chip _chip[2];
- union {
- uint16 normal;
- uint8 dual[2];
- } _reg;
-
- void free();
- void dualWrite(uint8 index, uint8 reg, uint8 val);
-public:
- OPL(Config::OplType type);
- ~OPL();
-
- bool init(int rate);
- void reset();
-
- void write(int a, int v);
- byte read(int a);
-
- void writeReg(int r, int v);
-
- void readBuffer(int16 *buffer, int length);
- bool isStereo() const { return _type != Config::kOpl2; }
-};
-
-} // End of namespace DOSBox
-} // End of namespace OPL
-
-#endif // !DISABLE_DOSBOX_OPL
-
-#endif
-
diff --git a/sound/softsynth/opl/mame.cpp b/sound/softsynth/opl/mame.cpp
deleted file mode 100644
index c875080e8f..0000000000
--- a/sound/softsynth/opl/mame.cpp
+++ /dev/null
@@ -1,1234 +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$
- *
- * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
- * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <math.h>
-
-#include "mame.h"
-
-#if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__)
-#include "common/config-manager.h"
-#endif
-
-#if defined(__DS__)
-#include "dsmain.h"
-#endif
-
-namespace OPL {
-namespace MAME {
-
-OPL::~OPL() {
- MAME::OPLDestroy(_opl);
- _opl = 0;
-}
-
-bool OPL::init(int rate) {
- if (_opl)
- MAME::OPLDestroy(_opl);
-
- _opl = MAME::makeAdLibOPL(rate);
- return (_opl != 0);
-}
-
-void OPL::reset() {
- MAME::OPLResetChip(_opl);
-}
-
-void OPL::write(int a, int v) {
- MAME::OPLWrite(_opl, a, v);
-}
-
-byte OPL::read(int a) {
- return MAME::OPLRead(_opl, a);
-}
-
-void OPL::writeReg(int r, int v) {
- MAME::OPLWriteReg(_opl, r, v);
-}
-
-void OPL::readBuffer(int16 *buffer, int length) {
- MAME::YM3812UpdateOne(_opl, buffer, length);
-}
-
-/* -------------------- preliminary define section --------------------- */
-/* attack/decay rate time rate */
-#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */
-#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */
-
-#define FREQ_BITS 24 /* frequency turn */
-
-/* counter bits = 20 , octerve 7 */
-#define FREQ_RATE (1<<(FREQ_BITS-20))
-#define TL_BITS (FREQ_BITS+2)
-
-/* final output shift , limit minimum and maximum */
-#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */
-#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
-#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
-
-/* -------------------- quality selection --------------------- */
-
-/* sinwave entries */
-/* used static memory = SIN_ENT * 4 (byte) */
-#ifdef __DS__
-#define SIN_ENT_SHIFT 8
-#else
-#define SIN_ENT_SHIFT 11
-#endif
-#define SIN_ENT (1<<SIN_ENT_SHIFT)
-
-/* output level entries (envelope,sinwave) */
-/* envelope counter lower bits */
-int ENV_BITS;
-/* envelope output entries */
-int EG_ENT;
-
-/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
-/* used static memory = EG_ENT*4 (byte) */
-int EG_OFF; /* OFF */
-int EG_DED;
-int EG_DST; /* DECAY START */
-int EG_AED;
-#define EG_AST 0 /* ATTACK START */
-
-#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
-
-/* LFO table entries */
-#define VIB_ENT 512
-#define VIB_SHIFT (32-9)
-#define AMS_ENT 512
-#define AMS_SHIFT (32-9)
-
-#define VIB_RATE_SHIFT 8
-#define VIB_RATE (1<<VIB_RATE_SHIFT)
-
-/* -------------------- local defines , macros --------------------- */
-
-/* register number to channel number , slot offset */
-#define SLOT1 0
-#define SLOT2 1
-
-/* envelope phase */
-#define ENV_MOD_RR 0x00
-#define ENV_MOD_DR 0x01
-#define ENV_MOD_AR 0x02
-
-/* -------------------- tables --------------------- */
-static const int slot_array[32] = {
- 0, 2, 4, 1, 3, 5,-1,-1,
- 6, 8,10, 7, 9,11,-1,-1,
- 12,14,16,13,15,17,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1
-};
-
-static uint KSL_TABLE[8 * 16];
-
-static const double KSL_TABLE_SEED[8 * 16] = {
- /* OCT 0 */
- 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000,
- /* OCT 1 */
- 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.750, 1.125, 1.500,
- 1.875, 2.250, 2.625, 3.000,
- /* OCT 2 */
- 0.000, 0.000, 0.000, 0.000,
- 0.000, 1.125, 1.875, 2.625,
- 3.000, 3.750, 4.125, 4.500,
- 4.875, 5.250, 5.625, 6.000,
- /* OCT 3 */
- 0.000, 0.000, 0.000, 1.875,
- 3.000, 4.125, 4.875, 5.625,
- 6.000, 6.750, 7.125, 7.500,
- 7.875, 8.250, 8.625, 9.000,
- /* OCT 4 */
- 0.000, 0.000, 3.000, 4.875,
- 6.000, 7.125, 7.875, 8.625,
- 9.000, 9.750, 10.125, 10.500,
- 10.875, 11.250, 11.625, 12.000,
- /* OCT 5 */
- 0.000, 3.000, 6.000, 7.875,
- 9.000, 10.125, 10.875, 11.625,
- 12.000, 12.750, 13.125, 13.500,
- 13.875, 14.250, 14.625, 15.000,
- /* OCT 6 */
- 0.000, 6.000, 9.000, 10.875,
- 12.000, 13.125, 13.875, 14.625,
- 15.000, 15.750, 16.125, 16.500,
- 16.875, 17.250, 17.625, 18.000,
- /* OCT 7 */
- 0.000, 9.000, 12.000, 13.875,
- 15.000, 16.125, 16.875, 17.625,
- 18.000, 18.750, 19.125, 19.500,
- 19.875, 20.250, 20.625, 21.000
-};
-
-/* sustain level table (3db per step) */
-/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
-
-static int SL_TABLE[16];
-
-static const uint SL_TABLE_SEED[16] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31
-};
-
-#define TL_MAX (EG_ENT * 2) /* limit(tl + ksr + envelope) + sinwave */
-/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
-/* TL_TABLE[ 0 to TL_MAX ] : plus section */
-/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
-static int *TL_TABLE;
-
-/* pointers to TL_TABLE with sinwave output offset */
-static int **SIN_TABLE;
-
-/* LFO table */
-static int *AMS_TABLE;
-static int *VIB_TABLE;
-
-/* envelope output curve table */
-/* attack + decay + OFF */
-//static int ENV_CURVE[2*EG_ENT+1];
-//static int ENV_CURVE[2 * 4096 + 1]; // to keep it static ...
-static int *ENV_CURVE;
-
-
-/* multiple table */
-#define ML(a) (int)(a * 2)
-static const uint MUL_TABLE[16]= {
-/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
- ML(0.50), ML(1.00), ML(2.00), ML(3.00), ML(4.00), ML(5.00), ML(6.00), ML(7.00),
- ML(8.00), ML(9.00), ML(10.00), ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00)
-};
-#undef ML
-
-/* dummy attack / decay rate ( when rate == 0 ) */
-static int RATE_0[16]=
-{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-/* -------------------- static state --------------------- */
-
-/* lock level of common table */
-static int num_lock = 0;
-
-/* work table */
-static void *cur_chip = NULL; /* current chip point */
-/* currenct chip state */
-/* static OPLSAMPLE *bufL,*bufR; */
-static OPL_CH *S_CH;
-static OPL_CH *E_CH;
-OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
-
-static int outd[1];
-static int ams;
-static int vib;
-int *ams_table;
-int *vib_table;
-static int amsIncr;
-static int vibIncr;
-static int feedback2; /* connect for SLOT 2 */
-
-/* --------------------- rebuild tables ------------------- */
-
-#define SC_KSL(mydb) ((uint) (mydb / (EG_STEP / 2)))
-#define SC_SL(db) (int)(db * ((3 / EG_STEP) * (1 << ENV_BITS))) + EG_DST
-
-void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM) {
- int i;
-
- ENV_BITS = ENV_BITS_PARAM;
- EG_ENT = EG_ENT_PARAM;
- EG_OFF = ((2 * EG_ENT)<<ENV_BITS); /* OFF */
- EG_DED = EG_OFF;
- EG_DST = (EG_ENT << ENV_BITS); /* DECAY START */
- EG_AED = EG_DST;
- //EG_STEP = (96.0/EG_ENT);
-
- for (i = 0; i < ARRAYSIZE(KSL_TABLE_SEED); i++)
- KSL_TABLE[i] = SC_KSL(KSL_TABLE_SEED[i]);
-
- for (i = 0; i < ARRAYSIZE(SL_TABLE_SEED); i++)
- SL_TABLE[i] = SC_SL(SL_TABLE_SEED[i]);
-}
-
-#undef SC_KSL
-#undef SC_SL
-
-/* --------------------- subroutines --------------------- */
-
-/* status set and IRQ handling */
-inline void OPL_STATUS_SET(FM_OPL *OPL, int flag) {
- /* set status flag */
- OPL->status |= flag;
- if (!(OPL->status & 0x80)) {
- if (OPL->status & OPL->statusmask) { /* IRQ on */
- OPL->status |= 0x80;
- /* callback user interrupt handler (IRQ is OFF to ON) */
- if (OPL->IRQHandler)
- (OPL->IRQHandler)(OPL->IRQParam,1);
- }
- }
-}
-
-/* status reset and IRQ handling */
-inline void OPL_STATUS_RESET(FM_OPL *OPL, int flag) {
- /* reset status flag */
- OPL->status &= ~flag;
- if ((OPL->status & 0x80)) {
- if (!(OPL->status & OPL->statusmask)) {
- OPL->status &= 0x7f;
- /* callback user interrupt handler (IRQ is ON to OFF) */
- if (OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
- }
- }
-}
-
-/* IRQ mask set */
-inline void OPL_STATUSMASK_SET(FM_OPL *OPL, int flag) {
- OPL->statusmask = flag;
- /* IRQ handling check */
- OPL_STATUS_SET(OPL,0);
- OPL_STATUS_RESET(OPL,0);
-}
-
-/* ----- key on ----- */
-inline void OPL_KEYON(OPL_SLOT *SLOT) {
- /* sin wave restart */
- SLOT->Cnt = 0;
- /* set attack */
- SLOT->evm = ENV_MOD_AR;
- SLOT->evs = SLOT->evsa;
- SLOT->evc = EG_AST;
- SLOT->eve = EG_AED;
-}
-
-/* ----- key off ----- */
-inline void OPL_KEYOFF(OPL_SLOT *SLOT) {
- if (SLOT->evm > ENV_MOD_RR) {
- /* set envelope counter from envleope output */
-
- // WORKAROUND: The Kyra engine does something very strange when
- // starting a new song. For each channel:
- //
- // * The release rate is set to "fastest".
- // * Any note is keyed off.
- // * A very low-frequency note is keyed on.
- //
- // Usually, what happens next is that the real notes is keyed
- // on immediately, in which case there's no problem.
- //
- // However, if the note is again keyed off (because the channel
- // begins on a rest rather than a note), the envelope counter
- // was moved from the very lowest point on the attack curve to
- // the very highest point on the release curve.
- //
- // Again, this might not be a problem, if the release rate is
- // still set to "fastest". But in many cases, it had already
- // been increased. And, possibly because of inaccuracies in the
- // envelope generator, that would cause the note to "fade out"
- // for quite a long time.
- //
- // What we really need is a way to find the correct starting
- // point for the envelope counter, and that may be what the
- // commented-out line below is meant to do. For now, simply
- // handle the pathological case.
-
- if (SLOT->evm == ENV_MOD_AR && SLOT->evc == EG_AST)
- SLOT->evc = EG_DED;
- else if (!(SLOT->evc & EG_DST))
- //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
- SLOT->evc = EG_DST;
- SLOT->eve = EG_DED;
- SLOT->evs = SLOT->evsr;
- SLOT->evm = ENV_MOD_RR;
- }
-}
-
-/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
-
-/* return : envelope output */
-inline uint OPL_CALC_SLOT(OPL_SLOT *SLOT) {
- /* calcrate envelope generator */
- if ((SLOT->evc += SLOT->evs) >= SLOT->eve) {
- switch (SLOT->evm) {
- case ENV_MOD_AR: /* ATTACK -> DECAY1 */
- /* next DR */
- SLOT->evm = ENV_MOD_DR;
- SLOT->evc = EG_DST;
- SLOT->eve = SLOT->SL;
- SLOT->evs = SLOT->evsd;
- break;
- case ENV_MOD_DR: /* DECAY -> SL or RR */
- SLOT->evc = SLOT->SL;
- SLOT->eve = EG_DED;
- if (SLOT->eg_typ) {
- SLOT->evs = 0;
- } else {
- SLOT->evm = ENV_MOD_RR;
- SLOT->evs = SLOT->evsr;
- }
- break;
- case ENV_MOD_RR: /* RR -> OFF */
- SLOT->evc = EG_OFF;
- SLOT->eve = EG_OFF + 1;
- SLOT->evs = 0;
- break;
- }
- }
- /* calcrate envelope */
- return SLOT->TLL + ENV_CURVE[SLOT->evc>>ENV_BITS] + (SLOT->ams ? ams : 0);
-}
-
-/* set algorythm connection */
-static void set_algorythm(OPL_CH *CH) {
- int *carrier = &outd[0];
- CH->connect1 = CH->CON ? carrier : &feedback2;
- CH->connect2 = carrier;
-}
-
-/* ---------- frequency counter for operater update ---------- */
-inline void CALC_FCSLOT(OPL_CH *CH, OPL_SLOT *SLOT) {
- int ksr;
-
- /* frequency step counter */
- SLOT->Incr = CH->fc * SLOT->mul;
- ksr = CH->kcode >> SLOT->KSR;
-
- if (SLOT->ksr != ksr) {
- SLOT->ksr = ksr;
- /* attack , decay rate recalcration */
- SLOT->evsa = SLOT->AR[ksr];
- SLOT->evsd = SLOT->DR[ksr];
- SLOT->evsr = SLOT->RR[ksr];
- }
- SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
-}
-
-/* set multi,am,vib,EG-TYP,KSR,mul */
-inline void set_mul(FM_OPL *OPL, int slot, int v) {
- OPL_CH *CH = &OPL->P_CH[slot>>1];
- OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
-
- SLOT->mul = MUL_TABLE[v & 0x0f];
- SLOT->KSR = (v & 0x10) ? 0 : 2;
- SLOT->eg_typ = (v & 0x20) >> 5;
- SLOT->vib = (v & 0x40);
- SLOT->ams = (v & 0x80);
- CALC_FCSLOT(CH, SLOT);
-}
-
-/* set ksl & tl */
-inline void set_ksl_tl(FM_OPL *OPL, int slot, int v) {
- OPL_CH *CH = &OPL->P_CH[slot>>1];
- OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
- int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */
-
- SLOT->ksl = ksl ? 3-ksl : 31;
- SLOT->TL = (int)((v & 0x3f) * (0.75 / EG_STEP)); /* 0.75db step */
-
- if (!(OPL->mode & 0x80)) { /* not CSM latch total level */
- SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
- }
-}
-
-/* set attack rate & decay rate */
-inline void set_ar_dr(FM_OPL *OPL, int slot, int v) {
- OPL_CH *CH = &OPL->P_CH[slot>>1];
- OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
- int ar = v >> 4;
- int dr = v & 0x0f;
-
- SLOT->AR = ar ? &OPL->AR_TABLE[ar << 2] : RATE_0;
- SLOT->evsa = SLOT->AR[SLOT->ksr];
- if (SLOT->evm == ENV_MOD_AR)
- SLOT->evs = SLOT->evsa;
-
- SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
- SLOT->evsd = SLOT->DR[SLOT->ksr];
- if (SLOT->evm == ENV_MOD_DR)
- SLOT->evs = SLOT->evsd;
-}
-
-/* set sustain level & release rate */
-inline void set_sl_rr(FM_OPL *OPL, int slot, int v) {
- OPL_CH *CH = &OPL->P_CH[slot>>1];
- OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
- int sl = v >> 4;
- int rr = v & 0x0f;
-
- SLOT->SL = SL_TABLE[sl];
- if (SLOT->evm == ENV_MOD_DR)
- SLOT->eve = SLOT->SL;
- SLOT->RR = &OPL->DR_TABLE[rr<<2];
- SLOT->evsr = SLOT->RR[SLOT->ksr];
- if (SLOT->evm == ENV_MOD_RR)
- SLOT->evs = SLOT->evsr;
-}
-
-/* operator output calcrator */
-
-#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt + con)>>(24-SIN_ENT_SHIFT)) & (SIN_ENT-1)][env]
-/* ---------- calcrate one of channel ---------- */
-inline void OPL_CALC_CH(OPL_CH *CH) {
- uint env_out;
- OPL_SLOT *SLOT;
-
- feedback2 = 0;
- /* SLOT 1 */
- SLOT = &CH->SLOT[SLOT1];
- env_out=OPL_CALC_SLOT(SLOT);
- if (env_out < (uint)(EG_ENT - 1)) {
- /* PG */
- if (SLOT->vib)
- SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
- else
- SLOT->Cnt += SLOT->Incr;
- /* connection */
- if (CH->FB) {
- int feedback1 = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
- CH->op1_out[1] = CH->op1_out[0];
- *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
- } else {
- *CH->connect1 += OP_OUT(SLOT, env_out, 0);
- }
- } else {
- CH->op1_out[1] = CH->op1_out[0];
- CH->op1_out[0] = 0;
- }
- /* SLOT 2 */
- SLOT = &CH->SLOT[SLOT2];
- env_out=OPL_CALC_SLOT(SLOT);
- if (env_out < (uint)(EG_ENT - 1)) {
- /* PG */
- if (SLOT->vib)
- SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
- else
- SLOT->Cnt += SLOT->Incr;
- /* connection */
- outd[0] += OP_OUT(SLOT, env_out, feedback2);
- }
-}
-
-/* ---------- calcrate rythm block ---------- */
-#define WHITE_NOISE_db 6.0
-inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
- uint env_tam, env_sd, env_top, env_hh;
- // This code used to do int(OPL->rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
- // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
- // int(OPL->rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
- // or 128, so we can safely avoid any FP ops.
- int whitenoise = OPL->rnd.getRandomBit() * (EG_ENT>>4);
-
- int tone8;
-
- OPL_SLOT *SLOT;
- int env_out;
-
- /* BD : same as FM serial mode and output level is large */
- feedback2 = 0;
- /* SLOT 1 */
- SLOT = &CH[6].SLOT[SLOT1];
- env_out = OPL_CALC_SLOT(SLOT);
- if (env_out < EG_ENT-1) {
- /* PG */
- if (SLOT->vib)
- SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
- else
- SLOT->Cnt += SLOT->Incr;
- /* connection */
- if (CH[6].FB) {
- int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
- CH[6].op1_out[1] = CH[6].op1_out[0];
- feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
- }
- else {
- feedback2 = OP_OUT(SLOT, env_out, 0);
- }
- } else {
- feedback2 = 0;
- CH[6].op1_out[1] = CH[6].op1_out[0];
- CH[6].op1_out[0] = 0;
- }
- /* SLOT 2 */
- SLOT = &CH[6].SLOT[SLOT2];
- env_out = OPL_CALC_SLOT(SLOT);
- if (env_out < EG_ENT-1) {
- /* PG */
- if (SLOT->vib)
- SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
- else
- SLOT->Cnt += SLOT->Incr;
- /* connection */
- outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2;
- }
-
- // SD (17) = mul14[fnum7] + white noise
- // TAM (15) = mul15[fnum8]
- // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
- // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
- env_sd = OPL_CALC_SLOT(SLOT7_2) + whitenoise;
- env_tam =OPL_CALC_SLOT(SLOT8_1);
- env_top = OPL_CALC_SLOT(SLOT8_2);
- env_hh = OPL_CALC_SLOT(SLOT7_1) + whitenoise;
-
- /* PG */
- if (SLOT7_1->vib)
- SLOT7_1->Cnt += (SLOT7_1->Incr * vib) >> (VIB_RATE_SHIFT-1);
- else
- SLOT7_1->Cnt += 2 * SLOT7_1->Incr;
- if (SLOT7_2->vib)
- SLOT7_2->Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT-3);
- else
- SLOT7_2->Cnt += (CH[7].fc * 8);
- if (SLOT8_1->vib)
- SLOT8_1->Cnt += (SLOT8_1->Incr * vib) >> VIB_RATE_SHIFT;
- else
- SLOT8_1->Cnt += SLOT8_1->Incr;
- if (SLOT8_2->vib)
- SLOT8_2->Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT-4);
- else
- SLOT8_2->Cnt += (CH[8].fc * 48);
-
- tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
-
- /* SD */
- if (env_sd < (uint)(EG_ENT - 1))
- outd[0] += OP_OUT(SLOT7_1, env_sd, 0) * 8;
- /* TAM */
- if (env_tam < (uint)(EG_ENT - 1))
- outd[0] += OP_OUT(SLOT8_1, env_tam, 0) * 2;
- /* TOP-CY */
- if (env_top < (uint)(EG_ENT - 1))
- outd[0] += OP_OUT(SLOT7_2, env_top, tone8) * 2;
- /* HH */
- if (env_hh < (uint)(EG_ENT-1))
- outd[0] += OP_OUT(SLOT7_2, env_hh, tone8) * 2;
-}
-
-/* ----------- initialize time tabls ----------- */
-static void init_timetables(FM_OPL *OPL, int ARRATE, int DRRATE) {
- int i;
- double rate;
-
- /* make attack rate & decay rate tables */
- for (i = 0; i < 4; i++)
- OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
- for (i = 4; i <= 60; i++) {
- rate = OPL->freqbase; /* frequency rate */
- if (i < 60)
- rate *= 1.0 + (i & 3) * 0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
- rate *= 1 << ((i >> 2) - 1); /* b2-5 : shift bit */
- rate *= (double)(EG_ENT << ENV_BITS);
- OPL->AR_TABLE[i] = (int)(rate / ARRATE);
- OPL->DR_TABLE[i] = (int)(rate / DRRATE);
- }
- for (i = 60; i < 76; i++) {
- OPL->AR_TABLE[i] = EG_AED-1;
- OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
- }
-}
-
-/* ---------- generic table initialize ---------- */
-static int OPLOpenTable(void) {
- int s,t;
- double rate;
- int i,j;
- double pom;
-
-#ifdef __DS__
- DS::fastRamReset();
-
- TL_TABLE = (int *) DS::fastRamAlloc(TL_MAX * 2 * sizeof(int *));
- SIN_TABLE = (int **) DS::fastRamAlloc(SIN_ENT * 4 * sizeof(int *));
-#else
-
- /* allocate dynamic tables */
- if ((TL_TABLE = (int *)malloc(TL_MAX * 2 * sizeof(int))) == NULL)
- return 0;
-
- if ((SIN_TABLE = (int **)malloc(SIN_ENT * 4 * sizeof(int *))) == NULL) {
- free(TL_TABLE);
- return 0;
- }
-#endif
-
- if ((AMS_TABLE = (int *)malloc(AMS_ENT * 2 * sizeof(int))) == NULL) {
- free(TL_TABLE);
- free(SIN_TABLE);
- return 0;
- }
-
- if ((VIB_TABLE = (int *)malloc(VIB_ENT * 2 * sizeof(int))) == NULL) {
- free(TL_TABLE);
- free(SIN_TABLE);
- free(AMS_TABLE);
- return 0;
- }
- /* make total level table */
- for (t = 0; t < EG_ENT - 1; t++) {
- rate = ((1 << TL_BITS) - 1) / pow(10.0, EG_STEP * t / 20); /* dB -> voltage */
- TL_TABLE[ t] = (int)rate;
- TL_TABLE[TL_MAX + t] = -TL_TABLE[t];
- }
- /* fill volume off area */
- for (t = EG_ENT - 1; t < TL_MAX; t++) {
- TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0;
- }
-
- /* make sinwave table (total level offet) */
- /* degree 0 = degree 180 = off */
- SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
- for (s = 1;s <= SIN_ENT / 4; s++) {
- pom = sin(2 * PI * s / SIN_ENT); /* sin */
- pom = 20 * log10(1 / pom); /* decibel */
- j = int(pom / EG_STEP); /* TL_TABLE steps */
-
- /* degree 0 - 90 , degree 180 - 90 : plus section */
- SIN_TABLE[ s] = SIN_TABLE[SIN_ENT / 2 - s] = &TL_TABLE[j];
- /* degree 180 - 270 , degree 360 - 270 : minus section */
- SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = &TL_TABLE[TL_MAX + j];
- }
- for (s = 0;s < SIN_ENT; s++) {
- SIN_TABLE[SIN_ENT * 1 + s] = s < (SIN_ENT / 2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
- SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)];
- SIN_TABLE[SIN_ENT * 3 + s] = (s / (SIN_ENT / 4)) & 1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT * 2 + s];
- }
-
-
- ENV_CURVE = (int *)malloc(sizeof(int) * (2*EG_ENT+1));
-
- /* envelope counter -> envelope output table */
- for (i=0; i < EG_ENT; i++) {
- /* ATTACK curve */
- pom = pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT;
- /* if (pom >= EG_ENT) pom = EG_ENT-1; */
- ENV_CURVE[i] = (int)pom;
- /* DECAY ,RELEASE curve */
- ENV_CURVE[(EG_DST >> ENV_BITS) + i]= i;
- }
- /* off */
- ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
- /* make LFO ams table */
- for (i=0; i < AMS_ENT; i++) {
- pom = (1.0 + sin(2 * PI * i / AMS_ENT)) / 2; /* sin */
- AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */
- AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
- }
- /* make LFO vibrate table */
- for (i=0; i < VIB_ENT; i++) {
- /* 100cent = 1seminote = 6% ?? */
- pom = (double)VIB_RATE * 0.06 * sin(2 * PI * i / VIB_ENT); /* +-100sect step */
- VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
- VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
- }
- return 1;
-}
-
-static void OPLCloseTable(void) {
- free(TL_TABLE);
- free(SIN_TABLE);
- free(AMS_TABLE);
- free(VIB_TABLE);
- free(ENV_CURVE);
-}
-
-/* CSM Key Controll */
-inline void CSMKeyControll(OPL_CH *CH) {
- OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
- OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
- /* all key off */
- OPL_KEYOFF(slot1);
- OPL_KEYOFF(slot2);
- /* total level latch */
- slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
- slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
- /* key on */
- CH->op1_out[0] = CH->op1_out[1] = 0;
- OPL_KEYON(slot1);
- OPL_KEYON(slot2);
-}
-
-/* ---------- opl initialize ---------- */
-static void OPL_initalize(FM_OPL *OPL) {
- int fn;
-
- /* frequency base */
- OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
- /* Timer base time */
- OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
- /* make time tables */
- init_timetables(OPL, OPL_ARRATE, OPL_DRRATE);
- /* make fnumber -> increment counter table */
- for (fn=0; fn < 1024; fn++) {
- OPL->FN_TABLE[fn] = (uint)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2);
- }
- /* LFO freq.table */
- OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT * (1 << AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0);
- OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT * (1 << VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0);
-}
-
-/* ---------- write a OPL registers ---------- */
-void OPLWriteReg(FM_OPL *OPL, int r, int v) {
- OPL_CH *CH;
- int slot;
- uint block_fnum;
-
- switch (r & 0xe0) {
- case 0x00: /* 00-1f:controll */
- switch (r & 0x1f) {
- case 0x01:
- /* wave selector enable */
- if (OPL->type&OPL_TYPE_WAVESEL) {
- OPL->wavesel = v & 0x20;
- if (!OPL->wavesel) {
- /* preset compatible mode */
- int c;
- for (c = 0; c < OPL->max_ch; c++) {
- OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
- OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
- }
- }
- }
- return;
- case 0x02: /* Timer 1 */
- OPL->T[0] = (256-v) * 4;
- break;
- case 0x03: /* Timer 2 */
- OPL->T[1] = (256-v) * 16;
- return;
- case 0x04: /* IRQ clear / mask and Timer enable */
- if (v & 0x80) { /* IRQ flag clear */
- OPL_STATUS_RESET(OPL, 0x7f);
- } else { /* set IRQ mask ,timer enable*/
- uint8 st1 = v & 1;
- uint8 st2 = (v >> 1) & 1;
- /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
- OPL_STATUS_RESET(OPL, v & 0x78);
- OPL_STATUSMASK_SET(OPL,((~v) & 0x78) | 0x01);
- /* timer 2 */
- if (OPL->st[1] != st2) {
- double interval = st2 ? (double)OPL->T[1] * OPL->TimerBase : 0.0;
- OPL->st[1] = st2;
- if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 1, interval);
- }
- /* timer 1 */
- if (OPL->st[0] != st1) {
- double interval = st1 ? (double)OPL->T[0] * OPL->TimerBase : 0.0;
- OPL->st[0] = st1;
- if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 0, interval);
- }
- }
- return;
- }
- break;
- case 0x20: /* am,vib,ksr,eg type,mul */
- slot = slot_array[r&0x1f];
- if (slot == -1)
- return;
- set_mul(OPL,slot,v);
- return;
- case 0x40:
- slot = slot_array[r&0x1f];
- if (slot == -1)
- return;
- set_ksl_tl(OPL,slot,v);
- return;
- case 0x60:
- slot = slot_array[r&0x1f];
- if (slot == -1)
- return;
- set_ar_dr(OPL,slot,v);
- return;
- case 0x80:
- slot = slot_array[r&0x1f];
- if (slot == -1)
- return;
- set_sl_rr(OPL,slot,v);
- return;
- case 0xa0:
- switch (r) {
- case 0xbd:
- /* amsep,vibdep,r,bd,sd,tom,tc,hh */
- {
- uint8 rkey = OPL->rythm ^ v;
- OPL->ams_table = &AMS_TABLE[v & 0x80 ? AMS_ENT : 0];
- OPL->vib_table = &VIB_TABLE[v & 0x40 ? VIB_ENT : 0];
- OPL->rythm = v & 0x3f;
- if (OPL->rythm & 0x20) {
- /* BD key on/off */
- if (rkey & 0x10) {
- if (v & 0x10) {
- OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
- OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
- OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
- } else {
- OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
- OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
- }
- }
- /* SD key on/off */
- if (rkey & 0x08) {
- if (v & 0x08)
- OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
- else
- OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
- }/* TAM key on/off */
- if (rkey & 0x04) {
- if (v & 0x04)
- OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
- else
- OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
- }
- /* TOP-CY key on/off */
- if (rkey & 0x02) {
- if (v & 0x02)
- OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
- else
- OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
- }
- /* HH key on/off */
- if (rkey & 0x01) {
- if (v & 0x01)
- OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
- else
- OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
- }
- }
- }
- return;
-
- default:
- break;
- }
- /* keyon,block,fnum */
- if ((r & 0x0f) > 8)
- return;
- CH = &OPL->P_CH[r & 0x0f];
- if (!(r&0x10)) { /* a0-a8 */
- block_fnum = (CH->block_fnum & 0x1f00) | v;
- } else { /* b0-b8 */
- int keyon = (v >> 5) & 1;
- block_fnum = ((v & 0x1f) << 8) | (CH->block_fnum & 0xff);
- if (CH->keyon != keyon) {
- if ((CH->keyon=keyon)) {
- CH->op1_out[0] = CH->op1_out[1] = 0;
- OPL_KEYON(&CH->SLOT[SLOT1]);
- OPL_KEYON(&CH->SLOT[SLOT2]);
- } else {
- OPL_KEYOFF(&CH->SLOT[SLOT1]);
- OPL_KEYOFF(&CH->SLOT[SLOT2]);
- }
- }
- }
- /* update */
- if (CH->block_fnum != block_fnum) {
- int blockRv = 7 - (block_fnum >> 10);
- int fnum = block_fnum & 0x3ff;
- CH->block_fnum = block_fnum;
- CH->ksl_base = KSL_TABLE[block_fnum >> 6];
- CH->fc = OPL->FN_TABLE[fnum] >> blockRv;
- CH->kcode = CH->block_fnum >> 9;
- if ((OPL->mode & 0x40) && CH->block_fnum & 0x100)
- CH->kcode |=1;
- CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
- CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
- }
- return;
- case 0xc0:
- /* FB,C */
- if ((r & 0x0f) > 8)
- return;
- CH = &OPL->P_CH[r&0x0f];
- {
- int feedback = (v >> 1) & 7;
- CH->FB = feedback ? (8 + 1) - feedback : 0;
- CH->CON = v & 1;
- set_algorythm(CH);
- }
- return;
- case 0xe0: /* wave type */
- slot = slot_array[r & 0x1f];
- if (slot == -1)
- return;
- CH = &OPL->P_CH[slot>>1];
- if (OPL->wavesel) {
- CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT];
- }
- return;
- }
-}
-
-/* lock/unlock for common table */
-static int OPL_LockTable(void) {
- num_lock++;
- if (num_lock>1)
- return 0;
- /* first time */
- cur_chip = NULL;
- /* allocate total level table (128kb space) */
- if (!OPLOpenTable()) {
- num_lock--;
- return -1;
- }
- return 0;
-}
-
-static void OPL_UnLockTable(void) {
- if (num_lock)
- num_lock--;
- if (num_lock)
- return;
- /* last time */
- cur_chip = NULL;
- OPLCloseTable();
-}
-
-/*******************************************************************************/
-/* YM3812 local section */
-/*******************************************************************************/
-
-/* ---------- update one of chip ----------- */
-void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length) {
- int i;
- int data;
- int16 *buf = buffer;
- uint amsCnt = OPL->amsCnt;
- uint vibCnt = OPL->vibCnt;
- uint8 rythm = OPL->rythm & 0x20;
- OPL_CH *CH, *R_CH;
-
-
- if ((void *)OPL != cur_chip) {
- cur_chip = (void *)OPL;
- /* channel pointers */
- S_CH = OPL->P_CH;
- E_CH = &S_CH[9];
- /* rythm slot */
- SLOT7_1 = &S_CH[7].SLOT[SLOT1];
- SLOT7_2 = &S_CH[7].SLOT[SLOT2];
- SLOT8_1 = &S_CH[8].SLOT[SLOT1];
- SLOT8_2 = &S_CH[8].SLOT[SLOT2];
- /* LFO state */
- amsIncr = OPL->amsIncr;
- vibIncr = OPL->vibIncr;
- ams_table = OPL->ams_table;
- vib_table = OPL->vib_table;
- }
- R_CH = rythm ? &S_CH[6] : E_CH;
- for (i = 0; i < length; i++) {
- /* channel A channel B channel C */
- /* LFO */
- ams = ams_table[(amsCnt += amsIncr) >> AMS_SHIFT];
- vib = vib_table[(vibCnt += vibIncr) >> VIB_SHIFT];
- outd[0] = 0;
- /* FM part */
- for (CH = S_CH; CH < R_CH; CH++)
- OPL_CALC_CH(CH);
- /* Rythn part */
- if (rythm)
- OPL_CALC_RH(OPL, S_CH);
- /* limit check */
- data = CLIP(outd[0], OPL_MINOUT, OPL_MAXOUT);
- /* store to sound buffer */
- buf[i] = data >> OPL_OUTSB;
- }
-
- OPL->amsCnt = amsCnt;
- OPL->vibCnt = vibCnt;
-}
-
-/* ---------- reset a chip ---------- */
-void OPLResetChip(FM_OPL *OPL) {
- int c,s;
- int i;
-
- /* reset chip */
- OPL->mode = 0; /* normal mode */
- OPL_STATUS_RESET(OPL, 0x7f);
- /* reset with register write */
- OPLWriteReg(OPL, 0x01,0); /* wabesel disable */
- OPLWriteReg(OPL, 0x02,0); /* Timer1 */
- OPLWriteReg(OPL, 0x03,0); /* Timer2 */
- OPLWriteReg(OPL, 0x04,0); /* IRQ mask clear */
- for (i = 0xff; i >= 0x20; i--)
- OPLWriteReg(OPL,i,0);
- /* reset OPerator parameter */
- for (c = 0; c < OPL->max_ch; c++) {
- OPL_CH *CH = &OPL->P_CH[c];
- /* OPL->P_CH[c].PAN = OPN_CENTER; */
- for (s = 0; s < 2; s++) {
- /* wave table */
- CH->SLOT[s].wavetable = &SIN_TABLE[0];
- /* CH->SLOT[s].evm = ENV_MOD_RR; */
- CH->SLOT[s].evc = EG_OFF;
- CH->SLOT[s].eve = EG_OFF + 1;
- CH->SLOT[s].evs = 0;
- }
- }
-}
-
-/* ---------- Create a virtual YM3812 ---------- */
-/* 'rate' is sampling rate and 'bufsiz' is the size of the */
-FM_OPL *OPLCreate(int type, int clock, int rate) {
- char *ptr;
- FM_OPL *OPL;
- int state_size;
- int max_ch = 9; /* normaly 9 channels */
-
- if (OPL_LockTable() == -1)
- return NULL;
- /* allocate OPL state space */
- state_size = sizeof(FM_OPL);
- state_size += sizeof(OPL_CH) * max_ch;
-
- /* allocate memory block */
- ptr = (char *)calloc(state_size, 1);
- if (ptr == NULL)
- return NULL;
-
- /* clear */
- memset(ptr, 0, state_size);
- OPL = (FM_OPL *)ptr; ptr += sizeof(FM_OPL);
- OPL->P_CH = (OPL_CH *)ptr; ptr += sizeof(OPL_CH) * max_ch;
-
- /* set channel state pointer */
- OPL->type = type;
- OPL->clock = clock;
- OPL->rate = rate;
- OPL->max_ch = max_ch;
-
- /* init grobal tables */
- OPL_initalize(OPL);
-
- /* reset chip */
- OPLResetChip(OPL);
- return OPL;
-}
-
-/* ---------- Destroy one of vietual YM3812 ---------- */
-void OPLDestroy(FM_OPL *OPL) {
- OPL_UnLockTable();
- free(OPL);
-}
-
-/* ---------- Option handlers ---------- */
-void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler,int channelOffset) {
- OPL->TimerHandler = TimerHandler;
- OPL->TimerParam = channelOffset;
-}
-
-void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param) {
- OPL->IRQHandler = IRQHandler;
- OPL->IRQParam = param;
-}
-
-void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler,int param) {
- OPL->UpdateHandler = UpdateHandler;
- OPL->UpdateParam = param;
-}
-
-/* ---------- YM3812 I/O interface ---------- */
-int OPLWrite(FM_OPL *OPL,int a,int v) {
- if (!(a & 1)) { /* address port */
- OPL->address = v & 0xff;
- } else { /* data port */
- if (OPL->UpdateHandler)
- OPL->UpdateHandler(OPL->UpdateParam,0);
- OPLWriteReg(OPL, OPL->address,v);
- }
- return OPL->status >> 7;
-}
-
-unsigned char OPLRead(FM_OPL *OPL,int a) {
- if (!(a & 1)) { /* status port */
- return OPL->status & (OPL->statusmask | 0x80);
- }
- /* data port */
- switch (OPL->address) {
- case 0x05: /* KeyBoard IN */
- warning("OPL:read unmapped KEYBOARD port");
- return 0;
- case 0x19: /* I/O DATA */
- warning("OPL:read unmapped I/O port");
- return 0;
- case 0x1a: /* PCM-DATA */
- return 0;
- default:
- break;
- }
- return 0;
-}
-
-int OPLTimerOver(FM_OPL *OPL, int c) {
- if (c) { /* Timer B */
- OPL_STATUS_SET(OPL, 0x20);
- } else { /* Timer A */
- OPL_STATUS_SET(OPL, 0x40);
- /* CSM mode key,TL controll */
- if (OPL->mode & 0x80) { /* CSM mode total level latch and auto key on */
- int ch;
- if (OPL->UpdateHandler)
- OPL->UpdateHandler(OPL->UpdateParam,0);
- for (ch = 0; ch < 9; ch++)
- CSMKeyControll(&OPL->P_CH[ch]);
- }
- }
- /* reload timer */
- if (OPL->TimerHandler)
- (OPL->TimerHandler)(OPL->TimerParam + c, (double)OPL->T[c] * OPL->TimerBase);
- return OPL->status >> 7;
-}
-
-FM_OPL *makeAdLibOPL(int rate) {
- // We need to emulate one YM3812 chip
- int env_bits = FMOPL_ENV_BITS_HQ;
- int eg_ent = FMOPL_EG_ENT_HQ;
-#if defined (_WIN32_WCE) || defined(__SYMBIAN32__) || defined(__GP32__) || defined (GP2X) || defined(__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__)
- if (ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) {
- env_bits = FMOPL_ENV_BITS_HQ;
- eg_ent = FMOPL_EG_ENT_HQ;
- } else if (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")) {
- env_bits = FMOPL_ENV_BITS_MQ;
- eg_ent = FMOPL_EG_ENT_MQ;
- } else {
- env_bits = FMOPL_ENV_BITS_LQ;
- eg_ent = FMOPL_EG_ENT_LQ;
- }
-#endif
-
- OPLBuildTables(env_bits, eg_ent);
- return OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
-}
-
-} // End of namespace MAME
-} // End of namespace OPL
-
diff --git a/sound/softsynth/opl/mame.h b/sound/softsynth/opl/mame.h
deleted file mode 100644
index ec812d0c4e..0000000000
--- a/sound/softsynth/opl/mame.h
+++ /dev/null
@@ -1,202 +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$
- *
- * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
- * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
- */
-
-
-#ifndef SOUND_SOFTSYNTH_OPL_MAME_H
-#define SOUND_SOFTSYNTH_OPL_MAME_H
-
-#include "common/scummsys.h"
-#include "common/util.h"
-#include "common/random.h"
-
-#include "sound/fmopl.h"
-
-namespace OPL {
-namespace MAME {
-
-enum {
- FMOPL_ENV_BITS_HQ = 16,
- FMOPL_ENV_BITS_MQ = 8,
- FMOPL_ENV_BITS_LQ = 8,
- FMOPL_EG_ENT_HQ = 4096,
- FMOPL_EG_ENT_MQ = 1024,
- FMOPL_EG_ENT_LQ = 128
-};
-
-
-typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
-typedef void (*OPL_IRQHANDLER)(int param,int irq);
-typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
-
-#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
-
-/* Saving is necessary for member of the 'R' mark for suspend/resume */
-/* ---------- OPL one of slot ---------- */
-typedef struct fm_opl_slot {
- int TL; /* total level :TL << 8 */
- int TLL; /* adjusted now TL */
- uint8 KSR; /* key scale rate :(shift down bit) */
- int *AR; /* attack rate :&AR_TABLE[AR<<2] */
- int *DR; /* decay rate :&DR_TABLE[DR<<2] */
- int SL; /* sustain level :SL_TABLE[SL] */
- int *RR; /* release rate :&DR_TABLE[RR<<2] */
- uint8 ksl; /* keyscale level :(shift down bits) */
- uint8 ksr; /* key scale rate :kcode>>KSR */
- uint mul; /* multiple :ML_TABLE[ML] */
- uint Cnt; /* frequency count */
- uint Incr; /* frequency step */
-
- /* envelope generator state */
- uint8 eg_typ;/* envelope type flag */
- uint8 evm; /* envelope phase */
- int evc; /* envelope counter */
- int eve; /* envelope counter end point */
- int evs; /* envelope counter step */
- int evsa; /* envelope step for AR :AR[ksr] */
- int evsd; /* envelope step for DR :DR[ksr] */
- int evsr; /* envelope step for RR :RR[ksr] */
-
- /* LFO */
- uint8 ams; /* ams flag */
- uint8 vib; /* vibrate flag */
- /* wave selector */
- int **wavetable;
-} OPL_SLOT;
-
-/* ---------- OPL one of channel ---------- */
-typedef struct fm_opl_channel {
- OPL_SLOT SLOT[2];
- uint8 CON; /* connection type */
- uint8 FB; /* feed back :(shift down bit)*/
- int *connect1; /* slot1 output pointer */
- int *connect2; /* slot2 output pointer */
- int op1_out[2]; /* slot1 output for selfeedback */
-
- /* phase generator state */
- uint block_fnum; /* block+fnum */
- uint8 kcode; /* key code : KeyScaleCode */
- uint fc; /* Freq. Increment base */
- uint ksl_base; /* KeyScaleLevel Base step */
- uint8 keyon; /* key on/off flag */
-} OPL_CH;
-
-/* OPL state */
-typedef struct fm_opl_f {
- uint8 type; /* chip type */
- int clock; /* master clock (Hz) */
- int rate; /* sampling rate (Hz) */
- double freqbase; /* frequency base */
- double TimerBase; /* Timer base time (==sampling time) */
- uint8 address; /* address register */
- uint8 status; /* status flag */
- uint8 statusmask; /* status mask */
- uint mode; /* Reg.08 : CSM , notesel,etc. */
-
- /* Timer */
- int T[2]; /* timer counter */
- uint8 st[2]; /* timer enable */
-
- /* FM channel slots */
- OPL_CH *P_CH; /* pointer of CH */
- int max_ch; /* maximum channel */
-
- /* Rythm sention */
- uint8 rythm; /* Rythm mode , key flag */
-
- /* time tables */
- int AR_TABLE[76]; /* atttack rate tables */
- int DR_TABLE[76]; /* decay rate tables */
- uint FN_TABLE[1024];/* fnumber -> increment counter */
-
- /* LFO */
- int *ams_table;
- int *vib_table;
- int amsCnt;
- int amsIncr;
- int vibCnt;
- int vibIncr;
-
- /* wave selector enable flag */
- uint8 wavesel;
-
- /* external event callback handler */
- OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
- int TimerParam; /* TIMER parameter */
- OPL_IRQHANDLER IRQHandler; /* IRQ handler */
- int IRQParam; /* IRQ parameter */
- OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
- int UpdateParam; /* stream update parameter */
-
- Common::RandomSource rnd;
-} FM_OPL;
-
-/* ---------- Generic interface section ---------- */
-#define OPL_TYPE_YM3526 (0)
-#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
-
-void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM);
-
-FM_OPL *OPLCreate(int type, int clock, int rate);
-void OPLDestroy(FM_OPL *OPL);
-void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler, int channelOffset);
-void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param);
-void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler, int param);
-
-void OPLResetChip(FM_OPL *OPL);
-int OPLWrite(FM_OPL *OPL, int a, int v);
-unsigned char OPLRead(FM_OPL *OPL, int a);
-int OPLTimerOver(FM_OPL *OPL, int c);
-void OPLWriteReg(FM_OPL *OPL, int r, int v);
-void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length);
-
-// Factory method
-FM_OPL *makeAdLibOPL(int rate);
-
-// OPL API implementation
-class OPL : public ::OPL::OPL {
-private:
- FM_OPL *_opl;
-public:
- OPL() : _opl(0) {}
- ~OPL();
-
- bool init(int rate);
- void reset();
-
- void write(int a, int v);
- byte read(int a);
-
- void writeReg(int r, int v);
-
- void readBuffer(int16 *buffer, int length);
- bool isStereo() const { return false; }
-};
-
-} // End of namespace MAME
-} // End of namespace OPL
-
-#endif
diff --git a/sound/softsynth/pcspk.cpp b/sound/softsynth/pcspk.cpp
deleted file mode 100644
index bdf9f112e8..0000000000
--- a/sound/softsynth/pcspk.cpp
+++ /dev/null
@@ -1,187 +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$
-*
-*/
-
-#include "sound/softsynth/pcspk.h"
-#include "sound/null.h"
-
-namespace Audio {
-
-const PCSpeaker::generatorFunc PCSpeaker::generateWave[] =
- {&PCSpeaker::generateSquare, &PCSpeaker::generateSine,
- &PCSpeaker::generateSaw, &PCSpeaker::generateTriangle};
-
-PCSpeaker::PCSpeaker(int rate) {
- _rate = rate;
- _wave = kWaveFormSquare;
- _playForever = false;
- _oscLength = 0;
- _oscSamples = 0;
- _remainingSamples = 0;
- _mixedSamples = 0;
- _volume = 255;
-}
-
-PCSpeaker::~PCSpeaker() {
-}
-
-void PCSpeaker::play(WaveForm wave, int freq, int32 length) {
- Common::StackLock lock(_mutex);
-
- assert((wave >= kWaveFormSquare) && (wave <= kWaveFormTriangle));
-
- _wave = wave;
- _oscLength = _rate / freq;
- _oscSamples = 0;
- if (length == -1) {
- _remainingSamples = 1;
- _playForever = true;
- } else {
- _remainingSamples = (_rate * length) / 1000;
- _playForever = false;
- }
- _mixedSamples = 0;
-}
-
-void PCSpeaker::stop(int32 delay) {
- Common::StackLock lock(_mutex);
-
- _remainingSamples = (_rate * delay) / 1000;
- _playForever = false;
-}
-
-void PCSpeaker::setVolume(byte volume) {
- _volume = volume;
-}
-
-bool PCSpeaker::isPlaying() const {
- return _remainingSamples != 0;
-}
-
-int PCSpeaker::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock lock(_mutex);
-
- int i;
-
- for (i = 0; _remainingSamples && (i < numSamples); i++) {
- buffer[i] = generateWave[_wave](_oscSamples, _oscLength) * _volume;
- if (_oscSamples++ >= _oscLength)
- _oscSamples = 0;
- if (!_playForever)
- _remainingSamples--;
- _mixedSamples++;
- }
-
- // Clear the rest of the buffer
- if (i < numSamples)
- memset(buffer + i, 0, (numSamples - i) * sizeof(int16));
-
- return numSamples;
-}
-
-int8 PCSpeaker::generateSquare(uint32 x, uint32 oscLength) {
- return (x < (oscLength / 2)) ? 127 : -128;
-}
-
-int8 PCSpeaker::generateSine(uint32 x, uint32 oscLength) {
- if (oscLength == 0)
- return 0;
-
- // TODO: Maybe using a look-up-table would be better?
- return CLIP<int16>((int16) (128 * sin(2.0 * PI * x / oscLength)), -128, 127);
-}
-
-int8 PCSpeaker::generateSaw(uint32 x, uint32 oscLength) {
- if (oscLength == 0)
- return 0;
-
- return ((x * (65536 / oscLength)) >> 8) - 128;
-}
-
-int8 PCSpeaker::generateTriangle(uint32 x, uint32 oscLength) {
- if (oscLength == 0)
- return 0;
-
- int y = ((x * (65536 / (oscLength / 2))) >> 8) - 128;
-
- return (x <= (oscLength / 2)) ? y : (256 - y);
-}
-
-} // End of namespace Audio
-
-
-// Plugin interface
-// (This can only create a null driver since pc speaker support is not part of the
-// midi driver architecture. But we need the plugin for the options menu in the launcher
-// and for MidiDriver::detectDevice() which is more or less used by all engines.)
-
-class PCSpeakerMusicPlugin : public NullMusicPlugin {
-public:
- const char *getName() const {
- return _s("PC Speaker Emulator");
- }
-
- const char *getId() const {
- return "pcspk";
- }
-
- MusicDevices getDevices() const;
-};
-
-MusicDevices PCSpeakerMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_PCSPK));
- return devices;
-}
-
-class PCjrMusicPlugin : public NullMusicPlugin {
-public:
- const char *getName() const {
- return _s("IBM PCjr Emulator");
- }
-
- const char *getId() const {
- return "pcjr";
- }
-
- MusicDevices getDevices() const;
-};
-
-MusicDevices PCjrMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_PCJR));
- return devices;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(PCSPK)
- //REGISTER_PLUGIN_DYNAMIC(PCSPK, PLUGIN_TYPE_MUSIC, PCSpeakerMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(PCSPK, PLUGIN_TYPE_MUSIC, PCSpeakerMusicPlugin);
-//#endif
-
-//#if PLUGIN_ENABLED_DYNAMIC(PCJR)
- //REGISTER_PLUGIN_DYNAMIC(PCJR, PLUGIN_TYPE_MUSIC, PCjrMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(PCJR, PLUGIN_TYPE_MUSIC, PCjrMusicPlugin);
-//#endif
diff --git a/sound/softsynth/pcspk.h b/sound/softsynth/pcspk.h
deleted file mode 100644
index 3cd8734a7e..0000000000
--- a/sound/softsynth/pcspk.h
+++ /dev/null
@@ -1,88 +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$
- */
-
-#ifndef SOUND_SOFTSYNTH_PCSPK_H
-#define SOUND_SOFTSYNTH_PCSPK_H
-
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "common/mutex.h"
-
-namespace Audio {
-
-class PCSpeaker : public AudioStream {
-public:
- enum WaveForm {
- kWaveFormSquare = 0,
- kWaveFormSine,
- kWaveFormSaw,
- kWaveFormTriangle
- };
-
- PCSpeaker(int rate = 44100);
- ~PCSpeaker();
-
- /** Play a note for length ms.
- *
- * If length is negative, play until told to stop.
- */
- void play(WaveForm wave, int freq, int32 length);
- /** Stop the currently playing note after delay ms. */
- void stop(int32 delay = 0);
- /** Adjust the volume. */
- void setVolume(byte volume);
-
- bool isPlaying() const;
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool isStereo() const { return false; }
- bool endOfData() const { return false; }
- bool endOfStream() const { return false; }
- int getRate() const { return _rate; }
-
-protected:
- Common::Mutex _mutex;
-
- int _rate;
- WaveForm _wave;
- bool _playForever;
- uint32 _oscLength;
- uint32 _oscSamples;
- uint32 _remainingSamples;
- uint32 _mixedSamples;
- byte _volume;
-
- typedef int8 (*generatorFunc)(uint32, uint32);
- static const generatorFunc generateWave[];
-
- static int8 generateSquare(uint32 x, uint32 oscLength);
- static int8 generateSine(uint32 x, uint32 oscLength);
- static int8 generateSaw(uint32 x, uint32 oscLength);
- static int8 generateTriangle(uint32 x, uint32 oscLength);
-};
-
-} // End of namespace Audio
-
-#endif // SOUND_SOFTSYNTH_PCSPEAKER_H
diff --git a/sound/softsynth/sid.cpp b/sound/softsynth/sid.cpp
deleted file mode 100644
index c05ae2e8f5..0000000000
--- a/sound/softsynth/sid.cpp
+++ /dev/null
@@ -1,1456 +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$
- *
- */
-
-/*
- * This file is based on reSID, a MOS6581 SID emulator engine.
- * Copyright (C) 2004 Dag Lem <resid@nimrod.no>
- */
-
-#ifndef DISABLE_SID
-
-#include "sid.h"
-#include "sound/null.h"
-#include <math.h>
-
-namespace Resid {
-
-// Fixpoint constants (16.16 bits).
-const int SID::FIXP_SHIFT = 16;
-const int SID::FIXP_MASK = 0xffff;
-
-/*
- * WaveformGenerator
- */
-
-WaveformGenerator::WaveformGenerator() {
- sync_source = this;
-
- reset();
-}
-
-void WaveformGenerator::set_sync_source(WaveformGenerator* source) {
- sync_source = source;
- source->sync_dest = this;
-}
-
-void WaveformGenerator::writeFREQ_LO(reg8 freq_lo) {
- freq = (freq & 0xff00) | (freq_lo & 0x00ff);
-}
-
-void WaveformGenerator::writeFREQ_HI(reg8 freq_hi) {
- freq = ((freq_hi << 8) & 0xff00) | (freq & 0x00ff);
-}
-
-void WaveformGenerator::writePW_LO(reg8 pw_lo) {
- pw = (pw & 0xf00) | (pw_lo & 0x0ff);
-}
-
-void WaveformGenerator::writePW_HI(reg8 pw_hi) {
- pw = ((pw_hi << 8) & 0xf00) | (pw & 0x0ff);
-}
-
-void WaveformGenerator::writeCONTROL_REG(reg8 control) {
- waveform = (control >> 4) & 0x0f;
- ring_mod = control & 0x04;
- sync = control & 0x02;
-
- reg8 test_next = control & 0x08;
-
- // Test bit set.
- if (test_next) {
- accumulator = 0;
- shift_register = 0;
- }
- // Test bit cleared.
- else if (test) {
- shift_register = 0x7ffff8;
- }
-
- test = test_next;
-
- // The gate bit is handled by the EnvelopeGenerator.
-}
-
-reg8 WaveformGenerator::readOSC() {
- return output() >> 4;
-}
-
-void WaveformGenerator::reset() {
- accumulator = 0;
- shift_register = 0x7ffff8;
- freq = 0;
- pw = 0;
-
- test = 0;
- ring_mod = 0;
- sync = 0;
-
- msb_rising = false;
-}
-
-RESID_INLINE void WaveformGenerator::clock(cycle_count delta_t) {
- // No operation if test bit is set.
- if (test) {
- return;
- }
-
- reg24 accumulator_prev = accumulator;
-
- // Calculate new accumulator value;
- reg24 delta_accumulator = delta_t*freq;
- accumulator += delta_accumulator;
- accumulator &= 0xffffff;
-
- // Check whether the MSB is set high. This is used for synchronization.
- msb_rising = !(accumulator_prev & 0x800000) && (accumulator & 0x800000);
-
- // Shift noise register once for each time accumulator bit 19 is set high.
- // Bit 19 is set high each time 2^20 (0x100000) is added to the accumulator.
- reg24 shift_period = 0x100000;
-
- while (delta_accumulator) {
- if (delta_accumulator < shift_period) {
- shift_period = delta_accumulator;
- // Determine whether bit 19 is set on the last period.
- // NB! Requires two's complement integer.
- if (shift_period <= 0x080000) {
- // Check for flip from 0 to 1.
- if (((accumulator - shift_period) & 0x080000) || !(accumulator & 0x080000))
- {
- break;
- }
- }
- else {
- // Check for flip from 0 (to 1 or via 1 to 0) or from 1 via 0 to 1.
- if (((accumulator - shift_period) & 0x080000) && !(accumulator & 0x080000))
- {
- break;
- }
- }
- }
-
- // Shift the noise/random register.
- // NB! The shift is actually delayed 2 cycles, this is not modeled.
- reg24 bit0 = ((shift_register >> 22) ^ (shift_register >> 17)) & 0x1;
- shift_register <<= 1;
- shift_register &= 0x7fffff;
- shift_register |= bit0;
-
- delta_accumulator -= shift_period;
- }
-}
-
-
-/**
- * Synchronize oscillators.
- * This must be done after all the oscillators have been clock()'ed since the
- * oscillators operate in parallel.
- * Note that the oscillators must be clocked exactly on the cycle when the
- * MSB is set high for hard sync to operate correctly. See SID::clock().
- */
-RESID_INLINE void WaveformGenerator::synchronize() {
- // A special case occurs when a sync source is synced itself on the same
- // cycle as when its MSB is set high. In this case the destination will
- // not be synced. This has been verified by sampling OSC3.
- if (msb_rising && sync_dest->sync && !(sync && sync_source->msb_rising)) {
- sync_dest->accumulator = 0;
- }
-}
-
-
-/*
- * Output functions
- */
-
-// No waveform: Zero output.
-RESID_INLINE reg12 WaveformGenerator::output____() {
- return 0x000;
-}
-
-// Triangle:
-RESID_INLINE reg12 WaveformGenerator::output___T() {
- reg24 msb = (ring_mod ? accumulator ^ sync_source->accumulator : accumulator)
- & 0x800000;
- return ((msb ? ~accumulator : accumulator) >> 11) & 0xfff;
-}
-
-// Sawtooth:
-RESID_INLINE reg12 WaveformGenerator::output__S_() {
- return accumulator >> 12;
-}
-
-// Pulse:
-RESID_INLINE reg12 WaveformGenerator::output_P__() {
- return (test || (accumulator >> 12) >= pw) ? 0xfff : 0x000;
-}
-
-// Noise:
-RESID_INLINE reg12 WaveformGenerator::outputN___() {
- return
- ((shift_register & 0x400000) >> 11) |
- ((shift_register & 0x100000) >> 10) |
- ((shift_register & 0x010000) >> 7) |
- ((shift_register & 0x002000) >> 5) |
- ((shift_register & 0x000800) >> 4) |
- ((shift_register & 0x000080) >> 1) |
- ((shift_register & 0x000010) << 1) |
- ((shift_register & 0x000004) << 2);
-}
-
-// Combined waveforms:
-
-RESID_INLINE reg12 WaveformGenerator::output__ST() {
- return wave6581__ST[output__S_()] << 4;
-}
-
-RESID_INLINE reg12 WaveformGenerator::output_P_T() {
- return (wave6581_P_T[output___T() >> 1] << 4) & output_P__();
-}
-
-RESID_INLINE reg12 WaveformGenerator::output_PS_() {
- return (wave6581_PS_[output__S_()] << 4) & output_P__();
-}
-
-RESID_INLINE reg12 WaveformGenerator::output_PST() {
- return (wave6581_PST[output__S_()] << 4) & output_P__();
-}
-
-// Combined waveforms including noise:
-
-RESID_INLINE reg12 WaveformGenerator::outputN__T() {
- return 0;
-}
-
-RESID_INLINE reg12 WaveformGenerator::outputN_S_() {
- return 0;
-}
-
-RESID_INLINE reg12 WaveformGenerator::outputN_ST() {
- return 0;
-}
-
-RESID_INLINE reg12 WaveformGenerator::outputNP__() {
- return 0;
-}
-
-RESID_INLINE reg12 WaveformGenerator::outputNP_T() {
- return 0;
-}
-
-RESID_INLINE reg12 WaveformGenerator::outputNPS_() {
- return 0;
-}
-
-RESID_INLINE reg12 WaveformGenerator::outputNPST() {
- return 0;
-}
-
-/**
- * Select one of 16 possible combinations of waveforms.
- */
-RESID_INLINE reg12 WaveformGenerator::output() {
- // It may seem cleaner to use an array of member functions to return
- // waveform output; however a switch with inline functions is faster.
-
- switch (waveform) {
- default:
- case 0x0:
- return output____();
- case 0x1:
- return output___T();
- case 0x2:
- return output__S_();
- case 0x3:
- return output__ST();
- case 0x4:
- return output_P__();
- case 0x5:
- return output_P_T();
- case 0x6:
- return output_PS_();
- case 0x7:
- return output_PST();
- case 0x8:
- return outputN___();
- case 0x9:
- return outputN__T();
- case 0xa:
- return outputN_S_();
- case 0xb:
- return outputN_ST();
- case 0xc:
- return outputNP__();
- case 0xd:
- return outputNP_T();
- case 0xe:
- return outputNPS_();
- case 0xf:
- return outputNPST();
- }
-}
-
-/*
- * Our objective is to construct a smooth interpolating single-valued function
- * y = f(x).
- * Our approach is to approximate the properties of Catmull-Rom splines for
- * piecewice cubic polynomials.
- */
-
-/**
- * Calculation of coefficients.
- */
-inline void cubic_coefficients(double x1, double y1, double x2, double y2,
- double k1, double k2,
- double& a, double& b, double& c, double& d)
-{
- double dx = x2 - x1, dy = y2 - y1;
-
- a = ((k1 + k2) - 2*dy/dx)/(dx*dx);
- b = ((k2 - k1)/dx - 3*(x1 + x2)*a)/2;
- c = k1 - (3*x1*a + 2*b)*x1;
- d = y1 - ((x1*a + b)*x1 + c)*x1;
-}
-
-/**
- * Evaluation of cubic polynomial by forward differencing.
- */
-template<class PointPlotter>
-inline void interpolate_segment(double x1, double y1, double x2, double y2,
- double k1, double k2,
- PointPlotter plot, double res)
-{
- double a, b, c, d;
- cubic_coefficients(x1, y1, x2, y2, k1, k2, a, b, c, d);
-
- double y = ((a*x1 + b)*x1 + c)*x1 + d;
- double dy = (3*a*(x1 + res) + 2*b)*x1*res + ((a*res + b)*res + c)*res;
- double d2y = (6*a*(x1 + res) + 2*b)*res*res;
- double d3y = 6*a*res*res*res;
-
- // Calculate each point.
- for (double x = x1; x <= x2; x += res) {
- plot(x, y);
- y += dy; dy += d2y; d2y += d3y;
- }
-}
-
-template<class PointIter>
-inline double x(PointIter p) {
- return (*p)[0];
-}
-
-template<class PointIter>
-inline double y(PointIter p) {
- return (*p)[1];
-}
-
-/**
- * Evaluation of complete interpolating function.
- * Note that since each curve segment is controlled by four points, the
- * end points will not be interpolated. If extra control points are not
- * desirable, the end points can simply be repeated to ensure interpolation.
- * Note also that points of non-differentiability and discontinuity can be
- * introduced by repeating points.
- */
-template<class PointIter, class PointPlotter>
-inline void interpolate(PointIter p0, PointIter pn, PointPlotter plot, double res) {
- double k1, k2;
-
- // Set up points for first curve segment.
- PointIter p1 = p0; ++p1;
- PointIter p2 = p1; ++p2;
- PointIter p3 = p2; ++p3;
-
- // Draw each curve segment.
- for (; p2 != pn; ++p0, ++p1, ++p2, ++p3) {
- // p1 and p2 equal; single point.
- if (x(p1) == x(p2)) {
- continue;
- }
- // Both end points repeated; straight line.
- if (x(p0) == x(p1) && x(p2) == x(p3)) {
- k1 = k2 = (y(p2) - y(p1))/(x(p2) - x(p1));
- }
- // p0 and p1 equal; use f''(x1) = 0.
- else if (x(p0) == x(p1)) {
- k2 = (y(p3) - y(p1))/(x(p3) - x(p1));
- k1 = (3*(y(p2) - y(p1))/(x(p2) - x(p1)) - k2)/2;
- }
- // p2 and p3 equal; use f''(x2) = 0.
- else if (x(p2) == x(p3)) {
- k1 = (y(p2) - y(p0))/(x(p2) - x(p0));
- k2 = (3*(y(p2) - y(p1))/(x(p2) - x(p1)) - k1)/2;
- }
- // Normal curve.
- else {
- k1 = (y(p2) - y(p0))/(x(p2) - x(p0));
- k2 = (y(p3) - y(p1))/(x(p3) - x(p1));
- }
-
- interpolate_segment(x(p1), y(p1), x(p2), y(p2), k1, k2, plot, res);
- }
-}
-
-/**
- * Class for plotting integers into an array.
- */
-template<class F>
-class PointPlotter {
-protected:
- F* f;
-
-public:
- PointPlotter(F* arr) : f(arr) {
- }
-
- void operator ()(double x, double y) {
- // Clamp negative values to zero.
- if (y < 0) {
- y = 0;
- }
-
- f[F(x)] = F(y);
- }
-};
-
-fc_point Filter::f0_points_6581[] = {
- // FC f FCHI FCLO
- // ----------------------------
- { 0, 220 }, // 0x00 - repeated end point
- { 0, 220 }, // 0x00
- { 128, 230 }, // 0x10
- { 256, 250 }, // 0x20
- { 384, 300 }, // 0x30
- { 512, 420 }, // 0x40
- { 640, 780 }, // 0x50
- { 768, 1600 }, // 0x60
- { 832, 2300 }, // 0x68
- { 896, 3200 }, // 0x70
- { 960, 4300 }, // 0x78
- { 992, 5000 }, // 0x7c
- { 1008, 5400 }, // 0x7e
- { 1016, 5700 }, // 0x7f
- { 1023, 6000 }, // 0x7f 0x07
- { 1023, 6000 }, // 0x7f 0x07 - discontinuity
- { 1024, 4600 }, // 0x80 -
- { 1024, 4600 }, // 0x80
- { 1032, 4800 }, // 0x81
- { 1056, 5300 }, // 0x84
- { 1088, 6000 }, // 0x88
- { 1120, 6600 }, // 0x8c
- { 1152, 7200 }, // 0x90
- { 1280, 9500 }, // 0xa0
- { 1408, 12000 }, // 0xb0
- { 1536, 14500 }, // 0xc0
- { 1664, 16000 }, // 0xd0
- { 1792, 17100 }, // 0xe0
- { 1920, 17700 }, // 0xf0
- { 2047, 18000 }, // 0xff 0x07
- { 2047, 18000 } // 0xff 0x07 - repeated end point
-};
-
-
-/*
- * Filter
- */
-
-Filter::Filter() {
- fc = 0;
-
- res = 0;
-
- filt = 0;
-
- voice3off = 0;
-
- hp_bp_lp = 0;
-
- vol = 0;
-
- // State of filter.
- Vhp = 0;
- Vbp = 0;
- Vlp = 0;
- Vnf = 0;
-
- enable_filter(true);
-
- // Create mappings from FC to cutoff frequency.
- interpolate(f0_points_6581, f0_points_6581
- + sizeof(f0_points_6581)/sizeof(*f0_points_6581) - 1,
- PointPlotter<sound_sample>(f0_6581), 1.0);
-
- mixer_DC = (-0xfff*0xff/18) >> 7;
-
- f0 = f0_6581;
- f0_points = f0_points_6581;
- f0_count = sizeof(f0_points_6581)/sizeof(*f0_points_6581);
-
- set_w0();
- set_Q();
-}
-
-void Filter::enable_filter(bool enable) {
- enabled = enable;
-}
-
-void Filter::reset(){
- fc = 0;
-
- res = 0;
-
- filt = 0;
-
- voice3off = 0;
-
- hp_bp_lp = 0;
-
- vol = 0;
-
- // State of filter.
- Vhp = 0;
- Vbp = 0;
- Vlp = 0;
- Vnf = 0;
-
- set_w0();
- set_Q();
-}
-
-void Filter::writeFC_LO(reg8 fc_lo) {
- fc = (fc & 0x7f8) | (fc_lo & 0x007);
- set_w0();
-}
-
-void Filter::writeFC_HI(reg8 fc_hi) {
- fc = ((fc_hi << 3) & 0x7f8) | (fc & 0x007);
- set_w0();
-}
-
-void Filter::writeRES_FILT(reg8 res_filt) {
- res = (res_filt >> 4) & 0x0f;
- set_Q();
-
- filt = res_filt & 0x0f;
-}
-
-void Filter::writeMODE_VOL(reg8 mode_vol) {
- voice3off = mode_vol & 0x80;
-
- hp_bp_lp = (mode_vol >> 4) & 0x07;
-
- vol = mode_vol & 0x0f;
-}
-
-// Set filter cutoff frequency.
-void Filter::set_w0() {
- const double pi = 3.1415926535897932385;
-
- // Multiply with 1.048576 to facilitate division by 1 000 000 by right-
- // shifting 20 times (2 ^ 20 = 1048576).
- w0 = static_cast<sound_sample>(2*pi*f0[fc]*1.048576);
-
- // Limit f0 to 16kHz to keep 1 cycle filter stable.
- const sound_sample w0_max_1 = static_cast<sound_sample>(2*pi*16000*1.048576);
- w0_ceil_1 = w0 <= w0_max_1 ? w0 : w0_max_1;
-
- // Limit f0 to 4kHz to keep delta_t cycle filter stable.
- const sound_sample w0_max_dt = static_cast<sound_sample>(2*pi*4000*1.048576);
- w0_ceil_dt = w0 <= w0_max_dt ? w0 : w0_max_dt;
-}
-
-// Set filter resonance.
-void Filter::set_Q() {
- // Q is controlled linearly by res. Q has approximate range [0.707, 1.7].
- // As resonance is increased, the filter must be clocked more often to keep
- // stable.
-
- // The coefficient 1024 is dispensed of later by right-shifting 10 times
- // (2 ^ 10 = 1024).
- _1024_div_Q = static_cast<sound_sample>(1024.0/(0.707 + 1.0*res/0x0f));
-}
-
-RESID_INLINE void Filter::clock(cycle_count delta_t,
- sound_sample voice1,
- sound_sample voice2,
- sound_sample voice3)
-{
- // Scale each voice down from 20 to 13 bits.
- voice1 >>= 7;
- voice2 >>= 7;
-
- // NB! Voice 3 is not silenced by voice3off if it is routed through
- // the filter.
- if (voice3off && !(filt & 0x04)) {
- voice3 = 0;
- }
- else {
- voice3 >>= 7;
- }
-
- // Enable filter on/off.
- // This is not really part of SID, but is useful for testing.
- // On slow CPUs it may be necessary to bypass the filter to lower the CPU
- // load.
- if (!enabled) {
- Vnf = voice1 + voice2 + voice3;
- Vhp = Vbp = Vlp = 0;
- return;
- }
-
- // Route voices into or around filter.
- // The code below is expanded to a switch for faster execution.
- // (filt1 ? Vi : Vnf) += voice1;
- // (filt2 ? Vi : Vnf) += voice2;
- // (filt3 ? Vi : Vnf) += voice3;
-
- sound_sample Vi;
-
- switch (filt) {
- default:
- case 0x0:
- Vi = 0;
- Vnf = voice1 + voice2 + voice3;
- break;
- case 0x1:
- Vi = voice1;
- Vnf = voice2 + voice3;
- break;
- case 0x2:
- Vi = voice2;
- Vnf = voice1 + voice3;
- break;
- case 0x3:
- Vi = voice1 + voice2;
- Vnf = voice3;
- break;
- case 0x4:
- Vi = voice3;
- Vnf = voice1 + voice2;
- break;
- case 0x5:
- Vi = voice1 + voice3;
- Vnf = voice2;
- break;
- case 0x6:
- Vi = voice2 + voice3;
- Vnf = voice1;
- break;
- case 0x7:
- Vi = voice1 + voice2 + voice3;
- Vnf = 0;
- break;
- case 0x8:
- Vi = 0;
- Vnf = voice1 + voice2 + voice3;
- break;
- case 0x9:
- Vi = voice1;
- Vnf = voice2 + voice3;
- break;
- case 0xa:
- Vi = voice2;
- Vnf = voice1 + voice3;
- break;
- case 0xb:
- Vi = voice1 + voice2;
- Vnf = voice3;
- break;
- case 0xc:
- Vi = voice3;
- Vnf = voice1 + voice2;
- break;
- case 0xd:
- Vi = voice1 + voice3;
- Vnf = voice2;
- break;
- case 0xe:
- Vi = voice2 + voice3;
- Vnf = voice1;
- break;
- case 0xf:
- Vi = voice1 + voice2 + voice3;
- Vnf = 0;
- break;
- }
-
- // Maximum delta cycles for the filter to work satisfactorily under current
- // cutoff frequency and resonance constraints is approximately 8.
- cycle_count delta_t_flt = 8;
-
- while (delta_t) {
- if (delta_t < delta_t_flt) {
- delta_t_flt = delta_t;
- }
-
- // delta_t is converted to seconds given a 1MHz clock by dividing
- // with 1 000 000. This is done in two operations to avoid integer
- // multiplication overflow.
-
- // Calculate filter outputs.
- // Vhp = Vbp/Q - Vlp - Vi;
- // dVbp = -w0*Vhp*dt;
- // dVlp = -w0*Vbp*dt;
- sound_sample w0_delta_t = w0_ceil_dt*delta_t_flt >> 6;
-
- sound_sample dVbp = (w0_delta_t*Vhp >> 14);
- sound_sample dVlp = (w0_delta_t*Vbp >> 14);
- Vbp -= dVbp;
- Vlp -= dVlp;
- Vhp = (Vbp*_1024_div_Q >> 10) - Vlp - Vi;
-
- delta_t -= delta_t_flt;
- }
-}
-
-RESID_INLINE sound_sample Filter::output() {
- // This is handy for testing.
- if (!enabled) {
- return (Vnf + mixer_DC)*static_cast<sound_sample>(vol);
- }
-
- // Mix highpass, bandpass, and lowpass outputs. The sum is not
- // weighted, this can be confirmed by sampling sound output for
- // e.g. bandpass, lowpass, and bandpass+lowpass from a SID chip.
-
- // The code below is expanded to a switch for faster execution.
- // if (hp) Vf += Vhp;
- // if (bp) Vf += Vbp;
- // if (lp) Vf += Vlp;
-
- sound_sample Vf;
-
- switch (hp_bp_lp) {
- default:
- case 0x0:
- Vf = 0;
- break;
- case 0x1:
- Vf = Vlp;
- break;
- case 0x2:
- Vf = Vbp;
- break;
- case 0x3:
- Vf = Vlp + Vbp;
- break;
- case 0x4:
- Vf = Vhp;
- break;
- case 0x5:
- Vf = Vlp + Vhp;
- break;
- case 0x6:
- Vf = Vbp + Vhp;
- break;
- case 0x7:
- Vf = Vlp + Vbp + Vhp;
- break;
- }
-
- // Sum non-filtered and filtered output.
- // Multiply the sum with volume.
- return (Vnf + Vf + mixer_DC)*static_cast<sound_sample>(vol);
-}
-
-
-/*
- * EnvelopeGenerator
- */
-
-EnvelopeGenerator::EnvelopeGenerator() {
- reset();
-}
-
-void EnvelopeGenerator::reset() {
- envelope_counter = 0;
-
- attack = 0;
- decay = 0;
- sustain = 0;
- release = 0;
-
- gate = 0;
-
- rate_counter = 0;
- exponential_counter = 0;
- exponential_counter_period = 1;
-
- state = RELEASE;
- rate_period = rate_counter_period[release];
- hold_zero = true;
-}
-
-reg16 EnvelopeGenerator::rate_counter_period[] = {
- 9, // 2ms*1.0MHz/256 = 7.81
- 32, // 8ms*1.0MHz/256 = 31.25
- 63, // 16ms*1.0MHz/256 = 62.50
- 95, // 24ms*1.0MHz/256 = 93.75
- 149, // 38ms*1.0MHz/256 = 148.44
- 220, // 56ms*1.0MHz/256 = 218.75
- 267, // 68ms*1.0MHz/256 = 265.63
- 313, // 80ms*1.0MHz/256 = 312.50
- 392, // 100ms*1.0MHz/256 = 390.63
- 977, // 250ms*1.0MHz/256 = 976.56
- 1954, // 500ms*1.0MHz/256 = 1953.13
- 3126, // 800ms*1.0MHz/256 = 3125.00
- 3907, // 1 s*1.0MHz/256 = 3906.25
- 11720, // 3 s*1.0MHz/256 = 11718.75
- 19532, // 5 s*1.0MHz/256 = 19531.25
- 31251 // 8 s*1.0MHz/256 = 31250.00
-};
-
-
-reg8 EnvelopeGenerator::sustain_level[] = {
- 0x00,
- 0x11,
- 0x22,
- 0x33,
- 0x44,
- 0x55,
- 0x66,
- 0x77,
- 0x88,
- 0x99,
- 0xaa,
- 0xbb,
- 0xcc,
- 0xdd,
- 0xee,
- 0xff,
-};
-
-void EnvelopeGenerator::writeCONTROL_REG(reg8 control) {
- reg8 gate_next = control & 0x01;
-
- // The rate counter is never reset, thus there will be a delay before the
- // envelope counter starts counting up (attack) or down (release).
-
- // Gate bit on: Start attack, decay, sustain.
- if (!gate && gate_next) {
- state = ATTACK;
- rate_period = rate_counter_period[attack];
-
- // Switching to attack state unlocks the zero freeze.
- hold_zero = false;
- }
- // Gate bit off: Start release.
- else if (gate && !gate_next) {
- state = RELEASE;
- rate_period = rate_counter_period[release];
- }
-
- gate = gate_next;
-}
-
-void EnvelopeGenerator::writeATTACK_DECAY(reg8 attack_decay) {
- attack = (attack_decay >> 4) & 0x0f;
- decay = attack_decay & 0x0f;
- if (state == ATTACK) {
- rate_period = rate_counter_period[attack];
- }
- else if (state == DECAY_SUSTAIN) {
- rate_period = rate_counter_period[decay];
- }
-}
-
-void EnvelopeGenerator::writeSUSTAIN_RELEASE(reg8 sustain_release) {
- sustain = (sustain_release >> 4) & 0x0f;
- release = sustain_release & 0x0f;
- if (state == RELEASE) {
- rate_period = rate_counter_period[release];
- }
-}
-
-reg8 EnvelopeGenerator::readENV() {
- return output();
-}
-
-RESID_INLINE void EnvelopeGenerator::clock(cycle_count delta_t) {
- // Check for ADSR delay bug.
- // If the rate counter comparison value is set below the current value of the
- // rate counter, the counter will continue counting up until it wraps around
- // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
- // envelope can finally be stepped.
- // This has been verified by sampling ENV3.
- //
-
- // NB! This requires two's complement integer.
- int rate_step = rate_period - rate_counter;
- if (rate_step <= 0) {
- rate_step += 0x7fff;
- }
-
- while (delta_t) {
- if (delta_t < rate_step) {
- rate_counter += delta_t;
- if (rate_counter & 0x8000) {
- ++rate_counter &= 0x7fff;
- }
- return;
- }
-
- rate_counter = 0;
- delta_t -= rate_step;
-
- // The first envelope step in the attack state also resets the exponential
- // counter. This has been verified by sampling ENV3.
- //
- if (state == ATTACK || ++exponential_counter == exponential_counter_period)
- {
- exponential_counter = 0;
-
- // Check whether the envelope counter is frozen at zero.
- if (hold_zero) {
- rate_step = rate_period;
- continue;
- }
-
- switch (state) {
- case ATTACK:
- // The envelope counter can flip from 0xff to 0x00 by changing state to
- // release, then to attack. The envelope counter is then frozen at
- // zero; to unlock this situation the state must be changed to release,
- // then to attack. This has been verified by sampling ENV3.
- //
- ++envelope_counter &= 0xff;
- if (envelope_counter == 0xff) {
- state = DECAY_SUSTAIN;
- rate_period = rate_counter_period[decay];
- }
- break;
- case DECAY_SUSTAIN:
- if (envelope_counter != sustain_level[sustain]) {
- --envelope_counter;
- }
- break;
- case RELEASE:
- // The envelope counter can flip from 0x00 to 0xff by changing state to
- // attack, then to release. The envelope counter will then continue
- // counting down in the release state.
- // This has been verified by sampling ENV3.
- // NB! The operation below requires two's complement integer.
- //
- --envelope_counter &= 0xff;
- break;
- }
-
- // Check for change of exponential counter period.
- switch (envelope_counter) {
- case 0xff:
- exponential_counter_period = 1;
- break;
- case 0x5d:
- exponential_counter_period = 2;
- break;
- case 0x36:
- exponential_counter_period = 4;
- break;
- case 0x1a:
- exponential_counter_period = 8;
- break;
- case 0x0e:
- exponential_counter_period = 16;
- break;
- case 0x06:
- exponential_counter_period = 30;
- break;
- case 0x00:
- exponential_counter_period = 1;
-
- // When the envelope counter is changed to zero, it is frozen at zero.
- // This has been verified by sampling ENV3.
- hold_zero = true;
- break;
- }
- }
-
- rate_step = rate_period;
- }
-}
-
-RESID_INLINE reg8 EnvelopeGenerator::output() {
- return envelope_counter;
-}
-
-
-/*
- * ExternalFilter
- */
-
-ExternalFilter::ExternalFilter() {
- reset();
- enable_filter(true);
- set_sampling_parameter(15915.6);
- mixer_DC = ((((0x800 - 0x380) + 0x800)*0xff*3 - 0xfff*0xff/18) >> 7)*0x0f;
-}
-
-void ExternalFilter::enable_filter(bool enable) {
- enabled = enable;
-}
-
-void ExternalFilter::set_sampling_parameter(double pass_freq) {
- static const double pi = 3.1415926535897932385;
-
- w0hp = 105;
- w0lp = (sound_sample) (pass_freq * (2.0 * pi * 1.048576));
- if (w0lp > 104858)
- w0lp = 104858;
-}
-
-void ExternalFilter::reset() {
- // State of filter.
- Vlp = 0;
- Vhp = 0;
- Vo = 0;
-}
-
-RESID_INLINE void ExternalFilter::clock(cycle_count delta_t, sound_sample Vi) {
- // This is handy for testing.
- if (!enabled) {
- // Remove maximum DC level since there is no filter to do it.
- Vlp = Vhp = 0;
- Vo = Vi - mixer_DC;
- return;
- }
-
- // Maximum delta cycles for the external filter to work satisfactorily
- // is approximately 8.
- cycle_count delta_t_flt = 8;
-
- while (delta_t) {
- if (delta_t < delta_t_flt) {
- delta_t_flt = delta_t;
- }
-
- // delta_t is converted to seconds given a 1MHz clock by dividing
- // with 1 000 000.
-
- // Calculate filter outputs.
- // Vo = Vlp - Vhp;
- // Vlp = Vlp + w0lp*(Vi - Vlp)*delta_t;
- // Vhp = Vhp + w0hp*(Vlp - Vhp)*delta_t;
-
- sound_sample dVlp = (w0lp*delta_t_flt >> 8)*(Vi - Vlp) >> 12;
- sound_sample dVhp = w0hp*delta_t_flt*(Vlp - Vhp) >> 20;
- Vo = Vlp - Vhp;
- Vlp += dVlp;
- Vhp += dVhp;
-
- delta_t -= delta_t_flt;
- }
-}
-
-RESID_INLINE sound_sample ExternalFilter::output() {
- return Vo;
-}
-
-
-/*
- * Voice
- */
-
-Voice::Voice() {
- wave_zero = 0x380;
- voice_DC = 0x800*0xff;
-}
-
-void Voice::set_sync_source(Voice* source) {
- wave.set_sync_source(&source->wave);
-}
-
-void Voice::writeCONTROL_REG(reg8 control) {
- wave.writeCONTROL_REG(control);
- envelope.writeCONTROL_REG(control);
-}
-
-void Voice::reset() {
- wave.reset();
- envelope.reset();
-}
-
-
-/*
- * SID
- */
-
-SID::SID() {
- voice[0].set_sync_source(&voice[2]);
- voice[1].set_sync_source(&voice[0]);
- voice[2].set_sync_source(&voice[1]);
-
- set_sampling_parameters(985248, 44100);
-
- bus_value = 0;
- bus_value_ttl = 0;
-}
-
-SID::~SID() {}
-
-void SID::reset() {
- for (int i = 0; i < 3; i++) {
- voice[i].reset();
- }
- filter.reset();
- extfilt.reset();
-
- bus_value = 0;
- bus_value_ttl = 0;
-}
-
-int SID::output() {
- const int range = 1 << 16;
- const int half = range >> 1;
- int sample = extfilt.output()/((4095*255 >> 7)*3*15*2/range);
- if (sample >= half) {
- return half - 1;
- }
- if (sample < -half) {
- return -half;
- }
- return sample;
-}
-
-
-/**
- * Read registers.
- *
- * Reading a write only register returns the last byte written to any SID
- * register. The individual bits in this value start to fade down towards
- * zero after a few cycles. All bits reach zero within approximately
- * $2000 - $4000 cycles.
- * It has been claimed that this fading happens in an orderly fashion, however
- * sampling of write only registers reveals that this is not the case.
- * NB! This is not correctly modeled.
- * The actual use of write only registers has largely been made in the belief
- * that all SID registers are readable. To support this belief the read
- * would have to be done immediately after a write to the same register
- * (remember that an intermediate write to another register would yield that
- * value instead). With this in mind we return the last value written to
- * any SID register for $2000 cycles without modeling the bit fading.
- */
-reg8 SID::read(reg8 offset) {
- switch (offset) {
- case 0x19:
- case 0x1a:
- return 0; //readPOT();
- case 0x1b:
- return voice[2].wave.readOSC();
- case 0x1c:
- return voice[2].envelope.readENV();
- default:
- return bus_value;
- }
-}
-
-void SID::write(reg8 offset, reg8 value) {
- bus_value = value;
- bus_value_ttl = 0x2000;
-
- switch (offset) {
- case 0x00:
- voice[0].wave.writeFREQ_LO(value);
- break;
- case 0x01:
- voice[0].wave.writeFREQ_HI(value);
- break;
- case 0x02:
- voice[0].wave.writePW_LO(value);
- break;
- case 0x03:
- voice[0].wave.writePW_HI(value);
- break;
- case 0x04:
- voice[0].writeCONTROL_REG(value);
- break;
- case 0x05:
- voice[0].envelope.writeATTACK_DECAY(value);
- break;
- case 0x06:
- voice[0].envelope.writeSUSTAIN_RELEASE(value);
- break;
- case 0x07:
- voice[1].wave.writeFREQ_LO(value);
- break;
- case 0x08:
- voice[1].wave.writeFREQ_HI(value);
- break;
- case 0x09:
- voice[1].wave.writePW_LO(value);
- break;
- case 0x0a:
- voice[1].wave.writePW_HI(value);
- break;
- case 0x0b:
- voice[1].writeCONTROL_REG(value);
- break;
- case 0x0c:
- voice[1].envelope.writeATTACK_DECAY(value);
- break;
- case 0x0d:
- voice[1].envelope.writeSUSTAIN_RELEASE(value);
- break;
- case 0x0e:
- voice[2].wave.writeFREQ_LO(value);
- break;
- case 0x0f:
- voice[2].wave.writeFREQ_HI(value);
- break;
- case 0x10:
- voice[2].wave.writePW_LO(value);
- break;
- case 0x11:
- voice[2].wave.writePW_HI(value);
- break;
- case 0x12:
- voice[2].writeCONTROL_REG(value);
- break;
- case 0x13:
- voice[2].envelope.writeATTACK_DECAY(value);
- break;
- case 0x14:
- voice[2].envelope.writeSUSTAIN_RELEASE(value);
- break;
- case 0x15:
- filter.writeFC_LO(value);
- break;
- case 0x16:
- filter.writeFC_HI(value);
- break;
- case 0x17:
- filter.writeRES_FILT(value);
- break;
- case 0x18:
- filter.writeMODE_VOL(value);
- break;
- default:
- break;
- }
-}
-
-void SID::enable_filter(bool enable) {
- filter.enable_filter(enable);
-}
-
-void SID::enable_external_filter(bool enable) {
- extfilt.enable_filter(enable);
-}
-
-
-/**
- * Setting of SID sampling parameters.
- *
- * Use a clock freqency of 985248Hz for PAL C64, 1022730Hz for NTSC C64.
- * The default end of passband frequency is pass_freq = 0.9*sample_freq/2
- * for sample frequencies up to ~ 44.1kHz, and 20kHz for higher sample
- * frequencies.
- *
- * For resampling, the ratio between the clock frequency and the sample
- * frequency is limited as follows:
- * 125*clock_freq/sample_freq < 16384
- * E.g. provided a clock frequency of ~ 1MHz, the sample frequency can not
- * be set lower than ~ 8kHz. A lower sample frequency would make the
- * resampling code overfill its 16k sample ring buffer.
- *
- * The end of passband frequency is also limited:
- * pass_freq <= 0.9*sample_freq/2
- *
- * E.g. for a 44.1kHz sampling rate the end of passband frequency is limited
- * to slightly below 20kHz. This constraint ensures that the FIR table is
- * not overfilled.
- */
-bool SID::set_sampling_parameters(double clock_freq,
- double sample_freq, double pass_freq,
- double filter_scale)
-{
- // The default passband limit is 0.9*sample_freq/2 for sample
- // frequencies below ~ 44.1kHz, and 20kHz for higher sample frequencies.
- if (pass_freq < 0) {
- pass_freq = 20000;
- if (2*pass_freq/sample_freq >= 0.9) {
- pass_freq = 0.9*sample_freq/2;
- }
- }
- // Check whether the FIR table would overfill.
- else if (pass_freq > 0.9*sample_freq/2) {
- return false;
- }
-
- // The filter scaling is only included to avoid clipping, so keep
- // it sane.
- if (filter_scale < 0.9 || filter_scale > 1.0) {
- return false;
- }
-
- // Set the external filter to the pass freq
- extfilt.set_sampling_parameter (pass_freq);
- clock_frequency = clock_freq;
-
- cycles_per_sample =
- cycle_count(clock_freq/sample_freq*(1 << FIXP_SHIFT) + 0.5);
-
- sample_offset = 0;
- sample_prev = 0;
-
- return true;
-}
-
-void SID::clock(cycle_count delta_t) {
- int i;
-
- if (delta_t <= 0) {
- return;
- }
-
- // Age bus value.
- bus_value_ttl -= delta_t;
- if (bus_value_ttl <= 0) {
- bus_value = 0;
- bus_value_ttl = 0;
- }
-
- // Clock amplitude modulators.
- for (i = 0; i < 3; i++) {
- voice[i].envelope.clock(delta_t);
- }
-
- // Clock and synchronize oscillators.
- // Loop until we reach the current cycle.
- cycle_count delta_t_osc = delta_t;
- while (delta_t_osc) {
- cycle_count delta_t_min = delta_t_osc;
-
- // Find minimum number of cycles to an oscillator accumulator MSB toggle.
- // We have to clock on each MSB on / MSB off for hard sync to operate
- // correctly.
- for (i = 0; i < 3; i++) {
- WaveformGenerator& wave = voice[i].wave;
-
- // It is only necessary to clock on the MSB of an oscillator that is
- // a sync source and has freq != 0.
- if (!(wave.sync_dest->sync && wave.freq)) {
- continue;
- }
-
- reg16 freq = wave.freq;
- reg24 accumulator = wave.accumulator;
-
- // Clock on MSB off if MSB is on, clock on MSB on if MSB is off.
- reg24 delta_accumulator =
- (accumulator & 0x800000 ? 0x1000000 : 0x800000) - accumulator;
-
- cycle_count delta_t_next = delta_accumulator/freq;
- if (delta_accumulator%freq) {
- ++delta_t_next;
- }
-
- if (delta_t_next < delta_t_min) {
- delta_t_min = delta_t_next;
- }
- }
-
- // Clock oscillators.
- for (i = 0; i < 3; i++) {
- voice[i].wave.clock(delta_t_min);
- }
-
- // Synchronize oscillators.
- for (i = 0; i < 3; i++) {
- voice[i].wave.synchronize();
- }
-
- delta_t_osc -= delta_t_min;
- }
-
- // Clock filter.
- filter.clock(delta_t,
- voice[0].output(), voice[1].output(), voice[2].output());
-
- // Clock external filter.
- extfilt.clock(delta_t, filter.output());
-}
-
-
-/**
- * SID clocking with audio sampling.
- * Fixpoint arithmetics is used.
- */
-int SID::clock(cycle_count& delta_t, short* buf, int n, int interleave) {
- int s = 0;
-
- for (;;) {
- cycle_count next_sample_offset = sample_offset + cycles_per_sample + (1 << (FIXP_SHIFT - 1));
- cycle_count delta_t_sample = next_sample_offset >> FIXP_SHIFT;
- if (delta_t_sample > delta_t) {
- break;
- }
- if (s >= n) {
- return s;
- }
- clock(delta_t_sample);
- delta_t -= delta_t_sample;
- sample_offset = (next_sample_offset & FIXP_MASK) - (1 << (FIXP_SHIFT - 1));
- buf[s++*interleave] = output();
- }
-
- clock(delta_t);
- sample_offset -= delta_t << FIXP_SHIFT;
- delta_t = 0;
- return s;
-}
-
-}
-
-// Plugin interface
-// (This can only create a null driver since C64 audio support is not part of the
-// midi driver architecture. But we need the plugin for the options menu in the launcher
-// and for MidiDriver::detectDevice() which is more or less used by all engines.)
-
-class C64MusicPlugin : public NullMusicPlugin {
-public:
- const char *getName() const {
- return _s("C64 Audio Emulator");
- }
-
- const char *getId() const {
- return "C64";
- }
-
- MusicDevices getDevices() const;
-};
-
-MusicDevices C64MusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_C64));
- return devices;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(C64)
- //REGISTER_PLUGIN_DYNAMIC(C64, PLUGIN_TYPE_MUSIC, C64MusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(C64, PLUGIN_TYPE_MUSIC, C64MusicPlugin);
-//#endif
-
-#endif
diff --git a/sound/softsynth/sid.h b/sound/softsynth/sid.h
deleted file mode 100644
index c78f538441..0000000000
--- a/sound/softsynth/sid.h
+++ /dev/null
@@ -1,348 +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$
- *
- */
-
-/*
- * This file is based on reSID, a MOS6581 SID emulator engine.
- * Copyright (C) 2004 Dag Lem <resid@nimrod.no>
- */
-
-#ifndef __SID_H__
-#define __SID_H__
-
-// Inlining on/off.
-#define RESID_INLINE inline
-
-namespace Resid {
-
-// We could have used the smallest possible data type for each SID register,
-// however this would give a slower engine because of data type conversions.
-// An int is assumed to be at least 32 bits (necessary in the types reg24,
-// cycle_count, and sound_sample). GNU does not support 16-bit machines
-// (GNU Coding Standards: Portability between CPUs), so this should be
-// a valid assumption.
-
-typedef unsigned int reg4;
-typedef unsigned int reg8;
-typedef unsigned int reg12;
-typedef unsigned int reg16;
-typedef unsigned int reg24;
-
-typedef int cycle_count;
-typedef int sound_sample;
-typedef sound_sample fc_point[2];
-
-
-class WaveformGenerator {
-public:
- WaveformGenerator();
-
- void set_sync_source(WaveformGenerator*);
-
- void clock(cycle_count delta_t);
- void synchronize();
- void reset();
-
- void writeFREQ_LO(reg8);
- void writeFREQ_HI(reg8);
- void writePW_LO(reg8);
- void writePW_HI(reg8);
- void writeCONTROL_REG(reg8);
- reg8 readOSC();
-
- // 12-bit waveform output.
- reg12 output();
-
-protected:
- const WaveformGenerator* sync_source;
- WaveformGenerator* sync_dest;
-
- // Tell whether the accumulator MSB was set high on this cycle.
- bool msb_rising;
-
- reg24 accumulator;
- reg24 shift_register;
-
- // Fout = (Fn*Fclk/16777216)Hz
- reg16 freq;
- // PWout = (PWn/40.95)%
- reg12 pw;
-
- // The control register right-shifted 4 bits; used for output function
- // table lookup.
- reg8 waveform;
-
- // The remaining control register bits.
- reg8 test;
- reg8 ring_mod;
- reg8 sync;
- // The gate bit is handled by the EnvelopeGenerator.
-
- // 16 possible combinations of waveforms.
- reg12 output____();
- reg12 output___T();
- reg12 output__S_();
- reg12 output__ST();
- reg12 output_P__();
- reg12 output_P_T();
- reg12 output_PS_();
- reg12 output_PST();
- reg12 outputN___();
- reg12 outputN__T();
- reg12 outputN_S_();
- reg12 outputN_ST();
- reg12 outputNP__();
- reg12 outputNP_T();
- reg12 outputNPS_();
- reg12 outputNPST();
-
- // Sample data for combinations of waveforms.
- static const reg8 wave6581__ST[];
- static const reg8 wave6581_P_T[];
- static const reg8 wave6581_PS_[];
- static const reg8 wave6581_PST[];
-
- friend class Voice;
- friend class SID;
-};
-
-class Filter {
-public:
- Filter();
-
- void enable_filter(bool enable);
-
- void clock(cycle_count delta_t,
- sound_sample voice1, sound_sample voice2, sound_sample voice3);
- void reset();
-
- // Write registers.
- void writeFC_LO(reg8);
- void writeFC_HI(reg8);
- void writeRES_FILT(reg8);
- void writeMODE_VOL(reg8);
-
- // SID audio output (16 bits).
- sound_sample output();
-
-protected:
- void set_w0();
- void set_Q();
-
- // Filter enabled.
- bool enabled;
-
- // Filter cutoff frequency.
- reg12 fc;
-
- // Filter resonance.
- reg8 res;
-
- // Selects which inputs to route through filter.
- reg8 filt;
-
- // Switch voice 3 off.
- reg8 voice3off;
-
- // Highpass, bandpass, and lowpass filter modes.
- reg8 hp_bp_lp;
-
- // Output master volume.
- reg4 vol;
-
- // Mixer DC offset.
- sound_sample mixer_DC;
-
- // State of filter.
- sound_sample Vhp; // highpass
- sound_sample Vbp; // bandpass
- sound_sample Vlp; // lowpass
- sound_sample Vnf; // not filtered
-
- // Cutoff frequency, resonance.
- sound_sample w0, w0_ceil_1, w0_ceil_dt;
- sound_sample _1024_div_Q;
-
- // Cutoff frequency tables.
- // FC is an 11 bit register.
- sound_sample f0_6581[2048];
- sound_sample* f0;
- static fc_point f0_points_6581[];
- fc_point* f0_points;
- int f0_count;
-
- friend class SID;
-};
-
-class EnvelopeGenerator {
-public:
- EnvelopeGenerator();
-
- enum State { ATTACK, DECAY_SUSTAIN, RELEASE };
-
- void clock(cycle_count delta_t);
- void reset();
-
- void writeCONTROL_REG(reg8);
- void writeATTACK_DECAY(reg8);
- void writeSUSTAIN_RELEASE(reg8);
- reg8 readENV();
-
- // 8-bit envelope output.
- reg8 output();
-
-protected:
- reg16 rate_counter;
- reg16 rate_period;
- reg8 exponential_counter;
- reg8 exponential_counter_period;
- reg8 envelope_counter;
- bool hold_zero;
-
- reg4 attack;
- reg4 decay;
- reg4 sustain;
- reg4 release;
-
- reg8 gate;
-
- State state;
-
- // Lookup table to convert from attack, decay, or release value to rate
- // counter period.
- static reg16 rate_counter_period[];
-
- // The 16 selectable sustain levels.
- static reg8 sustain_level[];
-
- friend class SID;
-};
-
-class ExternalFilter {
-public:
- ExternalFilter();
-
- void enable_filter(bool enable);
- void set_sampling_parameter(double pass_freq);
-
- void clock(cycle_count delta_t, sound_sample Vi);
- void reset();
-
- // Audio output (20 bits).
- sound_sample output();
-
-protected:
- // Filter enabled.
- bool enabled;
-
- // Maximum mixer DC offset.
- sound_sample mixer_DC;
-
- // State of filters.
- sound_sample Vlp; // lowpass
- sound_sample Vhp; // highpass
- sound_sample Vo;
-
- // Cutoff frequencies.
- sound_sample w0lp;
- sound_sample w0hp;
-
- friend class SID;
-};
-
-class Voice {
-public:
- Voice();
-
- void set_sync_source(Voice*);
- void reset();
-
- void writeCONTROL_REG(reg8);
-
- // Amplitude modulated waveform output.
- // Range [-2048*255, 2047*255].
- sound_sample output() {
- // Multiply oscillator output with envelope output.
- return (wave.output() - wave_zero)*envelope.output() + voice_DC;
- }
-
-protected:
- WaveformGenerator wave;
- EnvelopeGenerator envelope;
-
- // Waveform D/A zero level.
- sound_sample wave_zero;
-
- // Multiplying D/A DC offset.
- sound_sample voice_DC;
-
- friend class SID;
-};
-
-
-class SID {
-public:
- SID();
- ~SID();
-
- void enable_filter(bool enable);
- void enable_external_filter(bool enable);
- bool set_sampling_parameters(double clock_freq,
- double sample_freq, double pass_freq = -1,
- double filter_scale = 0.97);
-
- void clock(cycle_count delta_t);
- int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1);
- void reset();
-
- // Read/write registers.
- reg8 read(reg8 offset);
- void write(reg8 offset, reg8 value);
-
- // 16-bit output (AUDIO OUT).
- int output();
-
-protected:
- Voice voice[3];
- Filter filter;
- ExternalFilter extfilt;
-
- reg8 bus_value;
- cycle_count bus_value_ttl;
-
- double clock_frequency;
-
- // Fixpoint constants.
- static const int FIXP_SHIFT;
- static const int FIXP_MASK;
-
- // Sampling variables.
- cycle_count cycles_per_sample;
- cycle_count sample_offset;
- short sample_prev;
-};
-
-}
-
-#endif // not __SID_H__
diff --git a/sound/softsynth/wave6581.cpp b/sound/softsynth/wave6581.cpp
deleted file mode 100644
index d1ddad1623..0000000000
--- a/sound/softsynth/wave6581.cpp
+++ /dev/null
@@ -1,2098 +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$
- *
- */
-
-/*
- * This file is based on reSID, a MOS6581 SID emulator engine.
- * Copyright (C) 2004 Dag Lem <resid@nimrod.no>
- */
-
-#ifndef DISABLE_SID
-
-#include "sid.h"
-
-namespace Resid {
-
-const reg8 WaveformGenerator::wave6581__ST[] = {
-/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07,
-/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
-/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07,
-/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3f0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-/* 0x3f8: */ 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x3f, 0x3f,
-/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07,
-/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x1f,
-/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07,
-/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7e0: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
-/* 0x7e8: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
-/* 0x7f0: */ 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
-/* 0x7f8: */ 0x3e, 0x3e, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f,
-/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07,
-/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
-/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07,
-/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbf0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-/* 0xbf8: */ 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x3f, 0x3f,
-/* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07,
-/* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdf8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x1f,
-/* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07,
-/* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
-/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfe0: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
-/* 0xfe8: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
-/* 0xff0: */ 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
-/* 0xff8: */ 0x3e, 0x3e, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f,
-};
-
-const reg8 WaveformGenerator::wave6581_P_T[] = {
-/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x38, 0x3f,
-/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2f8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x5f,
-/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x378: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x6f,
-/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0x3b8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x70, 0x77,
-/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0x3d8: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7b,
-/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70,
-/* 0x3e8: */ 0x00, 0x40, 0x40, 0x70, 0x60, 0x70, 0x78, 0x7d,
-/* 0x3f0: */ 0x00, 0x40, 0x60, 0x78, 0x60, 0x78, 0x78, 0x7e,
-/* 0x3f8: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f,
-/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x4f8: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x9f,
-/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x578: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0xa0, 0xa0, 0xaf,
-/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
-/* 0x5b0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0,
-/* 0x5b8: */ 0x00, 0x80, 0x80, 0xa0, 0x80, 0xa0, 0xb0, 0xb7,
-/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x5c8: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0,
-/* 0x5d0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0,
-/* 0x5d8: */ 0x00, 0x80, 0x80, 0xa0, 0x80, 0xb0, 0xb0, 0xbb,
-/* 0x5e0: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xb0,
-/* 0x5e8: */ 0x80, 0x80, 0x80, 0xb0, 0x80, 0xb0, 0xb8, 0xbd,
-/* 0x5f0: */ 0x80, 0x80, 0x80, 0xb8, 0xa0, 0xb8, 0xb8, 0xbe,
-/* 0x5f8: */ 0xa0, 0xb8, 0xbc, 0xbf, 0xbe, 0xbf, 0xbf, 0xbf,
-/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0,
-/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x668: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0,
-/* 0x670: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0,
-/* 0x678: */ 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xcf,
-/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x698: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0,
-/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x6a8: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0,
-/* 0x6b0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0xc0, 0xc0,
-/* 0x6b8: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, 0xd7,
-/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x6c8: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0,
-/* 0x6d0: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc0,
-/* 0x6d8: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, 0xd0, 0xdb,
-/* 0x6e0: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xd0,
-/* 0x6e8: */ 0x80, 0xc0, 0xc0, 0xd0, 0xc0, 0xd0, 0xd8, 0xdd,
-/* 0x6f0: */ 0xc0, 0xc0, 0xc0, 0xd0, 0xc0, 0xd8, 0xd8, 0xde,
-/* 0x6f8: */ 0xc0, 0xd8, 0xdc, 0xdf, 0xdc, 0xdf, 0xdf, 0xdf,
-/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x718: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xe0,
-/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-/* 0x728: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0,
-/* 0x730: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0,
-/* 0x738: */ 0x80, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe7,
-/* 0x740: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0,
-/* 0x748: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0,
-/* 0x750: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0,
-/* 0x758: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xeb,
-/* 0x760: */ 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0,
-/* 0x768: */ 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xed,
-/* 0x770: */ 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe8, 0xe8, 0xee,
-/* 0x778: */ 0xe0, 0xe8, 0xec, 0xef, 0xec, 0xef, 0xef, 0xef,
-/* 0x780: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xc0,
-/* 0x788: */ 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0,
-/* 0x790: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0,
-/* 0x798: */ 0xc0, 0xe0, 0xe0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf3,
-/* 0x7a0: */ 0x80, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xf0,
-/* 0x7a8: */ 0xc0, 0xe0, 0xe0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf5,
-/* 0x7b0: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf6,
-/* 0x7b8: */ 0xf0, 0xf0, 0xf4, 0xf7, 0xf4, 0xf7, 0xf7, 0xf7,
-/* 0x7c0: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0,
-/* 0x7c8: */ 0xe0, 0xe0, 0xe0, 0xf8, 0xf0, 0xf8, 0xf8, 0xf9,
-/* 0x7d0: */ 0xe0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xf8, 0xfa,
-/* 0x7d8: */ 0xf0, 0xf8, 0xf8, 0xfb, 0xf8, 0xfb, 0xfb, 0xfb,
-/* 0x7e0: */ 0xe0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xfc, 0xfc,
-/* 0x7e8: */ 0xf8, 0xfc, 0xfc, 0xfd, 0xfc, 0xfd, 0xfd, 0xfd,
-/* 0x7f0: */ 0xf8, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
-/* 0x7f8: */ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-/* 0x800: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
-/* 0x808: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xf8,
-/* 0x810: */ 0xfd, 0xfd, 0xfd, 0xfc, 0xfd, 0xfc, 0xfc, 0xf8,
-/* 0x818: */ 0xfc, 0xfc, 0xfc, 0xf0, 0xf8, 0xf0, 0xf0, 0xe0,
-/* 0x820: */ 0xfb, 0xfb, 0xfb, 0xf8, 0xfb, 0xf8, 0xf8, 0xf0,
-/* 0x828: */ 0xfa, 0xf8, 0xf8, 0xf0, 0xf8, 0xf0, 0xf0, 0xe0,
-/* 0x830: */ 0xf9, 0xf8, 0xf8, 0xf0, 0xf8, 0xf0, 0xe0, 0xe0,
-/* 0x838: */ 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0,
-/* 0x840: */ 0xf7, 0xf7, 0xf7, 0xf4, 0xf7, 0xf4, 0xf0, 0xf0,
-/* 0x848: */ 0xf6, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0,
-/* 0x850: */ 0xf5, 0xf0, 0xf0, 0xe0, 0xf0, 0xe0, 0xe0, 0xc0,
-/* 0x858: */ 0xf0, 0xe0, 0xe0, 0xc0, 0xe0, 0xc0, 0xc0, 0x80,
-/* 0x860: */ 0xf3, 0xf0, 0xf0, 0xe0, 0xf0, 0xe0, 0xe0, 0xc0,
-/* 0x868: */ 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80,
-/* 0x870: */ 0xf0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80,
-/* 0x878: */ 0xc0, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
-/* 0x880: */ 0xef, 0xef, 0xef, 0xec, 0xef, 0xec, 0xe8, 0xe0,
-/* 0x888: */ 0xee, 0xe8, 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0,
-/* 0x890: */ 0xed, 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0,
-/* 0x898: */ 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80,
-/* 0x8a0: */ 0xeb, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0,
-/* 0x8a8: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00,
-/* 0x8b0: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00,
-/* 0x8b8: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0x8c0: */ 0xe7, 0xe0, 0xe0, 0xc0, 0xe0, 0xc0, 0xc0, 0x80,
-/* 0x8c8: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00,
-/* 0x8d0: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00,
-/* 0x8d8: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8e0: */ 0xe0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00,
-/* 0x8e8: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8f0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x900: */ 0xdf, 0xdf, 0xdf, 0xdc, 0xdf, 0xdc, 0xd8, 0xc0,
-/* 0x908: */ 0xde, 0xd8, 0xd8, 0xc0, 0xd8, 0xc0, 0xc0, 0xc0,
-/* 0x910: */ 0xdd, 0xd8, 0xd0, 0xc0, 0xd0, 0xc0, 0xc0, 0x80,
-/* 0x918: */ 0xd0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00,
-/* 0x920: */ 0xdb, 0xd0, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80,
-/* 0x928: */ 0xc0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00,
-/* 0x930: */ 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
-/* 0x938: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x940: */ 0xd7, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80,
-/* 0x948: */ 0xc0, 0xc0, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0x950: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0x958: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x960: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0x968: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x970: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x980: */ 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00,
-/* 0x988: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0x990: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9a0: */ 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9c0: */ 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa00: */ 0xbf, 0xbf, 0xbf, 0xbe, 0xbf, 0xbc, 0xbc, 0xa0,
-/* 0xa08: */ 0xbe, 0xbc, 0xb8, 0xa0, 0xb8, 0xa0, 0x80, 0x80,
-/* 0xa10: */ 0xbd, 0xb8, 0xb0, 0x80, 0xb0, 0x80, 0x80, 0x80,
-/* 0xa18: */ 0xb0, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
-/* 0xa20: */ 0xbb, 0xb0, 0xb0, 0x80, 0xa0, 0x80, 0x80, 0x00,
-/* 0xa28: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0xa30: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0xa38: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa40: */ 0xb7, 0xb0, 0xa0, 0x80, 0xa0, 0x80, 0x80, 0x00,
-/* 0xa48: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
-/* 0xa50: */ 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa60: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa80: */ 0xaf, 0xa0, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x00,
-/* 0xa88: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa90: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaa0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xac0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb00: */ 0x9f, 0x90, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
-/* 0xb08: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb10: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb20: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb40: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb80: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc00: */ 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7c, 0x7c, 0x70,
-/* 0xc08: */ 0x7e, 0x7c, 0x78, 0x60, 0x78, 0x60, 0x60, 0x00,
-/* 0xc10: */ 0x7d, 0x78, 0x78, 0x60, 0x70, 0x40, 0x40, 0x00,
-/* 0xc18: */ 0x70, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc20: */ 0x7b, 0x78, 0x70, 0x40, 0x70, 0x40, 0x00, 0x00,
-/* 0xc28: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc30: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc40: */ 0x77, 0x70, 0x70, 0x00, 0x60, 0x00, 0x00, 0x00,
-/* 0xc48: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc50: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc60: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc80: */ 0x6f, 0x60, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00,
-/* 0xc88: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc90: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd00: */ 0x5f, 0x58, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00,
-/* 0xd08: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe00: */ 0x3f, 0x3c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xff0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xff8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const reg8 WaveformGenerator::wave6581_PS_[] = {
-/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1f,
-/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f,
-/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37,
-/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b,
-/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d,
-/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
-/* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3f,
-/* 0x3f8: */ 0x00, 0x30, 0x38, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f,
-/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
-/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
-/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d,
-/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e,
-/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x5f,
-/* 0x5f8: */ 0x00, 0x40, 0x40, 0x5f, 0x5c, 0x5f, 0x5f, 0x5f,
-/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67,
-/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6b,
-/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x6d,
-/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x6e8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x6e,
-/* 0x6f0: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x6f,
-/* 0x6f8: */ 0x00, 0x60, 0x60, 0x6f, 0x60, 0x6f, 0x6f, 0x6f,
-/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x738: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x60, 0x73,
-/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0x758: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x75,
-/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0x768: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x76,
-/* 0x770: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x77,
-/* 0x778: */ 0x00, 0x70, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77,
-/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0x798: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x79,
-/* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0x7a8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x70, 0x70, 0x7a,
-/* 0x7b0: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7b,
-/* 0x7b8: */ 0x40, 0x70, 0x70, 0x7b, 0x78, 0x7b, 0x7b, 0x7b,
-/* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-/* 0x7c8: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7c,
-/* 0x7d0: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7d,
-/* 0x7d8: */ 0x40, 0x70, 0x78, 0x7d, 0x78, 0x7d, 0x7d, 0x7d,
-/* 0x7e0: */ 0x00, 0x40, 0x40, 0x78, 0x60, 0x78, 0x78, 0x7e,
-/* 0x7e8: */ 0x60, 0x78, 0x78, 0x7e, 0x7c, 0x7e, 0x7e, 0x7e,
-/* 0x7f0: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f,
-/* 0x7f8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
-/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1f,
-/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f,
-/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37,
-/* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b,
-/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d,
-/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
-/* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3f,
-/* 0xbf8: */ 0x00, 0x30, 0x38, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f,
-/* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-/* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f,
-/* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
-/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
-/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d,
-/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e,
-/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x5f,
-/* 0xdf8: */ 0x00, 0x40, 0x40, 0x5f, 0x5c, 0x5f, 0x5f, 0x5f,
-/* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67,
-/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6b,
-/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6d,
-/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0xee8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x6e,
-/* 0xef0: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x6f,
-/* 0xef8: */ 0x00, 0x60, 0x60, 0x6f, 0x60, 0x6f, 0x6f, 0x6f,
-/* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0xf38: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x60, 0x73,
-/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-/* 0xf58: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x75,
-/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0xf68: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x76,
-/* 0xf70: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x77,
-/* 0xf78: */ 0x00, 0x70, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77,
-/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0xf98: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x79,
-/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-/* 0xfa8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x70, 0x70, 0x7a,
-/* 0xfb0: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7b,
-/* 0xfb8: */ 0x40, 0x70, 0x70, 0x7b, 0x78, 0x7b, 0x7b, 0x7b,
-/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-/* 0xfc8: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7c,
-/* 0xfd0: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7d,
-/* 0xfd8: */ 0x40, 0x70, 0x78, 0x7d, 0x78, 0x7d, 0x7d, 0x7d,
-/* 0xfe0: */ 0x00, 0x40, 0x40, 0x78, 0x60, 0x78, 0x78, 0x7e,
-/* 0xfe8: */ 0x60, 0x78, 0x78, 0x7e, 0x7c, 0x7e, 0x7e, 0x7e,
-/* 0xff0: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7c, 0x7f, 0x7f, 0x7f,
-/* 0xff8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
-};
-
-const reg8 WaveformGenerator::wave6581_PST[] = {
-/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x3f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x5f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x7e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
-/* 0x7f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-/* 0x7f8: */ 0x00, 0x00, 0x00, 0x78, 0x78, 0x7e, 0x7f, 0x7f,
-/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-/* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xdf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 0xfe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
-/* 0xff0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-/* 0xff8: */ 0x00, 0x00, 0x00, 0x78, 0x78, 0x7e, 0x7f, 0x7f,
-};
-
-}
-#endif
diff --git a/sound/softsynth/ym2612.cpp b/sound/softsynth/ym2612.cpp
deleted file mode 100644
index 08331c6244..0000000000
--- a/sound/softsynth/ym2612.cpp
+++ /dev/null
@@ -1,789 +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$
- */
-
-#include <math.h>
-
-#include "sound/softsynth/ym2612.h"
-#include "common/util.h"
-#include "sound/musicplugin.h"
-#include "common/translation.h"
-
-////////////////////////////////////////
-//
-// Miscellaneous
-//
-////////////////////////////////////////
-
-static int *sintbl = 0;
-static int *powtbl = 0;
-static int *frequencyTable = 0;
-static int *keycodeTable = 0;
-static int *keyscaleTable = 0;
-static int *attackOut = 0;
-
-
-////////////////////////////////////////
-//
-// Operator2612 implementation
-//
-////////////////////////////////////////
-
-Operator2612::Operator2612 (Voice2612 *owner) :
- _owner (owner),
- _state (_s_ready),
- _currentLevel ((int32)0x7f << 15),
- _phase (0),
- _lastOutput (0),
- _feedbackLevel (0),
- _detune (0),
- _multiple (1),
- _keyScale (0),
- _specifiedTotalLevel (127),
- _specifiedAttackRate (0),
- _specifiedDecayRate (0),
- _specifiedSustainRate (0),
- _specifiedReleaseRate (15) {
- velocity(0);
-}
-
-Operator2612::~Operator2612()
-{ }
-
-void Operator2612::velocity(int velo) {
- _velocity = velo;
- _totalLevel = ((int32)_specifiedTotalLevel << 15) +
- ((int32)(127-_velocity) << 13);
- _sustainLevel = ((int32)_specifiedSustainLevel << 17);
-}
-
-void Operator2612::feedbackLevel(int level) {
- _feedbackLevel = level;
-}
-
-void Operator2612::setInstrument(byte const *instrument) {
- _detune = (instrument[8] >> 4) & 7;
- _multiple = instrument[8] & 15;
- _specifiedTotalLevel = instrument[12] & 127;
- _keyScale = (instrument[16] >> 6) & 3;
- _specifiedAttackRate = instrument[16] & 31;
- _specifiedDecayRate = instrument[20] & 31;
- _specifiedSustainRate = instrument[24] & 31;
- _specifiedSustainLevel = (instrument[28] >> 4) & 15;
- _specifiedReleaseRate = instrument[28] & 15;
- _state = _s_ready;
- velocity(_velocity);
-}
-
-void Operator2612::keyOn() {
- _state = _s_attacking;
- _tickCount = 0;
- _phase = 0;
- _currentLevel = ((int32)0x7f << 15);
-}
-
-void Operator2612::keyOff() {
- if (_state != _s_ready)
- _state = _s_releasing;
-}
-
-void Operator2612::frequency(int freq) {
- double value; // Use for intermediate computations to avoid int64 arithmetic
- int r;
-
- _frequency = freq / _owner->_rate;
-
- r = _specifiedAttackRate;
- if (r != 0) {
- r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
- if (r >= 64)
- r = 63;
- }
-
- r = 63 - r;
- if (_specifiedTotalLevel >= 128)
- value = 0;
- else {
- value = powtbl[(r&3) << 7];
- value *= 1 << (r >> 2);
- value *= 41;
- value /= 1 << (15 + 5);
- value *= 127 - _specifiedTotalLevel;
- value /= 127;
- }
- _attackTime = (int32) value; // 1 ?? == (1 << 12)
- if (_attackTime > 0)
- _attackTime = (1 << (12+10)) / (_owner->_rate * _attackTime);
-
- r = _specifiedDecayRate;
- if (r != 0) {
- r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
- if (r >= 64)
- r = 63;
- }
- value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31;
- _decayRate = (int32) value / _owner->_rate;
-
- r = _specifiedSustainRate;
- if (r != 0) {
- r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
- if (r >= 64)
- r = 63;
- }
- value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31;
- _sustainRate = (int32) value / _owner->_rate;
-
- r = _specifiedReleaseRate;
- if (r != 0) {
- r = r * 2 + 1; // (Translated) I cannot know whether the timing is a good choice or not
- r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
- // KS
- if (r >= 64)
- r = 63;
- }
- value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31;
- _releaseRate = (int32) value / _owner->_rate;
-}
-
-void Operator2612::nextTick(const int *phasebuf, int *outbuf, int buflen) {
- if (_state == _s_ready)
- return;
- if (_state == _s_attacking && _attackTime <= 0) {
- _currentLevel = 0;
- _state = _s_decaying;
- }
-
- int32 levelIncrement = 0;
- int32 target = 0;
- State next_state = _s_ready;
- const int32 zero_level = ((int32)0x7f << 15);
- const int phaseIncrement = (_multiple > 0) ? (_frequency * _multiple) : (_frequency / 2);
-
- int32 output = _lastOutput;
- int32 level = _currentLevel + _totalLevel;
-
- while (buflen) {
- switch (_state) {
- case _s_ready:
- return;
- case _s_attacking:
- next_state = _s_attacking;
- break;
- case _s_decaying:
- levelIncrement = _decayRate;
- target = _sustainLevel + _totalLevel;
- next_state = _s_sustaining;
- break;
- case _s_sustaining:
- levelIncrement = _sustainRate;
- target = zero_level + _totalLevel;
- next_state = _s_ready;
- break;
- case _s_releasing:
- levelIncrement = _releaseRate;
- target = zero_level + _totalLevel;
- next_state = _s_ready;
- break;
- }
-
- bool switching = false;
- do {
- if (next_state == _s_attacking) {
- // Attack phase
- ++_tickCount;
- int i = (int) (_tickCount * _attackTime);
- if (i >= 1024) {
- level = _totalLevel;
- _state = _s_decaying;
- switching = true;
- } else {
- level = (attackOut[i] << (31 - 8 - 16)) + _totalLevel;
- }
- } else {
- // Decay, Sustain and Release phases
- level += levelIncrement;
- if (level >= target) {
- level = target;
- _state = next_state;
- switching = true;
- }
- }
-
- if (level < zero_level) {
- int phaseShift = *phasebuf >> 2;
- if (_feedbackLevel)
- phaseShift += (output << (_feedbackLevel - 1)) / 1024;
- output = sintbl[((_phase >> 7) + phaseShift) & 0x7ff];
- output >>= (level >> 18);
- // Here is the original code, which requires 64-bit ints
-// output *= powtbl[511 - ((level>>25)&511)];
-// output >>= 16;
-// output >>= 1;
- // And here's our 32-bit trick for doing it. (Props to Fingolfin!)
- // Result varies from original code by max of 1.
-// int powVal = powtbl[511 - ((level>>9)&511)];
-// int outputHI = output / 256;
-// int powHI = powVal / 256;
-// output = (outputHI * powHI) / 2 + (outputHI * (powVal % 256) + powHI * (output % 256)) / 512;
- // And here's the even faster code.
- // Result varies from original code by max of 8.
- output = ((output >> 4) * (powtbl[511-((level>>9)&511)] >> 3)) / 1024;
-
- _phase += phaseIncrement;
- _phase &= 0x3ffff;
- } else
- output = 0;
-
- *outbuf += output;
- --buflen;
- ++phasebuf;
- ++outbuf;
- } while (buflen && !switching);
- }
- _lastOutput = output;
- _currentLevel = level - _totalLevel;
-}
-
-////////////////////////////////////////
-//
-// Voice2612 implementation
-//
-////////////////////////////////////////
-
-Voice2612::Voice2612() {
- next = 0;
- _control7 = 127;
- _note = 40;
- _frequency = 440;
- _frequencyOffs = 0x2000;
- _algorithm = 7;
-
- _buffer = 0;
- _buflen = 0;
-
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); ++i)
- _opr[i] = new Operator2612 (this);
- velocity(0);
-}
-
-Voice2612::~Voice2612() {
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); ++i)
- delete _opr[i];
- free(_buffer);
-}
-
-void Voice2612::velocity(int velo) {
- _velocity = velo;
-#if 0
- int v = (velo * _control7) >> 7;
-#else
- int v = velo + (_control7 - 127) * 4;
-#endif
- bool iscarrier[8][4] = {
- { false, false, false, true, }, //0
- { false, false, false, true, }, //1
- { false, false, false, true, }, //2
- { false, false, false, true, }, //3
- { false, true, false, true, }, //4
- { false, true, true, true, }, //5
- { false, true, true, true, }, //6
- { true, true, true, true, }, //7
- };
- int opr;
- for (opr = 0; opr < 4; opr++)
- if (iscarrier[_algorithm][opr])
- _opr[opr]->velocity(v);
- else
- _opr[opr]->velocity(127);
-}
-
-void Voice2612::setControlParameter(int control, int value) {
- switch (control) {
- case 7:
- _control7 = value;
- velocity(_velocity);
- break;
- case 123:
- // All notes off
- noteOff(_note);
- };
-}
-
-void Voice2612::setInstrument(byte const *instrument) {
- if (instrument == NULL)
- return;
-
- _algorithm = instrument[32] & 7;
- _opr[0]->feedbackLevel((instrument[32] >> 3) & 7);
- _opr[1]->feedbackLevel(0);
- _opr[2]->feedbackLevel(0);
- _opr[3]->feedbackLevel(0);
- _opr[0]->setInstrument(instrument + 0);
- _opr[1]->setInstrument(instrument + 2);
- _opr[2]->setInstrument(instrument + 1);
- _opr[3]->setInstrument(instrument + 3);
-}
-
-void Voice2612::nextTick(int *outbuf, int buflen) {
- if (_velocity == 0)
- return;
-
- if (_buflen < buflen) {
- free(_buffer);
- _buflen = buflen;
- _buffer = (int *) malloc(sizeof(int) * buflen * 2);
- }
-
- int *buf1 = _buffer;
- int *buf2 = _buffer + buflen;
- memset(_buffer, 0, sizeof(int) * buflen * 2);
-
- switch (_algorithm) {
- case 0:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, buf1, buflen);
- memset (buf2, 0, sizeof (int) * buflen);
- _opr[2]->nextTick(buf1, buf2, buflen);
- _opr[3]->nextTick(buf2, outbuf, buflen);
- break;
- case 1:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf1, buf2, buflen);
- _opr[2]->nextTick(buf2, buf1, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 2:
- _opr[1]->nextTick(buf1, buf2, buflen);
- _opr[2]->nextTick(buf2, buf1, buflen);
- memset(buf2, 0, sizeof(int) * buflen);
- _opr[0]->nextTick(buf2, buf1, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 3:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, buf1, buflen);
- memset(buf2, 0, sizeof(int) * buflen);
- _opr[2]->nextTick(buf2, buf1, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 4:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, outbuf, buflen);
- _opr[2]->nextTick(buf1, buf1, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 5:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, outbuf, buflen);
- _opr[2]->nextTick(buf2, outbuf, buflen);
- _opr[3]->nextTick(buf2, outbuf, buflen);
- break;
- case 6:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, outbuf, buflen);
- _opr[2]->nextTick(buf1, outbuf, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 7:
- _opr[0]->nextTick(buf1, outbuf, buflen);
- _opr[1]->nextTick(buf1, outbuf, buflen);
- _opr[2]->nextTick(buf1, outbuf, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- };
-}
-
-void Voice2612::noteOn(int n, int onVelo) {
- _note = n;
- velocity(onVelo);
- recalculateFrequency();
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); i++)
- _opr[i]->keyOn();
-}
-
-bool Voice2612::noteOff(int note) {
- if (_note != note)
- return false;
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); i++)
- _opr[i]->keyOff();
- return true;
-}
-
-void Voice2612::pitchBend(int value) {
- _frequencyOffs = value;
- recalculateFrequency();
-}
-
-void Voice2612::recalculateFrequency() {
- //
- //
- //
- int32 basefreq = frequencyTable[_note];
- int cfreq = frequencyTable[_note - (_note % 12)];
- int oct = _note / 12;
- int fnum = (int) (((double)basefreq * (1 << 13)) / cfreq);
- fnum += _frequencyOffs - 0x2000;
- if (fnum < 0x2000) {
- fnum += 0x2000;
- oct--;
- }
- if (fnum >= 0x4000) {
- fnum -= 0x2000;
- oct++;
- }
-
- //
- _frequency = (int) ((frequencyTable[oct*12] * (double)fnum) / 8);
-
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); i++)
- _opr[i]->frequency(_frequency);
-}
-
-////////////////////////////////////////
-//
-// MidiChannel_YM2612
-//
-////////////////////////////////////////
-
-MidiChannel_YM2612::MidiChannel_YM2612() {
- _voices = 0;
- _next_voice = 0;
-}
-
-MidiChannel_YM2612::~MidiChannel_YM2612() {
- removeAllVoices();
-}
-
-void MidiChannel_YM2612::removeAllVoices() {
- if (!_voices)
- return;
- Voice2612 *last, *voice = _voices;
- for (; voice; voice = last) {
- last = voice->next;
- delete voice;
- }
- _voices = _next_voice = 0;
-}
-
-void MidiChannel_YM2612::noteOn(byte note, byte onVelo) {
- if (!_voices)
- return;
- _next_voice = _next_voice ? _next_voice : _voices;
- _next_voice->noteOn(note, onVelo);
- _next_voice = _next_voice->next;
-}
-
-void MidiChannel_YM2612::noteOff(byte note) {
- if (!_voices)
- return;
- if (_next_voice == _voices)
- _next_voice = 0;
- Voice2612 *voice = _next_voice;
- do {
- if (!voice)
- voice = _voices;
- if (voice->noteOff(note)) {
- _next_voice = voice;
- break;
- }
- voice = voice->next;
- } while (voice != _next_voice);
-}
-
-void MidiChannel_YM2612::controlChange(byte control, byte value) {
- //
- if (control == 121) {
- // Reset controller
- removeAllVoices();
- } else {
- Voice2612 *voice = _voices;
- for (; voice; voice = voice->next)
- voice->setControlParameter(control, value);
- }
-}
-
-void MidiChannel_YM2612::sysEx_customInstrument(uint32 type, const byte *fmInst) {
- if (type != 'EUP ')
- return;
- Voice2612 *voice = new Voice2612;
- voice->next = _voices;
- _voices = voice;
- voice->_rate = _rate;
- voice->setInstrument(fmInst);
-}
-
-void MidiChannel_YM2612::pitchBend(int16 value) {
- //
- Voice2612 *voice = _voices;
- for (; voice; voice = voice->next)
- voice->pitchBend(value);
-}
-
-void MidiChannel_YM2612::nextTick(int *outbuf, int buflen) {
- Voice2612 *voice = _voices;
- for (; voice; voice = voice->next)
- voice->nextTick(outbuf, buflen);
-}
-
-void MidiChannel_YM2612::rate(uint16 r) {
- _rate = r;
- Voice2612 *voice = _voices;
- for (; voice; voice = voice->next)
- voice->_rate = r;
-}
-
-////////////////////////////////////////
-//
-// MidiDriver_YM2612
-//
-////////////////////////////////////////
-
-MidiDriver_YM2612::MidiDriver_YM2612(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer) {
- _next_voice = 0;
-
- createLookupTables();
- _volume = 256;
- int i;
- for (i = 0; i < ARRAYSIZE(_channel); i++)
- _channel[i] = new MidiChannel_YM2612;
- rate(getRate());
-}
-
-MidiDriver_YM2612::~MidiDriver_YM2612() {
- int i;
- for (i = 0; i < ARRAYSIZE(_channel); i++)
- delete _channel[i];
- removeLookupTables();
-}
-
-int MidiDriver_YM2612::open() {
- if (_isOpen)
- return MERR_ALREADY_OPEN;
-
- MidiDriver_Emulated::open();
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
- return 0;
-}
-
-void MidiDriver_YM2612::close() {
- if (!_isOpen)
- return;
- _isOpen = false;
-
- _mixer->stopHandle(_mixerSoundHandle);
-}
-
-void MidiDriver_YM2612::send(uint32 b) {
- send(b & 0xF, b & 0xFFFFFFF0);
-}
-
-void MidiDriver_YM2612::send(byte chan, uint32 b) {
- //byte param3 = (byte) ((b >> 24) & 0xFF);
- byte param2 = (byte) ((b >> 16) & 0xFF);
- byte param1 = (byte) ((b >> 8) & 0xFF);
- byte cmd = (byte) (b & 0xF0);
- if (chan > ARRAYSIZE(_channel))
- return;
-
- switch (cmd) {
- case 0x80:// Note Off
- _channel[chan]->noteOff(param1);
- break;
- case 0x90: // Note On
- _channel[chan]->noteOn(param1, param2);
- break;
- case 0xA0: // Aftertouch
- break; // Not supported.
- case 0xB0: // Control Change
- _channel[chan]->controlChange(param1, param2);
- break;
- case 0xC0: // Program Change
- _channel[chan]->programChange(param1);
- break;
- case 0xD0: // Channel Pressure
- break; // Not supported.
- case 0xE0: // Pitch Bend
- _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000);
- break;
- case 0xF0: // SysEx
- // We should never get here! SysEx information has to be
- // sent via high-level semantic methods.
- warning("MidiDriver_YM2612: Receiving SysEx command on a send() call");
- break;
-
- default:
- warning("MidiDriver_YM2612: Unknown send() command 0x%02X", cmd);
- }
-}
-
-void MidiDriver_YM2612::sysEx(const byte *msg, uint16 length) {
- if (msg[0] != 0x7C || msg[1] >= ARRAYSIZE(_channel))
- return;
- _channel[msg[1]]->sysEx_customInstrument('EUP ', &msg[2]);
-}
-
-void MidiDriver_YM2612::generateSamples(int16 *data, int len) {
- memset(data, 0, 2 * sizeof(int16) * len);
- nextTick(data, len);
-}
-
-void MidiDriver_YM2612::nextTick(int16 *buf1, int buflen) {
- int *buf0 = (int *)buf1;
-
- int i;
- for (i = 0; i < ARRAYSIZE(_channel); i++)
- _channel[i]->nextTick(buf0, buflen);
-
- for (i = 0; i < buflen; ++i)
- buf1[i*2+1] = buf1[i*2] = ((buf0[i] * volume()) >> 10) & 0xffff;
-}
-
-void MidiDriver_YM2612::rate(uint16 r)
-{
- int i;
- for (i = 0; i < ARRAYSIZE(_channel); i++)
- _channel[i]->rate(r);
-}
-
-void MidiDriver_YM2612::createLookupTables() {
- {
- int i;
- sintbl = new int [2048];
- for (i = 0; i < 2048; i++)
- sintbl[i] = (int)(0xffff * sin(i/2048.0*2.0*PI));
- }
-
- {
- int i;
- powtbl = new int [1025];
- for (i = 0; i <= 1024; i++)
- powtbl[i] = (int)(0x10000 * pow(2.0, (i-512)/512.0));
- }
-
- {
- int i;
- int block;
-
- static int fnum[] = {
- 0x026a, 0x028f, 0x02b6, 0x02df,
- 0x030b, 0x0339, 0x036a, 0x039e,
- 0x03d5, 0x0410, 0x044e, 0x048f,
- };
-
- // (int)(880.0 * 256.0 * pow(2.0, (note-0x51)/12.0))
- //
- frequencyTable = new int [120];
- for (block = -1; block < 9; block++) {
- for (i = 0; i < 12; i++) {
- double freq = fnum[i] * (166400.0 / 3) * pow(2.0, block-21);
- frequencyTable[(block+1)*12+i] = (int)(256.0 * freq);
- }
- }
-
- keycodeTable = new int [120];
- // detune
- for (block = -1; block < 9; block++) {
- for (i = 0; i < 12; i++) {
- // see p.204
- int f8 = (fnum[i] >> 7) & 1;
- int f9 = (fnum[i] >> 8) & 1;
- int f10 = (fnum[i] >> 9) & 1;
- int f11 = (fnum[i] >> 10) & 1;
- int n4 = f11;
- int n3 = (f11&(f10|f9|f8)) | (~f11&f10&f9&f8);
- int note = n4*2 + n3;
- // see p.207
- keycodeTable[(block+1)*12+i] = block*4 + note;
- }
- }
- }
-
- {
- int freq;
- keyscaleTable = new int [8192];
- keyscaleTable[0] = 0;
- for (freq = 1; freq < 8192; freq++) {
- keyscaleTable[freq] = (int)(log((double)freq) / 9.03 * 32.0) - 1;
- // 8368[Hz] (o9c)
- }
- }
-
- {
- int i;
- attackOut = new int [1024];
- for (i = 0; i < 1024; i++)
- attackOut[i] = (int)(((0x7fff+0x03a5)*30.0) / (30.0+i)) - 0x03a5;
- }
-}
-
-void MidiDriver_YM2612::removeLookupTables() {
- delete[] sintbl;
- delete[] powtbl;
- delete[] frequencyTable;
- delete[] keycodeTable;
- delete[] keyscaleTable;
- delete[] attackOut;
- sintbl = powtbl = frequencyTable = keycodeTable = keyscaleTable = attackOut = 0;
-}
-
-
-// Plugin interface
-
-class TownsEmuMusicPlugin : public MusicPluginObject {
-public:
- const char *getName() const {
- return _s("FM Towns Emulator");
- }
-
- const char *getId() const {
- return "towns";
- }
-
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
-};
-
-MusicDevices TownsEmuMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_TOWNS));
- return devices;
-}
-
-Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_YM2612(g_system->getMixer());
-
- return Common::kNoError;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(TOWNS)
- //REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);
-//#endif
diff --git a/sound/softsynth/ym2612.h b/sound/softsynth/ym2612.h
deleted file mode 100644
index 5fb2f32ef0..0000000000
--- a/sound/softsynth/ym2612.h
+++ /dev/null
@@ -1,179 +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$
- */
-
-#ifndef SOUND_SOFTSYNTH_Y2612_H
-#define SOUND_SOFTSYNTH_Y2612_H
-
-#include "common/scummsys.h"
-
-#include "sound/softsynth/emumidi.h"
-
-////////////////////////////////////////
-//
-// Class declarations
-//
-////////////////////////////////////////
-
-class Voice2612;
-class Operator2612 {
-protected:
- Voice2612 *_owner;
- enum State { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };
- State _state;
- int32 _currentLevel;
- int _frequency;
- uint32 _phase;
- int _lastOutput;
- int _feedbackLevel;
- int _detune;
- int _multiple;
- int32 _totalLevel;
- int _keyScale;
- int _velocity;
- int _specifiedTotalLevel;
- int _specifiedAttackRate;
- int _specifiedDecayRate;
- int _specifiedSustainLevel;
- int _specifiedSustainRate;
- int _specifiedReleaseRate;
- int _tickCount;
- int _attackTime;
- int32 _decayRate;
- int32 _sustainLevel;
- int32 _sustainRate;
- int32 _releaseRate;
-
-public:
- Operator2612 (Voice2612 *owner);
- ~Operator2612();
- void feedbackLevel(int level);
- void setInstrument(byte const *instrument);
- void velocity(int velo);
- void keyOn();
- void keyOff();
- void frequency(int freq);
- void nextTick(const int *phaseShift, int *outbuf, int buflen);
- bool inUse() { return (_state != _s_ready); }
-};
-
-class Voice2612 {
-public:
- Voice2612 *next;
- uint16 _rate;
-
-protected:
- Operator2612 *_opr[4];
- int _velocity;
- int _control7;
- int _note;
- int _frequencyOffs;
- int _frequency;
- int _algorithm;
-
- int *_buffer;
- int _buflen;
-
-public:
- Voice2612();
- ~Voice2612();
- void setControlParameter(int control, int value);
- void setInstrument(byte const *instrument);
- void velocity(int velo);
- void nextTick(int *outbuf, int buflen);
- void noteOn(int n, int onVelo);
- bool noteOff(int note);
- void pitchBend(int value);
- void recalculateFrequency();
-};
-
-class MidiChannel_YM2612 : public MidiChannel {
-protected:
- uint16 _rate;
- Voice2612 *_voices;
- Voice2612 *_next_voice;
-
-public:
- void removeAllVoices();
- void nextTick(int *outbuf, int buflen);
- void rate(uint16 r);
-
-public:
- MidiChannel_YM2612();
- virtual ~MidiChannel_YM2612();
-
- // MidiChannel interface
- MidiDriver *device() { return 0; }
- byte getNumber() { return 0; }
- void release() { }
- void send(uint32 b) { }
- void noteOff(byte note);
- void noteOn(byte note, byte onVelo);
- void programChange(byte program) { }
- void pitchBend(int16 value);
- void controlChange(byte control, byte value);
- void pitchBendFactor(byte value) { }
- void sysEx_customInstrument(uint32 type, const byte *instr);
-};
-
-class MidiDriver_YM2612 : public MidiDriver_Emulated {
-protected:
- MidiChannel_YM2612 *_channel[16];
-
- int _next_voice;
- int _volume;
-
-protected:
- void nextTick(int16 *buf1, int buflen);
- int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; }
- void rate(uint16 r);
-
- void generateSamples(int16 *buf, int len);
-
-public:
- MidiDriver_YM2612(Audio::Mixer *mixer);
- virtual ~MidiDriver_YM2612();
-
- static void createLookupTables();
- static void removeLookupTables();
-
- int open();
- void close();
- void send(uint32 b);
- void send(byte channel, uint32 b); // Supports higher than channel 15
- uint32 property(int prop, uint32 param) { return 0; }
-
- void setPitchBendRange(byte channel, uint range) { }
- void sysEx(const byte *msg, uint16 length);
-
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
-
- // AudioStream API
- bool isStereo() const { return true; }
- int getRate() const { return _mixer->getOutputRate(); }
-};
-
-#endif
-