music support,
fixed timing bugs svn-id: r3491
This commit is contained in:
parent
279d5b2fd7
commit
b8d259d60e
18 changed files with 3298 additions and 376 deletions
3
Makefile
3
Makefile
|
@ -13,7 +13,8 @@ INCS = scumm.h scummsys.h stdafx.h
|
||||||
|
|
||||||
OBJS = actor.o boxes.o costume.o gfx.o object.o resource.o \
|
OBJS = actor.o boxes.o costume.o gfx.o object.o resource.o \
|
||||||
saveload.o script.o scummvm.o sound.o string.o \
|
saveload.o script.o scummvm.o sound.o string.o \
|
||||||
sys.o verbs.o sdl.o script_v1.o script_v2.o debug.o gui.o
|
sys.o verbs.o sdl.o script_v1.o script_v2.o debug.o gui.o \
|
||||||
|
imuse.o
|
||||||
|
|
||||||
DISTFILES=actor.cpp boxes.cpp costume.cpp gfx.cpp object.cpp resource.cpp \
|
DISTFILES=actor.cpp boxes.cpp costume.cpp gfx.cpp object.cpp resource.cpp \
|
||||||
saveload.cpp script.cpp scummvm.cpp sound.cpp string.cpp \
|
saveload.cpp script.cpp scummvm.cpp sound.cpp string.cpp \
|
||||||
|
|
|
@ -585,6 +585,8 @@ void Scumm::showActors() {
|
||||||
void Scumm::stopTalk() {
|
void Scumm::stopTalk() {
|
||||||
int act;
|
int act;
|
||||||
|
|
||||||
|
stopTalkSound();
|
||||||
|
|
||||||
_haveMsg = 0;
|
_haveMsg = 0;
|
||||||
_talkDelay = 0;
|
_talkDelay = 0;
|
||||||
|
|
||||||
|
|
2
gfx.cpp
2
gfx.cpp
|
@ -1396,7 +1396,7 @@ void Scumm::unkScreenEffect7(int a) {
|
||||||
tab_2[i] += tab_1[i];
|
tab_2[i] += tab_1[i];
|
||||||
|
|
||||||
updateScreen(this);
|
updateScreen(this);
|
||||||
waitForTimer(this,3);
|
waitForTimer(this,30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
71
gui.cpp
71
gui.cpp
|
@ -2,6 +2,11 @@
|
||||||
#include "scumm.h"
|
#include "scumm.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SAVELOAD_DIALOG,
|
||||||
|
PAUSE_DIALOG
|
||||||
|
};
|
||||||
|
|
||||||
void Gui::draw(int start,int end) {
|
void Gui::draw(int start,int end) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -249,6 +254,12 @@ const GuiWidget save_load_dialog[] = {
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const GuiWidget pause_dialog[] = {
|
||||||
|
{GUI_TEXT,0x01,GWF_DEFAULT,50,80,220,16,0,10},
|
||||||
|
{0},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void Gui::handleCommand(int cmd) {
|
void Gui::handleCommand(int cmd) {
|
||||||
int lastEdit = _editString;
|
int lastEdit = _editString;
|
||||||
showCaret(false);
|
showCaret(false);
|
||||||
|
@ -332,18 +343,20 @@ const byte string_map_table_v6[] = {
|
||||||
99, /* Cancel */
|
99, /* Cancel */
|
||||||
100, /* Quit */
|
100, /* Quit */
|
||||||
101, /* Ok */
|
101, /* Ok */
|
||||||
|
93, /* Game paused */
|
||||||
};
|
};
|
||||||
|
|
||||||
const byte string_map_table_v5[] = {
|
const byte string_map_table_v5[] = {
|
||||||
0, /* How may I serve you? */
|
0, /* How may I serve you? */
|
||||||
20, /* Select a game to LOAD */
|
20, /* Select a game to LOAD */
|
||||||
21, /* Name your SAVE game */
|
19, /* Name your SAVE game */
|
||||||
7, /* Save */
|
7, /* Save */
|
||||||
8, /* Load */
|
8, /* Load */
|
||||||
9, /* Play */
|
9, /* Play */
|
||||||
10, /* Cancel */
|
10, /* Cancel */
|
||||||
11, /* Quit */
|
11, /* Quit */
|
||||||
12, /* Ok */
|
12, /* Ok */
|
||||||
|
4, /* Game paused */
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *Gui::queryString(int string, int id) {
|
const char *Gui::queryString(int string, int id) {
|
||||||
|
@ -399,27 +412,28 @@ void Gui::editString(int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gui::addLetter(byte letter) {
|
void Gui::addLetter(byte letter) {
|
||||||
if (_editString==-1)
|
switch(_dialog) {
|
||||||
return;
|
case SAVELOAD_DIALOG:
|
||||||
|
if (_editString==-1)
|
||||||
|
return;
|
||||||
|
|
||||||
if (letter==13) {
|
if (letter==13) {
|
||||||
handleCommand(8);
|
handleCommand(8);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (letter>=32 && letter<128 && _editLen < SAVEGAME_NAME_LEN-1) {
|
||||||
|
game_names[_editString][_editLen++] = letter;
|
||||||
|
} else if (letter==8 && _editLen>0) {
|
||||||
|
_editLen--;
|
||||||
|
}
|
||||||
|
showCaret(true);
|
||||||
|
break;
|
||||||
|
case PAUSE_DIALOG:
|
||||||
|
if (letter==32)
|
||||||
|
close();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (letter>=32 && letter<128 && _editLen < SAVEGAME_NAME_LEN-1) {
|
|
||||||
game_names[_editString][_editLen++] = letter;
|
|
||||||
} else if (letter==8 && _editLen>0) {
|
|
||||||
_editLen--;
|
|
||||||
}
|
|
||||||
showCaret(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gui::saveLoadDialog() {
|
|
||||||
_widgets[0] = save_load_dialog;
|
|
||||||
_editString = -1;
|
|
||||||
_cur_page = 0;
|
|
||||||
_active = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte Gui::getDefaultColor(int color) {
|
byte Gui::getDefaultColor(int color) {
|
||||||
|
@ -431,7 +445,6 @@ byte Gui::getDefaultColor(int color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Gui::init(Scumm *s) {
|
void Gui::init(Scumm *s) {
|
||||||
_s = s;
|
_s = s;
|
||||||
_bgcolor = getDefaultColor(0);
|
_bgcolor = getDefaultColor(0);
|
||||||
|
@ -447,6 +460,7 @@ void Gui::loop() {
|
||||||
draw(0,100);
|
draw(0,100);
|
||||||
_s->_cursorAnimate++;
|
_s->_cursorAnimate++;
|
||||||
_s->gdi._cursorActive = 1;
|
_s->gdi._cursorActive = 1;
|
||||||
|
_s->pauseSounds(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_s->getKeyInput(0);
|
_s->getKeyInput(0);
|
||||||
|
@ -471,5 +485,20 @@ void Gui::close() {
|
||||||
_s->_fullRedraw = true;
|
_s->_fullRedraw = true;
|
||||||
_s->_completeScreenRedraw = true;
|
_s->_completeScreenRedraw = true;
|
||||||
_s->_cursorAnimate--;
|
_s->_cursorAnimate--;
|
||||||
|
_s->pauseSounds(false);
|
||||||
_active = false;
|
_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gui::saveLoadDialog() {
|
||||||
|
_widgets[0] = save_load_dialog;
|
||||||
|
_editString = -1;
|
||||||
|
_cur_page = 0;
|
||||||
|
_active = true;
|
||||||
|
_dialog = SAVELOAD_DIALOG;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui::pause() {
|
||||||
|
_widgets[0] = pause_dialog;
|
||||||
|
_active = true;
|
||||||
|
_dialog = PAUSE_DIALOG;
|
||||||
|
}
|
||||||
|
|
2
gui.h
2
gui.h
|
@ -43,6 +43,7 @@ struct Gui {
|
||||||
byte _active;
|
byte _active;
|
||||||
byte _clickTimer;
|
byte _clickTimer;
|
||||||
byte _cur_page;
|
byte _cur_page;
|
||||||
|
byte _dialog;
|
||||||
int _clickWidget;
|
int _clickWidget;
|
||||||
char *_queryMess;
|
char *_queryMess;
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ struct Gui {
|
||||||
void saveLoadDialog();
|
void saveLoadDialog();
|
||||||
void queryMessage(const char *msg, const char *alts);
|
void queryMessage(const char *msg, const char *alts);
|
||||||
byte getDefaultColor(int color);
|
byte getDefaultColor(int color);
|
||||||
|
void pause();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -551,12 +551,12 @@ byte *Scumm::getResourceAddress(int type, int index) {
|
||||||
ensureResourceLoaded(type, index);
|
ensureResourceLoaded(type, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
setResourceCounter(type, index, 1);
|
|
||||||
|
|
||||||
ptr=(byte*)res.address[type][index];
|
ptr=(byte*)res.address[type][index];
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
setResourceCounter(type, index, 1);
|
||||||
|
|
||||||
return ptr + sizeof(ResHeader);
|
return ptr + sizeof(ResHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
48
saveload.cpp
48
saveload.cpp
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "scumm.h"
|
#include "scumm.h"
|
||||||
|
#include "sound.h"
|
||||||
|
|
||||||
struct SaveGameHeader {
|
struct SaveGameHeader {
|
||||||
uint32 type;
|
uint32 type;
|
||||||
|
@ -29,7 +30,7 @@ struct SaveGameHeader {
|
||||||
char name[32];
|
char name[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CURRENT_VER 4
|
#define CURRENT_VER 5
|
||||||
|
|
||||||
bool Scumm::saveState(int slot, bool compat) {
|
bool Scumm::saveState(int slot, bool compat) {
|
||||||
char filename[256];
|
char filename[256];
|
||||||
|
@ -67,6 +68,7 @@ bool Scumm::loadState(int slot, bool compat) {
|
||||||
SaveGameHeader hdr;
|
SaveGameHeader hdr;
|
||||||
Serializer ser;
|
Serializer ser;
|
||||||
int sb,sh;
|
int sb,sh;
|
||||||
|
SoundEngine *se;
|
||||||
|
|
||||||
makeSavegameName(filename, slot, compat);
|
makeSavegameName(filename, slot, compat);
|
||||||
out = fopen(filename,"rb");
|
out = fopen(filename,"rb");
|
||||||
|
@ -88,7 +90,9 @@ bool Scumm::loadState(int slot, bool compat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(_saveLoadName, hdr.name, sizeof(hdr.name));
|
memcpy(_saveLoadName, hdr.name, sizeof(hdr.name));
|
||||||
|
|
||||||
|
pauseSounds(true);
|
||||||
|
|
||||||
CHECK_HEAP
|
CHECK_HEAP
|
||||||
|
|
||||||
openRoom(-1);
|
openRoom(-1);
|
||||||
|
@ -134,6 +138,8 @@ bool Scumm::loadState(int slot, bool compat) {
|
||||||
|
|
||||||
debug(1,"State loaded from '%s'", filename);
|
debug(1,"State loaded from '%s'", filename);
|
||||||
|
|
||||||
|
pauseSounds(false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,20 +419,22 @@ void Scumm::saveOrLoad(Serializer *s) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const SaveLoadEntry stringTabEntries[] = {
|
const SaveLoadEntry stringTabEntries[] = {
|
||||||
MKLINE(StringTab,t_xpos,sleInt16),
|
|
||||||
MKLINE(StringTab,t_ypos,sleInt16),
|
|
||||||
MKLINE(StringTab,t_center,sleByte),
|
|
||||||
MKLINE(StringTab,t_overhead,sleByte),
|
|
||||||
MKLINE(StringTab,t_no_talk_anim,sleByte),
|
|
||||||
MKLINE(StringTab,t_right,sleInt16),
|
|
||||||
MKLINE(StringTab,t_color,sleInt16),
|
|
||||||
MKLINE(StringTab,t_charset,sleInt16),
|
|
||||||
MKLINE(StringTab,xpos,sleInt16),
|
MKLINE(StringTab,xpos,sleInt16),
|
||||||
|
MKLINE(StringTab,t_xpos,sleInt16),
|
||||||
MKLINE(StringTab,ypos,sleInt16),
|
MKLINE(StringTab,ypos,sleInt16),
|
||||||
MKLINE(StringTab,center,sleInt16),
|
MKLINE(StringTab,t_ypos,sleInt16),
|
||||||
MKLINE(StringTab,overhead,sleInt16),
|
|
||||||
MKLINE(StringTab,no_talk_anim,sleInt16),
|
|
||||||
MKLINE(StringTab,right,sleInt16),
|
MKLINE(StringTab,right,sleInt16),
|
||||||
|
MKLINE(StringTab,t_right,sleInt16),
|
||||||
|
MKLINE(StringTab,color,sleInt8),
|
||||||
|
MKLINE(StringTab,t_color,sleInt8),
|
||||||
|
MKLINE(StringTab,charset,sleInt8),
|
||||||
|
MKLINE(StringTab,t_charset,sleInt8),
|
||||||
|
MKLINE(StringTab,center,sleByte),
|
||||||
|
MKLINE(StringTab,t_center,sleByte),
|
||||||
|
MKLINE(StringTab,overhead,sleByte),
|
||||||
|
MKLINE(StringTab,t_overhead,sleByte),
|
||||||
|
MKLINE(StringTab,no_talk_anim,sleByte),
|
||||||
|
MKLINE(StringTab,t_no_talk_anim,sleByte),
|
||||||
MKEND()
|
MKEND()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -478,6 +486,9 @@ void Scumm::saveOrLoad(Serializer *s) {
|
||||||
res.flags[r][s->loadWord()] |= 0x80;
|
res.flags[r][s->loadWord()] |= 0x80;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_soundDriver)
|
||||||
|
((SoundEngine*)_soundDriver)->save_or_load(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scumm::saveLoadResource(Serializer *ser, int type, int index) {
|
void Scumm::saveLoadResource(Serializer *ser, int type, int index) {
|
||||||
|
@ -630,9 +641,10 @@ void Serializer::saveLoadEntries(void *d, const SaveLoadEntry *sle) {
|
||||||
int replen;
|
int replen;
|
||||||
byte type;
|
byte type;
|
||||||
byte *at;
|
byte *at;
|
||||||
|
|
||||||
int size;
|
int size;
|
||||||
int value;
|
int value;
|
||||||
|
int num;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
while(sle->offs != 0xFFFF) {
|
while(sle->offs != 0xFFFF) {
|
||||||
at = (byte*)d + sle->offs;
|
at = (byte*)d + sle->offs;
|
||||||
|
@ -642,10 +654,12 @@ void Serializer::saveLoadEntries(void *d, const SaveLoadEntry *sle) {
|
||||||
if (size==0xFF) {
|
if (size==0xFF) {
|
||||||
if (_saveOrLoad) {
|
if (_saveOrLoad) {
|
||||||
/* save reference */
|
/* save reference */
|
||||||
saveWord((*_save_ref)(_ref_me, type, *((void**)at)));
|
ptr = *((void**)at);
|
||||||
|
saveWord(ptr ? ((*_save_ref)(_ref_me, type, ptr ) + 1) : 0);
|
||||||
} else {
|
} else {
|
||||||
/* load reference */
|
/* load reference */
|
||||||
*((void**)at) = (*_load_ref)(_ref_me, type, loadWord());
|
num = loadWord();
|
||||||
|
*((void**)at) = num ? (*_load_ref)(_ref_me, type, num-1) : NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
replen = 1;
|
replen = 1;
|
||||||
|
@ -655,8 +669,8 @@ void Serializer::saveLoadEntries(void *d, const SaveLoadEntry *sle) {
|
||||||
type&=~128;
|
type&=~128;
|
||||||
}
|
}
|
||||||
saveLoadArrayOf(at, replen, size, type);
|
saveLoadArrayOf(at, replen, size, type);
|
||||||
sle++;
|
|
||||||
}
|
}
|
||||||
|
sle++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1227,7 +1227,7 @@ void Scumm::o5_putActorInRoom() {
|
||||||
void Scumm::o5_quitPauseRestart() {
|
void Scumm::o5_quitPauseRestart() {
|
||||||
switch(fetchScriptByte()) {
|
switch(fetchScriptByte()) {
|
||||||
case 1:
|
case 1:
|
||||||
pauseGame(0);
|
pauseGame(false);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
shutDown(0);
|
shutDown(0);
|
||||||
|
|
|
@ -1794,7 +1794,7 @@ void Scumm::o6_isAnyOf() {
|
||||||
void Scumm::o6_quitPauseRestart() {
|
void Scumm::o6_quitPauseRestart() {
|
||||||
switch(fetchScriptByte()) {
|
switch(fetchScriptByte()) {
|
||||||
case 158:
|
case 158:
|
||||||
pauseGame(0);
|
pauseGame(false);
|
||||||
break;
|
break;
|
||||||
case 160:
|
case 160:
|
||||||
shutDown(0);
|
shutDown(0);
|
||||||
|
|
43
scumm.h
43
scumm.h
|
@ -28,8 +28,14 @@ struct Actor;
|
||||||
|
|
||||||
typedef void (Scumm::*OpcodeProc)();
|
typedef void (Scumm::*OpcodeProc)();
|
||||||
|
|
||||||
#define NUM_SCRIPT_SLOT 25
|
/* System Wide Constants */
|
||||||
#define NUM_ACTORS 13
|
enum {
|
||||||
|
SAMPLES_PER_SEC = 22050,
|
||||||
|
BITS_PER_SAMPLE = 16,
|
||||||
|
NUM_MIXER = 4,
|
||||||
|
NUM_SCRIPT_SLOT = 25,
|
||||||
|
NUM_ACTORS = 13
|
||||||
|
};
|
||||||
|
|
||||||
#pragma START_PACK_STRUCTS
|
#pragma START_PACK_STRUCTS
|
||||||
|
|
||||||
|
@ -596,6 +602,16 @@ struct Gdi {
|
||||||
void updateDirtyScreen(VirtScreen *vs);
|
void updateDirtyScreen(VirtScreen *vs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MixerChannel {
|
||||||
|
void *_sfx_sound;
|
||||||
|
uint32 _sfx_pos;
|
||||||
|
uint32 _sfx_size;
|
||||||
|
uint32 _sfx_fp_speed;
|
||||||
|
uint32 _sfx_fp_pos;
|
||||||
|
|
||||||
|
void mix(int16 *data, uint32 len);
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
enum GameId {
|
enum GameId {
|
||||||
GID_TENTACLE = 1,
|
GID_TENTACLE = 1,
|
||||||
|
@ -640,6 +656,8 @@ struct Scumm {
|
||||||
bool _dynamicRoomOffsets;
|
bool _dynamicRoomOffsets;
|
||||||
byte _resFilePathId;
|
byte _resFilePathId;
|
||||||
|
|
||||||
|
bool _soundsPaused;
|
||||||
|
|
||||||
bool _useTalkAnims;
|
bool _useTalkAnims;
|
||||||
|
|
||||||
char *_resFilePrefix;
|
char *_resFilePrefix;
|
||||||
|
@ -918,6 +936,8 @@ struct Scumm {
|
||||||
|
|
||||||
char _saveLoadName[32];
|
char _saveLoadName[32];
|
||||||
|
|
||||||
|
MixerChannel _mixer_channel[NUM_MIXER];
|
||||||
|
|
||||||
OpcodeProc getOpcode(int i) { return _opcodes[i]; }
|
OpcodeProc getOpcode(int i) { return _opcodes[i]; }
|
||||||
|
|
||||||
void openRoom(int room);
|
void openRoom(int room);
|
||||||
|
@ -925,7 +945,6 @@ struct Scumm {
|
||||||
void readRoomsOffsets();
|
void readRoomsOffsets();
|
||||||
void askForDisk(const char *filename);
|
void askForDisk(const char *filename);
|
||||||
|
|
||||||
|
|
||||||
bool openResourceFile(const char *filename);
|
bool openResourceFile(const char *filename);
|
||||||
|
|
||||||
void fileClose(void *file);
|
void fileClose(void *file);
|
||||||
|
@ -1449,7 +1468,7 @@ struct Scumm {
|
||||||
void addObjectToInventory(uint obj, uint room);
|
void addObjectToInventory(uint obj, uint room);
|
||||||
void removeObjectFromRoom(int obj);
|
void removeObjectFromRoom(int obj);
|
||||||
void decodeParseString();
|
void decodeParseString();
|
||||||
void pauseGame(int i);
|
void pauseGame(bool user);
|
||||||
void shutDown(int i);
|
void shutDown(int i);
|
||||||
void lock(int type, int i);
|
void lock(int type, int i);
|
||||||
void unlock(int type, int i);
|
void unlock(int type, int i);
|
||||||
|
@ -1590,6 +1609,7 @@ struct Scumm {
|
||||||
void talkSound(uint32 a, uint32 b, int mode);
|
void talkSound(uint32 a, uint32 b, int mode);
|
||||||
void processSfxQueues();
|
void processSfxQueues();
|
||||||
void startTalkSound(uint32 a, uint32 b, int mode);
|
void startTalkSound(uint32 a, uint32 b, int mode);
|
||||||
|
void stopTalkSound();
|
||||||
bool isMouthSyncOff(uint pos);
|
bool isMouthSyncOff(uint pos);
|
||||||
void startSfxSound(void *file);
|
void startSfxSound(void *file);
|
||||||
void *openSfxFile();
|
void *openSfxFile();
|
||||||
|
@ -1631,6 +1651,17 @@ struct Scumm {
|
||||||
void drawEnqueuedObject(EnqueuedObject *eo);
|
void drawEnqueuedObject(EnqueuedObject *eo);
|
||||||
void removeEnqueuedObjects();
|
void removeEnqueuedObjects();
|
||||||
void removeEnqueuedObject(EnqueuedObject *eo);
|
void removeEnqueuedObject(EnqueuedObject *eo);
|
||||||
|
|
||||||
|
void pauseSounds(bool pause);
|
||||||
|
|
||||||
|
MixerChannel *allocateMixer();
|
||||||
|
bool isSfxFinished();
|
||||||
|
void playSfxSound(void *sound, uint32 size, uint rate);
|
||||||
|
void stopSfxSound();
|
||||||
|
|
||||||
|
void mixWaves(int16 *sounds, int len);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScummDebugger {
|
struct ScummDebugger {
|
||||||
|
@ -1671,6 +1702,7 @@ struct Serializer {
|
||||||
union {
|
union {
|
||||||
SerializerSaveReference *_save_ref;
|
SerializerSaveReference *_save_ref;
|
||||||
SerializerLoadReference *_load_ref;
|
SerializerLoadReference *_load_ref;
|
||||||
|
void *_saveload_ref;
|
||||||
};
|
};
|
||||||
void *_ref_me;
|
void *_ref_me;
|
||||||
|
|
||||||
|
@ -1690,6 +1722,7 @@ struct Serializer {
|
||||||
uint32 loadUint32();
|
uint32 loadUint32();
|
||||||
|
|
||||||
bool isSaving() { return _saveOrLoad; }
|
bool isSaving() { return _saveOrLoad; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1714,4 +1747,4 @@ void blit(byte *dst, byte *src, int w, int h);
|
||||||
byte *findResource(uint32 id, byte *searchin, int index);
|
byte *findResource(uint32 id, byte *searchin, int index);
|
||||||
void playSfxSound(void *sound, uint32 size, uint rate);
|
void playSfxSound(void *sound, uint32 size, uint rate);
|
||||||
bool isSfxFinished();
|
bool isSfxFinished();
|
||||||
void waitForTimer(Scumm *s, int delay);
|
void waitForTimer(Scumm *s, int msec_delay);
|
20
scummvm.cpp
20
scummvm.cpp
|
@ -196,8 +196,8 @@ void Scumm::scummMain(int argc, char **argv) {
|
||||||
|
|
||||||
_debugMode = 1;
|
_debugMode = 1;
|
||||||
|
|
||||||
_maxHeapThreshold = 500000;
|
_maxHeapThreshold = 450000;
|
||||||
_minHeapThreshold = 450000;
|
_minHeapThreshold = 400000;
|
||||||
|
|
||||||
parseCommandLine(argc, argv);
|
parseCommandLine(argc, argv);
|
||||||
|
|
||||||
|
@ -213,6 +213,11 @@ void Scumm::scummMain(int argc, char **argv) {
|
||||||
_bootParam = -7873;
|
_bootParam = -7873;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_gameId==GID_MONKEY2 && _bootParam==0) {
|
||||||
|
_bootParam = 10001;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
initGraphics(this, _fullScreen);
|
initGraphics(this, _fullScreen);
|
||||||
|
|
||||||
if (_majorScummVersion==6)
|
if (_majorScummVersion==6)
|
||||||
|
@ -752,9 +757,8 @@ void Scumm::unkRoomFunc4(int a, int b, int c, int d, int e) {
|
||||||
warning("unkRoomFunc4: not implemented");
|
warning("unkRoomFunc4: not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scumm::pauseGame(int i) {
|
void Scumm::pauseGame(bool user) {
|
||||||
/* TODO: implement this */
|
((Gui*)_gui)->pause();
|
||||||
warning("pauseGame: not implemented");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scumm::shutDown(int i) {
|
void Scumm::shutDown(int i) {
|
||||||
|
@ -777,12 +781,12 @@ void Scumm::processKbd() {
|
||||||
|
|
||||||
if (_lastKeyHit==_vars[VAR_RESTART_KEY]) {
|
if (_lastKeyHit==_vars[VAR_RESTART_KEY]) {
|
||||||
warning("Restart not implemented");
|
warning("Restart not implemented");
|
||||||
pauseGame(1);
|
// pauseGame(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_lastKeyHit==_vars[VAR_PAUSE_KEY]) {
|
if (_lastKeyHit==_vars[VAR_PAUSE_KEY]) {
|
||||||
warning("Pause not implemented");
|
pauseGame(true);
|
||||||
/* pause */
|
/* pause */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -793,6 +797,8 @@ void Scumm::processKbd() {
|
||||||
((Gui*)_gui)->saveLoadDialog();
|
((Gui*)_gui)->saveLoadDialog();
|
||||||
} else if (_lastKeyHit==_vars[VAR_TALKSTOP_KEY]) {
|
} else if (_lastKeyHit==_vars[VAR_TALKSTOP_KEY]) {
|
||||||
_talkDelay = 0;
|
_talkDelay = 0;
|
||||||
|
if (_sfxMode==2)
|
||||||
|
stopTalk();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
scummvm.dsp
10
scummvm.dsp
|
@ -42,7 +42,7 @@ RSC=rc.exe
|
||||||
# PROP Ignore_Export_Lib 0
|
# PROP Ignore_Export_Lib 0
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
# ADD CPP /nologo /Zp4 /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "DUMP_SCRIPTS" /Yu"stdafx.h" /FD /c
|
# ADD CPP /nologo /Zp4 /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
# ADD BASE RSC /l 0x41d /d "NDEBUG"
|
# ADD BASE RSC /l 0x41d /d "NDEBUG"
|
||||||
# ADD RSC /l 0x41d /d "NDEBUG"
|
# ADD RSC /l 0x41d /d "NDEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
|
@ -157,6 +157,10 @@ SOURCE=.\gui.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\imuse.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\object.cpp
|
SOURCE=.\object.cpp
|
||||||
|
|
||||||
!IF "$(CFG)" == "scummvm - Win32 Release"
|
!IF "$(CFG)" == "scummvm - Win32 Release"
|
||||||
|
@ -335,6 +339,10 @@ SOURCE=.\scummsys.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sound.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\StdAfx.h
|
SOURCE=.\StdAfx.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
|
|
293
sdl.cpp
293
sdl.cpp
|
@ -24,10 +24,9 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "scumm.h"
|
#include "scumm.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
#if defined(USE_IMUSE)
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#endif
|
|
||||||
|
#include "SDL_thread.h"
|
||||||
|
|
||||||
#define SCALEUP_2x2
|
#define SCALEUP_2x2
|
||||||
|
|
||||||
|
@ -35,9 +34,7 @@ Scumm scumm;
|
||||||
ScummDebugger debugger;
|
ScummDebugger debugger;
|
||||||
Gui gui;
|
Gui gui;
|
||||||
|
|
||||||
#if defined(USE_IMUSE)
|
|
||||||
SoundEngine sound;
|
SoundEngine sound;
|
||||||
#endif
|
|
||||||
|
|
||||||
static SDL_Surface *screen;
|
static SDL_Surface *screen;
|
||||||
|
|
||||||
|
@ -74,78 +71,90 @@ int mapKey(int key, byte mod) {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForTimer(Scumm *s, int delay) {
|
void waitForTimer(Scumm *s, int msec_delay) {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
uint32 start_time;
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
switch(event.type) {
|
|
||||||
case SDL_KEYDOWN:
|
|
||||||
s->_keyPressed = mapKey(event.key.keysym.sym, event.key.keysym.mod);
|
|
||||||
if (event.key.keysym.sym >= '0' && event.key.keysym.sym<='9') {
|
|
||||||
s->_saveLoadSlot = event.key.keysym.sym - '0';
|
|
||||||
if (event.key.keysym.mod&KMOD_SHIFT) {
|
|
||||||
sprintf(s->_saveLoadName, "Quicksave %d", s->_saveLoadSlot);
|
|
||||||
s->_saveLoadFlag = 1;
|
|
||||||
} else if (event.key.keysym.mod&KMOD_CTRL)
|
|
||||||
s->_saveLoadFlag = 2;
|
|
||||||
s->_saveLoadCompatible = false;
|
|
||||||
}
|
|
||||||
if (event.key.keysym.sym=='z' && event.key.keysym.mod&KMOD_CTRL) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (event.key.keysym.sym=='f' && event.key.keysym.mod&KMOD_CTRL) {
|
|
||||||
s->_fastMode ^= 1;
|
|
||||||
}
|
|
||||||
if (event.key.keysym.sym=='g' && event.key.keysym.mod&KMOD_CTRL) {
|
|
||||||
s->_fastMode ^= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.key.keysym.sym=='d' && event.key.keysym.mod&KMOD_CTRL) {
|
if (msec_delay<0)
|
||||||
debugger.attach(s);
|
return;
|
||||||
}
|
|
||||||
if (event.key.keysym.sym=='s' && event.key.keysym.mod&KMOD_CTRL) {
|
|
||||||
s->resourceStats();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
if (s->_fastMode&2)
|
||||||
if (event.key.keysym.sym=='q' && event.key.keysym.mod&KMOD_LMETA) {
|
msec_delay = 0;
|
||||||
|
else if (s->_fastMode&1)
|
||||||
|
msec_delay = 10;
|
||||||
|
|
||||||
|
start_time = SDL_GetTicks();
|
||||||
|
|
||||||
|
do {
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch(event.type) {
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
s->_keyPressed = mapKey(event.key.keysym.sym, event.key.keysym.mod);
|
||||||
|
if (event.key.keysym.sym >= '0' && event.key.keysym.sym<='9') {
|
||||||
|
s->_saveLoadSlot = event.key.keysym.sym - '0';
|
||||||
|
if (event.key.keysym.mod&KMOD_SHIFT) {
|
||||||
|
sprintf(s->_saveLoadName, "Quicksave %d", s->_saveLoadSlot);
|
||||||
|
s->_saveLoadFlag = 1;
|
||||||
|
} else if (event.key.keysym.mod&KMOD_CTRL)
|
||||||
|
s->_saveLoadFlag = 2;
|
||||||
|
s->_saveLoadCompatible = false;
|
||||||
|
}
|
||||||
|
if (event.key.keysym.sym=='z' && event.key.keysym.mod&KMOD_CTRL) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (event.key.keysym.sym=='f' && event.key.keysym.mod&KMOD_CTRL) {
|
||||||
|
s->_fastMode ^= 1;
|
||||||
|
}
|
||||||
|
if (event.key.keysym.sym=='g' && event.key.keysym.mod&KMOD_CTRL) {
|
||||||
|
s->_fastMode ^= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key.keysym.sym=='d' && event.key.keysym.mod&KMOD_CTRL) {
|
||||||
|
debugger.attach(s);
|
||||||
|
}
|
||||||
|
if (event.key.keysym.sym=='s' && event.key.keysym.mod&KMOD_CTRL) {
|
||||||
|
s->resourceStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
if (event.key.keysym.sym=='q' && event.key.keysym.mod&KMOD_LMETA) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEMOTION: {
|
||||||
|
int newx,newy;
|
||||||
|
#if !defined(SCALEUP_2x2)
|
||||||
|
newx = event.motion.x;
|
||||||
|
newy = event.motion.y;
|
||||||
|
#else
|
||||||
|
newx = event.motion.x>>1;
|
||||||
|
newy = event.motion.y>>1;
|
||||||
|
#endif
|
||||||
|
if (newx != s->mouse.x || newy != s->mouse.y) {
|
||||||
|
s->mouse.x = newx;
|
||||||
|
s->mouse.y = newy;
|
||||||
|
s->drawMouse();
|
||||||
|
updateScreen(s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
if (event.button.button==SDL_BUTTON_LEFT)
|
||||||
|
s->_leftBtnPressed |= 1;
|
||||||
|
else if (event.button.button==SDL_BUTTON_RIGHT)
|
||||||
|
s->_rightBtnPressed |= 1;
|
||||||
|
break;
|
||||||
|
case SDL_QUIT:
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
break;
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case SDL_MOUSEMOTION: {
|
|
||||||
int newx,newy;
|
|
||||||
#if !defined(SCALEUP_2x2)
|
|
||||||
newx = event.motion.x;
|
|
||||||
newy = event.motion.y;
|
|
||||||
#else
|
|
||||||
newx = event.motion.x>>1;
|
|
||||||
newy = event.motion.y>>1;
|
|
||||||
#endif
|
|
||||||
if (newx != s->mouse.x || newy != s->mouse.y) {
|
|
||||||
s->mouse.x = newx;
|
|
||||||
s->mouse.y = newy;
|
|
||||||
s->drawMouse();
|
|
||||||
updateScreen(s);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
|
||||||
if (event.button.button==SDL_BUTTON_LEFT)
|
|
||||||
s->_leftBtnPressed |= 1;
|
|
||||||
else if (event.button.button==SDL_BUTTON_RIGHT)
|
|
||||||
s->_rightBtnPressed |= 1;
|
|
||||||
break;
|
|
||||||
case SDL_QUIT:
|
|
||||||
exit(1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (SDL_GetTicks() >= start_time + msec_delay)
|
||||||
if (!(s->_fastMode&2)) {
|
break;
|
||||||
assert(delay<500);
|
SDL_Delay(10);
|
||||||
SDL_Delay(delay*10);
|
} while (1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_DIRTY_RECTS 40
|
#define MAX_DIRTY_RECTS 40
|
||||||
|
@ -468,111 +477,31 @@ void drawMouse(Scumm *s, int xdraw, int ydraw, int color, byte *mask, bool visib
|
||||||
old_mouse_x = xdraw;
|
old_mouse_x = xdraw;
|
||||||
old_mouse_y = ydraw;
|
old_mouse_y = ydraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SAMPLES_PER_SEC 22050
|
static uint32 midi_counter;
|
||||||
#define BUFFER_SIZE (8192)
|
|
||||||
#define BITS_PER_SAMPLE 16
|
|
||||||
|
|
||||||
struct MixerChannel {
|
|
||||||
void *_sfx_sound;
|
|
||||||
uint32 _sfx_pos;
|
|
||||||
uint32 _sfx_size;
|
|
||||||
uint32 _sfx_fp_speed;
|
|
||||||
uint32 _sfx_fp_pos;
|
|
||||||
|
|
||||||
void mix(int16 *data, uint32 len);
|
|
||||||
void clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NUM_MIXER 4
|
|
||||||
|
|
||||||
static MixerChannel mixer_channel[NUM_MIXER];
|
|
||||||
|
|
||||||
MixerChannel *find_channel() {
|
|
||||||
int i;
|
|
||||||
MixerChannel *mc = mixer_channel;
|
|
||||||
for(i=0; i<NUM_MIXER; i++,mc++) {
|
|
||||||
if (!mc->_sfx_sound)
|
|
||||||
return mc;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool isSfxFinished() {
|
|
||||||
int i;
|
|
||||||
for(i=0; i<NUM_MIXER; i++)
|
|
||||||
if (mixer_channel[i]._sfx_sound)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void playSfxSound(void *sound, uint32 size, uint rate) {
|
|
||||||
MixerChannel *mc = find_channel();
|
|
||||||
|
|
||||||
if (!mc) {
|
|
||||||
warning("No mixer channel available");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mc->_sfx_sound = sound;
|
|
||||||
mc->_sfx_pos = 0;
|
|
||||||
mc->_sfx_fp_speed = (1<<16) * rate / 22050;
|
|
||||||
mc->_sfx_fp_pos = 0;
|
|
||||||
|
|
||||||
while (size&0xFFFF0000) size>>=1, rate>>=1;
|
|
||||||
mc->_sfx_size = size * 22050 / rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixerChannel::mix(int16 *data, uint32 len) {
|
|
||||||
int8 *s;
|
|
||||||
int i;
|
|
||||||
uint32 fp_pos, fp_speed;
|
|
||||||
|
|
||||||
if (!_sfx_sound)
|
|
||||||
return;
|
|
||||||
if (len > _sfx_size)
|
|
||||||
len = _sfx_size;
|
|
||||||
_sfx_size -= len;
|
|
||||||
|
|
||||||
s = (int8*)_sfx_sound + _sfx_pos;
|
|
||||||
fp_pos = _sfx_fp_pos;
|
|
||||||
fp_speed = _sfx_fp_speed;
|
|
||||||
|
|
||||||
do {
|
|
||||||
fp_pos += fp_speed;
|
|
||||||
*data++ += (*s<<6);
|
|
||||||
s += fp_pos >> 16;
|
|
||||||
fp_pos &= 0x0000FFFF;
|
|
||||||
} while (--len);
|
|
||||||
|
|
||||||
_sfx_pos = s - (int8*)_sfx_sound;
|
|
||||||
_sfx_fp_speed = fp_speed;
|
|
||||||
_sfx_fp_pos = fp_pos;
|
|
||||||
|
|
||||||
if (!_sfx_size)
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixerChannel::clear() {
|
|
||||||
free(_sfx_sound);
|
|
||||||
_sfx_sound = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill_sound(void *userdata, Uint8 *stream, int len) {
|
void fill_sound(void *userdata, Uint8 *stream, int len) {
|
||||||
int i;
|
|
||||||
|
|
||||||
#if defined(USE_IMUSE)
|
|
||||||
sound.generate_samples((int16*)stream, len>>1);
|
|
||||||
#else
|
|
||||||
memset(stream, 0, len);
|
memset(stream, 0, len);
|
||||||
#endif
|
scumm.mixWaves((int16*)stream, len>>1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int music_thread(Scumm *s) {
|
||||||
|
int old_time, cur_time;
|
||||||
|
|
||||||
|
old_time = SDL_GetTicks();
|
||||||
|
|
||||||
|
do {
|
||||||
|
SDL_Delay(10);
|
||||||
|
|
||||||
|
cur_time = SDL_GetTicks();
|
||||||
|
while (old_time < cur_time) {
|
||||||
|
old_time += 10;
|
||||||
|
sound.on_timer();
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
|
||||||
for(i=NUM_MIXER-1; i>=0;i--) {
|
return 0;
|
||||||
mixer_channel[i].mix((int16*)stream, len>>1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initGraphics(Scumm *s, bool fullScreen) {
|
void initGraphics(Scumm *s, bool fullScreen) {
|
||||||
|
@ -599,10 +528,12 @@ void initGraphics(Scumm *s, bool fullScreen) {
|
||||||
SDL_OpenAudio(&desired, NULL);
|
SDL_OpenAudio(&desired, NULL);
|
||||||
SDL_PauseAudio(0);
|
SDL_PauseAudio(0);
|
||||||
|
|
||||||
|
|
||||||
SDL_WM_SetCaption(buf,buf);
|
SDL_WM_SetCaption(buf,buf);
|
||||||
SDL_ShowCursor(SDL_DISABLE);
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
|
|
||||||
|
/* Create Music Thread */
|
||||||
|
SDL_CreateThread((int (*)(void *))&music_thread, &scumm);
|
||||||
|
|
||||||
#if !defined(SCALEUP_2x2)
|
#if !defined(SCALEUP_2x2)
|
||||||
screen = SDL_SetVideoMode(320, 200, 8, fullScreen ? (SDL_SWSURFACE | SDL_FULLSCREEN) : SDL_SWSURFACE);
|
screen = SDL_SetVideoMode(320, 200, 8, fullScreen ? (SDL_SWSURFACE | SDL_FULLSCREEN) : SDL_SWSURFACE);
|
||||||
#else
|
#else
|
||||||
|
@ -627,33 +558,31 @@ void initGraphics(Scumm *s, bool fullScreen) {
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
int delta,tmp;
|
int delta,tmp;
|
||||||
|
int last_time, new_time;
|
||||||
|
|
||||||
#if defined(USE_IMUSE)
|
sound.initialize(&scumm);
|
||||||
sound.initialize(NULL);
|
|
||||||
scumm._soundDriver = &sound;
|
scumm._soundDriver = &sound;
|
||||||
#endif
|
|
||||||
|
|
||||||
scumm._gui = &gui;
|
scumm._gui = &gui;
|
||||||
scumm.scummMain(argc, argv);
|
scumm.scummMain(argc, argv);
|
||||||
|
|
||||||
gui.init(&scumm);
|
gui.init(&scumm);
|
||||||
|
|
||||||
|
last_time = SDL_GetTicks();
|
||||||
delta = 0;
|
delta = 0;
|
||||||
do {
|
do {
|
||||||
updateScreen(&scumm);
|
updateScreen(&scumm);
|
||||||
|
|
||||||
|
new_time = SDL_GetTicks();
|
||||||
|
waitForTimer(&scumm, delta * 15 + last_time - new_time);
|
||||||
|
last_time = SDL_GetTicks();
|
||||||
|
|
||||||
if (gui._active) {
|
if (gui._active) {
|
||||||
gui.loop();
|
gui.loop();
|
||||||
tmp = 5;
|
delta = 5;
|
||||||
} else {
|
} else {
|
||||||
tmp = delta = scumm.scummLoop(delta);
|
delta = scumm.scummLoop(delta);
|
||||||
tmp += tmp>>1;
|
|
||||||
|
|
||||||
if (scumm._fastMode)
|
|
||||||
tmp=1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForTimer(&scumm, tmp);
|
|
||||||
} while(1);
|
} while(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
140
sound.cpp
140
sound.cpp
|
@ -21,20 +21,7 @@
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "scumm.h"
|
#include "scumm.h"
|
||||||
|
|
||||||
#if defined(USE_IMUSE)
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#else
|
|
||||||
struct SoundEngine {
|
|
||||||
byte **_base_sounds;
|
|
||||||
int start_sound(int sound) { return -1; }
|
|
||||||
int stop_sound(int sound) { return -1; }
|
|
||||||
int stop_all_sounds() { return -1; }
|
|
||||||
int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h) { return -1; }
|
|
||||||
int get_sound_status(int sound) { return -1; }
|
|
||||||
int clear_queue() { return -1; }
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Scumm::addSoundToQueue(int sound) {
|
void Scumm::addSoundToQueue(int sound) {
|
||||||
_vars[VAR_LAST_SOUND] = sound;
|
_vars[VAR_LAST_SOUND] = sound;
|
||||||
|
@ -170,6 +157,13 @@ void Scumm::startTalkSound(uint32 offset, uint32 b, int mode) {
|
||||||
startSfxSound(_sfxFile);
|
startSfxSound(_sfxFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scumm::stopTalkSound() {
|
||||||
|
if (_sfxMode==2) {
|
||||||
|
stopSfxSound();
|
||||||
|
_sfxMode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Scumm::isMouthSyncOff(uint pos) {
|
bool Scumm::isMouthSyncOff(uint pos) {
|
||||||
uint j;
|
uint j;
|
||||||
bool val = true;
|
bool val = true;
|
||||||
|
@ -203,7 +197,6 @@ int Scumm::isSoundRunning(int sound) {
|
||||||
|
|
||||||
if (!isResourceLoaded(rtSound, sound))
|
if (!isResourceLoaded(rtSound, sound))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
se = (SoundEngine*)_soundDriver;
|
se = (SoundEngine*)_soundDriver;
|
||||||
if (!se)
|
if (!se)
|
||||||
|
@ -251,6 +244,7 @@ void Scumm::stopAllSounds() {
|
||||||
se->clear_queue();
|
se->clear_queue();
|
||||||
}
|
}
|
||||||
clearSoundQue();
|
clearSoundQue();
|
||||||
|
stopSfxSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scumm::clearSoundQue() {
|
void Scumm::clearSoundQue() {
|
||||||
|
@ -283,27 +277,41 @@ void Scumm::talkSound(uint32 a, uint32 b, int mode) {
|
||||||
_talk_sound_mode = mode;
|
_talk_sound_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The sound code currently only supports General Midi.
|
||||||
|
* General Midi is used in Day Of The Tentacle.
|
||||||
|
* Roland music is also playable, but doesn't sound well.
|
||||||
|
* A mapping between roland instruments and GM instruments
|
||||||
|
* is needed.
|
||||||
|
*/
|
||||||
|
|
||||||
static const uint32 sound_tags[] = {
|
static const uint32 sound_tags[] = {
|
||||||
MKID('ADL ')
|
MKID('GMD ')
|
||||||
};
|
};
|
||||||
|
|
||||||
void Scumm::setupSound() {
|
void Scumm::setupSound() {
|
||||||
SoundEngine *se = (SoundEngine*)_soundDriver;
|
SoundEngine *se = (SoundEngine*)_soundDriver;
|
||||||
if (se) {
|
if (se)
|
||||||
se->_base_sounds = res.address[rtSound];
|
se->_base_sounds = res.address[rtSound];
|
||||||
}
|
|
||||||
_soundTagTable = (byte*)sound_tags;
|
_soundTagTable = (byte*)sound_tags;
|
||||||
_numSoundTags = 1;
|
_numSoundTags = 1;
|
||||||
_sfxFile = openSfxFile();
|
_sfxFile = openSfxFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scumm::pauseSounds(bool pause) {
|
||||||
|
SoundEngine *se = (SoundEngine*)_soundDriver;
|
||||||
|
if (se)
|
||||||
|
se->pause(pause);
|
||||||
|
_soundsPaused = pause;
|
||||||
|
}
|
||||||
|
|
||||||
struct VOCHeader {
|
struct VOCHeader {
|
||||||
byte id[19];
|
byte id[19];
|
||||||
byte extra[7];
|
byte extra[7];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char VALID_VOC_ID[] = "Creative Voice File";
|
static const char VALID_VOC_ID[] = "Creative Voice File";
|
||||||
static const char VALID_VOC_VERSION[] = "";
|
|
||||||
void Scumm::startSfxSound(void *file) {
|
void Scumm::startSfxSound(void *file) {
|
||||||
VOCHeader hdr;
|
VOCHeader hdr;
|
||||||
int block_type;
|
int block_type;
|
||||||
|
@ -354,4 +362,98 @@ void Scumm::startSfxSound(void *file) {
|
||||||
|
|
||||||
void *Scumm::openSfxFile() {
|
void *Scumm::openSfxFile() {
|
||||||
return fopen("monster.sou", "rb");
|
return fopen("monster.sou", "rb");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NUM_MIXER 4
|
||||||
|
|
||||||
|
MixerChannel *Scumm::allocateMixer() {
|
||||||
|
int i;
|
||||||
|
MixerChannel *mc = _mixer_channel;
|
||||||
|
for(i=0; i<NUM_MIXER; i++,mc++) {
|
||||||
|
if (!mc->_sfx_sound)
|
||||||
|
return mc;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::stopSfxSound() {
|
||||||
|
MixerChannel *mc = _mixer_channel;
|
||||||
|
int i;
|
||||||
|
for(i=0; i<NUM_MIXER; i++,mc++) {
|
||||||
|
if (mc->_sfx_sound)
|
||||||
|
mc->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Scumm::isSfxFinished() {
|
||||||
|
int i;
|
||||||
|
for(i=0; i<NUM_MIXER; i++)
|
||||||
|
if (_mixer_channel[i]._sfx_sound)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::playSfxSound(void *sound, uint32 size, uint rate) {
|
||||||
|
MixerChannel *mc = allocateMixer();
|
||||||
|
|
||||||
|
if (!mc) {
|
||||||
|
warning("No mixer channel available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mc->_sfx_sound = sound;
|
||||||
|
mc->_sfx_pos = 0;
|
||||||
|
mc->_sfx_fp_speed = (1<<16) * rate / 22050;
|
||||||
|
mc->_sfx_fp_pos = 0;
|
||||||
|
|
||||||
|
while (size&0xFFFF0000) size>>=1, rate>>=1;
|
||||||
|
mc->_sfx_size = size * 22050 / rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MixerChannel::mix(int16 *data, uint32 len) {
|
||||||
|
int8 *s;
|
||||||
|
int i;
|
||||||
|
uint32 fp_pos, fp_speed;
|
||||||
|
|
||||||
|
if (!_sfx_sound)
|
||||||
|
return;
|
||||||
|
if (len > _sfx_size)
|
||||||
|
len = _sfx_size;
|
||||||
|
_sfx_size -= len;
|
||||||
|
|
||||||
|
s = (int8*)_sfx_sound + _sfx_pos;
|
||||||
|
fp_pos = _sfx_fp_pos;
|
||||||
|
fp_speed = _sfx_fp_speed;
|
||||||
|
|
||||||
|
do {
|
||||||
|
fp_pos += fp_speed;
|
||||||
|
*data++ += (*s<<6);
|
||||||
|
s += fp_pos >> 16;
|
||||||
|
fp_pos &= 0x0000FFFF;
|
||||||
|
} while (--len);
|
||||||
|
|
||||||
|
_sfx_pos = s - (int8*)_sfx_sound;
|
||||||
|
_sfx_fp_speed = fp_speed;
|
||||||
|
_sfx_fp_pos = fp_pos;
|
||||||
|
|
||||||
|
if (!_sfx_size)
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MixerChannel::clear() {
|
||||||
|
free(_sfx_sound);
|
||||||
|
_sfx_sound = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::mixWaves(int16 *sounds, int len) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (_soundsPaused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(i=NUM_MIXER-1; i>=0;i--) {
|
||||||
|
_mixer_channel[i].mix(sounds, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
358
sound.h
Normal file
358
sound.h
Normal file
|
@ -0,0 +1,358 @@
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/11/14 18:37:38 strigeus
|
||||||
|
* music support,
|
||||||
|
* fixed timing bugs
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Part;
|
||||||
|
struct MidiChannel;
|
||||||
|
struct VolumeFader;
|
||||||
|
struct Player;
|
||||||
|
struct HookDatas;
|
||||||
|
struct SoundEngine;
|
||||||
|
|
||||||
|
struct Part {
|
||||||
|
SoundEngine *_se;
|
||||||
|
Part *_next, *_prev;
|
||||||
|
MidiChannel *_mc;
|
||||||
|
Player *_player;
|
||||||
|
int16 _pitchbend;
|
||||||
|
byte _pitchbend_factor;
|
||||||
|
int8 _transpose,_transpose_eff;
|
||||||
|
byte _vol,_vol_eff;
|
||||||
|
int8 _detune,_detune_eff;
|
||||||
|
int8 _pan,_pan_eff;
|
||||||
|
bool _on;
|
||||||
|
byte _modwheel;
|
||||||
|
bool _pedal;
|
||||||
|
byte _program;
|
||||||
|
int8 _pri;
|
||||||
|
byte _pri_eff;
|
||||||
|
byte _chan;
|
||||||
|
byte _effect_level;
|
||||||
|
byte _chorus;
|
||||||
|
byte _gmidi_5;
|
||||||
|
byte _gmidi_1;
|
||||||
|
|
||||||
|
void key_on(byte note, byte velocity);
|
||||||
|
void key_off(byte note);
|
||||||
|
void set_param(int b, byte c) {}
|
||||||
|
void init(SoundEngine *se);
|
||||||
|
void setup(Player *player);
|
||||||
|
void uninit();
|
||||||
|
void off();
|
||||||
|
void silence();
|
||||||
|
void set_instrument(uint b);
|
||||||
|
void set_instrument(byte *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_pan(int8 pan);
|
||||||
|
void set_modwheel(uint value);
|
||||||
|
void set_pedal(bool value);
|
||||||
|
void set_pitchbend(int value);
|
||||||
|
void release_pedal();
|
||||||
|
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();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MidiChannel {
|
||||||
|
Part *_part;
|
||||||
|
byte _chan;
|
||||||
|
uint16 _actives[8];
|
||||||
|
|
||||||
|
void init(byte chan);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VolumeFader {
|
||||||
|
Player *player;
|
||||||
|
bool active;
|
||||||
|
byte curvol;
|
||||||
|
uint16 speed_lo_max,num_steps;
|
||||||
|
int8 speed_hi;
|
||||||
|
int8 direction;
|
||||||
|
int8 speed_lo;
|
||||||
|
uint16 speed_lo_counter;
|
||||||
|
|
||||||
|
void initialize() { active = false; }
|
||||||
|
void on_timer();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HookDatas {
|
||||||
|
byte _jump,_transpose;
|
||||||
|
byte _part_onoff[16];
|
||||||
|
byte _part_volume[16];
|
||||||
|
byte _part_program[16];
|
||||||
|
byte _part_transpose[16];
|
||||||
|
|
||||||
|
int query_param(int param, byte chan);
|
||||||
|
int set(byte cls, byte value, byte chan);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Player {
|
||||||
|
SoundEngine *_se;
|
||||||
|
|
||||||
|
Part *_parts;
|
||||||
|
bool _active;
|
||||||
|
bool _scanning;
|
||||||
|
int _id;
|
||||||
|
byte _priority;
|
||||||
|
byte _volume;
|
||||||
|
int8 _pan;
|
||||||
|
int8 _transpose;
|
||||||
|
int8 _detune;
|
||||||
|
uint _vol_chan;
|
||||||
|
byte _vol_eff;
|
||||||
|
|
||||||
|
uint _song_index;
|
||||||
|
uint _track_index;
|
||||||
|
uint _timer_counter;
|
||||||
|
uint _loop_to_beat;
|
||||||
|
uint _loop_from_beat;
|
||||||
|
uint _loop_counter;
|
||||||
|
uint _loop_to_tick;
|
||||||
|
uint _loop_from_tick;
|
||||||
|
uint32 _tempo;
|
||||||
|
uint32 _tempo_eff; /* NoSave */
|
||||||
|
uint32 _cur_pos;
|
||||||
|
uint32 _next_pos;
|
||||||
|
uint32 _song_offset;
|
||||||
|
uint32 _timer_speed; /* NoSave */
|
||||||
|
uint _tick_index;
|
||||||
|
uint _beat_index;
|
||||||
|
uint _ticks_per_beat;
|
||||||
|
byte _speed; /* NoSave */
|
||||||
|
bool _abort;
|
||||||
|
|
||||||
|
HookDatas _hook;
|
||||||
|
|
||||||
|
/* Player part */
|
||||||
|
void hook_clear();
|
||||||
|
void clear();
|
||||||
|
bool start_sound(int sound);
|
||||||
|
void uninit_parts();
|
||||||
|
byte *parse_midi(byte *s);
|
||||||
|
void key_off(uint8 chan, byte data);
|
||||||
|
void key_on(uint8 chan, byte data, byte velocity);
|
||||||
|
void part_set_transpose(uint8 chan, byte relative, int8 b);
|
||||||
|
void parse_sysex(byte *p, uint len);
|
||||||
|
void maybe_jump(byte *data);
|
||||||
|
void maybe_set_transpose(byte *data);
|
||||||
|
void maybe_part_onoff(byte *data);
|
||||||
|
void maybe_set_volume(byte *data);
|
||||||
|
void maybe_set_program(byte *data);
|
||||||
|
void maybe_set_transpose_part(byte *data);
|
||||||
|
uint update_actives();
|
||||||
|
Part *get_part(uint8 part);
|
||||||
|
void turn_off_pedals();
|
||||||
|
int set_vol(byte vol);
|
||||||
|
int get_param(int param, byte chan);
|
||||||
|
int query_part_param(int param, byte chan);
|
||||||
|
int set_transpose(byte relative, int b);
|
||||||
|
void set_priority(int pri);
|
||||||
|
void set_pan(int pan);
|
||||||
|
void set_detune(int detune);
|
||||||
|
void silence_parts();
|
||||||
|
void play_active_notes();
|
||||||
|
void cancel_volume_fade();
|
||||||
|
|
||||||
|
static void decode_sysex_bytes(byte *src, byte *dst, int len);
|
||||||
|
|
||||||
|
void clear_active_note(int chan, byte note);
|
||||||
|
void set_active_note(int chan, byte note);
|
||||||
|
void clear_active_notes();
|
||||||
|
|
||||||
|
/* Sequencer part */
|
||||||
|
bool set_loop(uint count, uint tobeat, uint totick, uint frombeat, uint fromtick);
|
||||||
|
void clear_loop();
|
||||||
|
void set_speed(byte speed);
|
||||||
|
bool jump(uint track, uint beat, uint tick);
|
||||||
|
void uninit_seq();
|
||||||
|
void set_tempo(uint32 data);
|
||||||
|
int start_seq_sound(int sound);
|
||||||
|
void find_sustaining_notes(byte *a, byte *b, uint32 l);
|
||||||
|
int scan(uint totrack, uint tobeat, uint totick);
|
||||||
|
int query_param(int param);
|
||||||
|
|
||||||
|
int fade_vol(byte vol, int time);
|
||||||
|
void sequencer_timer();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SustainingNotes {
|
||||||
|
SustainingNotes *next;
|
||||||
|
SustainingNotes *prev;
|
||||||
|
Player *player;
|
||||||
|
byte note,chan;
|
||||||
|
uint32 off_pos;
|
||||||
|
uint32 pos;
|
||||||
|
uint16 counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommandQueue {
|
||||||
|
uint16 array[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IsNoteCmdData {
|
||||||
|
byte chan;
|
||||||
|
byte note;
|
||||||
|
byte vel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SoundEngine {
|
||||||
|
void *_mo; /* midi out */
|
||||||
|
|
||||||
|
byte **_base_sounds;
|
||||||
|
|
||||||
|
Scumm *_s;
|
||||||
|
|
||||||
|
byte _locked;
|
||||||
|
|
||||||
|
bool _paused;
|
||||||
|
bool _active_volume_faders;
|
||||||
|
bool _initialized;
|
||||||
|
byte _volume_fader_counter;
|
||||||
|
|
||||||
|
uint _queue_end, _queue_pos, _queue_sound;
|
||||||
|
byte _queue_adding;
|
||||||
|
|
||||||
|
SustainingNotes *_sustain_notes_used;
|
||||||
|
SustainingNotes *_sustain_notes_free;
|
||||||
|
SustainingNotes *_sustain_notes_head;
|
||||||
|
|
||||||
|
uint16 _timer_counter_1;
|
||||||
|
|
||||||
|
byte _queue_marker;
|
||||||
|
byte _queue_cleared;
|
||||||
|
byte _master_volume;
|
||||||
|
|
||||||
|
uint16 _trigger_count;
|
||||||
|
|
||||||
|
uint16 _channel_volume[8];
|
||||||
|
uint16 _channel_volume_eff[8]; /* NoSave */
|
||||||
|
uint16 _volchan_table[8];
|
||||||
|
|
||||||
|
Player _players[8];
|
||||||
|
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);
|
||||||
|
int get_channel_volume(uint a);
|
||||||
|
void init_players();
|
||||||
|
void init_parts();
|
||||||
|
void init_volume_fader();
|
||||||
|
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);
|
||||||
|
Player *get_player_byid(int id);
|
||||||
|
|
||||||
|
int get_volchan_entry(uint a);
|
||||||
|
int set_volchan_entry(uint a, uint b);
|
||||||
|
int set_channel_volume(uint chan, uint vol);
|
||||||
|
void update_volumes();
|
||||||
|
void reset_tick();
|
||||||
|
VolumeFader *allocate_volume_fader();
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
static int saveReference(SoundEngine *me, byte type, void *ref);
|
||||||
|
static void *loadReference(SoundEngine *me, byte type, int ref);
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
void pause(bool paused);
|
||||||
|
};
|
|
@ -276,6 +276,8 @@ void Scumm::CHARSET_1() {
|
||||||
_lastXstart = virtscr[0].xstart;
|
_lastXstart = virtscr[0].xstart;
|
||||||
if (charset._center) {
|
if (charset._center) {
|
||||||
charset._xpos2 -= charset.getStringWidth(0, buffer,0) >> 1;
|
charset._xpos2 -= charset.getStringWidth(0, buffer,0) >> 1;
|
||||||
|
if (charset._xpos2<0)
|
||||||
|
charset._xpos2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
charset._disableOffsX = charset._unk12 = !_keepText;
|
charset._disableOffsX = charset._unk12 = !_keepText;
|
||||||
|
|
143
windows.cpp
143
windows.cpp
|
@ -31,11 +31,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "scumm.h"
|
#include "scumm.h"
|
||||||
|
|
||||||
#if defined(USE_IMUSE)
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
#if !defined(ALLOW_GDI)
|
#if !defined(ALLOW_GDI)
|
||||||
|
@ -135,10 +131,7 @@ int sel;
|
||||||
Scumm scumm;
|
Scumm scumm;
|
||||||
ScummDebugger debugger;
|
ScummDebugger debugger;
|
||||||
Gui gui;
|
Gui gui;
|
||||||
|
|
||||||
#if defined(USE_IMUSE)
|
|
||||||
SoundEngine sound;
|
SoundEngine sound;
|
||||||
#endif
|
|
||||||
|
|
||||||
WndMan wm[1];
|
WndMan wm[1];
|
||||||
byte veryFastMode;
|
byte veryFastMode;
|
||||||
|
@ -819,95 +812,6 @@ void blitToScreen(Scumm *s, byte *src,int x, int y, int w, int h) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SAMPLES_PER_SEC 22050
|
|
||||||
#define BUFFER_SIZE (8192)
|
|
||||||
#define BITS_PER_SAMPLE 16
|
|
||||||
|
|
||||||
struct MixerChannel {
|
|
||||||
void *_sfx_sound;
|
|
||||||
uint32 _sfx_pos;
|
|
||||||
uint32 _sfx_size;
|
|
||||||
uint32 _sfx_fp_speed;
|
|
||||||
uint32 _sfx_fp_pos;
|
|
||||||
|
|
||||||
void mix(int16 *data, uint32 len);
|
|
||||||
void clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NUM_MIXER 4
|
|
||||||
|
|
||||||
static MixerChannel mixer_channel[NUM_MIXER];
|
|
||||||
|
|
||||||
MixerChannel *find_channel() {
|
|
||||||
int i;
|
|
||||||
MixerChannel *mc = mixer_channel;
|
|
||||||
for(i=0; i<NUM_MIXER; i++,mc++) {
|
|
||||||
if (!mc->_sfx_sound)
|
|
||||||
return mc;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool isSfxFinished() {
|
|
||||||
int i;
|
|
||||||
for(i=0; i<NUM_MIXER; i++)
|
|
||||||
if (mixer_channel[i]._sfx_sound)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void playSfxSound(void *sound, uint32 size, uint rate) {
|
|
||||||
MixerChannel *mc = find_channel();
|
|
||||||
|
|
||||||
if (!mc) {
|
|
||||||
warning("No mixer channel available");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mc->_sfx_sound = sound;
|
|
||||||
mc->_sfx_pos = 0;
|
|
||||||
mc->_sfx_fp_speed = (1<<16) * rate / 22050;
|
|
||||||
mc->_sfx_fp_pos = 0;
|
|
||||||
|
|
||||||
while (size&0xFFFF0000) size>>=1, rate>>=1;
|
|
||||||
mc->_sfx_size = size * 22050 / rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixerChannel::mix(int16 *data, uint32 len) {
|
|
||||||
int8 *s;
|
|
||||||
int i;
|
|
||||||
uint32 fp_pos, fp_speed;
|
|
||||||
|
|
||||||
if (!_sfx_sound)
|
|
||||||
return;
|
|
||||||
if (len > _sfx_size)
|
|
||||||
len = _sfx_size;
|
|
||||||
_sfx_size -= len;
|
|
||||||
|
|
||||||
s = (int8*)_sfx_sound + _sfx_pos;
|
|
||||||
fp_pos = _sfx_fp_pos;
|
|
||||||
fp_speed = _sfx_fp_speed;
|
|
||||||
|
|
||||||
do {
|
|
||||||
fp_pos += fp_speed;
|
|
||||||
*data++ += (*s<<6);
|
|
||||||
s += fp_pos >> 16;
|
|
||||||
fp_pos &= 0x0000FFFF;
|
|
||||||
} while (--len);
|
|
||||||
|
|
||||||
_sfx_pos = s - (int8*)_sfx_sound;
|
|
||||||
_sfx_fp_speed = fp_speed;
|
|
||||||
_sfx_fp_pos = fp_pos;
|
|
||||||
|
|
||||||
if (!_sfx_size)
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MixerChannel::clear() {
|
|
||||||
free(_sfx_sound);
|
|
||||||
_sfx_sound = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int clock;
|
int clock;
|
||||||
|
|
||||||
|
@ -923,8 +827,8 @@ void updateScreen(Scumm *s) {
|
||||||
void waitForTimer(Scumm *s, int delay) {
|
void waitForTimer(Scumm *s, int delay) {
|
||||||
wm->handleMessage();
|
wm->handleMessage();
|
||||||
if (!veryFastMode) {
|
if (!veryFastMode) {
|
||||||
assert(delay<500);
|
assert(delay<5000);
|
||||||
Sleep(delay*10);
|
Sleep(delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,16 +844,8 @@ void drawMouse(Scumm *s, int x, int y, int w, int h, byte *buf, bool visible) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_buffer(int16 *buf, int len) {
|
void fill_buffer(int16 *buf, int len) {
|
||||||
int i;
|
|
||||||
#if defined(USE_IMUSE)
|
|
||||||
sound.generate_samples(buf,len);
|
|
||||||
#else
|
|
||||||
memset(buf, 0, len*2);
|
memset(buf, 0, len*2);
|
||||||
#endif
|
scumm.mixWaves(buf, len);
|
||||||
for(i=NUM_MIXER-1; i>=0;i--) {
|
|
||||||
mixer_channel[i].mix((int16*)buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WndMan::prepare_header(WAVEHDR *wh, int i) {
|
void WndMan::prepare_header(WAVEHDR *wh, int i) {
|
||||||
|
@ -975,6 +871,7 @@ void WndMan::sound_init() {
|
||||||
wfx.nBlockAlign = BITS_PER_SAMPLE * 1 / 8;
|
wfx.nBlockAlign = BITS_PER_SAMPLE * 1 / 8;
|
||||||
|
|
||||||
CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))&sound_thread, this, 0, &_threadId);
|
CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))&sound_thread, this, 0, &_threadId);
|
||||||
|
SetThreadPriority((void*)_threadId, THREAD_PRIORITY_HIGHEST);
|
||||||
|
|
||||||
_event = CreateEvent(NULL, false, false, NULL);
|
_event = CreateEvent(NULL, false, false, NULL);
|
||||||
|
|
||||||
|
@ -988,13 +885,25 @@ void WndMan::sound_init() {
|
||||||
|
|
||||||
DWORD _stdcall WndMan::sound_thread(WndMan *wm) {
|
DWORD _stdcall WndMan::sound_thread(WndMan *wm) {
|
||||||
int i;
|
int i;
|
||||||
|
bool signaled;
|
||||||
|
int time = GetTickCount(), cur;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
WaitForSingleObject(wm->_event, INFINITE);
|
cur = GetTickCount();
|
||||||
for(i=0; i<2; i++) {
|
while (time < cur) {
|
||||||
WAVEHDR *hdr = &wm->_hdr[i];
|
sound.on_timer();
|
||||||
if (hdr->dwFlags & WHDR_DONE) {
|
time += 10;
|
||||||
fill_buffer((int16*)hdr->lpData, hdr->dwBufferLength>>1);
|
}
|
||||||
waveOutWrite(wm->_handle, hdr, sizeof(WAVEHDR));
|
|
||||||
|
signaled = WaitForSingleObject(wm->_event, time - cur) == WAIT_OBJECT_0;
|
||||||
|
|
||||||
|
if (signaled) {
|
||||||
|
for(i=0; i<2; i++) {
|
||||||
|
WAVEHDR *hdr = &wm->_hdr[i];
|
||||||
|
if (hdr->dwFlags & WHDR_DONE) {
|
||||||
|
fill_buffer((int16*)hdr->lpData, hdr->dwBufferLength>>1);
|
||||||
|
waveOutWrite(wm->_handle, hdr, sizeof(WAVEHDR));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1011,10 +920,8 @@ int main(int argc, char* argv[]) {
|
||||||
wm->_vgabuf = (byte*)calloc(320,200);
|
wm->_vgabuf = (byte*)calloc(320,200);
|
||||||
wm->_scumm = &scumm;
|
wm->_scumm = &scumm;
|
||||||
|
|
||||||
#if defined(USE_IMUSE)
|
sound.initialize(&scumm);
|
||||||
sound.initialize(NULL);
|
|
||||||
scumm._soundDriver = &sound;
|
scumm._soundDriver = &sound;
|
||||||
#endif
|
|
||||||
|
|
||||||
scumm._gui = &gui;
|
scumm._gui = &gui;
|
||||||
scumm.scummMain(argc, argv);
|
scumm.scummMain(argc, argv);
|
||||||
|
@ -1024,6 +931,8 @@ int main(int argc, char* argv[]) {
|
||||||
do {
|
do {
|
||||||
updateScreen(&scumm);
|
updateScreen(&scumm);
|
||||||
|
|
||||||
|
waitForTimer(&scumm, tmp*10);
|
||||||
|
|
||||||
if (gui._active) {
|
if (gui._active) {
|
||||||
gui.loop();
|
gui.loop();
|
||||||
tmp = 5;
|
tmp = 5;
|
||||||
|
@ -1035,8 +944,6 @@ int main(int argc, char* argv[]) {
|
||||||
if (scumm._fastMode)
|
if (scumm._fastMode)
|
||||||
tmp=1;
|
tmp=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForTimer(&scumm, tmp);
|
|
||||||
} while(1);
|
} while(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue