Time for the weekly progress report! This week I have finals, so studies had to be prioritized, but here is what has progressed since the last report:
Bugs
Here are the newly identified bugs:
Bug | Steps to reproduce | Explanation | Solved |
The first track played when the game start is random | When running in DOSBox, it always starts in track 4 | No | |
Battle sound effects not synchronizing | Sometimes the battle sound effects last after the battle is over | No | |
Crash when starting new game after ending | The New Game dialog pops up after an ending | Yes | |
Non-printable keys being printed in savefiles | For instance, SHIFT inserts a character when inserting the savefile name | Yes | |
The wrong game version shows when viewing credits | Credits show vW95 on Scummvm (vDOS on DOSBox) | No | |
Attack after death being possible | Wait until your HP is 0 but the enemy attack animation/sound isn’t over, then attack back | Sometimes your attack animation can span until after you’re dead. This requires a few retries. Something similar can be achieved in the original (DOSBox), so maybe this is expected behavior | No |
Crash on reading documents | Read every single document in the inn | Heap-buffer overflow caused by pointer arithmetic | Yes |
Doors not opening | Try to open the first door to the upper right in the starting screen | That (and a few other) doors are supposed to be openable | No |
Crash after saving | Save the game once and walk around the map | No |
Some of these have already been solved, while the third and fourth seemed low-priority, so I left them for later. The last two bugs were discovered recently and they’re quite high-priority, due to affecting the gameplay (doors not opening) and being a common source of crash (may crash after saving).
Meanwhile, some of the bugs I mentioned in the last post have also been solved:
Sound Issues
- Music volume not syncing to what is on the config at game startup
How it was fixed:
Music::Music(hResContext *musicRes) : _musicContext(musicRes), _parser(0) {
...
_currentVolume = 255;
_currentMusicBuffer = nullptr;
_trackNumber = 0;
+++ syncSoundSettings();
}
syncSoundSettings
is a method for syncing the internal volume with the config.
Notify the engine that the sound settings in the config manager might have changed and that it should adjust any internal volume (and other) values accordingly.
ScummVM Doxygen
Therefore we call it once in the Music
constructor to initialize its values accordingly to the config manager.
- Music does not cut out at zero
How it was fixed:
inline int16 quantizedVolume(uint16 trueVolume) {
int16 quantized = trueVolume & 0xFFF8;
quantized += (quantized / 16);
--- quantized += 2; // In ScummVM the range is 0..255
+++ quantized = CLIP(quantized, (int16)0, (int16)255);
return quantized;
}
Here quantized
is the value used for the config manager, which is 0-255 for ScummVM. Thankfully quantized already goes from 0-255 (except when fully maxed, at which point it slightly caps over 255, which is why we clip it).
Document Issues
- Arrow sprites not changing
// Sets the mouse pointer imagery
void gMousePointer::setImage(
gPixelMap &img,
int x,
int y) {
Point16 pos = currentPosition - offsetPosition;
if (pointerImage != &img
|| x != offsetPosition.x
|| y != offsetPosition.y
|| img.size != saveMap.size) {
offsetPosition.x = x;
offsetPosition.y = y;
...
}
...
}
When changing the pointer image (done with gMousePointer::setImage
) we check whether the img
pointer changed. However in mouseimg.cpp
where we call setImage
,
createStackedImage(combinedImage, &combinedImageCenter, imageArray, imageCenterArray, imageIndex);
imageOffset.x = combinedImageCenter - mouseImage->size.x / 2;
imageOffset.y = 0;
// Set the combined image as the new mouse cursor
g_vm->_pointer->hide();
g_vm->_pointer->setImage(combinedImage, mouseImageOffset.x - imageOffset.x, mouseImageOffset.y - imageOffset.y);
g_vm->_pointer->show();
combinedImage
never actually changes value. Therefore we change createStackedImage
to modify combined combinedImage
everytime it is called:
void createStackedImage(gPixelMap **newImage, int *newImageCenter, gPixelMap **imageArray, int *imageCenterArray, int images) {
assert(images != 0);
if (*newImage)
delete *newImage;
*newImage = new gPixelMap;
...
}
Of course, we modify the usage in the rest of code for this.
- Close parchment button not working
The cause for this was a typo. Oops.
CDocumentAppearance parchAppearance = {
{202, 54, 208, 256},
1,
pageOrientVertical,
bookTextColors,
{ {27, 18, 149, 212}, {0, 0, 0, 0} },
-- {64, 229, 20, 20},
++ {164, 229, 20, 20},
parchDecorations,
ARRAYSIZE(parchDecorations),
MKTAG('P', 'A', 'R', 'C'),
MKTAG('P', 'C', 'H', 0)
};
- Crash on reading Kaidar’s book
The cause for this was a unsigned to signed conversion. Therefore, we make a cast to uint16
.
uint8 *Thread::strAddress(int strNum) {
uint16 seg = READ_LE_INT16(codeSeg + 2);
uint16 offset = READ_LE_INT16(codeSeg + 4);
uint8 *strSeg = segmentAddress(seg, offset);
assert(strNum >= 0);
assert(codeSeg);
assert(strSeg);
--- return strSeg + READ_LE_INT16(strSeg + 2 * strNum);
+++ return strSeg + (uint16)READ_LE_INT16(strSeg + 2 * strNum);
}
- Crash on Credits
The cause for this was a strcat overlap. How did this work in the original, even?
bool CDocument::checkForPageBreak(char *string, uint16 index, int32 &offset) {
// get the current index into the string
char *strIndex = string + index;
+++ char *strAfter;
// page break detected
if (strIndex[1] == dPageBreak[0] &&
strIndex[2] == dPageBreak[1]) {
// eat the page breaks chars
// tie off the end
strIndex[0] = 0;
+++ strAfter = new char[textSize];
+++ Common::strlcpy(strAfter, &strIndex[3], textSize);
// string them together
--- strcat(&strIndex[0], &strIndex[2 + 1]);
+++ strcat(&strIndex[0], strAfter);
// take the offset to the end of this line
offset = index;
// and set the new page flag
+++ delete[] strAfter;
return true;
}
return false;
}
Keyboard
We change the original game’s scheme of key recognition to the one found in common/keyboard.h
. Therefore we change things like SpecialKey(upArrowKey)
to Common::KEYCODE_UP
.
switch (key) {
case Common::KEYCODE_UP:
selectionUp(1);
return true;
case Common::KEYCODE_DOWN:
selectionDown(1);
return true;
case Common::KEYCODE_PAGEUP:
selectionUp(linesPerPage);
return true;
case Common::KEYCODE_PAGEDOWN:
selectionDown(linesPerPage);
return true;
}
A few weeks left until GSoC ends, while summer break is about to start here. Let’s do our best.
Leave a Reply