adlib sound support, use USE_ADLIB
svn-id: r3510
This commit is contained in:
parent
5ff70c5de1
commit
95646feac9
17 changed files with 2998 additions and 138 deletions
10
actor.cpp
10
actor.cpp
|
@ -168,13 +168,9 @@ int Scumm::remapDirection(Actor *a, int dir) {
|
|||
|
||||
switch(flags & 7) {
|
||||
case 1:
|
||||
if (dir >= 180)
|
||||
return 270;
|
||||
return 90;
|
||||
case 2:
|
||||
if (dir <= 90 || dir>270)
|
||||
return 0;
|
||||
return 180;
|
||||
return a->walkdata.XYFactor >0 ? 90 : 270;
|
||||
case 2:
|
||||
return a->walkdata.YXFactor >0 ? 180 : 0;
|
||||
case 3: return 270;
|
||||
case 4: return 90;
|
||||
case 5: return 0;
|
||||
|
|
20
gui.cpp
20
gui.cpp
|
@ -1,3 +1,23 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 The ScummVM project
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "scumm.h"
|
||||
#include "gui.h"
|
||||
|
|
46
resource.cpp
46
resource.cpp
|
@ -457,16 +457,17 @@ int Scumm::loadResource(int type, int index) {
|
|||
}
|
||||
|
||||
int Scumm::readSoundResource(int type, int index) {
|
||||
uint32 resStart, size, tag, size2, basetag;
|
||||
byte *ptr;
|
||||
uint32 pos, total_size, size, tag,basetag;
|
||||
int i;
|
||||
int pri, best_pri;
|
||||
uint32 best_size, best_offs;
|
||||
|
||||
debug(9, "readSoundResource(%d,%d)", type, index);
|
||||
|
||||
resStart = 0;
|
||||
pos = 0;
|
||||
|
||||
basetag = fileReadDwordLE();
|
||||
size = fileReadDwordBE();
|
||||
total_size = fileReadDwordBE();
|
||||
|
||||
#if defined(SAMNMAX) || defined(FULL_THROTTLE)
|
||||
if (basetag == MKID('MIDI')) {
|
||||
|
@ -475,23 +476,36 @@ int Scumm::readSoundResource(int type, int index) {
|
|||
return 1;
|
||||
}
|
||||
#else
|
||||
while (size>resStart) {
|
||||
while (pos < total_size) {
|
||||
tag = fileReadDword();
|
||||
size2 = fileReadDwordBE();
|
||||
size = fileReadDwordBE() + 8;
|
||||
pos += size;
|
||||
|
||||
resStart += size2 + 8;
|
||||
|
||||
for (i=0,ptr=_soundTagTable; i<_numSoundTags; i++,ptr+=4) {
|
||||
/* endian OK, tags are in native format */
|
||||
if (READ_UINT32_UNALIGNED(ptr) == tag) {
|
||||
fileSeek(_fileHandle, -8, SEEK_CUR);
|
||||
fileRead(_fileHandle,createResource(type, index, size2+8), size2+8);
|
||||
return 1;
|
||||
}
|
||||
switch(tag) {
|
||||
#ifdef USE_ADLIB
|
||||
case MKID('ADL '): pri = 10; break;
|
||||
#else
|
||||
case MKID('ROL '): pri = 1; break;
|
||||
case MKID('GMD '): pri = 2; break;
|
||||
#endif
|
||||
default: pri = -1;
|
||||
}
|
||||
|
||||
fileSeek(_fileHandle, size2, SEEK_CUR);
|
||||
if (pri > best_pri) {
|
||||
best_pri = pri;
|
||||
best_size = size;
|
||||
best_offs = filePos(_fileHandle);
|
||||
}
|
||||
|
||||
fileSeek(_fileHandle, size - 8, SEEK_CUR);
|
||||
}
|
||||
|
||||
if (best_pri != -1) {
|
||||
fileSeek(_fileHandle, best_offs - 8, SEEK_SET);
|
||||
fileRead(_fileHandle,createResource(type, index, best_size), best_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
res.roomoffs[type][index] = 0xFFFFFFFF;
|
||||
return 0;
|
||||
|
|
|
@ -499,8 +499,8 @@ void Scumm::saveOrLoad(Serializer *s) {
|
|||
}
|
||||
}
|
||||
|
||||
if (_soundDriver)
|
||||
((SoundEngine*)_soundDriver)->save_or_load(s);
|
||||
if (_soundEngine)
|
||||
((SoundEngine*)_soundEngine)->save_or_load(s);
|
||||
|
||||
}
|
||||
|
||||
|
|
13
script.cpp
13
script.cpp
|
@ -293,6 +293,12 @@ int Scumm::readVar(uint var) {
|
|||
#endif
|
||||
debug(9, "readvar=%d", var);
|
||||
if (!(var&0xF000)) {
|
||||
#if defined(BYPASS_COPY_PROT)
|
||||
if (var==490 && _gameId == GID_MONKEY2 && !copyprotbypassed) {
|
||||
copyprotbypassed = true;
|
||||
var = 518;
|
||||
}
|
||||
#endif
|
||||
checkRange(_numVariables-1, 0, var, "Variable %d out of range(r)");
|
||||
return _vars[var];
|
||||
}
|
||||
|
@ -317,13 +323,6 @@ int Scumm::readVar(uint var) {
|
|||
if (var&0x4000) {
|
||||
var &= 0xFFF;
|
||||
checkRange(0x10, 0, var, "Local variable %d out of range(r)");
|
||||
|
||||
#if defined(BYPASS_COPY_PROT)
|
||||
if (!copyprotbypassed && _currentScript==1 && _gameId==GID_MONKEY2 && var==0) {
|
||||
copyprotbypassed=1;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return vm.localvar[_currentScript][var];
|
||||
}
|
||||
|
||||
|
|
8
scumm.h
8
scumm.h
|
@ -22,6 +22,7 @@
|
|||
#include "scummsys.h"
|
||||
|
||||
#define SWAP(a,b) do{int tmp=a; a=b; b=tmp; } while(0)
|
||||
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
struct Scumm;
|
||||
struct Actor;
|
||||
|
@ -936,7 +937,7 @@ struct Scumm {
|
|||
|
||||
int _keyPressed;
|
||||
|
||||
void *_soundDriver;
|
||||
void *_soundEngine;
|
||||
|
||||
uint16 *_inventory;
|
||||
byte *_arrays;
|
||||
|
@ -1128,8 +1129,8 @@ struct Scumm {
|
|||
|
||||
byte *_shadowPalette;
|
||||
|
||||
int _numSoundTags;
|
||||
byte *_soundTagTable;
|
||||
// int _numSoundTags;
|
||||
// byte *_soundTagTable;
|
||||
|
||||
int16 _bootParam;
|
||||
|
||||
|
@ -1220,6 +1221,7 @@ struct Scumm {
|
|||
void fileSeek(void *file, long offs, int whence);
|
||||
void fileRead(void *handle, void *ptr, uint32 size);
|
||||
bool fileEof(void *handle);
|
||||
uint32 filePos(void *handle);
|
||||
|
||||
int fileReadByte();
|
||||
uint32 fileReadDwordLE();
|
||||
|
|
|
@ -196,9 +196,9 @@ void Scumm::scummMain(int argc, char **argv) {
|
|||
_bootParam = -7873;
|
||||
}
|
||||
|
||||
if (_gameId==GID_MONKEY2 && _bootParam==0) {
|
||||
_bootParam = 10001;
|
||||
}
|
||||
// if (_gameId==GID_MONKEY2 && _bootParam==0) {
|
||||
// _bootParam = 10001;
|
||||
// }
|
||||
|
||||
initGraphics(this, _fullScreen);
|
||||
|
||||
|
|
38
scummvm.dsp
38
scummvm.dsp
|
@ -66,7 +66,7 @@ LINK32=link.exe
|
|||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "ALLOW_GDI" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "./sound" /I "./" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "ALLOW_GDI" /D "BYPASS_COPY_PROT" /D "USE_ADLIB" /Yu"stdafx.h" /FD /GZ /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE RSC /l 0x41d /d "_DEBUG"
|
||||
# ADD RSC /l 0x41d /d "_DEBUG"
|
||||
|
@ -86,6 +86,26 @@ LINK32=link.exe
|
|||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Group "sound"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\adlib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\fmopl.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\gmidi.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\imuse.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\actor.cpp
|
||||
|
@ -152,10 +172,6 @@ SOURCE=.\gui.cpp
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\imuse.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\object.cpp
|
||||
|
||||
!IF "$(CFG)" == "scummvm - Win32 Release"
|
||||
|
@ -247,6 +263,10 @@ SOURCE=.\scummvm.cpp
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sdl.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound.cpp
|
||||
|
||||
!IF "$(CFG)" == "scummvm - Win32 Release"
|
||||
|
@ -311,10 +331,6 @@ SOURCE=.\verbs.cpp
|
|||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\windows.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
@ -322,6 +338,10 @@ SOURCE=.\windows.cpp
|
|||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\fmopl.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gui.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
12
sdl.cpp
12
sdl.cpp
|
@ -35,6 +35,7 @@ ScummDebugger debugger;
|
|||
Gui gui;
|
||||
|
||||
SoundEngine sound;
|
||||
SOUND_DRIVER_TYPE snd_driv;
|
||||
|
||||
static SDL_Surface *screen;
|
||||
|
||||
|
@ -479,7 +480,6 @@ void drawMouse(Scumm *s, int xdraw, int ydraw, int color, byte *mask, bool visib
|
|||
static uint32 midi_counter;
|
||||
|
||||
void fill_sound(void *userdata, Uint8 *stream, int len) {
|
||||
memset(stream, 0, len);
|
||||
scumm.mixWaves((int16*)stream, len>>1);
|
||||
}
|
||||
|
||||
|
@ -501,6 +501,7 @@ int music_thread(Scumm *s) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void initGraphics(Scumm *s, bool fullScreen) {
|
||||
SDL_AudioSpec desired;
|
||||
|
||||
|
@ -528,8 +529,10 @@ void initGraphics(Scumm *s, bool fullScreen) {
|
|||
SDL_WM_SetCaption(buf,buf);
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
/* Create Music Thread */
|
||||
SDL_CreateThread((int (*)(void *))&music_thread, &scumm);
|
||||
if (!snd_driv.wave_based()) {
|
||||
/* Create Music Thread */
|
||||
SDL_CreateThread((int (*)(void *))&music_thread, &scumm);
|
||||
}
|
||||
|
||||
#if !defined(SCALEUP_2x2)
|
||||
screen = SDL_SetVideoMode(320, 200, 8, fullScreen ? (SDL_SWSURFACE | SDL_FULLSCREEN) : SDL_SWSURFACE);
|
||||
|
@ -557,8 +560,7 @@ int main(int argc, char* argv[]) {
|
|||
int delta,tmp;
|
||||
int last_time, new_time;
|
||||
|
||||
sound.initialize(&scumm);
|
||||
scumm._soundDriver = &sound;
|
||||
sound.initialize(&scumm, &snd_driv);
|
||||
|
||||
scumm._gui = &gui;
|
||||
scumm.scummMain(argc, argv);
|
||||
|
|
31
sound.cpp
31
sound.cpp
|
@ -65,7 +65,7 @@ void Scumm::processSoundQues() {
|
|||
data[j] = _soundQue[i+j];
|
||||
i += num;
|
||||
|
||||
se = (SoundEngine*)_soundDriver;
|
||||
se = (SoundEngine*)_soundEngine;
|
||||
#if 0
|
||||
debug(1,"processSoundQues(%d,%d,%d,%d,%d,%d,%d,%d,%d)",
|
||||
data[0]>>8,
|
||||
|
@ -89,7 +89,7 @@ void Scumm::processSoundQues() {
|
|||
}
|
||||
|
||||
void Scumm::playSound(int sound) {
|
||||
SoundEngine *se = (SoundEngine*)_soundDriver;
|
||||
SoundEngine *se = (SoundEngine*)_soundEngine;
|
||||
if (se) {
|
||||
getResourceAddress(rtSound, sound);
|
||||
se->start_sound(sound);
|
||||
|
@ -202,7 +202,7 @@ int Scumm::isSoundRunning(int sound) {
|
|||
if (!isResourceLoaded(rtSound, sound))
|
||||
return 0;
|
||||
|
||||
se = (SoundEngine*)_soundDriver;
|
||||
se = (SoundEngine*)_soundEngine;
|
||||
if (!se)
|
||||
return 0;
|
||||
return se->get_sound_status(sound);
|
||||
|
@ -232,7 +232,7 @@ void Scumm::stopSound(int a) {
|
|||
SoundEngine *se;
|
||||
int i;
|
||||
|
||||
se = (SoundEngine*)_soundDriver;
|
||||
se = (SoundEngine*)_soundEngine;
|
||||
if (se)
|
||||
se->stop_sound(a);
|
||||
|
||||
|
@ -242,7 +242,7 @@ void Scumm::stopSound(int a) {
|
|||
}
|
||||
|
||||
void Scumm::stopAllSounds() {
|
||||
SoundEngine *se = (SoundEngine*)_soundDriver;
|
||||
SoundEngine *se = (SoundEngine*)_soundEngine;
|
||||
if (se) {
|
||||
se->stop_all_sounds();
|
||||
se->clear_queue();
|
||||
|
@ -288,22 +288,16 @@ void Scumm::talkSound(uint32 a, uint32 b, int mode) {
|
|||
* is needed.
|
||||
*/
|
||||
|
||||
static const uint32 sound_tags[] = {
|
||||
MKID('GMD ')
|
||||
};
|
||||
|
||||
void Scumm::setupSound() {
|
||||
SoundEngine *se = (SoundEngine*)_soundDriver;
|
||||
SoundEngine *se = (SoundEngine*)_soundEngine;
|
||||
if (se)
|
||||
se->_base_sounds = res.address[rtSound];
|
||||
se->setBase(res.address[rtSound]);
|
||||
|
||||
_soundTagTable = (byte*)sound_tags;
|
||||
_numSoundTags = 1;
|
||||
_sfxFile = openSfxFile();
|
||||
}
|
||||
|
||||
void Scumm::pauseSounds(bool pause) {
|
||||
SoundEngine *se = (SoundEngine*)_soundDriver;
|
||||
SoundEngine *se = (SoundEngine*)_soundEngine;
|
||||
if (se)
|
||||
se->pause(pause);
|
||||
_soundsPaused = pause;
|
||||
|
@ -466,9 +460,16 @@ void MixerChannel::clear() {
|
|||
void Scumm::mixWaves(int16 *sounds, int len) {
|
||||
int i;
|
||||
|
||||
memset(sounds, 0,len * sizeof(int16));
|
||||
|
||||
if (_soundsPaused)
|
||||
return;
|
||||
|
||||
|
||||
SoundEngine *se = (SoundEngine*)_soundEngine;
|
||||
if (se) {
|
||||
se->driver()->generate_samples(sounds, len);
|
||||
}
|
||||
|
||||
for(i=NUM_MIXER-1; i>=0;i--) {
|
||||
_mixer_channel[i].mix(sounds, len);
|
||||
}
|
||||
|
|
310
sound.h
310
sound.h
|
@ -17,21 +17,89 @@
|
|||
*
|
||||
* Change Log:
|
||||
* $Log$
|
||||
* Revision 1.2 2001/12/01 17:06:13 strigeus
|
||||
* adlib sound support, use USE_ADLIB
|
||||
*
|
||||
* Revision 1.1 2001/11/14 18:37:38 strigeus
|
||||
* music support,
|
||||
* fixed timing bugs
|
||||
*
|
||||
*/
|
||||
|
||||
int clamp(int val, int min, int max);
|
||||
|
||||
struct FM_OPL;
|
||||
struct Part;
|
||||
struct MidiChannel;
|
||||
struct MidiChannelAdl;
|
||||
struct MidiChannelGM;
|
||||
struct VolumeFader;
|
||||
struct Player;
|
||||
struct HookDatas;
|
||||
struct SoundEngine;
|
||||
struct SoundDriver;
|
||||
struct Instrument;
|
||||
struct AdlibSoundDriver;
|
||||
struct MidiSoundDriver;
|
||||
|
||||
#if defined(USE_ADLIB)
|
||||
#define SOUND_DRIVER_TYPE AdlibSoundDriver
|
||||
#else
|
||||
#define SOUND_DRIVER_TYPE MidiSoundDriver
|
||||
#endif
|
||||
|
||||
struct Struct10 {
|
||||
byte active;
|
||||
int16 cur_val;
|
||||
int16 count;
|
||||
uint16 param;
|
||||
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 InstrumentExtra {
|
||||
byte a,b,c,d,e,f,g,h;
|
||||
};
|
||||
|
||||
struct Instrument {
|
||||
byte flags_1;
|
||||
byte oplvl_1;
|
||||
byte atdec_1;
|
||||
byte sustrel_1;
|
||||
byte waveform_1;
|
||||
byte flags_2;
|
||||
byte oplvl_2;
|
||||
byte atdec_2;
|
||||
byte sustrel_2;
|
||||
byte waveform_2;
|
||||
byte feedback;
|
||||
byte flags_a;
|
||||
InstrumentExtra extra_a;
|
||||
byte flags_b;
|
||||
InstrumentExtra extra_b;
|
||||
byte duration;
|
||||
};
|
||||
|
||||
struct Part {
|
||||
SoundEngine *_se;
|
||||
int _slot;
|
||||
SOUND_DRIVER_TYPE *_drv;
|
||||
Part *_next, *_prev;
|
||||
MidiChannel *_mc;
|
||||
Player *_player;
|
||||
|
@ -50,24 +118,24 @@ struct Part {
|
|||
byte _chan;
|
||||
byte _effect_level;
|
||||
byte _chorus;
|
||||
byte _gmidi_5;
|
||||
byte _gmidi_1;
|
||||
byte _percussion;
|
||||
byte _bank;
|
||||
|
||||
void key_on(byte note, byte velocity);
|
||||
void key_off(byte note);
|
||||
void set_param(int b, byte c) {}
|
||||
void init(SoundEngine *se);
|
||||
void set_param(byte param, int value);
|
||||
void init(SoundDriver *_driver);
|
||||
void setup(Player *player);
|
||||
void uninit();
|
||||
void off();
|
||||
void silence();
|
||||
void set_instrument(uint b);
|
||||
void set_instrument(byte *data) {}
|
||||
void set_instrument(Instrument *data);
|
||||
|
||||
void set_transpose(int8 transpose);
|
||||
void set_vol(uint8 volume);
|
||||
void set_detune(int8 detune);
|
||||
void set_pri(int8 pri, bool recalc);
|
||||
void set_pri(int8 pri);
|
||||
void set_pan(int8 pan);
|
||||
void set_modwheel(uint value);
|
||||
void set_pedal(bool value);
|
||||
|
@ -76,28 +144,42 @@ struct Part {
|
|||
void set_program(byte program);
|
||||
void set_chorus(uint chorus);
|
||||
void set_effect_level(uint level);
|
||||
void set_chan_param(int b, int c) {}
|
||||
void mod_changed();
|
||||
void vol_changed();
|
||||
void pedal_changed();
|
||||
void modwheel_changed();
|
||||
void pan_changed();
|
||||
void effect_level_changed();
|
||||
void program_changed();
|
||||
void chorus_changed();
|
||||
|
||||
int update_actives(uint16 *active);
|
||||
void set_pitchbend_factor(uint8 value);
|
||||
void set_onoff(bool on);
|
||||
|
||||
void fix_after_load();
|
||||
|
||||
void update_pris();
|
||||
|
||||
void changed(byte what);
|
||||
};
|
||||
|
||||
|
||||
struct MidiChannel {
|
||||
Part *_part;
|
||||
MidiChannelAdl *adl() { return (MidiChannelAdl*)this; }
|
||||
MidiChannelGM *gm() { return (MidiChannelGM*)this; }
|
||||
};
|
||||
|
||||
struct MidiChannelAdl : MidiChannel {
|
||||
MidiChannelAdl *_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;
|
||||
};
|
||||
|
||||
struct MidiChannelGM : MidiChannel {
|
||||
byte _chan;
|
||||
uint16 _actives[8];
|
||||
|
||||
void init(byte chan);
|
||||
};
|
||||
|
||||
struct VolumeFader {
|
||||
|
@ -188,7 +270,7 @@ struct Player {
|
|||
void set_priority(int pri);
|
||||
void set_pan(int pan);
|
||||
void set_detune(int detune);
|
||||
void silence_parts();
|
||||
void turn_off_parts();
|
||||
void play_active_notes();
|
||||
void cancel_volume_fade();
|
||||
|
||||
|
@ -235,8 +317,133 @@ struct IsNoteCmdData {
|
|||
byte vel;
|
||||
};
|
||||
|
||||
struct SoundDriver {
|
||||
enum {
|
||||
pcMod = 1,
|
||||
pcVolume = 2,
|
||||
pcPedal = 4,
|
||||
pcModwheel = 8,
|
||||
pcPan = 16,
|
||||
pcEffectLevel = 32,
|
||||
pcProgram = 64,
|
||||
pcChorus = 128,
|
||||
pcAll = 255,
|
||||
};
|
||||
};
|
||||
|
||||
struct AdlibSoundDriver : SoundDriver {
|
||||
private:
|
||||
FM_OPL *_opl;
|
||||
byte *_adlib_reg_cache;
|
||||
SoundEngine *_se;
|
||||
|
||||
int _adlib_timer_counter;
|
||||
|
||||
uint16 channel_table_2[9];
|
||||
int _midichan_index;
|
||||
int _next_tick;
|
||||
uint16 curnote_table[9];
|
||||
MidiChannelAdl _midi_channels[9];
|
||||
|
||||
Instrument _part_instr[32];
|
||||
Instrument _glob_instr[32];
|
||||
|
||||
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_read_param(int chan, byte data);
|
||||
void adlib_setup_channel(int chan, Instrument *instr, byte vol_1, byte vol_2);
|
||||
byte adlib_read(byte port) { return _adlib_reg_cache[port]; }
|
||||
void adlib_set_param(int channel, byte param, int value);
|
||||
void adlib_key_onoff(int channel);
|
||||
void adlib_write(byte port, byte value);
|
||||
void adlib_playnote(int channel, int note);
|
||||
|
||||
MidiChannelAdl *allocate_midichan(byte pri);
|
||||
|
||||
void reset_tick();
|
||||
void mc_off(MidiChannel *mc);
|
||||
|
||||
static void link_mc(Part *part, MidiChannelAdl *mc);
|
||||
static void mc_inc_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11);
|
||||
static void mc_init_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11, byte flags, InstrumentExtra *ie);
|
||||
static 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(MidiChannel *mc, byte note, byte velocity);
|
||||
|
||||
public:
|
||||
void uninit();
|
||||
void init(SoundEngine *eng);
|
||||
void update_pris() { }
|
||||
void generate_samples(int16 *buf, int len);
|
||||
void on_timer();
|
||||
void set_instrument(uint slot, byte *instr);
|
||||
void part_set_instrument(Part *part, Instrument *instr);
|
||||
void part_key_on(Part *part, byte note, byte velocity);
|
||||
void part_key_off(Part *part, byte note);
|
||||
void part_set_param(Part *part, byte param, int value);
|
||||
void part_changed(Part *part,byte what);
|
||||
void part_off(Part *part);
|
||||
int part_update_active(Part *part,uint16 *active);
|
||||
void adjust_priorities() {}
|
||||
|
||||
bool wave_based() { return true; }
|
||||
};
|
||||
|
||||
struct MidiSoundDriver : SoundDriver {
|
||||
HMIDIOUT *_mo;
|
||||
bool _mt32emulate;
|
||||
SoundEngine *_se;
|
||||
|
||||
MidiChannelGM _midi_channels[9];
|
||||
|
||||
int16 _midi_pitchbend_last[16];
|
||||
uint8 _midi_volume_last[16];
|
||||
bool _midi_pedal_last[16];
|
||||
byte _midi_modwheel_last[16];
|
||||
byte _midi_effectlevel_last[16];
|
||||
byte _midi_chorus_last[16];
|
||||
int8 _midi_pan_last[16];
|
||||
|
||||
void midiPitchBend(byte chan, int16 pitchbend);
|
||||
void midiVolume(byte chan, byte volume);
|
||||
void midiPedal(byte chan, bool pedal);
|
||||
void midiModWheel(byte chan, byte modwheel);
|
||||
void midiEffectLevel(byte chan, byte level);
|
||||
void midiChorus(byte chan, byte chorus);
|
||||
void midiControl0(byte chan, byte value);
|
||||
void midiProgram(byte chan, byte program);
|
||||
void midiPan(byte chan, int8 pan);
|
||||
void midiNoteOn(byte chan, byte note, byte velocity);
|
||||
void midiNoteOff(byte chan, byte note);
|
||||
void midiSilence(byte chan);
|
||||
void midiInit();
|
||||
|
||||
public:
|
||||
void uninit();
|
||||
void init(SoundEngine *eng);
|
||||
void update_pris();
|
||||
void part_off(Part *part);
|
||||
int part_update_active(Part *part,uint16 *active);
|
||||
|
||||
void generate_samples(int16 *buf, int len) {}
|
||||
void on_timer() {}
|
||||
void set_instrument(uint slot, byte *instr) {}
|
||||
void part_set_instrument(Part *part, Instrument *instr) {}
|
||||
void part_set_param(Part *part, byte param, int value) {}
|
||||
void part_key_on(Part *part, byte note, byte velocity);
|
||||
void part_key_off(Part *part, byte note);
|
||||
void part_changed(Part *part,byte what);
|
||||
|
||||
bool wave_based() { return false; }
|
||||
};
|
||||
|
||||
struct SoundEngine {
|
||||
void *_mo; /* midi out */
|
||||
friend struct Player;
|
||||
private:
|
||||
SOUND_DRIVER_TYPE *_driver;
|
||||
|
||||
byte **_base_sounds;
|
||||
|
||||
|
@ -256,8 +463,6 @@ struct SoundEngine {
|
|||
SustainingNotes *_sustain_notes_free;
|
||||
SustainingNotes *_sustain_notes_head;
|
||||
|
||||
uint16 _timer_counter_1;
|
||||
|
||||
byte _queue_marker;
|
||||
byte _queue_cleared;
|
||||
byte _master_volume;
|
||||
|
@ -272,28 +477,11 @@ struct SoundEngine {
|
|||
SustainingNotes _sustaining_notes[24];
|
||||
VolumeFader _volume_fader[8];
|
||||
Part _parts[32];
|
||||
MidiChannel _midi_channels[9];
|
||||
|
||||
uint16 _active_notes[128];
|
||||
CommandQueue _cmd_queue[64];
|
||||
|
||||
int16 _midi_pitchbend_last[16];
|
||||
uint8 _midi_volume_last[16];
|
||||
bool _midi_pedal_last[16];
|
||||
byte _midi_modwheel_last[16];
|
||||
byte _midi_effectlevel_last[16];
|
||||
byte _midi_chorus_last[16];
|
||||
int8 _midi_pan_last[16];
|
||||
|
||||
byte *findTag(int sound, char *tag, int index);
|
||||
int initialize(Scumm *scumm);
|
||||
int terminate();
|
||||
int save_or_load(Serializer *ser);
|
||||
int set_master_volume(uint vol);
|
||||
int get_master_volume();
|
||||
bool start_sound(int sound);
|
||||
int stop_sound(int sound);
|
||||
int stop_all_sounds();
|
||||
int get_sound_status(int sound);
|
||||
int get_queue_sound_status(int sound);
|
||||
Player *allocate_player(byte priority);
|
||||
void handle_marker(uint id, byte data);
|
||||
|
@ -304,17 +492,12 @@ struct SoundEngine {
|
|||
void init_sustaining_notes();
|
||||
void init_queue();
|
||||
|
||||
void on_timer();
|
||||
void sequencer_timers();
|
||||
void expire_sustain_notes();
|
||||
void expire_volume_faders();
|
||||
|
||||
void set_instrument(uint slot, byte *data) {}
|
||||
|
||||
int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h);
|
||||
Part *allocate_part(byte pri);
|
||||
|
||||
int clear_queue();
|
||||
int enqueue_command(int a, int b, int c, int d, int e, int f, int g);
|
||||
int enqueue_trigger(int sound, int marker);
|
||||
int query_queue(int param);
|
||||
|
@ -329,22 +512,6 @@ struct SoundEngine {
|
|||
|
||||
int set_volchan(int sound, int volchan);
|
||||
|
||||
void midiPitchBend(byte chan, int16 pitchbend);
|
||||
void midiVolume(byte chan, byte volume);
|
||||
void midiPedal(byte chan, bool pedal);
|
||||
void midiModWheel(byte chan, byte modwheel);
|
||||
void midiEffectLevel(byte chan, byte level);
|
||||
void midiChorus(byte chan, byte chorus);
|
||||
void midiControl0(byte chan, byte value);
|
||||
void midiProgram(byte chan, byte program);
|
||||
void midiPan(byte chan, int8 pan);
|
||||
void midiNoteOn(byte chan, byte note, byte velocity);
|
||||
void midiNoteOff(byte chan, byte note);
|
||||
void midiSilence(byte chan);
|
||||
void midiInit();
|
||||
|
||||
void adjust_priorities();
|
||||
|
||||
void fix_parts_after_load();
|
||||
void fix_players_after_load();
|
||||
|
||||
|
@ -354,5 +521,24 @@ struct SoundEngine {
|
|||
void lock();
|
||||
void unlock();
|
||||
|
||||
public:
|
||||
void on_timer();
|
||||
Part *parts_ptr() { return _parts; }
|
||||
void pause(bool paused);
|
||||
int initialize(Scumm *scumm, SoundDriver *driver);
|
||||
int terminate();
|
||||
int save_or_load(Serializer *ser);
|
||||
int set_master_volume(uint vol);
|
||||
int get_master_volume();
|
||||
bool start_sound(int sound);
|
||||
int stop_sound(int sound);
|
||||
int stop_all_sounds();
|
||||
int get_sound_status(int sound);
|
||||
int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h);
|
||||
int clear_queue();
|
||||
void setBase(byte **base) { _base_sounds = base; }
|
||||
|
||||
SOUND_DRIVER_TYPE *driver() { return _driver; }
|
||||
};
|
||||
|
||||
|
||||
|
|
938
sound/adlib.cpp
Normal file
938
sound/adlib.cpp
Normal file
|
@ -0,0 +1,938 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 The ScummVM project
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "scumm.h"
|
||||
#include "sound.h"
|
||||
#include "fmopl.h"
|
||||
|
||||
#if defined USE_ADLIB
|
||||
|
||||
static byte lookup_table[64][32];
|
||||
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
|
||||
};
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
MidiChannelAdl *AdlibSoundDriver::allocate_midichan(byte pri) {
|
||||
MidiChannelAdl *ac,*best=NULL;
|
||||
int i;
|
||||
|
||||
for (i=0; i<9; i++) {
|
||||
if (++_midichan_index >= 9)
|
||||
_midichan_index = 0;
|
||||
ac = &_midi_channels[_midichan_index];
|
||||
if (!ac->_part)
|
||||
return ac;
|
||||
if (!ac->_next) {
|
||||
if (ac->_part->_pri_eff <= pri) {
|
||||
pri = ac->_part->_pri_eff;
|
||||
best = ac;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best)
|
||||
mc_off(best);
|
||||
else
|
||||
;//debug(1, "Denying adlib channel request");
|
||||
return best;
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::init(SoundEngine *eng) {
|
||||
int i;
|
||||
MidiChannelAdl *mc;
|
||||
|
||||
_se = eng;
|
||||
|
||||
for(i=0,mc=_midi_channels; i!=ARRAYSIZE(_midi_channels);i++,mc++)
|
||||
mc->_channel = i;
|
||||
|
||||
_adlib_reg_cache = (byte*)calloc(256,1);
|
||||
_opl = OPLCreate(OPL_TYPE_YM3812,3579545,22050);
|
||||
adlib_write(1,0x20);
|
||||
adlib_write(8,0x40);
|
||||
adlib_write(0xBD, 0x00);
|
||||
create_lookup_table();
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::adlib_write(byte port, byte value) {
|
||||
if (_adlib_reg_cache[port] == value)
|
||||
return;
|
||||
_adlib_reg_cache[port] = value;
|
||||
|
||||
static FILE *myout;
|
||||
if (!myout)
|
||||
myout = fopen("d:\\old.ims", "w");
|
||||
fprintf(myout, "[%x]=%x\n", port, value);
|
||||
|
||||
|
||||
OPLWriteReg(_opl, port, value);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::adlib_key_off(int chan) {
|
||||
byte port = chan + 0xB0;
|
||||
adlib_write(port, adlib_read(port)&~0x20);
|
||||
}
|
||||
|
||||
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}, /* waveform 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 */
|
||||
};
|
||||
|
||||
void AdlibSoundDriver::adlib_set_param(int channel, byte param, int value) {
|
||||
const AdlibSetParams *as;
|
||||
byte port;
|
||||
|
||||
assert(channel>=0 && channel<9);
|
||||
|
||||
if (param <= 12) {
|
||||
port = channel_mappings_2[channel];
|
||||
} else if (param <= 25) {
|
||||
param -= 13;
|
||||
port = channel_mappings[channel];
|
||||
} else if (param <= 27) {
|
||||
param -= 13;
|
||||
port = 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;
|
||||
port += as->a;
|
||||
adlib_write(port, (adlib_read(port) & ~as->c) | (((byte)value)<<as->b));
|
||||
}
|
||||
|
||||
static const byte octave_numbers[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7
|
||||
};
|
||||
|
||||
static const byte note_numbers[]= {
|
||||
3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
3, 4, 5, 6, 7, 8, 9, 10
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
void AdlibSoundDriver::adlib_playnote(int channel, int note) {
|
||||
byte old,oct,notex;
|
||||
int note2;
|
||||
int i;
|
||||
|
||||
note2 = (note>>7) - 4;
|
||||
|
||||
oct = octave_numbers[note2]<<2;
|
||||
notex = note_numbers[note2];
|
||||
|
||||
old = adlib_read(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);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::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, channel_table_2[chan] + code);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::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 AdlibSoundDriver::adlib_key_onoff(int channel) {
|
||||
byte val;
|
||||
byte port = channel + 0xB0;
|
||||
assert(channel>=0 && channel<9);
|
||||
|
||||
val = adlib_read(port);
|
||||
adlib_write(port, val&~0x20);
|
||||
adlib_write(port, val|0x20);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::adlib_setup_channel(int chan, Instrument *instr, byte vol_1, byte vol_2) {
|
||||
byte port;
|
||||
|
||||
assert(chan>=0 && chan<9);
|
||||
|
||||
port = channel_mappings[chan];
|
||||
adlib_write(port + 0x20, instr->flags_1);
|
||||
adlib_write(port + 0x40, (instr->oplvl_1|0x3F) - vol_1);
|
||||
adlib_write(port + 0x60, ~instr->atdec_1);
|
||||
adlib_write(port + 0x80, ~instr->sustrel_1);
|
||||
adlib_write(port + 0xE0, instr->waveform_1);
|
||||
|
||||
port = channel_mappings_2[chan];
|
||||
adlib_write(port + 0x20, instr->flags_2);
|
||||
adlib_write(port + 0x40, (instr->oplvl_2|0x3F) - vol_2);
|
||||
adlib_write(port + 0x60, ~instr->atdec_2);
|
||||
adlib_write(port + 0x80, ~instr->sustrel_2);
|
||||
adlib_write(port + 0xE0, instr->waveform_2);
|
||||
|
||||
adlib_write((byte)chan + 0xC0, instr->feedback);
|
||||
}
|
||||
|
||||
int AdlibSoundDriver::adlib_read_param(int chan, byte param) {
|
||||
const AdlibSetParams *as;
|
||||
byte val;
|
||||
byte port;
|
||||
|
||||
assert(chan>=0 && chan<9);
|
||||
|
||||
if (param <= 12) {
|
||||
port = channel_mappings_2[chan];
|
||||
} else if (param <= 25) {
|
||||
param -= 13;
|
||||
port = channel_mappings[chan];
|
||||
} else if (param <= 27) {
|
||||
param -= 13;
|
||||
port = chan;
|
||||
} else if (param==28) {
|
||||
return 0xF;
|
||||
} else if (param==29) {
|
||||
return 0x17F;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
as = &adlib_setparam_table[param];
|
||||
val = adlib_read(port + as->a);
|
||||
val &= as->c;
|
||||
val >>= as->b;
|
||||
if (as->d)
|
||||
val = as->d - val;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::generate_samples(int16 *data, int len) {
|
||||
int step;
|
||||
|
||||
if (!_opl) {
|
||||
memset(data, 0, len*sizeof(int16));
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
step = len;
|
||||
if (step > _next_tick)
|
||||
step = _next_tick;
|
||||
YM3812UpdateOne(_opl,data,step);
|
||||
|
||||
if(!(_next_tick -= step)) {
|
||||
_se->on_timer();
|
||||
reset_tick();
|
||||
}
|
||||
data += step;
|
||||
} while (len-=step);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::reset_tick() {
|
||||
_next_tick = 88;
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::on_timer() {
|
||||
MidiChannelAdl *mc;
|
||||
int i;
|
||||
|
||||
_adlib_timer_counter += 0xD69;
|
||||
while (_adlib_timer_counter >= 0x411B) {
|
||||
_adlib_timer_counter -= 0x411B;
|
||||
mc = _midi_channels;
|
||||
for (i=0; i!=ARRAYSIZE(_midi_channels); i++,mc++) {
|
||||
if (!mc->_part)
|
||||
continue;
|
||||
if (mc->_duration && (mc->_duration -= 0x11) <= 0) {
|
||||
mc_off(mc);
|
||||
return;
|
||||
}
|
||||
if (mc->_s10a.active) {
|
||||
mc_inc_stuff(mc, &mc->_s10a, &mc->_s11a);
|
||||
}
|
||||
if (mc->_s10b.active) {
|
||||
mc_inc_stuff(mc, &mc->_s10b, &mc->_s11b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const byte param_table_1[16] = {
|
||||
29,28,27,0,
|
||||
3,4,7,8,
|
||||
13,16,17,20,
|
||||
21,30,31,0
|
||||
};
|
||||
|
||||
const uint16 param_table_2[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
|
||||
};
|
||||
|
||||
int AdlibSoundDriver::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 AdlibSoundDriver::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->param;
|
||||
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;
|
||||
}
|
||||
|
||||
byte AdlibSoundDriver::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;
|
||||
}
|
||||
}
|
||||
assert(s10->num_steps>=0);
|
||||
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 AdlibSoundDriver::struct10_init(Struct10 *s10, InstrumentExtra *ie) {
|
||||
s10->active = 1;
|
||||
s10->cur_val = 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);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::mc_init_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11, byte flags, InstrumentExtra *ie) {
|
||||
Part *part = mc->_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->param = param_table_2[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 = mc->_vol_2;
|
||||
break;
|
||||
case 13:
|
||||
s10->start_value = mc->_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 = part->_drv->adlib_read_param(mc->_channel, s11->param);
|
||||
}
|
||||
|
||||
struct10_init(s10, ie);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::mc_inc_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11) {
|
||||
byte code;
|
||||
Part *part= mc->_part;
|
||||
|
||||
code = struct10_ontimer(s10,s11);
|
||||
|
||||
if (code&1) {
|
||||
switch(s11->param) {
|
||||
case 0:
|
||||
mc->_vol_2 = s10->start_value + s11->modify_val;
|
||||
part->_drv->adlib_set_param(mc->_channel, 0, volume_table[lookup_table[mc->_vol_2][part->_vol_eff>>2]]);
|
||||
break;
|
||||
case 13:
|
||||
mc->_vol_1 = s10->start_value + s11->modify_val;
|
||||
if (mc->_twochan) {
|
||||
part->_drv->adlib_set_param(mc->_channel, 13, volume_table[lookup_table[mc->_vol_1][part->_vol_eff>>2]]);
|
||||
} else {
|
||||
part->_drv->adlib_set_param(mc->_channel, 13, mc->_vol_1);
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
s11->s10->modwheel = s11->modify_val;
|
||||
break;
|
||||
case 31:
|
||||
s11->s10->unk3 = s11->modify_val;
|
||||
break;
|
||||
default:
|
||||
part->_drv->adlib_set_param(mc->_channel, s11->param, s10->start_value + s11->modify_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (code&2 && s11->flag0x10)
|
||||
part->_drv->adlib_key_onoff(mc->_channel);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::part_changed(Part *part,byte what) {
|
||||
MidiChannelAdl *mc;
|
||||
|
||||
if (what & pcProgram) {
|
||||
if (part->_program < 32) {
|
||||
part_set_instrument(part, &_glob_instr[part->_program]);
|
||||
}
|
||||
}
|
||||
|
||||
if (what & pcMod) {
|
||||
for(mc=part->_mc->adl(); mc; mc=mc->_next) {
|
||||
adlib_note_on(mc->_channel, mc->_note + part->_transpose_eff, part->_pitchbend + part->_detune_eff);
|
||||
}
|
||||
}
|
||||
|
||||
if (what & pcVolume) {
|
||||
for(mc=part->_mc->adl(); mc; mc=mc->_next) {
|
||||
adlib_set_param(mc->_channel, 0, volume_table[lookup_table[mc->_vol_2][part->_vol_eff>>2]]);
|
||||
if (mc->_twochan) {
|
||||
adlib_set_param(mc->_channel, 13, volume_table[lookup_table[mc->_vol_1][part->_vol_eff>>2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (what & pcPedal) {
|
||||
if (!part->_pedal) {
|
||||
for(mc=(MidiChannelAdl*)part->_mc; mc; mc=mc->_next) {
|
||||
if (mc->_waitforpedal)
|
||||
mc_off(mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (what & pcModwheel) {
|
||||
for(mc=(MidiChannelAdl*)part->_mc; mc; mc=mc->_next) {
|
||||
if (mc->_s10a.active && mc->_s11a.flag0x40)
|
||||
mc->_s10a.modwheel = part->_modwheel>>2;
|
||||
if (mc->_s10b.active && mc->_s11b.flag0x40)
|
||||
mc->_s10b.modwheel = part->_modwheel>>2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::mc_key_on(MidiChannel *mc2, byte note, byte velocity) {
|
||||
MidiChannelAdl *mc = (MidiChannelAdl*)mc2;
|
||||
Part *part = mc->_part;
|
||||
Instrument *instr = &_part_instr[part->_slot];
|
||||
int c;
|
||||
byte vol_1,vol_2;
|
||||
|
||||
mc->_twochan = instr->feedback&1;
|
||||
mc->_note = note;
|
||||
mc->_waitforpedal = false;
|
||||
mc->_duration = instr->duration;
|
||||
if (mc->_duration != 0)
|
||||
mc->_duration *= 63;
|
||||
|
||||
vol_1 = (instr->oplvl_1&0x3F) + lookup_table[velocity>>1][instr->waveform_1>>2];
|
||||
if (vol_1 > 0x3F)
|
||||
vol_1 = 0x3F;
|
||||
mc->_vol_1 = vol_1;
|
||||
|
||||
vol_2 = (instr->oplvl_2&0x3F) + lookup_table[velocity>>1][instr->waveform_2>>2];
|
||||
if (vol_2 > 0x3F)
|
||||
vol_2 = 0x3F;
|
||||
mc->_vol_2 = vol_2;
|
||||
|
||||
c = part->_vol_eff >> 2;
|
||||
|
||||
vol_2 = volume_table[lookup_table[vol_2][c]];
|
||||
if (mc->_twochan)
|
||||
vol_1 = volume_table[lookup_table[vol_1][c]];
|
||||
|
||||
adlib_setup_channel(mc->_channel, instr, vol_1, vol_2);
|
||||
adlib_note_on_ex(mc->_channel, part->_transpose_eff + note, part->_detune_eff + part->_pitchbend);
|
||||
|
||||
if (instr->flags_a & 0x80) {
|
||||
mc_init_stuff(mc, &mc->_s10a, &mc->_s11a, instr->flags_a, &instr->extra_a);
|
||||
} else {
|
||||
mc->_s10a.active = 0;
|
||||
}
|
||||
|
||||
if (instr->flags_b & 0x80) {
|
||||
mc_init_stuff(mc, &mc->_s10b, &mc->_s11b, instr->flags_b, &instr->extra_b);
|
||||
} else {
|
||||
mc->_s10b.active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::set_instrument(uint slot, byte *data) {
|
||||
if (slot < 32) {
|
||||
memcpy(&_glob_instr[slot], data, sizeof(Instrument));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AdlibSoundDriver::link_mc(Part *part, MidiChannelAdl *mc) {
|
||||
mc->_part = part;
|
||||
mc->_next = (MidiChannelAdl*)part->_mc;
|
||||
part->_mc = mc;
|
||||
mc->_prev = NULL;
|
||||
|
||||
if (mc->_next)
|
||||
mc->_next->_prev = mc;
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::part_key_on(Part *part, byte note, byte velocity) {
|
||||
MidiChannelAdl *mc;
|
||||
|
||||
mc = allocate_midichan(part->_pri_eff);
|
||||
if (!mc)
|
||||
return;
|
||||
|
||||
link_mc(part, mc);
|
||||
mc_key_on(mc,note, velocity);
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::part_key_off(Part *part, byte note) {
|
||||
MidiChannelAdl *mc;
|
||||
|
||||
for(mc=(MidiChannelAdl*)part->_mc; mc; mc=mc->_next) {
|
||||
if (mc->_note==note) {
|
||||
if (part->_pedal)
|
||||
mc->_waitforpedal = true;
|
||||
else
|
||||
mc_off(mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AdlibInstrSetParams {
|
||||
byte param;
|
||||
byte shl;
|
||||
byte mask;
|
||||
};
|
||||
|
||||
#define MKLINE(_a_,_b_,_c_) { (int)&((Instrument*)0)->_a_, _b_, ((1<<(_c_))-1)<<(_b_) }
|
||||
static const AdlibInstrSetParams adlib_instr_params[69] = {
|
||||
MKLINE(oplvl_2,0,6),
|
||||
MKLINE(waveform_2,2,5),
|
||||
MKLINE(oplvl_2,6,2),
|
||||
MKLINE(flags_2,0,4),
|
||||
MKLINE(atdec_2,4,4),
|
||||
MKLINE(atdec_2,0,4),
|
||||
MKLINE(sustrel_2,4,4),
|
||||
MKLINE(sustrel_2,0,4),
|
||||
MKLINE(waveform_2,0,2),
|
||||
MKLINE(flags_2,7,1),
|
||||
MKLINE(flags_2,6,1),
|
||||
MKLINE(flags_2,5,1),
|
||||
MKLINE(flags_2,4,1),
|
||||
|
||||
MKLINE(oplvl_1,0,6),
|
||||
MKLINE(waveform_1,2,5),
|
||||
MKLINE(oplvl_1,6,2),
|
||||
MKLINE(flags_1,0,4),
|
||||
MKLINE(atdec_1,4,4),
|
||||
MKLINE(atdec_1,0,4),
|
||||
MKLINE(sustrel_1,4,4),
|
||||
MKLINE(sustrel_1,0,4),
|
||||
MKLINE(waveform_1,0,2),
|
||||
MKLINE(flags_1,7,1),
|
||||
MKLINE(flags_1,6,1),
|
||||
MKLINE(flags_1,5,1),
|
||||
MKLINE(flags_1,4,1),
|
||||
|
||||
MKLINE(feedback,0,1),
|
||||
MKLINE(feedback,1,3),
|
||||
|
||||
MKLINE(flags_a,7,1),
|
||||
MKLINE(flags_a,6,1),
|
||||
MKLINE(flags_a,5,1),
|
||||
MKLINE(flags_a,4,1),
|
||||
MKLINE(flags_a,0,4),
|
||||
MKLINE(extra_a.a,0,8),
|
||||
MKLINE(extra_a.b,0,7),
|
||||
MKLINE(extra_a.c,0,7),
|
||||
MKLINE(extra_a.d,0,7),
|
||||
MKLINE(extra_a.e,0,7),
|
||||
MKLINE(extra_a.f,0,7),
|
||||
MKLINE(extra_a.g,0,7),
|
||||
MKLINE(extra_a.h,0,7),
|
||||
MKLINE(extra_a.b,7,1),
|
||||
MKLINE(extra_a.c,7,1),
|
||||
MKLINE(extra_a.d,7,1),
|
||||
MKLINE(extra_a.e,7,1),
|
||||
MKLINE(extra_a.f,7,1),
|
||||
MKLINE(extra_a.g,7,1),
|
||||
MKLINE(extra_a.h,7,1),
|
||||
|
||||
MKLINE(flags_b,7,1),
|
||||
MKLINE(flags_b,6,1),
|
||||
MKLINE(flags_b,5,1),
|
||||
MKLINE(flags_b,4,1),
|
||||
MKLINE(flags_b,0,4),
|
||||
MKLINE(extra_b.a,0,8),
|
||||
MKLINE(extra_b.b,0,7),
|
||||
MKLINE(extra_b.c,0,7),
|
||||
MKLINE(extra_b.d,0,7),
|
||||
MKLINE(extra_b.e,0,7),
|
||||
MKLINE(extra_b.f,0,7),
|
||||
MKLINE(extra_b.g,0,7),
|
||||
MKLINE(extra_b.h,0,7),
|
||||
MKLINE(extra_b.b,7,1),
|
||||
MKLINE(extra_b.c,7,1),
|
||||
MKLINE(extra_b.d,7,1),
|
||||
MKLINE(extra_b.e,7,1),
|
||||
MKLINE(extra_b.f,7,1),
|
||||
MKLINE(extra_b.g,7,1),
|
||||
MKLINE(extra_b.h,7,1),
|
||||
|
||||
MKLINE(duration,0,8),
|
||||
};
|
||||
#undef MKLINE
|
||||
|
||||
void AdlibSoundDriver::part_set_param(Part *part, byte param, int value) {
|
||||
const AdlibInstrSetParams *sp = &adlib_instr_params[param];
|
||||
byte *p = (byte*)&_part_instr[part->_slot] + sp->param;
|
||||
*p = (*p&~sp->mask) | (value<<sp->shl);
|
||||
|
||||
if (param < 28) {
|
||||
MidiChannelAdl *mc;
|
||||
|
||||
for(mc=(MidiChannelAdl*)part->_mc; mc; mc=mc->_next) {
|
||||
adlib_set_param(mc->_channel, param, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::part_off(Part *part) {
|
||||
MidiChannelAdl *mc = (MidiChannelAdl*)part->_mc;
|
||||
part->_mc = NULL;
|
||||
for(; mc; mc=mc->_next) {
|
||||
mc_off(mc);
|
||||
}
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::mc_off(MidiChannel *mc2) {
|
||||
MidiChannelAdl *mc = (MidiChannelAdl*)mc2, *tmp;
|
||||
|
||||
adlib_key_off(mc->_channel);
|
||||
|
||||
tmp = mc->_prev;
|
||||
|
||||
if (mc->_next)
|
||||
mc->_next->_prev = tmp;
|
||||
if (tmp)
|
||||
tmp->_next = mc->_next;
|
||||
else
|
||||
mc->_part->_mc = mc->_next;
|
||||
mc->_part = NULL;
|
||||
}
|
||||
|
||||
void AdlibSoundDriver::part_set_instrument(Part *part, Instrument *instr) {
|
||||
Instrument *i = &_part_instr[part->_slot];
|
||||
memcpy(i, instr, sizeof(Instrument));
|
||||
}
|
||||
|
||||
int AdlibSoundDriver::part_update_active(Part *part,uint16 *active) {
|
||||
int i;
|
||||
uint16 bits;
|
||||
int count = 0;
|
||||
MidiChannelAdl *mc;
|
||||
|
||||
bits = 1<<part->_chan;
|
||||
|
||||
for(mc=part->_mc->adl(); mc; mc=mc->_next) {
|
||||
if (!(active[mc->_note] & bits)) {
|
||||
active[mc->_note] |= bits;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
1106
sound/fmopl.cpp
Normal file
1106
sound/fmopl.cpp
Normal file
File diff suppressed because it is too large
Load diff
155
sound/fmopl.h
Normal file
155
sound/fmopl.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
|
||||
#ifndef __FMOPL_H_
|
||||
#define __FMOPL_H_
|
||||
|
||||
/* --- select emulation chips --- */
|
||||
#define BUILD_YM3812 (HAS_YM3812)
|
||||
#define BUILD_YM3526 (HAS_YM3526)
|
||||
#define BUILD_Y8950 (HAS_Y8950)
|
||||
|
||||
/* --- system optimize --- */
|
||||
/* select bit size of output : 8 or 16 */
|
||||
#define OPL_OUTPUT_BIT 16
|
||||
|
||||
/* compiler dependence */
|
||||
#ifndef OSD_CPU_H
|
||||
#define OSD_CPU_H
|
||||
typedef unsigned char UINT8; /* unsigned 8bit */
|
||||
typedef unsigned short UINT16; /* unsigned 16bit */
|
||||
typedef unsigned int UINT32; /* unsigned 32bit */
|
||||
typedef signed char INT8; /* signed 8bit */
|
||||
typedef signed short INT16; /* signed 16bit */
|
||||
typedef signed int INT32; /* signed 32bit */
|
||||
#endif
|
||||
|
||||
#if (OPL_OUTPUT_BIT==16)
|
||||
typedef INT16 OPLSAMPLE;
|
||||
#endif
|
||||
#if (OPL_OUTPUT_BIT==8)
|
||||
typedef unsigned char OPLSAMPLE;
|
||||
#endif
|
||||
|
||||
|
||||
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);
|
||||
typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
|
||||
typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
|
||||
|
||||
/* !!!!! here is private section , do not access there member direct !!!!! */
|
||||
|
||||
#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
|
||||
#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
|
||||
#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
|
||||
#define OPL_TYPE_IO 0x08 /* I/O port */
|
||||
|
||||
/* Saving is necessary for member of the 'R' mark for suspend/resume */
|
||||
/* ---------- OPL one of slot ---------- */
|
||||
typedef struct fm_opl_slot {
|
||||
INT32 TL; /* total level :TL << 8 */
|
||||
INT32 TLL; /* adjusted now TL */
|
||||
UINT8 KSR; /* key scale rate :(shift down bit) */
|
||||
INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */
|
||||
INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */
|
||||
INT32 SL; /* sustin level :SL_TALBE[SL] */
|
||||
INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */
|
||||
UINT8 ksl; /* keyscale level :(shift down bits) */
|
||||
UINT8 ksr; /* key scale rate :kcode>>KSR */
|
||||
UINT32 mul; /* multiple :ML_TABLE[ML] */
|
||||
UINT32 Cnt; /* frequency count : */
|
||||
UINT32 Incr; /* frequency step : */
|
||||
/* envelope generator state */
|
||||
UINT8 eg_typ; /* envelope type flag */
|
||||
UINT8 evm; /* envelope phase */
|
||||
INT32 evc; /* envelope counter */
|
||||
INT32 eve; /* envelope counter end point */
|
||||
INT32 evs; /* envelope counter step */
|
||||
INT32 evsa; /* envelope step for AR :AR[ksr] */
|
||||
INT32 evsd; /* envelope step for DR :DR[ksr] */
|
||||
INT32 evsr; /* envelope step for RR :RR[ksr] */
|
||||
/* LFO */
|
||||
UINT8 ams; /* ams flag */
|
||||
UINT8 vib; /* vibrate flag */
|
||||
/* wave selector */
|
||||
INT32 **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) */
|
||||
INT32 *connect1; /* slot1 output pointer */
|
||||
INT32 *connect2; /* slot2 output pointer */
|
||||
INT32 op1_out[2]; /* slot1 output for selfeedback */
|
||||
/* phase generator state */
|
||||
UINT32 block_fnum; /* block+fnum : */
|
||||
UINT8 kcode; /* key code : KeyScaleCode */
|
||||
UINT32 fc; /* Freq. Increment base */
|
||||
UINT32 ksl_base; /* KeyScaleLevel Base step */
|
||||
UINT8 keyon; /* key on/off flag */
|
||||
} OPL_CH;
|
||||
|
||||
/* OPL state */
|
||||
struct FM_OPL {
|
||||
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 */
|
||||
UINT32 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 */
|
||||
/* LFO */
|
||||
INT32 *ams_table;
|
||||
INT32 *vib_table;
|
||||
INT32 amsCnt;
|
||||
INT32 amsIncr;
|
||||
INT32 vibCnt;
|
||||
INT32 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 */
|
||||
INT32 AR_TABLE[75]; /* atttack rate tables */
|
||||
INT32 DR_TABLE[75]; /* decay rate tables */
|
||||
UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */
|
||||
};
|
||||
|
||||
/* ---------- Generic interface section ---------- */
|
||||
#define OPL_TYPE_YM3526 (0)
|
||||
#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
|
||||
#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
|
||||
|
||||
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);
|
||||
|
||||
/* YM3626/YM3812 local section */
|
||||
void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
|
||||
|
||||
#endif
|
414
sound/gmidi.cpp
Normal file
414
sound/gmidi.cpp
Normal file
|
@ -0,0 +1,414 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 The ScummVM project
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Timidity support by Lionel Ulmer <lionel.ulmer@free.fr>
|
||||
*/
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#if !defined USE_ADLIB
|
||||
|
||||
#include "scumm.h"
|
||||
#include "sound.h"
|
||||
|
||||
#ifdef USE_TIMIDITY
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Copy-pasted from Timidity */
|
||||
#define SEQ_MIDIPUTC 5
|
||||
|
||||
#endif /* USE_TIMIDITY */
|
||||
|
||||
|
||||
#define SPECIAL_CHANNEL 9
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
void MidiSoundDriver::midiInit() {
|
||||
if (midiOutOpen((HMIDIOUT*)&_mo, MIDI_MAPPER, NULL, NULL, 0) != MMSYSERR_NOERROR)
|
||||
error("midiOutOpen failed");
|
||||
}
|
||||
|
||||
#define MIDI_OUT(a,b) midiOutShortMsg((HMIDIOUT)(a), (b))
|
||||
|
||||
#elif defined(USE_TIMIDITY)
|
||||
|
||||
static int connect_to_timidity(int port)
|
||||
{
|
||||
struct hostent *serverhost;
|
||||
struct sockaddr_in sadd;
|
||||
int s;
|
||||
|
||||
serverhost = gethostbyname("localhost");
|
||||
if (serverhost == NULL)
|
||||
error("Could not resolve host");
|
||||
sadd.sin_family = serverhost->h_addrtype;
|
||||
sadd.sin_port = htons(port);
|
||||
memcpy(&(sadd.sin_addr), serverhost->h_addr_list[0], serverhost->h_length);
|
||||
|
||||
s = socket(AF_INET,SOCK_STREAM,0);
|
||||
if (s < 0)
|
||||
error("Could not open socket");
|
||||
if (connect(s, (struct sockaddr *) &sadd, sizeof(struct sockaddr_in)) < 0)
|
||||
error("Could not connect to server");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void SoundEngine::midiInit() {
|
||||
int s, s2;
|
||||
int len;
|
||||
int dummy, newport;
|
||||
char buf[256];
|
||||
|
||||
s = connect_to_timidity(7777);
|
||||
len = read(s, buf, 256);
|
||||
buf[len] = '\0';
|
||||
printf("%s", buf);
|
||||
|
||||
sprintf(buf, "SETBUF %f %f\n", 0.1, 0.15);
|
||||
write(s, buf, strlen(buf));
|
||||
len = read(s, buf, 256);
|
||||
buf[len] = '\0';
|
||||
printf("%s", buf);
|
||||
|
||||
sprintf(buf, "OPEN lsb\n");
|
||||
write(s, buf, strlen(buf));
|
||||
len = read(s, buf, 256);
|
||||
buf[len] = '\0';
|
||||
printf("%s", buf);
|
||||
|
||||
sscanf(buf, "%d %d", &dummy, &newport);
|
||||
printf(" => port = %d\n", newport);
|
||||
|
||||
s2 = connect_to_timidity(newport);
|
||||
_mo = (void *) s2;
|
||||
}
|
||||
|
||||
#define DEVICE_NUM 0
|
||||
|
||||
static inline void MIDI_OUT(void *a, int b) {
|
||||
int s = (int) a;
|
||||
unsigned char buf[256];
|
||||
int position = 0;
|
||||
|
||||
switch (b & 0xF0) {
|
||||
case 0x80:
|
||||
case 0x90:
|
||||
case 0xA0:
|
||||
case 0xB0:
|
||||
case 0xE0:
|
||||
buf[position++] = SEQ_MIDIPUTC;
|
||||
buf[position++] = b;
|
||||
buf[position++] = DEVICE_NUM;
|
||||
buf[position++] = 0;
|
||||
buf[position++] = SEQ_MIDIPUTC;
|
||||
buf[position++] = (b >> 8) & 0x7F;
|
||||
buf[position++] = DEVICE_NUM;
|
||||
buf[position++] = 0;
|
||||
buf[position++] = SEQ_MIDIPUTC;
|
||||
buf[position++] = (b >> 16) & 0x7F;
|
||||
buf[position++] = DEVICE_NUM;
|
||||
buf[position++] = 0;
|
||||
break;
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
buf[position++] = SEQ_MIDIPUTC;
|
||||
buf[position++] = b;
|
||||
buf[position++] = DEVICE_NUM;
|
||||
buf[position++] = 0;
|
||||
buf[position++] = SEQ_MIDIPUTC;
|
||||
buf[position++] = (b >> 8) & 0x7F;
|
||||
buf[position++] = DEVICE_NUM;
|
||||
buf[position++] = 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown : %08x\n", b);
|
||||
break;
|
||||
}
|
||||
write(s, buf, position);
|
||||
}
|
||||
|
||||
#else
|
||||
#define MIDI_OUT(a,b)
|
||||
void SoundEngine::midiInit() { }
|
||||
#endif
|
||||
|
||||
void MidiSoundDriver::midiPitchBend(byte chan, int16 pitchbend) {
|
||||
uint16 tmp;
|
||||
|
||||
if (_midi_pitchbend_last[chan] != pitchbend) {
|
||||
_midi_pitchbend_last[chan] = pitchbend;
|
||||
tmp = (pitchbend<<2) + 0x2000;
|
||||
MIDI_OUT(_mo, ((tmp>>7)&0x7F)<<16 | (tmp&0x7F)<<8 | 0xE0 | chan);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiVolume(byte chan, byte volume) {
|
||||
if (_midi_volume_last[chan] != volume) {
|
||||
_midi_volume_last[chan] = volume;
|
||||
MIDI_OUT(_mo, volume<<16 | 7<<8 | 0xB0 | chan);
|
||||
}
|
||||
}
|
||||
void MidiSoundDriver::midiPedal(byte chan, bool pedal) {
|
||||
if (_midi_pedal_last[chan] != pedal) {
|
||||
_midi_pedal_last[chan] = pedal;
|
||||
MIDI_OUT(_mo, pedal<<16 | 64<<8 | 0xB0 | chan);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiModWheel(byte chan, byte modwheel) {
|
||||
if (_midi_modwheel_last[chan] != modwheel) {
|
||||
_midi_modwheel_last[chan] = modwheel;
|
||||
MIDI_OUT(_mo, modwheel<<16 | 1<<8 | 0xB0 | chan);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiEffectLevel(byte chan, byte level) {
|
||||
if (_midi_effectlevel_last[chan] != level) {
|
||||
_midi_effectlevel_last[chan] = level;
|
||||
MIDI_OUT(_mo, level<<16 | 91<<8 | 0xB0 | chan);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiChorus(byte chan, byte chorus) {
|
||||
if (_midi_chorus_last[chan] != chorus) {
|
||||
_midi_chorus_last[chan] = chorus;
|
||||
MIDI_OUT(_mo, chorus<<16 | 93<<8 | 0xB0 | chan);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiControl0(byte chan, byte value) {
|
||||
MIDI_OUT(_mo, value<<16 | 0<<8 | 0xB0 | chan);
|
||||
}
|
||||
|
||||
static const byte mt32_to_gmidi[128] = {
|
||||
0, 1, 2, 4, 4, 5, 5, 3, 16, 17, 18, 18, 19,
|
||||
19, 20, 21, 6, 6, 6, 7, 7, 7, 8, 8, 62, 63,
|
||||
62, 63, 38, 39, 38, 39, 88, 89, 52, 113, 97, 96, 91,
|
||||
85, 14, 101, 68, 95, 86, 103, 88, 80, 48, 49, 51, 45,
|
||||
40, 40, 42, 42, 43, 46, 46, 24, 25, 26, 27, 104, 32,
|
||||
33, 34, 39, 36, 37, 38, 35, 79, 73, 72, 72, 74, 75,
|
||||
64, 65, 66, 67, 71, 71, 68, 69, 70, 22, 56, 59, 57,
|
||||
63, 60, 60, 58, 61, 61, 11, 11, 12, 88, 9, 14, 13,
|
||||
12, 107, 111, 77, 78, 78, 76, 121, 47, 117, 127, 115, 118,
|
||||
116, 118, 94, 115, 9, 55, 124, 123, 125, 126, 127
|
||||
};
|
||||
|
||||
|
||||
void MidiSoundDriver::midiProgram(byte chan, byte program) {
|
||||
if (_mt32emulate)
|
||||
program=mt32_to_gmidi[program];
|
||||
MIDI_OUT(_mo, program<<8 | 0xC0 | chan);
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiPan(byte chan, int8 pan) {
|
||||
if (_midi_pan_last[chan] != pan) {
|
||||
_midi_pan_last[chan] = pan;
|
||||
MIDI_OUT(_mo, ((pan-64)&0x7F)<<16 | 10<<8 | 0xB0 | chan);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiNoteOn(byte chan, byte note, byte velocity) {
|
||||
MIDI_OUT(_mo, velocity<<16 | note<<8 | 0x90 | chan);
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiNoteOff(byte chan, byte note) {
|
||||
MIDI_OUT(_mo, note<<8 | 0x80 | chan);
|
||||
}
|
||||
|
||||
void MidiSoundDriver::midiSilence(byte chan) {
|
||||
MIDI_OUT(_mo, (64<<8)|0xB0|chan);
|
||||
MIDI_OUT(_mo, (123<<8)|0xB0|chan);
|
||||
}
|
||||
|
||||
|
||||
void MidiSoundDriver::part_key_on(Part *part, byte note, byte velocity) {
|
||||
MidiChannelGM *mc = part->_mc->gm();
|
||||
|
||||
if (mc) {
|
||||
mc->_actives[note>>4] |= (1<<(note&0xF));
|
||||
midiNoteOn(mc->_chan, note, velocity);
|
||||
} else if (part->_percussion) {
|
||||
midiVolume(SPECIAL_CHANNEL, part->_vol_eff);
|
||||
midiProgram(SPECIAL_CHANNEL, part->_bank);
|
||||
midiNoteOn(SPECIAL_CHANNEL, note, velocity);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiSoundDriver::part_key_off(Part *part, byte note) {
|
||||
MidiChannelGM *mc = part->_mc->gm();
|
||||
|
||||
if (mc) {
|
||||
mc->_actives[note>>4] &= ~(1<<(note&0xF));
|
||||
midiNoteOff(mc->_chan, note);
|
||||
} else if (part->_percussion) {
|
||||
midiNoteOff(SPECIAL_CHANNEL, note);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiSoundDriver::init(SoundEngine *eng) {
|
||||
int i;
|
||||
MidiChannelGM *mc;
|
||||
|
||||
_se = eng;
|
||||
|
||||
for(i=0,mc=_midi_channels; i!=ARRAYSIZE(_midi_channels);i++,mc++)
|
||||
mc->_chan = i;
|
||||
|
||||
midiInit();
|
||||
}
|
||||
|
||||
void MidiSoundDriver::update_pris() {
|
||||
Part *part,*hipart;
|
||||
int i;
|
||||
byte hipri,lopri;
|
||||
MidiChannelGM *mc,*lomc;
|
||||
|
||||
while(true) {
|
||||
hipri = 0;
|
||||
hipart = NULL;
|
||||
for(i=32,part=_se->parts_ptr(); i; i--,part++) {
|
||||
if (part->_player && !part->_percussion && part->_on && !part->_mc && part->_pri_eff>=hipri) {
|
||||
hipri = part->_pri_eff;
|
||||
hipart = part;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hipart)
|
||||
return;
|
||||
|
||||
lopri = 255;
|
||||
lomc = NULL;
|
||||
for(i=ARRAYSIZE(_midi_channels),mc=_midi_channels;;mc++) {
|
||||
if (!mc->_part) {
|
||||
lomc = mc;
|
||||
break;
|
||||
}
|
||||
if (mc->_part->_pri_eff<=lopri) {
|
||||
lopri = mc->_part->_pri_eff;
|
||||
lomc = mc;
|
||||
}
|
||||
|
||||
if (!--i) {
|
||||
if (lopri >= hipri)
|
||||
return;
|
||||
lomc->_part->off();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hipart->_mc = lomc;
|
||||
lomc->_part = hipart;
|
||||
hipart->changed(pcAll);
|
||||
}
|
||||
}
|
||||
|
||||
int MidiSoundDriver::part_update_active(Part *part, uint16 *active) {
|
||||
int i,j;
|
||||
uint16 *act,mask,bits;
|
||||
int count = 0;
|
||||
|
||||
bits = 1<<part->_chan;
|
||||
|
||||
act = part->_mc->gm()->_actives;
|
||||
|
||||
for(i=8; i; i--) {
|
||||
mask = *act++;
|
||||
if (mask) {
|
||||
for(j=16; j; j--,mask>>=1,active++) {
|
||||
if (mask&1 && !(*active&bits)) {
|
||||
*active|=bits;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
active += 16;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void MidiSoundDriver::part_changed(Part *part, byte what) {
|
||||
MidiChannelGM *mc;
|
||||
|
||||
/* Mark for re-schedule if program changed when in pre-state */
|
||||
if (what&pcProgram && part->_percussion) {
|
||||
part->_percussion = false;
|
||||
update_pris();
|
||||
}
|
||||
|
||||
if (!(mc = part->_mc->gm()))
|
||||
return;
|
||||
|
||||
if (what & pcMod)
|
||||
midiPitchBend(mc->_chan, clamp(part->_pitchbend + part->_detune_eff + (part->_transpose_eff<<7), -2048, 2047));
|
||||
|
||||
if (what & pcVolume)
|
||||
midiVolume(mc->_chan, part->_vol_eff);
|
||||
|
||||
if (what & pcPedal)
|
||||
midiPedal(mc->_chan, part->_pedal);
|
||||
|
||||
if (what & pcModwheel)
|
||||
midiModWheel(mc->_chan, part->_modwheel);
|
||||
|
||||
if (what & pcPan)
|
||||
midiPan(mc->_chan, part->_pan_eff);
|
||||
|
||||
if (what & pcEffectLevel)
|
||||
midiEffectLevel(mc->_chan, part->_effect_level);
|
||||
|
||||
if (what & pcProgram) {
|
||||
if (part->_bank) {
|
||||
midiControl0(mc->_chan, part->_bank);
|
||||
midiProgram(mc->_chan, part->_program);
|
||||
midiControl0(mc->_chan, 0);
|
||||
} else {
|
||||
midiProgram(mc->_chan, part->_program);
|
||||
}
|
||||
}
|
||||
|
||||
if (what & pcChorus)
|
||||
midiChorus(mc->_chan, part->_effect_level);
|
||||
}
|
||||
|
||||
|
||||
void MidiSoundDriver::part_off(Part *part) {
|
||||
MidiChannelGM *mc = part->_mc->gm();
|
||||
if (mc) {
|
||||
part->_mc = NULL;
|
||||
mc->_part = NULL;
|
||||
memset(mc->_actives, 0, sizeof(mc->_actives));
|
||||
midiSilence(mc->_chan);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
4
sys.cpp
4
sys.cpp
|
@ -55,6 +55,10 @@ bool Scumm::fileEof(void *file) {
|
|||
return feof((FILE*)file) != 0;
|
||||
}
|
||||
|
||||
uint32 Scumm::filePos(void *handle) {
|
||||
return ftell((FILE*)handle);
|
||||
}
|
||||
|
||||
void Scumm::fileSeek(void *file, long offs, int whence) {
|
||||
switch(_fileMode) {
|
||||
case 1: case 2:
|
||||
|
|
21
windows.cpp
21
windows.cpp
|
@ -132,6 +132,7 @@ Scumm scumm;
|
|||
ScummDebugger debugger;
|
||||
Gui gui;
|
||||
SoundEngine sound;
|
||||
SOUND_DRIVER_TYPE snd_driv;
|
||||
|
||||
WndMan wm[1];
|
||||
byte veryFastMode;
|
||||
|
@ -846,7 +847,6 @@ void drawMouse(Scumm *s, int x, int y, int w, int h, byte *buf, bool visible) {
|
|||
}
|
||||
|
||||
void fill_buffer(int16 *buf, int len) {
|
||||
memset(buf, 0, len*2);
|
||||
scumm.mixWaves(buf, len);
|
||||
}
|
||||
|
||||
|
@ -891,10 +891,13 @@ DWORD _stdcall WndMan::sound_thread(WndMan *wm) {
|
|||
int time = GetTickCount(), cur;
|
||||
|
||||
while (1) {
|
||||
cur = GetTickCount();
|
||||
while (time < cur) {
|
||||
sound.on_timer();
|
||||
time += 10;
|
||||
|
||||
if (!snd_driv.wave_based()) {
|
||||
cur = GetTickCount();
|
||||
while (time < cur) {
|
||||
sound.on_timer();
|
||||
time += 10;
|
||||
}
|
||||
}
|
||||
|
||||
signaled = WaitForSingleObject(wm->_event, time - cur) == WAIT_OBJECT_0;
|
||||
|
@ -917,12 +920,12 @@ int main(int argc, char* argv[]) {
|
|||
int delta;
|
||||
|
||||
wm->init();
|
||||
wm->sound_init();
|
||||
wm->_vgabuf = (byte*)calloc(320,200);
|
||||
wm->_scumm = &scumm;
|
||||
|
||||
sound.initialize(&scumm);
|
||||
scumm._soundDriver = &sound;
|
||||
|
||||
sound.initialize(&scumm,&snd_driv);
|
||||
|
||||
wm->sound_init();
|
||||
|
||||
scumm._gui = &gui;
|
||||
scumm.scummMain(argc, argv);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue