diff options
-rw-r--r-- | Makefile.common | 2 | ||||
-rw-r--r-- | bundle.cpp | 69 | ||||
-rw-r--r-- | bundle.h | 5 | ||||
-rw-r--r-- | gui/ListWidget.cpp | 1 | ||||
-rw-r--r-- | init.cpp | 2 | ||||
-rw-r--r-- | morphos/Makefile | 2 | ||||
-rw-r--r-- | scumm.h | 13 | ||||
-rw-r--r-- | scummvm.cpp | 8 | ||||
-rw-r--r-- | scummvm.dsp | 17 | ||||
-rw-r--r-- | sound.cpp | 140 | ||||
-rw-r--r-- | sound/mixer.cpp | 2 | ||||
-rw-r--r-- | timer.cpp | 174 | ||||
-rw-r--r-- | timer.h | 62 |
13 files changed, 461 insertions, 36 deletions
diff --git a/Makefile.common b/Makefile.common index 0fce38f34b..183540d78b 100644 --- a/Makefile.common +++ b/Makefile.common @@ -16,7 +16,7 @@ OBJS += util.o newgui.o gui/widget.o gui/dialog.o \ v3/resource_v3.o v4/resource_v4.o scaler.o main.o \ simon/midi.o simon/simon.o simon/simonsys.o simon/simonvga.o \ simon/simondebug.o simon/simonres.o simon/simonitems.o simon/simonverb.o \ - sound/mididrv.o config-file.o bundle.o + sound/mididrv.o config-file.o bundle.o timer.o DISTFILES=$(OBJS:.o=.cpp) Makefile scumm.h scummsys.h stdafx.h stdafx.cpp \ debugrl.h whatsnew.txt readme.txt copying.txt \ diff --git a/bundle.cpp b/bundle.cpp index ca695c9c2b..67eade6ea6 100644 --- a/bundle.cpp +++ b/bundle.cpp @@ -27,6 +27,7 @@ Bundle::Bundle(Scumm * parent) { _voiceFile = NULL; _musicFile = NULL; _scumm = parent; + _lastSong = -1; } Bundle::~Bundle() { @@ -37,7 +38,7 @@ Bundle::~Bundle() { fclose (_musicFile); } -int32 Bundle::openVoiceFile(char * filename) { +bool Bundle::openVoiceFile(char * filename) { int32 tag, offset; if (_voiceFile != NULL) { @@ -79,7 +80,7 @@ int32 Bundle::openVoiceFile(char * filename) { return true; } -int32 Bundle::openMusicFile(char * filename) { +bool Bundle::openMusicFile(char * filename) { int32 tag, offset; if (_musicFile != NULL) { @@ -113,9 +114,9 @@ int32 Bundle::openMusicFile(char * filename) { if ((c = _scumm->fileReadByte(_musicFile)) != 0) name[z++] = c; name[z] = '\0'; - strcpy(_bundleVoiceTable[i].filename, name); - _bundleVoiceTable[i].offset = _scumm->fileReadDwordBE(_musicFile); - _bundleVoiceTable[i].size = _scumm->fileReadDwordBE(_musicFile); + strcpy(_bundleMusicTable[i].filename, name); + _bundleMusicTable[i].offset = _scumm->fileReadDwordBE(_musicFile); + _bundleMusicTable[i].size = _scumm->fileReadDwordBE(_musicFile); } return true; @@ -177,32 +178,36 @@ int32 Bundle::decompressMusicSampleByIndex(int32 index, int32 number, byte * com return 0; } - _scumm->fileSeek(_musicFile, _bundleMusicTable[index].offset, SEEK_SET); - tag = _scumm->fileReadDwordBE(_musicFile); - num = _scumm->fileReadDwordBE(_musicFile); - _scumm->fileReadDwordBE(_musicFile); - _scumm->fileReadDwordBE(_musicFile); + if (_lastSong != index) { + _scumm->fileSeek(_musicFile, _bundleMusicTable[index].offset, SEEK_SET); + tag = _scumm->fileReadDwordBE(_musicFile); + num = _scumm->fileReadDwordBE(_musicFile); + _scumm->fileReadDwordBE(_musicFile); + _scumm->fileReadDwordBE(_musicFile); - if (tag != MKID_BE('COMP')) { - warning("Bundle: Compressed sound %d invalid (%c%c%c%c)", index, tag>>24, tag>>16, tag>>8, tag); - return 0; - } + if (tag != MKID_BE('COMP')) { + warning("Bundle: Compressed sound %d invalid (%c%c%c%c)", index, tag>>24, tag>>16, tag>>8, tag); + return 0; + } - for (i = 0; i < num; i++) { - _compMusicTable[i].offset = _scumm->fileReadDwordBE(_musicFile); - _compMusicTable[i].size = _scumm->fileReadDwordBE(_musicFile); - _compMusicTable[i].codec = _scumm->fileReadDwordBE(_musicFile); - _scumm->fileReadDwordBE(_musicFile); + for (i = 0; i < num; i++) { + _compMusicTable[i].offset = _scumm->fileReadDwordBE(_musicFile); + _compMusicTable[i].size = _scumm->fileReadDwordBE(_musicFile); + _compMusicTable[i].codec = _scumm->fileReadDwordBE(_musicFile); + _scumm->fileReadDwordBE(_musicFile); + } } - comp_input = (byte *)malloc(_compMusicTable[i].size); + comp_input = (byte *)malloc(_compMusicTable[number].size); - _scumm->fileSeek(_musicFile, _bundleMusicTable[index].offset + _compMusicTable[i].offset, SEEK_SET); - _scumm->fileRead(_musicFile, comp_input, _compMusicTable[i].size); - final_size = decompressCodec(_compMusicTable[i].codec, comp_input, comp_final, _compMusicTable[i].size); + _scumm->fileSeek(_musicFile, _bundleMusicTable[index].offset + _compMusicTable[number].offset, SEEK_SET); + _scumm->fileRead(_musicFile, comp_input, _compMusicTable[number].size); + final_size = decompressCodec(_compMusicTable[number].codec, comp_input, comp_final, _compMusicTable[number].size); free(comp_input); + _lastSong = index; + return final_size; } @@ -339,23 +344,41 @@ int32 Bundle::decompressCodec(int32 codec, byte * comp_input, byte * comp_output case 4: output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; // FIXME: not implemented yet memset (comp_output, 0, output_size); + output_size = 0; break; case 5: output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; // FIXME: not implemented yet memset (comp_output, 0, output_size); + output_size = 0; break; case 6: output_size = compDecode(comp_input, comp_output); + p = comp_output; + for (z = 2; z < output_size; z++) + p[z] += p[z - 1]; + for (z = 1; z < output_size; z++) + p[z] += p[z - 1]; // FIXME: not implemented yet memset (comp_output, 0, output_size); + output_size = 0; break; case 10: @@ -52,13 +52,14 @@ private: int32 _numVoiceFiles; int32 _numMusicFiles; Scumm * _scumm; + int32 _lastSong; public: Bundle(Scumm * parent); ~Bundle(); - int32 openVoiceFile(char * filename); - int32 openMusicFile(char * filename); + bool openVoiceFile(char * filename); + bool openMusicFile(char * filename); int32 decompressVoiceSampleByName(char * name, byte * comp_final); int32 decompressVoiceSampleByIndex(int32 index, byte * comp_final); int32 decompressMusicSampleByName(char * name, int32 number, byte * comp_final); diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index d19833dbe8..13ce14e833 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -188,6 +188,7 @@ bool ListWidget::handleKeyUp(char key, int modifiers) { if (key == _currentKeyDown) _currentKeyDown = 0; + return true; } void ListWidget::lostFocusWidget() @@ -28,10 +28,12 @@ Scumm::Scumm (void) { _newgui = new NewGui(this); _bundle = new Bundle(this); + _timer = new Timer(this); } Scumm::~Scumm (void) { delete [] _actors; delete _newgui; delete _bundle; + delete _timer; } diff --git a/morphos/Makefile b/morphos/Makefile index 82e5fa55a4..53909bec93 100644 --- a/morphos/Makefile +++ b/morphos/Makefile @@ -21,7 +21,7 @@ OBJS = actor.o akos.o boxes.o config-file.o costume.o gfx.o object.o resource.o morphos.o morphos_sound.o morphos_start.o script_v1.o script_v2.o debug.o gui.o \ imuse.o fmopl.o mixer.o mididrv.o debugrl.o vars.o insane.o \ gameDetector.o init.o resource_v3.o resource_v4.o util.o main.o \ - bundle.o $(GUIOBJS) $(SIMONOBJS) + bundle.o timer.o $(GUIOBJS) $(SIMONOBJS) DISTFILES=$(OBJS:.o=.cpp) Makefile scumm.h scummsys.h stdafx.h stdafx.cpp \ windows.cpp debugrl.h whatsnew.txt readme.txt copying.txt \ @@ -27,6 +27,7 @@ #include "system.h" #include "sound/mixer.h" #include "bundle.h" +#include "timer.h" #define SCUMMVM_VERSION "0.2.2 CVS" #define SCUMMVM_CVS "2002-08-03" @@ -339,6 +340,7 @@ public: ObjectData *_objs; ScummDebugger *_debugger; Bundle * _bundle; + Timer * _timer; struct { byte mode[rtNumTypes]; @@ -747,6 +749,14 @@ public: bool _soundsPaused, _soundsPaused2; bool _soundVolumePreset; + int32 _numberBundleMusic; + int32 _currentSampleBundleMusic; + int32 _numberSamplesBundleMusic; + int32 _offsetSampleBundleMusic; + int32 _offsetBufBundleMusic; + byte * _musicBundleBufFinal; + byte * _musicBundleBufOutput; + void setupSound(); void processSoundQues(); void playSound(int sound); @@ -770,6 +780,9 @@ public: void pauseSounds(bool pause); bool isSfxFinished(); void playBundleSound(char *sound); + void playBundleMusic(int32 song); + void stopBundleMusic(); + int bundleMusicHandler(int t); void decompressBundleSound(int index); int playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned = false); int playSfxSound_MP3(void *sound, uint32 size); diff --git a/scummvm.cpp b/scummvm.cpp index d1c60cc260..212dcf82cc 100644 --- a/scummvm.cpp +++ b/scummvm.cpp @@ -83,6 +83,8 @@ void Scumm::scummInit() setShake(0); setupCursor(); + + _timer->init(); /* Allocate and initilise actors */ _actors = new Actor[MAX_ACTORS]; @@ -190,8 +192,10 @@ void Scumm::scummInit() #ifdef COMPRESSED_SOUND_FILE _current_cache = 0; #endif - - _system->set_timer(5 * 60 * 1000, &autosave); + + _numberBundleMusic = -1; + + _timer->installProcedure(&autosave, 5 * 60 * 1000); } diff --git a/scummvm.dsp b/scummvm.dsp index 891380824e..f2a372e4bc 100644 --- a/scummvm.dsp +++ b/scummvm.dsp @@ -259,10 +259,6 @@ SOURCE=.\gui\widget.h # End Group
# Begin Source File
-SOURCE=.\scaler.cpp
-# End Source File
-# Begin Source File
-
SOURCE=.\actor.cpp
!IF "$(CFG)" == "scummvm - Win32 Release"
@@ -404,6 +400,10 @@ SOURCE=.\saveload.cpp # End Source File
# Begin Source File
+SOURCE=.\scaler.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\script.cpp
!IF "$(CFG)" == "scummvm - Win32 Release"
@@ -526,6 +526,10 @@ SOURCE=.\sys.cpp # End Source File
# Begin Source File
+SOURCE=.\timer.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\vars.cpp
# End Source File
# Begin Source File
@@ -611,6 +615,10 @@ SOURCE=.\StdAfx.h SOURCE=.\system.h
# End Source File
+# Begin Source File
+
+SOURCE=.\timer.h
+# End Source File
# End Group
# Begin Source File
@@ -622,4 +630,3 @@ SOURCE=.\scummvm.ico # End Source File
# End Target
# End Project
-
@@ -6,7 +6,6 @@ * 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 @@ -89,6 +88,10 @@ void Scumm::processSoundQues() data[1], data[2], data[3], data[4], data[5], data[6], data[7] ); #endif + + if ((_gameId == GID_DIG) && (data[0] == 4096)){ + playBundleMusic(data[1] - 1); + } if ((_gameId == GID_DIG) && ((data[0] == 12) || (data[0] == 14))){ uint32 size = 0, rate = 0, tag, chan = 0, bits = 0; uint8 * ptr = getResourceAddress(rtSound, data[1]); @@ -771,6 +774,141 @@ bool Scumm::isSfxFinished() return !_mixer->has_active_channel(); } +static Scumm * h_scumm; + +static int music_handler (int t) { + h_scumm->bundleMusicHandler(t); + return t; +} + +#define OUTPUT_SIZE 66150 // ((22050 * 2 * 2) / 4) * 3 + +void Scumm::playBundleMusic(int32 song) { + char buf[256]; + + if (_numberBundleMusic == -1) { + sprintf(buf, "%s%smusic.bun", _gameDataPath, _exe_name); + if (_bundle->openMusicFile((char*)&buf) == false) + return; + h_scumm = this; + _musicBundleBufFinal = (byte*)malloc(OUTPUT_SIZE); + _musicBundleBufOutput = (byte*)malloc(10 * 0x2000); + _currentSampleBundleMusic = 0; + _offsetSampleBundleMusic = 0; + _offsetBufBundleMusic = 0; + _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByIndex(song); + _numberBundleMusic = song; + _timer->installProcedure(&music_handler, 1000); + return; + } + if (_numberBundleMusic != song) { + _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByIndex(song); + _numberBundleMusic = song; + _currentSampleBundleMusic = 0; + _offsetSampleBundleMusic = 0; + _offsetBufBundleMusic = 0; + } +} + +void Scumm::stopBundleMusic() { + _numberBundleMusic = -1; + if (_musicBundleBufFinal) + free(_musicBundleBufFinal); + if (_musicBundleBufOutput) + free(_musicBundleBufOutput); +} + +int Scumm::bundleMusicHandler(int t) { + byte * ptr; + int32 l, num = _numberSamplesBundleMusic, length, k; + int32 rate = 22050; + int32 tag, size = -1, header_size = 0; + if (_numberBundleMusic == -1) + _timer->releaseProcedure(&music_handler); + + ptr = _musicBundleBufOutput; + + + for (k = 0, l = _currentSampleBundleMusic; l < num; k++) { + length = _bundle->decompressMusicSampleByIndex(_numberBundleMusic, l, (_musicBundleBufOutput + ((k * 0x2000) + _offsetBufBundleMusic))); + _offsetSampleBundleMusic += length; + + if (l == 0) { + tag = READ_BE_UINT32(ptr); ptr += 4; + if (tag != MKID_BE('iMUS')) { + warning("Decompression of bundle sound failed"); + _numberBundleMusic = -1; + return t; + } + + ptr += 12; + while(tag != MKID_BE('DATA')) { + tag = READ_BE_UINT32(ptr); ptr += 4; + switch(tag) { + case MKID_BE('FRMT'): + size = READ_BE_UINT32(ptr); ptr += 24; + break; + case MKID_BE('TEXT'): + case MKID_BE('REGN'): + case MKID_BE('STOP'): + case MKID_BE('JUMP'): + size = READ_BE_UINT32(ptr); ptr += size + 4; + break; + case MKID_BE('DATA'): + size = READ_BE_UINT32(ptr); ptr += 4; + break; + + default: + error("Unknown sound header %c%c%c%c", tag>>24, tag>>16, tag>>8, tag); + } + } + if (size < 0) { + warning("Decompression sound failed (no size field)"); + _numberBundleMusic = -1; + return t; + } + header_size = (ptr - _musicBundleBufOutput); + } + + l++; + _currentSampleBundleMusic = l; + + if (_offsetSampleBundleMusic >= OUTPUT_SIZE + header_size) { + memcpy(_musicBundleBufFinal, (_musicBundleBufOutput + header_size), OUTPUT_SIZE); + _offsetBufBundleMusic = _offsetSampleBundleMusic - OUTPUT_SIZE - header_size; + memcpy(_musicBundleBufOutput, (_musicBundleBufOutput + (OUTPUT_SIZE + header_size)), _offsetBufBundleMusic); + _offsetSampleBundleMusic = _offsetBufBundleMusic; + break; + } + } + + if (l == num) + l = 0; + + size = OUTPUT_SIZE; + ptr = _musicBundleBufFinal; + uint32 s_size = (size * 4) / 3; + byte * buffer = (byte*)malloc (s_size + 4); + uint32 r = 0, tmp; + for (l = 0; l < size; l += 3) { + tmp = (ptr[l + 1] & 0x0f) << 8; + tmp = (tmp | ptr[l + 0]) << 4; + tmp -= 0x8000; + buffer[r++] = (uint8)((tmp >> 8) & 0xff); + buffer[r++] = (uint8)(tmp & 0xff); + + tmp = (ptr[l + 1] & 0xf0) << 4; + tmp = (tmp | ptr[l + 2]) << 4; + tmp -= 0x8000; + buffer[r++] = (uint8)((tmp >> 8) & 0xff); + buffer[r++] = (uint8)(tmp & 0xff); + } + + _mixer->play_raw(NULL, buffer, s_size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO); + + return t; +} + void Scumm::playBundleSound(char *sound) { char buf[256]; diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 7cb75050cf..daa9ab842d 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -211,7 +211,7 @@ void SoundMixer::set_volume(int volume) for (int i = 0; i < 128; i++) _volume_table[i] = i * volume ; - for (int i = -128; i < 0; i++) + for (i = -128; i < 0; i++) _volume_table[i+256] = i * volume ; } diff --git a/timer.cpp b/timer.cpp new file mode 100644 index 0000000000..a67e46bc09 --- /dev/null +++ b/timer.cpp @@ -0,0 +1,174 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002 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 "scummsys.h" +#include "timer.h" + +static Scumm * scumm; + +Timer::Timer(Scumm * parent) { + _initialized = false; + _timerRunning = false; + scumm = _scumm = parent; +} + +Timer::~Timer() { + release (); +} + +static int timer_handler (int t) +{ + scumm->_timer->handler (&t); + return t; +} + +int Timer::handler(int * t) { + uint32 interval, l; + uint32 beginTime, endTime; + + if (_timerRunning == false) + return *t; + + _osystem->lock_mutex(_mutex); + beginTime = _osystem->get_msecs(); + + if (_timerRunning) { + _lastTime = _thisTime; + _thisTime = _osystem->get_msecs(); + interval = _thisTime - _lastTime; + + for (l = 0; l < MAX_TIMERS; l++) { + if ((_timerSlots[l].procedure) && (_timerSlots[l].interval > 0)) { + _timerSlots[l].counter -= interval; + if (_timerSlots[l].counter <= 0) { + _timerSlots[l].counter += _timerSlots[l].interval; + _timerSlots[l].procedure (0); + } + } + } + } + + endTime = _osystem->get_msecs(); + interval = endTime - beginTime; + if (interval < 10) interval = 10; + if (interval > 10000) interval = 10000; + _osystem->unlock_mutex(_mutex); + + _osystem->set_timer (interval, &timer_handler); + + return *t; +} + +bool Timer::init() { + int32 l; + + _osystem = _scumm->_system; + if (_osystem == NULL) { + printf("Timer: OSystem not initialized !\n"); + return false; + } + + if (_initialized == true) + return true; + + for (l = 0; l < MAX_TIMERS; l++) { + _timerSlots[l].procedure = NULL; + _timerSlots[l].interval = 0; + _timerSlots[l].counter = 0; + } + + _mutex = _osystem->create_mutex(); + _thisTime = _osystem->get_msecs(); + _osystem->set_timer (1000, &timer_handler); + + _timerRunning = true; + _initialized = true; + return true; +} + +void Timer::release() { + int32 l; + + if (_initialized == false) + return; + + _timerRunning = false; + _initialized = false; + + for (l = 0; l < MAX_TIMERS; l++) { + _timerSlots[l].procedure = NULL; + _timerSlots[l].interval = 0; + _timerSlots[l].counter = 0; + } + _osystem->delete_mutex(_mutex); + +} + +bool Timer::installProcedure (int ((*procedure)(int)), int32 interval) { + int32 l; + bool found = false; + + if (_initialized == false) { + printf ("Timer: is not initialized !"); + return false; + } + + _timerRunning = false; + for (l = 0; l < MAX_TIMERS; l++) { + if (!_timerSlots[l].procedure) { + _timerSlots[l].procedure = procedure; + _timerSlots[l].interval = interval; + _timerSlots[l].counter = interval; + found = true; + break; + } + } + + _timerRunning = true; + if (!found) { + printf ("Can't find free slot !"); + return false; + } + + return true; +} + +void Timer::releaseProcedure (int ((*procedure)(int))) { + int32 l; + + if (_initialized == false) { + printf ("Timer: is not initialized !"); + return; + } + + _timerRunning = false; + for (l = 0; l < MAX_TIMERS; l++) { + if (_timerSlots[l].procedure == procedure) { + _timerSlots[l].procedure = 0; + _timerSlots[l].interval = 0; + _timerSlots[l].counter = 0; + } + } + _timerRunning = true; +} + + diff --git a/timer.h b/timer.h new file mode 100644 index 0000000000..6ceeff0ca0 --- /dev/null +++ b/timer.h @@ -0,0 +1,62 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002 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: + */ + +#ifndef TIMER_H +#define TIMER_H + +#include "scummsys.h" + +#define MAX_TIMERS 5 + +class OSystem; + +class Timer { + +protected: + +private: + OSystem * _osystem; + Scumm * _scumm; + bool _initialized; + bool _timerRunning; + void * _timerHandler; + int32 _thisTime; + int32 _lastTime; + void * _mutex; + +struct TimerSlots +{ + int ((*procedure)(int)); + int32 interval; + int32 counter; +} _timerSlots [MAX_TIMERS]; + +public: + Timer(Scumm * system); + ~Timer(); + + int handler(int * t); + bool init(); + void release(); + bool installProcedure (int ((*procedure)(int)), int32 interval); + void releaseProcedure (int ((*procedure)(int))); +}; + +#endif |