aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sword1/control.cpp144
-rw-r--r--sword1/control.h14
-rw-r--r--sword1/music.cpp14
-rw-r--r--sword1/music.h5
-rw-r--r--sword1/sound.cpp16
-rw-r--r--sword1/sound.h7
-rw-r--r--sword1/sword1.cpp10
7 files changed, 172 insertions, 38 deletions
diff --git a/sword1/control.cpp b/sword1/control.cpp
index 2ee19498d0..be1a523dc5 100644
--- a/sword1/control.cpp
+++ b/sword1/control.cpp
@@ -32,6 +32,8 @@
#include "common/util.h"
#include "mouse.h"
#include "music.h"
+#include "sound.h"
+#include <math.h> // for sqrt()
#define SAVEFILE_WRITE true
#define SAVEFILE_READ false
@@ -150,12 +152,13 @@ void ControlButton::setSelected(uint8 selected) {
draw();
}
-SwordControl::SwordControl(ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, SwordMouse *pMouse, SwordMusic *pMusic, const char *savePath) {
+SwordControl::SwordControl(ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, SwordMouse *pMouse, SwordSound *pSound, SwordMusic *pMusic, const char *savePath) {
_resMan = pResMan;
_objMan = pObjMan;
_system = system;
_mouse = pMouse;
_music = pMusic;
+ _sound = pSound;
strcpy(_savePath, savePath);
_lStrings = _languageStrings + MIN(SwordEngine::_systemVars.language, (uint8)BS1_SPANISH) * 20;
}
@@ -212,6 +215,7 @@ void SwordControl::askForCd(void) {
}
uint8 SwordControl::runPanel(void) {
+ _mouseDown = false;
_restoreBuf = NULL;
_keyPressed = _numButtons = 0;
_screenBuf = (uint8*)malloc(640 * 480);
@@ -283,10 +287,16 @@ uint8 SwordControl::runPanel(void) {
}
uint8 SwordControl::getClicks(uint8 mode, uint8 *retVal) {
+ uint8 checkButtons = _numButtons;
+ if (mode == BUTTON_VOLUME_PANEL) {
+ handleVolumeClicks();
+ checkButtons = 1;
+ }
+
if (!_mouseState)
return 0;
if (_mouseState & BS1L_BUTTON_DOWN)
- for (uint8 cnt = 0; cnt < _numButtons; cnt++)
+ for (uint8 cnt = 0; cnt < checkButtons; cnt++)
if (_buttons[cnt]->wasClicked(_mouseX, _mouseY)) {
_selectedButton = cnt;
_buttons[cnt]->setSelected(1);
@@ -294,7 +304,7 @@ uint8 SwordControl::getClicks(uint8 mode, uint8 *retVal) {
showSavegameNames();
}
if (_mouseState & BS1L_BUTTON_UP) {
- for (uint8 cnt = 0; cnt < _numButtons; cnt++)
+ for (uint8 cnt = 0; cnt < checkButtons; cnt++)
if (_buttons[cnt]->wasClicked(_mouseX, _mouseY))
if (_selectedButton == cnt) {
// saveslots stay selected after clicking
@@ -303,7 +313,7 @@ uint8 SwordControl::getClicks(uint8 mode, uint8 *retVal) {
_selectedButton = 255;
return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
}
- if (_selectedButton < _numButtons) {
+ if (_selectedButton < checkButtons) {
_buttons[_selectedButton]->setSelected(0);
if (_buttons[_selectedButton]->isSaveslot())
showSavegameNames();
@@ -436,10 +446,101 @@ void SwordControl::setupVolumePanel(void) {
renderText(_lStrings[STR_SPEECH], 320, 39 + 40, TEXT_CENTER);
renderText(_lStrings[STR_FX], 438, 39 + 40, TEXT_LEFT_ALIGN);
- renderText((const uint8*)"NOT YET IMPLEMENTED", 320, 240, TEXT_CENTER);
-
- createButtons(_volumeButtons, 1);
+ createButtons(_volumeButtons, 4);
renderText(_lStrings[STR_DONE], _volumeButtons[0].x - 10, _volumeButtons[0].y, TEXT_RIGHT_ALIGN);
+
+ uint8 volL, volR;
+ _music->giveVolume(&volL, &volR);
+ renderVolumeBar(1, volL, volR);
+ _sound->giveSpeechVol(&volL, &volR);
+ renderVolumeBar(2, volL, volR);
+ _sound->giveSfxVol(&volL, &volR);
+ renderVolumeBar(3, volL, volR);
+}
+
+void SwordControl::handleVolumeClicks(void) {
+ if (_mouseDown) {
+ uint8 clickedId = 0;
+ for (uint8 cnt = 1; cnt < 4; cnt++)
+ if (_buttons[cnt]->wasClicked(_mouseX, _mouseY))
+ clickedId = cnt;
+ if (clickedId) { // these are circle shaped, so check again if it was clicked.
+ uint8 clickDest = 0;
+ int16 mouseDiffX = _mouseX - (_volumeButtons[clickedId].x + 48);
+ int16 mouseDiffY = _mouseY - (_volumeButtons[clickedId].y + 48);
+ int16 mouseOffs = (int16)sqrt(mouseDiffX * mouseDiffX + mouseDiffY * mouseDiffY);
+ // check if the player really hit the button (but not the center).
+ if ((mouseOffs <= 42) && (mouseOffs >= 8)) {
+ if (mouseDiffX > 8) { // right part
+ if (mouseDiffY < -8) // upper right
+ clickDest = 2;
+ else if (ABS(mouseDiffY) <= 8) // right
+ clickDest = 3;
+ else // lower right
+ clickDest = 4;
+ } else if (mouseDiffX < -8) { // left part
+ if (mouseDiffY < -8) // upper left
+ clickDest = 8;
+ else if (ABS(mouseDiffY) <= 8) // left
+ clickDest = 7;
+ else // lower left
+ clickDest = 6;
+ } else { // middle
+ if (mouseDiffY < -8)
+ clickDest = 1; // upper
+ else if (mouseDiffY > 8)
+ clickDest = 5; // lower
+ }
+ }
+ _buttons[clickedId]->setSelected(clickDest);
+ changeVolume(clickedId, clickDest);
+ }
+ } else if (_mouseState & BS1L_BUTTON_UP) {
+ _buttons[1]->setSelected(0);
+ _buttons[2]->setSelected(0);
+ _buttons[3]->setSelected(0);
+ }
+}
+
+void SwordControl::changeVolume(uint8 id, uint8 action) {
+ // ids: 1 = music, 2 = speech, 3 = sfx
+ uint8 volL = 0, volR = 0;
+ if (id == 1)
+ _music->giveVolume(&volL, &volR);
+ else if (id == 2)
+ _sound->giveSpeechVol(&volL, &volR);
+ else if (id == 3)
+ _sound->giveSfxVol(&volL, &volR);
+
+ int8 direction = 0;
+ if ((action >= 4) && (action <= 6)) // lower part of the button => decrease volume
+ direction = -1;
+ else if ((action == 8) || (action == 1) || (action == 2)) // upper part => increase volume
+ direction = 1;
+ else if ((action == 3) || (action == 7)) // middle part => pan volume
+ direction = 1;
+ int8 factorL = 8, factorR = 8;
+ if ((action >= 6) && (action <= 8)) { // left part => left pan
+ factorL = 8;
+ factorR = (action == 7) ? -8 : 0;
+ } else if ((action >= 2) && (action <= 4)) { // right part
+ factorR = 8;
+ factorL = (action == 3) ? -8 : 0;
+ }
+ int16 resVolL = volL + direction * factorL;
+ int16 resVolR = volR + direction * factorR;
+
+ volL = (uint8)MAX((int16)0, MIN(resVolL, (int16)255));
+ volR = (uint8)MAX((int16)0, MIN(resVolR, (int16)255));
+
+ if (id == 1)
+ _music->setVolume(volL, volR);
+ else if (id == 2)
+ _sound->setSpeechVol(volL, volR);
+ else if (id == 3)
+ _sound->setSfxVol(volL, volR);
+
+ renderVolumeBar(id, volL, volR);
}
bool SwordControl::getConfirm(const uint8 *title) {
@@ -701,8 +802,24 @@ void SwordControl::renderText(const uint8 *str, uint16 x, uint16 y, uint8 mode)
_system->copy_rect(_screenBuf + y * SCREEN_WIDTH + x, SCREEN_WIDTH, x, y, (destX - x) + 3, 28);
}
-void SwordControl::renderVolumeBar(uint8 id) {
-
+void SwordControl::renderVolumeBar(uint8 id, uint8 volL, uint8 volR) {
+ uint16 destX = _volumeButtons[id].x + 20;
+ uint16 destY = _volumeButtons[id].y + 116;
+
+ for (uint8 chCnt = 0; chCnt < 2; chCnt++) {
+ uint8 vol = (chCnt == 0) ? volL : volR;
+ FrameHeader *frHead = _resMan->fetchFrame(_resMan->openFetchRes(SR_VLIGHT), (vol + 15) >> 4);
+ uint8 *destMem = _screenBuf + destY * SCREEN_WIDTH + destX;
+ uint8 *srcMem = (uint8*)frHead + sizeof(FrameHeader);
+ for (uint16 cnty = 0; cnty < FROM_LE_16(frHead->height); cnty++) {
+ memcpy(destMem, srcMem, FROM_LE_16(frHead->width));
+ srcMem += FROM_LE_16(frHead->width);
+ destMem += SCREEN_WIDTH;
+ }
+ _system->copy_rect(_screenBuf + destY * SCREEN_WIDTH + destX, SCREEN_WIDTH, destX, destY, FROM_LE_16(frHead->width), FROM_LE_16(frHead->height));
+ _resMan->resClose(SR_VLIGHT);
+ destX += 32;
+ }
}
void SwordControl::saveGameToFile(uint8 slot) {
@@ -823,6 +940,7 @@ void SwordControl::delay(uint32 msecs) {
_mouseY = event.mouse.y;
break;
case OSystem::EVENT_LBUTTONDOWN:
+ _mouseDown = true;
_mouseState |= BS1L_BUTTON_DOWN;
#ifdef _WIN32_WCE
_mouseX = event.mouse.x;
@@ -830,6 +948,7 @@ void SwordControl::delay(uint32 msecs) {
#endif
break;
case OSystem::EVENT_LBUTTONUP:
+ _mouseDown = false;
_mouseState |= BS1L_BUTTON_UP;
break;
case OSystem::EVENT_QUIT:
@@ -878,8 +997,11 @@ const ButtonInfo SwordControl::_saveButtons[16] = {
{462, 338 + 40, SR_BUTTON, BUTTON_SAVE_CANCEL}
};
-const ButtonInfo SwordControl::_volumeButtons[1] = {
- { 478, 338 + 40, SR_BUTTON, BUTTON_MAIN_PANEL }
+const ButtonInfo SwordControl::_volumeButtons[4] = {
+ { 478, 338 + 40, SR_BUTTON, BUTTON_MAIN_PANEL },
+ { 138, 135, SR_VKNOB, 0 },
+ { 273, 135, SR_VKNOB, 0 },
+ { 404, 135, SR_VKNOB, 0 },
};
const uint8 SwordControl::_languageStrings[8 * 20][43] = {
diff --git a/sword1/control.h b/sword1/control.h
index e8959acea9..e83b0a6982 100644
--- a/sword1/control.h
+++ b/sword1/control.h
@@ -30,6 +30,7 @@ class ResMan;
class OSystem;
class SwordMouse;
class SwordMusic;
+class SwordSound;
#define MAX_BUTTONS 16
@@ -63,16 +64,13 @@ struct ButtonInfo {
class SwordControl {
public:
- SwordControl(ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, SwordMouse *pMouse, SwordMusic *pMusic, const char *savePath);
+ SwordControl(ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, SwordMouse *pMouse, SwordSound *pSound, SwordMusic *pMusic, const char *savePath);
~SwordControl(void);
uint8 runPanel(void);
void doRestore(void);
void askForCd(void);
bool savegamesExist(void);
private:
- void initData(void);
- void closeData(void);
-
void saveGameToFile(uint8 slot);
bool restoreGameFromFile(uint8 slot);
void readSavegameDescriptions(void);
@@ -88,6 +86,8 @@ private:
uint8 getClicks(uint8 mode, uint8 *retVal);
uint8 handleButtonClick(uint8 id, uint8 mode, uint8 *retVal);
+ void handleVolumeClicks(void);
+ void changeVolume(uint8 id, uint8 action);
void setupMainPanel(void);
void setupSaveRestorePanel(bool saving);
@@ -101,7 +101,7 @@ private:
bool keyAccepted(uint8 key);
void handleSaveKey(uint8 key);
- void renderVolumeBar(uint8 id);
+ void renderVolumeBar(uint8 id, uint8 volL, uint8 volR);
uint16 getTextWidth(const uint8 *str);
void renderText(const uint8 *str, uint16 x, uint16 y, uint8 mode);
uint8 _numButtons;
@@ -109,7 +109,7 @@ private:
void createButtons(const ButtonInfo *buttons, uint8 num);
void destroyButtons(void);
ControlButton *_buttons[MAX_BUTTONS];
- static const ButtonInfo _deathButtons[3], _panelButtons[7], _saveButtons[16], _volumeButtons[1];
+ static const ButtonInfo _deathButtons[3], _panelButtons[7], _saveButtons[16], _volumeButtons[4];
static const uint8 _languageStrings[8 * 20][43];
const uint8 (*_lStrings)[43];
ObjectMan *_objMan;
@@ -117,12 +117,14 @@ private:
OSystem *_system;
SwordMouse *_mouse;
SwordMusic *_music;
+ SwordSound *_sound;
char _savePath[256];
uint8 *_font, *_redFont;
uint8 *_screenBuf;
uint8 _keyPressed;
void delay(uint32 msecs);
uint16 _mouseX, _mouseY, _mouseState;
+ bool _mouseDown;
};
diff --git a/sword1/music.cpp b/sword1/music.cpp
index fa23acbe46..3895cc95a5 100644
--- a/sword1/music.cpp
+++ b/sword1/music.cpp
@@ -116,7 +116,7 @@ SwordMusic::SwordMusic(OSystem *system, SoundMixer *pMixer) {
_mutex = _system->create_mutex();
_converter[0] = NULL;
_converter[1] = NULL;
- _volume = 192;
+ _volumeL = _volumeR = 192;
}
SwordMusic::~SwordMusic() {
@@ -135,11 +135,17 @@ void SwordMusic::mixer(int16 *buf, uint32 len) {
Common::StackLock lock(_mutex);
for (int i = 0; i < ARRAYSIZE(_handles); i++)
if (_handles[i].streaming() && _converter[i])
- _converter[i]->flow(_handles[i], buf, len, _volume, _volume);
+ _converter[i]->flow(_handles[i], buf, len, _volumeL, _volumeR);
}
-void SwordMusic::setVolume(uint8 vol) {
- _volume = (st_volume_t)vol;
+void SwordMusic::setVolume(uint8 volL, uint8 volR) {
+ _volumeL = (st_volume_t)volL;
+ _volumeR = (st_volume_t)volR;
+}
+
+void SwordMusic::giveVolume(uint8 *volL, uint8 *volR) {
+ *volL = (uint8)_volumeL;
+ *volR = (uint8)_volumeR;
}
void SwordMusic::startMusic(int32 tuneId, int32 loopFlag) {
diff --git a/sword1/music.h b/sword1/music.h
index 9e917fc003..c30c7cfce7 100644
--- a/sword1/music.h
+++ b/sword1/music.h
@@ -64,9 +64,10 @@ public:
~SwordMusic();
void startMusic(int32 tuneId, int32 loopFlag);
void fadeDown();
- void setVolume(uint8 vol);
+ void setVolume(uint8 volL, uint8 volR);
+ void giveVolume(uint8 *volL, uint8 *volR);
private:
- st_volume_t _volume;
+ st_volume_t _volumeL, _volumeR;
SwordMusicHandle _handles[2];
RateConverter *_converter[2];
OSystem *_system;
diff --git a/sword1/sound.cpp b/sword1/sound.cpp
index 31e6851f1a..026c6eb954 100644
--- a/sword1/sound.cpp
+++ b/sword1/sound.cpp
@@ -36,12 +36,7 @@ SwordSound::SwordSound(const char *searchPath, SoundMixer *mixer, ResMan *pResMa
_cowHeader = NULL;
_endOfQueue = 0;
_currentCowFile = 0;
- _speechVol = _sfxVol = 192;
-}
-
-void SwordSound::setVolume(uint8 sfxVol, uint8 speechVol) {
- _sfxVol = sfxVol;
- _speechVol = speechVol;
+ _speechVolL = _speechVolR = _sfxVolL = _sfxVolR = 192;
}
int SwordSound::addToQueue(int32 fxNo) {
@@ -140,11 +135,10 @@ void SwordSound::playSample(QueueElement *elem) {
if ((_fxList[elem->id].roomVolList[cnt].roomNo == (int)SwordLogic::_scriptVars[SCREEN]) ||
(_fxList[elem->id].roomVolList[cnt].roomNo == -1)) {
- uint8 volL = _fxList[elem->id].roomVolList[cnt].leftVol * 10;
- uint8 volR = _fxList[elem->id].roomVolList[cnt].rightVol * 10;
+ uint8 volL = (_fxList[elem->id].roomVolList[cnt].leftVol * 10 * _sfxVolL) / 255;
+ uint8 volR = (_fxList[elem->id].roomVolList[cnt].rightVol * 10 * _sfxVolR) / 255;
int8 pan = (volR - volL) / 2;
uint8 volume = (volR + volL) / 2;
- volume = (volume * _sfxVol) >> 8;
uint32 size = READ_LE_UINT32(sampleData + 0x28);
uint8 flags;
if (READ_LE_UINT16(sampleData + 0x22) == 16)
@@ -173,8 +167,10 @@ bool SwordSound::startSpeech(uint16 roomNo, uint16 localNo) {
if (sampleSize) {
uint32 size;
int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
+ uint8 speechVol = (_speechVolR + _speechVolL) / 2;
+ int8 speechPan = (_speechVolR - _speechVolL) / 2;
if (data)
- _mixer->playRaw(&_speechHandle, data, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID, _speechVol);
+ _mixer->playRaw(&_speechHandle, data, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID, speechVol, speechPan);
return true;
} else
return false;
diff --git a/sword1/sound.h b/sword1/sound.h
index 6ade373bff..ad06a93daf 100644
--- a/sword1/sound.h
+++ b/sword1/sound.h
@@ -59,7 +59,10 @@ class SwordSound {
public:
SwordSound(const char *searchPath, SoundMixer *mixer, ResMan *pResMan);
~SwordSound(void);
- void setVolume(uint8 sfxVol, uint8 speechVol);
+ void setSpeechVol(uint8 volL, uint8 volR) { _speechVolL = volL; _speechVolR = volR; };
+ void setSfxVol(uint8 volL, uint8 volR) { _sfxVolL = volL; _sfxVolR = volR; };
+ void giveSpeechVol(uint8 *volL, uint8 *volR) { *volL = _speechVolL; *volR = _speechVolR; };
+ void giveSfxVol(uint8 *volL, uint8 *volR) { *volL = _sfxVolL; *volR = _sfxVolR; };
void newScreen(uint32 screen);
void quitScreen(void);
void closeCowSystem(void);
@@ -75,7 +78,7 @@ public:
void engine(void);
private:
- uint8 _sfxVol, _speechVol;
+ uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR;
void playSample(QueueElement *elem);
void initCowSystem(void);
diff --git a/sword1/sword1.cpp b/sword1/sword1.cpp
index 20af1c038f..ce2d9db887 100644
--- a/sword1/sword1.cpp
+++ b/sword1/sword1.cpp
@@ -109,11 +109,15 @@ void SwordEngine::initialize(void) {
_logic = new SwordLogic(_objectMan, _resMan, _screen, _mouse, _sound, _music, _menu);
_mouse->useLogicAndMenu(_logic, _menu);
- _music->setVolume((uint8)ConfMan.getInt("music_volume"));
+ uint8 musicVol = (uint8)ConfMan.getInt("music_volume");
uint8 speechVol = (uint8)ConfMan.getInt("speech_volume");
+ uint8 sfxVol = (uint8)ConfMan.getInt("sfx_volume");
if (!speechVol)
speechVol = 192;
- _sound->setVolume((uint8)ConfMan.getInt("sfx_volume"), speechVol);
+
+ _music->setVolume(musicVol, musicVol); // these routines expect left and right volume,
+ _sound->setSpeechVol(speechVol, speechVol); // but our config manager doesn't support it.
+ _sound->setSfxVol(sfxVol, sfxVol);
_systemVars.justRestoredGame = _systemVars.currentCD =
_systemVars.gamePaused = 0;
@@ -151,7 +155,7 @@ void SwordEngine::initialize(void) {
_logic->initialize();
_objectMan->initialize();
_mouse->initialize();
- _control = new SwordControl(_resMan, _objectMan, _system, _mouse, _music, getSavePath());
+ _control = new SwordControl(_resMan, _objectMan, _system, _mouse, _sound, _music, getSavePath());
}
void SwordEngine::reinitialize(void) {