aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--saga/actor.cpp5
-rw-r--r--saga/font.cpp9
-rw-r--r--saga/game.cpp73
-rw-r--r--saga/game.h4
-rw-r--r--saga/game_mod.h11
-rw-r--r--saga/interface.cpp4
-rw-r--r--saga/music.cpp32
-rw-r--r--saga/music.h3
-rw-r--r--saga/rscfile.cpp4
-rw-r--r--saga/rscfile_mod.h1
-rw-r--r--saga/saga.cpp36
-rw-r--r--saga/scene.cpp4
-rw-r--r--saga/script.cpp8
-rw-r--r--saga/sndres.cpp123
-rw-r--r--saga/sndres.h4
-rw-r--r--saga/sound.cpp118
-rw-r--r--saga/sound.h1
-rw-r--r--saga/sprite.cpp6
18 files changed, 292 insertions, 154 deletions
diff --git a/saga/actor.cpp b/saga/actor.cpp
index efec4379e5..f1337a1cb6 100644
--- a/saga/actor.cpp
+++ b/saga/actor.cpp
@@ -69,12 +69,11 @@ int Actor::reg() {
}
Actor::Actor(SagaEngine *vm) : _vm(vm), _initialized(false) {
- int result;
int i;
// Get actor resource file context
- result = GAME_GetFileContext(&_actorContext, GAME_RESOURCEFILE, 0);
- if (result != SUCCESS) {
+ _actorContext = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
+ if (_actorContext == NULL) {
error("Actor::Actor(): Couldn't load actor module resource context.");
}
diff --git a/saga/font.cpp b/saga/font.cpp
index 736237c6d4..d317b17a94 100644
--- a/saga/font.cpp
+++ b/saga/font.cpp
@@ -37,8 +37,8 @@ Font::Font(SagaEngine *vm) : _vm(vm), _initialized(false) {
int i;
// Load font module resource context
- if (GAME_GetFileContext(&_fontContext,
- GAME_RESOURCEFILE, 0) != SUCCESS) {
+ _fontContext = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
+ if (_fontContext == NULL) {
error("Font::Font(): Couldn't get resource context.");
}
@@ -102,7 +102,8 @@ int Font::loadFont(uint32 font_rn, int font_id) {
}
if (fontres_len < FONT_DESCSIZE) {
- error("Font::loadFont(): Invalid font length.");
+ warning("Font::loadFont(): Invalid font length (%d < %d)", fontres_len, FONT_DESCSIZE);
+ return FAILURE;
}
MemoryReadStream readS(fontres_p, fontres_len);
@@ -119,7 +120,7 @@ int Font::loadFont(uint32 font_rn, int font_id) {
fh.c_width = readS.readUint16LE();
fh.row_length = readS.readUint16LE();
- debug(1, "Font::loadFont(): Reading font resource...");
+ debug(1, "Font::loadFont(): Reading font resource #%d...", font_rn);
debug(2, "Character width: %d", fh.c_width);
debug(2, "Character height: %d", fh.c_height);
diff --git a/saga/game.cpp b/saga/game.cpp
index f109206421..99b0bfd2ea 100644
--- a/saga/game.cpp
+++ b/saga/game.cpp
@@ -57,24 +57,33 @@ GAME_SOUNDINFO ITEDEMO_GameSound = {
GAME_SOUND_VOC, 0, 0, 0
};
-// Inherit the Earth - win32 Wyrmkeep Demo version
+// Inherit the Earth - win32 Wyrmkeep Linux Demo version
GAME_FILEDESC ITEWINDEMO_GameFiles[] = {
{"ITED.RSC", GAME_RESOURCEFILE},
{"SCRIPTSD.RSC", GAME_SCRIPTFILE},
{"SOUNDSD.RSC", GAME_SOUNDFILE},
+ {"VOICESD.RSC", GAME_VOICEFILE},
+ {"MUSICD.RSC", GAME_MUSICFILE}
+};
+
+// Inherit the Earth - win32 Wyrmkeep Demo version older release
+GAME_FILEDESC ITEWINDEMOOld_GameFiles[] = {
+ {"ITED.RSC", GAME_RESOURCEFILE},
+ {"SCRIPTSD.RSC", GAME_SCRIPTFILE},
+ {"SOUNDSD.RSC", GAME_SOUNDFILE},
{"VOICESD.RSC", GAME_VOICEFILE}
};
// Inherit the Earth - Diskette version
GAME_FILEDESC ITEDISK_GameFiles[] = {
- {"ITE.RSC", GAME_RESOURCEFILE} ,
- {"SCRIPTS.RSC", GAME_SCRIPTFILE} ,
+ {"ITE.RSC", GAME_RESOURCEFILE},
+ {"SCRIPTS.RSC", GAME_SCRIPTFILE},
{"VOICES.RSC", GAME_SOUNDFILE | GAME_VOICEFILE}
};
GAME_FONTDESC ITEDISK_GameFonts[] = {
- {GAME_FONT_MEDIUM, 0} ,
- {GAME_FONT_LARGE, 1} ,
+ {GAME_FONT_MEDIUM, 0},
+ {GAME_FONT_LARGE, 1},
{GAME_FONT_SMALL, 2}
};
@@ -174,12 +183,13 @@ GAMEDESC GameDescs[] = {
0 // features
},
- // Inherit the earth - win32 Wyrmkeep Demo version
+ // Inherit the earth - Linux Demo version
+ // Note: it should be before win32 version
{
- "ite-demo-win",
+ "ite-demo",
GID_ITE,
GAME_ITE_WINDEMO,
- "Inherit the Earth (Win32 Demo)",
+ "Inherit the Earth (Linux Demo)",
320, 200,
137,
ITE_DEFAULT_SCENE,
@@ -189,13 +199,31 @@ GAMEDESC GameDescs[] = {
ARRAYSIZE(ITECD_GameFonts),
ITECD_GameFonts,
&ITECD_GameSound,
- 0
+ GF_VOX_VOICES
+ },
+
+ // Inherit the earth - Win32 Demo version
+ {
+ "ite-demo",
+ GID_ITE,
+ GAME_ITE_WINDEMO,
+ "Inherit the Earth (Win32 Demo)",
+ 320, 200,
+ 137,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEWINDEMOOld_GameFiles),
+ ITEWINDEMO_GameFiles,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ GF_VOX_VOICES
},
// Inherit the earth - CD version
// NOTE: it should be before floppy version
{
- "itecd",
+ "ite",
GID_ITE,
GAME_ITE_CD,
"Inherit the Earth (DOS CD Version)",
@@ -343,27 +371,17 @@ int LoadLanguage() {
return SUCCESS;
}
-int GAME_GetFileContext(RSCFILE_CONTEXT ** ctxt_p, uint16 type, int param) {
+RSCFILE_CONTEXT *GAME_GetFileContext(uint16 type, int param) {
RSCFILE_CONTEXT *found_ctxt = NULL;
uint16 i;
- if (ctxt_p == NULL) {
- return FAILURE;
- }
-
for (i = 0; i < GameModule.gfile_n; i++) {
if (GameModule.gfile_data[i].file_types & type) {
found_ctxt = GameModule.gfile_data[i].file_ctxt;
}
}
- if (found_ctxt != NULL) {
- *ctxt_p = found_ctxt;
- } else {
- *ctxt_p = NULL;
- }
-
- return SUCCESS;
+ return found_ctxt;
}
DetectedGameList GAME_ProbeGame(const FSList &fslist) {
@@ -560,15 +578,8 @@ int GAME_GetGameType() {
return GameModule.gamedesc->gd_game_type;
}
-GameList GAME_GameList() {
- int gNum = ARRAYSIZE(GameDescs);
- int i;
- GameList games;
-
- for (i = 0; i < gNum; i++)
- games.push_back(GameDescs[i].toGameSettings());
-
- return games;
+uint32 GAME_GetFeatures() {
+ return GameModule.gamedesc->features;
}
} // End of namespace Saga
diff --git a/saga/game.h b/saga/game.h
index d92a15dcc2..1cbefa8156 100644
--- a/saga/game.h
+++ b/saga/game.h
@@ -47,8 +47,8 @@ struct GAME_FILEDESC {
struct GAMEDESC {
const char *name;
- int gd_game_type;
- uint32 gd_game_id;
+ const int gd_game_type;
+ const uint32 gd_game_id;
const char *gd_title;
int gd_logical_w;
int gd_logical_h;
diff --git a/saga/game_mod.h b/saga/game_mod.h
index 6e2254fcc8..0d69ab83e7 100644
--- a/saga/game_mod.h
+++ b/saga/game_mod.h
@@ -51,7 +51,8 @@ enum GAME_FILETYPES {
enum GAME_SOUNDINFO_TYPES {
GAME_SOUND_PCM = 0,
GAME_SOUND_VOC,
- GAME_SOUND_WAV
+ GAME_SOUND_WAV,
+ GAME_SOUND_VOX
};
enum GAME_FONT_IDS {
@@ -64,6 +65,10 @@ enum GAME_FONT_IDS {
GAME_FONT_LARGE3
};
+enum GAME_FEATURES {
+ GF_VOX_VOICES = 1
+};
+
struct GAME_DISPLAYINFO {
int logical_w;
int logical_h;
@@ -96,7 +101,7 @@ struct GAME_RESOURCEDESC {
int GAME_Register();
int GAME_Init();
-int GAME_GetFileContext(RSCFILE_CONTEXT **ctxt_p, uint16 type, int param);
+RSCFILE_CONTEXT *GAME_GetFileContext(uint16 type, int param);
int GAME_GetFontInfo(GAME_FONTDESC **, int *);
int GAME_GetResourceInfo(GAME_RESOURCEDESC *);
int GAME_GetSoundInfo(GAME_SOUNDINFO *);
@@ -104,8 +109,8 @@ int GAME_GetDisplayInfo(GAME_DISPLAYINFO *);
int GAME_GetSceneInfo(GAME_SCENEDESC *);
int GAME_GetGame();
int GAME_GetGameType();
-GameList GAME_GameList();
DetectedGameList GAME_ProbeGame(const FSList &fslist);
+uint32 GAME_GetFeatures();
} // End of namespace Saga
diff --git a/saga/interface.cpp b/saga/interface.cpp
index 5b3a59f24d..c104d6092a 100644
--- a/saga/interface.cpp
+++ b/saga/interface.cpp
@@ -177,8 +177,8 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) {
}
// Load interface module resource file context
- result = GAME_GetFileContext(&_interfaceContext, GAME_RESOURCEFILE, 0);
- if (result != SUCCESS) {
+ _interfaceContext = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
+ if (_interfaceContext == NULL) {
return;
}
diff --git a/saga/music.cpp b/saga/music.cpp
index 164f4c754f..d8ab563e65 100644
--- a/saga/music.cpp
+++ b/saga/music.cpp
@@ -308,10 +308,22 @@ Music::Music(SoundMixer *mixer, MidiDriver *driver, int enabled) : _mixer(mixer)
// know why it has 27 elements, but the last one represents a
// very short tune. Perhaps it's a dummy?
//
- // TODO: The demo uses compressed music?
+ // FIXME: Well, it's a hack which I don't like. Logically it should
+ // call LoadResource() et al, but I don't want to load those
+ // huge files into memory. So I use FileContext just for getting file
+ // name and reuse its opened file a bit.
+ //
+ // Proper approach would be to extend resource manager so it could
+ // return File object.
- if (file.open("music.rsc")) {
+ _musicContext = GAME_GetFileContext(GAME_MUSICFILE, 0);
+ if (_musicContext != NULL) {
_hasDigiMusic = true;
+
+ debug(0, "DHFJKHDFKJLHDFKLJHDFKJHDASF");
+ _musicFname = RSC_FileName(_musicContext);
+
+ file.open(_musicFname);
file.seek(-ARRAYSIZE(_digiTableITECD) * 8, SEEK_END);
for (int i = 0; i < ARRAYSIZE(_digiTableITECD); i++) {
@@ -403,13 +415,18 @@ int Music::play(uint32 music_rn, uint16 flags) {
uint32 length = _digiTableITECD[music_rn - 9].length;
if (length > 0) {
- audioStream = makeRAWStream("music.rsc", start, length, flags == MUSIC_LOOP);
+ audioStream = makeRAWStream(_musicFname, start, length, flags == MUSIC_LOOP);
}
}
// No digitized music - try standalone MIDI.
- if (!audioStream)
+ if (!audioStream) {
midiFile.open(_midiTableITECD[music_rn - 9].filename);
+
+ if (!midiFile.isOpen()) {
+ warning("Cannot open music file %s", _midiTableITECD[music_rn - 9].filename);
+ }
+ }
}
}
@@ -437,7 +454,7 @@ int Music::play(uint32 music_rn, uint16 flags) {
} else {
// Load XMI resource data
- GAME_GetFileContext(&rsc_ctxt, GAME_RESOURCEFILE, 0);
+ rsc_ctxt = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
if (RSC_LoadResource(rsc_ctxt, music_rn, &resource_data,
&resource_size) != SUCCESS ) {
@@ -449,6 +466,11 @@ int Music::play(uint32 music_rn, uint16 flags) {
parser = MidiParser::createParser_XMIDI();
}
+ if (resource_size <= 0) {
+ warning("Music::play(): Resource load failed: %u", music_rn);
+ return FAILURE;
+ }
+
if (!parser->loadMusic(resource_data, resource_size)) {
warning("Error reading track!");
delete parser;
diff --git a/saga/music.h b/saga/music.h
index 21e6292859..f7249628de 100644
--- a/saga/music.h
+++ b/saga/music.h
@@ -126,6 +126,9 @@ private:
int _musicInitialized;
int _enabled;
bool _hasDigiMusic;
+
+ RSCFILE_CONTEXT *_musicContext;
+ const char *_musicFname;
};
} // End of namespace Saga
diff --git a/saga/rscfile.cpp b/saga/rscfile.cpp
index 804de7f5ee..929c1c5f6e 100644
--- a/saga/rscfile.cpp
+++ b/saga/rscfile.cpp
@@ -211,6 +211,10 @@ int RSC_GetResourceOffset(RSCFILE_CONTEXT *rsc, uint32 res_num, uint32 *res_offs
return SUCCESS;
}
+const char *RSC_FileName(RSCFILE_CONTEXT *rsc) {
+ return rsc->rc_file_fspec;
+}
+
int RSC_LoadResource(RSCFILE_CONTEXT *rsc, uint32 res_num, byte **res_p, size_t *res_size_p) {
uint32 res_offset;
size_t res_size;
diff --git a/saga/rscfile_mod.h b/saga/rscfile_mod.h
index 1efb879a18..4bcf7ce32c 100644
--- a/saga/rscfile_mod.h
+++ b/saga/rscfile_mod.h
@@ -39,6 +39,7 @@ int RSC_GetResourceSize(RSCFILE_CONTEXT *, uint32, uint32 *);
int RSC_GetResourceOffset(RSCFILE_CONTEXT *, uint32, uint32 *);
int RSC_LoadResource(RSCFILE_CONTEXT *, uint32, byte **, size_t *);
int RSC_FreeResource(byte *);
+const char *RSC_FileName(RSCFILE_CONTEXT *rsc);
} // End of namespace Saga
diff --git a/saga/saga.cpp b/saga/saga.cpp
index 42f9b6a5e3..1c05086ebf 100644
--- a/saga/saga.cpp
+++ b/saga/saga.cpp
@@ -55,8 +55,24 @@
#include "saga/game_mod.h"
#include "saga/palanim.h"
+static const GameSettings saga_games[] = {
+ {"ite", "Inherit the Earth", 0},
+ {"ite-demo", "Inherit the Earth (Demo)", 0},
+ {"ihnm", "I Have No Mouth and I Must Scream", 0 },
+ {"ihnm-demo", "I Have No Mouth and I Must Scream (Demo)", 0 },
+ {0, 0, 0}
+};
+
GameList Engine_SAGA_gameList() {
- return Saga::GAME_GameList();
+ GameList games;
+ const GameSettings *g = saga_games;
+
+ while (g->name) {
+ games.push_back(*g);
+ g++;
+ }
+
+ return games;
}
DetectedGameList Engine_SAGA_detectGames(const FSList &fslist) {
@@ -124,13 +140,17 @@ void SagaEngine::go() {
CVAR_RegisterFunc(CF_quitfunc, "quit", NULL, CVAR_NONE, 0, 0, this);
- // Process config file
- // FIXME
- /*
- if (CFG_Read(NULL) != SUCCESS) {
- warning("Couldn't read configuration file");
- }
- */
+ // Add some default directories
+ // Win32 demo & full game
+ File::addDefaultDirectory("graphics");
+ File::addDefaultDirectory("music");
+ File::addDefaultDirectory("sound");
+
+ // Linux demo
+ File::addDefaultDirectory("itedata");
+
+ // Mac demos & full game
+ File::addDefaultDirectory("patch");
// Process command line
diff --git a/saga/scene.cpp b/saga/scene.cpp
index bccc198b5c..8b91cfbd94 100644
--- a/saga/scene.cpp
+++ b/saga/scene.cpp
@@ -75,8 +75,8 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) {
GAME_GetSceneInfo(&gs_desc);
// Load scene module resource context
- result = GAME_GetFileContext(&_sceneContext, GAME_RESOURCEFILE, 0);
- if (result != SUCCESS) {
+ _sceneContext = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
+ if (_sceneContext == NULL) {
warning("Scene::Scene(): Couldn't load scene resource context");
return;
}
diff --git a/saga/script.cpp b/saga/script.cpp
index 50035fa5d8..feef94dc9b 100644
--- a/saga/script.cpp
+++ b/saga/script.cpp
@@ -70,14 +70,14 @@ Script::Script() {
debug(0, "Initializing scripting subsystem");
// Load script resource file context
- result = GAME_GetFileContext(&_scriptContext, GAME_SCRIPTFILE, 0);
- if (result != SUCCESS) {
+ _scriptContext = GAME_GetFileContext(GAME_SCRIPTFILE, 0);
+ if (_scriptContext == NULL) {
error("Couldn't get script file context");
}
// Load script LUT resource
- result = GAME_GetFileContext(&s_lut_ctxt, GAME_RESOURCEFILE, 0);
- if (result != SUCCESS) {
+ s_lut_ctxt = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
+ if (s_lut_ctxt == NULL) {
error("Couldn't get resource file context");
}
diff --git a/saga/sndres.cpp b/saga/sndres.cpp
index c36845d99c..f491f0aff3 100644
--- a/saga/sndres.cpp
+++ b/saga/sndres.cpp
@@ -36,16 +36,14 @@
namespace Saga {
SndRes::SndRes(SagaEngine *vm) : _vm(vm) {
- int result;
-
/* Load sound module resource file contexts */
- result = GAME_GetFileContext(&_sfx_ctxt, GAME_SOUNDFILE, 0);
- if (result != SUCCESS) {
+ _sfx_ctxt = GAME_GetFileContext(GAME_SOUNDFILE, 0);
+ if (_sfx_ctxt == NULL) {
return;
}
- result = GAME_GetFileContext(&_voice_ctxt, GAME_VOICEFILE, 0);
- if (result != SUCCESS) {
+ _voice_ctxt = GAME_GetFileContext(GAME_VOICEFILE, 0);
+ if (_voice_ctxt == NULL) {
return;
}
@@ -72,7 +70,8 @@ int SndRes::playSound(uint32 sound_rn, int volume) {
int SndRes::playVoice(uint32 voice_rn) {
SOUNDBUFFER snd_buffer;
- int result;
+ int result = FAILURE;
+ bool voiceFile = false;
debug(0, "SndRes::playVoice(%ld)", voice_rn);
@@ -90,34 +89,40 @@ int SndRes::playVoice(uint32 voice_rn) {
else
f.open("P2_A.iaf");
- if (!f.isOpen())
- return FAILURE;
+ if (f.isOpen()) {
+ size = f.size();
+ byte *snd_res = (byte *)malloc(size);
+ f.read(snd_res, size);
+ f.close();
- size = f.size();
- byte *snd_res = (byte *)malloc(size);
- f.read(snd_res, size);
- f.close();
-
- if (!voc) {
- snd_buffer.s_stereo = 0;
- snd_buffer.s_samplebits = 16;
- snd_buffer.s_freq = 22050;
- snd_buffer.s_buf = snd_res;
- snd_buffer.s_buf_len = size;
- snd_buffer.s_signed = 1;
- result = SUCCESS;
- } else {
- result = loadVocSound(snd_res, size, &snd_buffer);
- RSC_FreeResource(snd_res);
+ if (!voc) {
+ snd_buffer.s_stereo = 0;
+ snd_buffer.s_samplebits = 16;
+ snd_buffer.s_freq = 22050;
+ snd_buffer.s_buf = snd_res;
+ snd_buffer.s_buf_len = size;
+ snd_buffer.s_signed = 1;
+ result = SUCCESS;
+ } else {
+ result = loadVocSound(snd_res, size, &snd_buffer);
+ RSC_FreeResource(snd_res);
+ }
+ voiceFile = true;
}
- } else
+ }
+
+ // File is not present. It is DOS CD or Floppy
+ if (result != SUCCESS)
result = load(_voice_ctxt, voice_rn, &snd_buffer);
if (result != SUCCESS) {
return FAILURE;
}
- _vm->_sound->playVoice(&snd_buffer);
+ if (GAME_GetFeatures() & GF_VOX_VOICES && !voiceFile)
+ _vm->_sound->playVoxVoice(&snd_buffer);
+ else
+ _vm->_sound->playVoice(&snd_buffer);
return SUCCESS;
}
@@ -248,6 +253,7 @@ int SndRes::loadVocSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf
int SndRes::getVoiceLength(uint32 voice_rn) {
int res_type = _snd_info.res_type;
uint32 length = 0;
+ bool voiceFile = false;
double ms_f;
int ms_i = -1;
@@ -268,11 +274,13 @@ int SndRes::getVoiceLength(uint32 voice_rn) {
length = f.size();
res_type = GAME_SOUND_VOC;
f.close();
+ voiceFile = true;
} else if (f.open("P2_A.iaf")) {
result = SUCCESS;
length = f.size();
res_type = GAME_SOUND_PCM;
f.close();
+ voiceFile = true;
}
}
@@ -284,7 +292,11 @@ int SndRes::getVoiceLength(uint32 voice_rn) {
}
}
- if (res_type == GAME_SOUND_PCM) {
+ if (GAME_GetFeatures() & GF_VOX_VOICES && !voiceFile) {
+ // Rough hack, fix this to be accurate
+ ms_f = (double)length / 22050 * 2000.0;
+ ms_i = (int)ms_f;
+ } else if (res_type == GAME_SOUND_PCM) {
ms_f = (double)length / (_snd_info.sample_size / CHAR_BIT) / (_snd_info.freq) * 1000.0;
ms_i = (int)ms_f;
} else if (res_type == GAME_SOUND_VOC) {
@@ -298,59 +310,4 @@ int SndRes::getVoiceLength(uint32 voice_rn) {
return ms_i;
}
-int SndRes::ITEVOC_Resample(long src_freq, long dst_freq, byte *src_buf,
- size_t src_buf_len, byte **dst_buf, size_t *dst_buf_len) {
- byte *resamp_buf;
- size_t resamp_len;
-
- byte src_samp_a;
- byte src_samp_b;
-
- const byte *read_pa;
- const byte *read_pb;
-
- byte *write_pa;
- byte *write_pb;
- byte *write_pc;
-
- size_t src_i;
-
- assert(src_freq == 14705);
- assert(dst_freq == 22050);
-
- resamp_len = (size_t) (src_buf_len * 1.5);
- resamp_buf = (byte *)malloc(resamp_len);
- if (resamp_buf == NULL) {
- return FAILURE;
- }
-
- read_pa = src_buf;
- read_pb = src_buf + 1;
-
- write_pa = resamp_buf;
- write_pb = resamp_buf + 1;
- write_pc = resamp_buf + 2;
-
- for (src_i = 0; src_i < src_buf_len / 2; src_i++) {
- src_samp_a = *read_pa;
- src_samp_b = *read_pb;
-
- read_pa += 2;
- read_pb += 2;
-
- *write_pa = src_samp_a;
- *write_pb = (byte) ((src_samp_a / 2) + (src_samp_b / 2));
- *write_pc = src_samp_b;
-
- write_pa += 3;
- write_pb += 3;
- write_pc += 3;
- }
-
- *dst_buf = resamp_buf;
- *dst_buf_len = resamp_len;
-
- return SUCCESS;
-}
-
} // End of namespace Saga
diff --git a/saga/sndres.h b/saga/sndres.h
index 53de34641a..bbe91fe02d 100644
--- a/saga/sndres.h
+++ b/saga/sndres.h
@@ -70,8 +70,6 @@ public:
int playSound(uint32 sound_rn, int volume);
int playVoice(uint32 voice_rn);
int getVoiceLength(uint32 voice_rn);
- int ITEVOC_Resample(long src_freq, long dst_freq, byte *src_buf,
- size_t src_buf_len, byte **dst_buf, size_t *dst_buf_len);
private:
int load(RSCFILE_CONTEXT *snd_ctxt, uint32 snd_rn, SOUNDBUFFER *snd_buf_i);
@@ -79,7 +77,7 @@ public:
int _init;
- RSCFILE_CONTEXT *_sfx_ctxt;
+ RSCFILE_CONTEXT *_sfx_ctxt;
RSCFILE_CONTEXT *_voice_ctxt;
GAME_SOUNDINFO _snd_info;
diff --git a/saga/sound.cpp b/saga/sound.cpp
index a6859134ae..e63f675ca0 100644
--- a/saga/sound.cpp
+++ b/saga/sound.cpp
@@ -25,9 +25,118 @@
#include "saga/sound.h"
#include "saga/game_mod.h"
+#include "sound/audiostream.h"
#include "sound/mixer.h"
namespace Saga {
+#define BUFFER_SIZE 4096
+
+// Routines to convert 12 bit linear samples to the
+// Dialogic or Oki ADPCM coding format.
+class VOXInputStream : public AudioStream {
+private:
+ const byte *_buf;
+ uint32 _pos;
+ uint32 _inputLen;
+ bool _evenPos;
+
+ struct adpcmStatus {
+ int16 last;
+ int16 stepIndex;
+ } _status;
+
+ int16 stepAdjust(byte);
+ int16 adpcmDecode(byte);
+
+public:
+ VOXInputStream(const byte *input, int inputLen);
+ ~VOXInputStream() {};
+
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ bool endOfData() const { return _pos >= _inputLen; }
+ bool isStereo() const { return false; }
+ int getRate() const { return 22050; }
+};
+
+
+VOXInputStream::VOXInputStream(const byte *input, int inputLen)
+ : _buf(input), _pos(0), _inputLen(inputLen), _evenPos(true) {
+
+ _status.last = 0;
+ _status.stepIndex = 0;
+}
+
+int VOXInputStream::readBuffer(int16 *buffer, const int numSamples) {
+ int samples = 0;
+
+ while (samples < numSamples && !endOfData()) {
+ const int len = MIN(numSamples - samples, (int) (_inputLen - _pos));
+
+ // * 16 effectively converts 12-bit input to 16-bit output
+ for (int i = 0; i < len; i++) {
+ if (_evenPos)
+ buffer[i] = adpcmDecode((_buf[_pos] >> 4) & 0x0f) * 16;
+ else {
+ buffer[i] = adpcmDecode(_buf[_pos] & 0x0f) * 16;
+ _pos++;
+ }
+ _evenPos = !_evenPos;
+ }
+
+ samples += len;
+ }
+ return samples;
+}
+
+// adjust the step for use on the next sample.
+int16 VOXInputStream::stepAdjust(byte code) {
+ static int16 adjusts[] = {-1, -1, -1, -1, 2, 4, 6, 8};
+
+ return adjusts[code & 0x07];
+}
+
+static int16 stepSize[49] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41,
+ 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173,
+ 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
+ 724, 796, 876, 963, 1060, 1166, 1282, 1408, 1552 };
+
+// Decode Linear to ADPCM
+int16 VOXInputStream::adpcmDecode(byte code) {
+ int16 diff, E, SS, samp;
+
+ SS = stepSize[_status.stepIndex];
+ E = SS/8;
+ if (code & 0x01)
+ E += SS/4;
+ if (code & 0x02)
+ E += SS/2;
+ if (code & 0x04)
+ E += SS;
+ diff = (code & 0x08) ? -E : E;
+ samp = _status.last + diff;
+
+ // Clip the values to +/- 2^11 (supposed to be 12 bits)
+ if(samp > 2048)
+ samp = 2048;
+ if(samp < -2048)
+ samp = -2048;
+
+ _status.last = samp;
+ _status.stepIndex += stepAdjust(code);
+ if(_status.stepIndex < 0)
+ _status.stepIndex = 0;
+ if(_status.stepIndex > 48)
+ _status.stepIndex = 48;
+
+ return samp;
+}
+
+AudioStream *makeVOXStream(const byte *input, int size) {
+ AudioStream *audioStream = new VOXInputStream(input, size);
+
+ return audioStream;
+}
Sound::Sound(SagaEngine *vm, SoundMixer *mixer, int enabled) :
_vm(vm), _mixer(mixer), _enabled(enabled) {
@@ -119,6 +228,15 @@ int Sound::playVoice(SOUNDBUFFER *buf) {
return playSoundBuffer(&_voiceHandle, buf, 255, false);
}
+int Sound::playVoxVoice(SOUNDBUFFER *buf) {
+ AudioStream *audioStream;
+
+ audioStream = makeVOXStream(buf->s_buf, buf->s_buf_len);
+ _mixer->playInputStream(&_voiceHandle, audioStream, false);
+
+ return SUCCESS;
+}
+
int Sound::pauseVoice() {
if (!_soundInitialized) {
return FAILURE;
diff --git a/saga/sound.h b/saga/sound.h
index 46d05f5ede..06292c2099 100644
--- a/saga/sound.h
+++ b/saga/sound.h
@@ -54,6 +54,7 @@ public:
int stopSound();
int playVoice(SOUNDBUFFER *buf);
+ int playVoxVoice(SOUNDBUFFER *buf);
int pauseVoice();
int resumeVoice();
int stopVoice();
diff --git a/saga/sprite.cpp b/saga/sprite.cpp
index 102b2360f8..96631006e9 100644
--- a/saga/sprite.cpp
+++ b/saga/sprite.cpp
@@ -37,13 +37,11 @@
namespace Saga {
Sprite::Sprite(SagaEngine *vm) : _vm(vm), _initialized(false) {
- int result;
-
debug(0, "Initializing sprite subsystem...");
// Load sprite module resource context
- result = GAME_GetFileContext(&_spriteContext, GAME_RESOURCEFILE, 0);
- if (result != SUCCESS) {
+ _spriteContext = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
+ if (_spriteContext == NULL) {
return;
}