manually merged engines from trunk into branch

svn-id: r51964
This commit is contained in:
Tony Puccinelli 2010-08-11 01:11:16 +00:00
commit 3a7a0ba720
71 changed files with 464 additions and 12213 deletions

View File

@ -1695,7 +1695,7 @@ void DrasculaEngine::animation_9_6() {
// We set the room number to -1 for the same purpose.
// Also check animation_2_1(), where the same hack was used
// by the original
roomNumber = -1;
roomNumber = -2;
loadPic("nota2.alg", bgSurface, HALF_PAL);
black();
trackProtagonist = 1;

View File

@ -88,6 +88,7 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam
_textverbs = 0;
_textmisc = 0;
_textd1 = 0;
_talkSequences = 0;
_color = 0;
blinking = 0;

View File

@ -92,7 +92,8 @@ void DrasculaEngine::gotoObject(int pointX, int pointY) {
updateRoom();
updateScreen();
if (cursorVisible)
// roomNumber -2 is end credits. Do not show cursor there
if (cursorVisible && roomNumber != -2)
showCursor();
}

View File

@ -66,8 +66,8 @@ public:
class FabDecompressor {
private:
int _bitsLeft;
uint32 _bitBuffer;
int _bitsLeft;
uint32 _bitBuffer;
const byte *_srcData, *_srcP;
int _srcSize;

View File

@ -47,7 +47,6 @@ Console::Console(MadsM4Engine *vm) : GUI::Debugger() {
DCmd_Register("start_conv", WRAP_METHOD(Console, cmdStartConversation));
DCmd_Register("textview", WRAP_METHOD(Console, cmdShowTextview));
DCmd_Register("animview", WRAP_METHOD(Console, cmdShowAnimview));
DCmd_Register("anim", WRAP_METHOD(Console, cmdPlayAnimation));
}
Console::~Console() {
@ -247,33 +246,6 @@ bool Console::cmdShowAnimview(int argc, const char **argv) {
return false;
}
bool Console::cmdPlayAnimation(int argc, const char **argv) {
View *view = _vm->_viewManager->getView(VIEWID_SCENE);
if (view == NULL) {
DebugPrintf("The scene view isn't currently active\n");
} else if (argc != 2 && argc != 3) {
DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]);
DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n");
} else {
char resourceName[20];
strncpy(resourceName, argv[1], 15);
resourceName[15] = '\0';
if (!strchr(resourceName, '.'))
strcat(resourceName, ".AA");
_vm->_viewManager->moveToFront(view);
if (argc == 3 && atoi(argv[2]) == 1)
_vm->_animation->loadFullScreen(resourceName);
else
_vm->_animation->load(resourceName);
_vm->_animation->start();
view->restore(0, 0, view->width(), view->height());
return false;
}
return true;
}
/*--------------------------------------------------------------------------*/
MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) {
@ -282,6 +254,7 @@ MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) {
DCmd_Register("object", WRAP_METHOD(MadsConsole, cmdObject));
DCmd_Register("message", WRAP_METHOD(MadsConsole, cmdMessage));
DCmd_Register("scene_info", WRAP_METHOD(MadsConsole, cmdSceneInfo));
DCmd_Register("anim", WRAP_METHOD(MadsConsole, cmdPlayAnimation));
}
bool MadsConsole::cmdObject(int argc, const char **argv) {
@ -386,6 +359,33 @@ bool MadsConsole::cmdSceneInfo(int argc, const char **argv) {
return true;
}
bool MadsConsole::cmdPlayAnimation(int argc, const char **argv) {
View *view = _vm->_viewManager->getView(VIEWID_SCENE);
if (view == NULL) {
DebugPrintf("The scene view isn't currently active\n");
} else if (argc != 2 && argc != 3) {
DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]);
DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n");
} else {
char resourceName[20];
strncpy(resourceName, argv[1], 15);
resourceName[15] = '\0';
if (!strchr(resourceName, '.'))
strcat(resourceName, ".AA");
_vm->_viewManager->moveToFront(view);
if (argc == 3 && atoi(argv[2]) == 1)
_madsVm->_palette->deleteAllRanges();
_madsVm->scene()->_sceneAnimation->load(resourceName, 0);
view->restore(0, 0, view->width(), view->height());
return false;
}
return true;
}
/*--------------------------------------------------------------------------*/
M4Console::M4Console(M4Engine *vm): Console(vm) {

View File

@ -50,7 +50,6 @@ private:
bool cmdStartConversation(int argc, const char **argv);
bool cmdShowTextview(int argc, const char **argv);
bool cmdShowAnimview(int argc, const char **argv);
bool cmdPlayAnimation(int argc, const char **argv);
public:
Console(MadsM4Engine *vm);
@ -64,6 +63,8 @@ private:
bool cmdObject(int argc, const char **argv);
bool cmdMessage(int argc, const char **argv);
bool cmdSceneInfo(int argc, const char **argv);
bool cmdPlayAnimation(int argc, const char **argv);
public:
MadsConsole(MadsEngine *vm);
virtual ~MadsConsole() {}

View File

@ -96,7 +96,7 @@ void ConversationView::setNode(int32 nodeIndex) {
_vm->_font->setFont(FONT_CONVERSATION);
// TODO: Conversation styles and colors
_vm->_font->setColors(2, 1, 3);
_vm->_font->current()->setColours(2, 1, 3);
_currentNodeIndex = nodeIndex;
@ -124,7 +124,7 @@ void ConversationView::setNode(int32 nodeIndex) {
}
// Figure out the longest string to determine where option highlighting ends
int tempX = _vm->_font->getWidth(node->entries[i]->text, 0) +
int tempX = _vm->_font->current()->getWidth(node->entries[i]->text, 0) +
CONV_ENTRIES_X_OFFSET + 10;
_xEnd = MAX(_xEnd, tempX);
}
@ -163,10 +163,10 @@ void ConversationView::onRefresh(RectList *rects, M4Surface *destSurface) {
if (i > CONV_MAX_SHOWN_ENTRIES - 1)
break;
_vm->_font->setColor((_highlightedIndex == i) ? CONVERSATION_ENTRY_HIGHLIGHTED :
_vm->_font->current()->setColour((_highlightedIndex == i) ? CONVERSATION_ENTRY_HIGHLIGHTED :
CONVERSATION_ENTRY_NORMAL);
_vm->_font->writeString(this, _activeItems[i]->text, CONV_ENTRIES_X_OFFSET,
_vm->_font->current()->writeString(this, _activeItems[i]->text, CONV_ENTRIES_X_OFFSET,
CONV_ENTRIES_Y_OFFSET + CONV_ENTRIES_HEIGHT * i, 0, 0);
}
}

View File

@ -127,7 +127,7 @@ void Dialog::writeChars(const char *srcLine) {
strcat(line, wordStr);
lineLen = strlen(line);
lineWidth = _vm->_font->getWidth(line, DIALOG_SPACING);
lineWidth = _vm->_font->current()->getWidth(line, DIALOG_SPACING);
if (((_lineX + lineLen) > _widthChars) || ((_widthX + lineWidth) > _dialogWidth)) {
incLine();
@ -146,7 +146,7 @@ void Dialog::writeChars(const char *srcLine) {
*/
void Dialog::appendText(const char *line) {
_lineX += strlen(line);
_widthX += _vm->_font->getWidth(line, DIALOG_SPACING);
_widthX += _vm->_font->current()->getWidth(line, DIALOG_SPACING);
strcat(_lines[_lines.size() - 1].data, line);
}
@ -158,7 +158,7 @@ void Dialog::addLine(const char *line, bool underlineP) {
if ((_widthX > 0) || (_lineX > 0))
incLine();
int lineWidth = _vm->_font->getWidth(line, DIALOG_SPACING);
int lineWidth = _vm->_font->current()->getWidth(line, DIALOG_SPACING);
int lineLen = strlen(line);
if ((lineWidth > _dialogWidth) || (lineLen >= _widthChars))
@ -383,7 +383,7 @@ Dialog::Dialog(MadsM4Engine *vm, const char *msgData, const char *title): View(v
if (id > 0) {
// Suffix provided - specifies the dialog width in number of chars
_widthChars = id * 2;
_dialogWidth = id * (_vm->_font->getMaxWidth() + DIALOG_SPACING) + 10;
_dialogWidth = id * (_vm->_font->current()->getMaxWidth() + DIALOG_SPACING) + 10;
}
} else if (matchCommand(cmdText, "UNDER")) {
@ -416,7 +416,7 @@ Dialog::Dialog(MadsM4Engine *vm, const char *msgData, const char *title): View(v
Dialog::Dialog(MadsM4Engine *vm, int widthChars): View(vm, Common::Rect(0, 0, 0, 0)) {
_vm->_font->setFont(FONT_INTERFACE_MADS);
_widthChars = widthChars * 2;
_dialogWidth = widthChars * (_vm->_font->getMaxWidth() + DIALOG_SPACING) + 10;
_dialogWidth = widthChars * (_vm->_font->current()->getMaxWidth() + DIALOG_SPACING) + 10;
_screenType = LAYER_DIALOG;
_lineX = 0;
_widthX = 0;
@ -439,7 +439,7 @@ void Dialog::draw() {
// Calculate bounds
int dlgWidth = _dialogWidth;
int dlgHeight = _lines.size() * (_vm->_font->getHeight() + 1) + 10;
int dlgHeight = _lines.size() * (_vm->_font->current()->getHeight() + 1) + 10;
int dialogX = (_vm->_screen->width() - dlgWidth) / 2;
int dialogY = (_vm->_screen->height() - dlgHeight) / 2;
@ -480,26 +480,26 @@ void Dialog::draw() {
}
// Handle drawing the text contents
_vm->_font->setColours(7, 7, 7);
_vm->_font->current()->setColours(7, 7, 7);
setColour(7);
for (uint lineCtr = 0, yp = 5; lineCtr < _lines.size(); ++lineCtr, yp += _vm->_font->getHeight() + 1) {
for (uint lineCtr = 0, yp = 5; lineCtr < _lines.size(); ++lineCtr, yp += _vm->_font->current()->getHeight() + 1) {
if (_lines[lineCtr].barLine) {
// Bar separation line
hLine(5, width() - 6, ((_vm->_font->getHeight() + 1) >> 1) + yp);
hLine(5, width() - 6, ((_vm->_font->current()->getHeight() + 1) >> 1) + yp);
} else {
// Standard line
Common::Point pt(_lines[lineCtr].xp + 5, yp);
if (_lines[lineCtr].xp & 0x40)
++pt.y;
_vm->_font->writeString(this, _lines[lineCtr].data, pt.x, pt.y, 0, DIALOG_SPACING);
_vm->_font->current()->writeString(this, _lines[lineCtr].data, pt.x, pt.y, 0, DIALOG_SPACING);
if (_lines[lineCtr].underline)
// Underline needed
hLine(pt.x, pt.x + _vm->_font->getWidth(_lines[lineCtr].data, DIALOG_SPACING),
pt.y + _vm->_font->getHeight());
hLine(pt.x, pt.x + _vm->_font->current()->getWidth(_lines[lineCtr].data, DIALOG_SPACING),
pt.y + _vm->_font->current()->getHeight());
}
}
@ -528,7 +528,7 @@ void Dialog::display(MadsM4Engine *vm, int widthChars, const char **descEntries)
dlg->incLine();
dlg->writeChars(*descEntries);
int lineWidth = vm->_font->getWidth(*descEntries, DIALOG_SPACING);
int lineWidth = vm->_font->current()->getWidth(*descEntries, DIALOG_SPACING);
dlg->_lines[dlg->_lines.size() - 1].xp = (dlg->_dialogWidth - 10 - lineWidth) / 2;
++descEntries;
}

View File

@ -276,6 +276,7 @@ public:
// DEPRECATED: ScummVM re-implementation keeps all the quotes loaded, so the methods below are stubs
void clearQuotes() {}
void loadQuoteRange(int startNum, int endNum) {}
void loadQuoteSet(...) {}
void loadQuote(int quoteNum) {}
void loadMadsMessagesInfo();

View File

@ -290,26 +290,26 @@ void MenuButton::onRefresh() {
case OBJTYPE_SL_TEXT:
switch (_objectState) {
case OS_MOUSEOVER:
_vm->_font->setColors(TEXT_COLOR_MOUSEOVER_SHADOW, TEXT_COLOR_MOUSEOVER_FOREGROUND,
_vm->_font->current()->setColours(TEXT_COLOR_MOUSEOVER_SHADOW, TEXT_COLOR_MOUSEOVER_FOREGROUND,
TEXT_COLOR_MOUSEOVER_HILIGHT);
sprite = sprites[SL_LINE_MOUSEOVER];
break;
case OS_PRESSED:
_vm->_font->setColors(TEXT_COLOR_PRESSED_SHADOW, TEXT_COLOR_PRESSED_FOREGROUND,
_vm->_font->current()->setColours(TEXT_COLOR_PRESSED_SHADOW, TEXT_COLOR_PRESSED_FOREGROUND,
TEXT_COLOR_PRESSED_HILIGHT);
sprite = sprites[SL_LINE_PRESSED];
break;
case OS_GREYED:
_vm->_font->setColors(TEXT_COLOR_GREYED_SHADOW, TEXT_COLOR_GREYED_FOREGROUND,
_vm->_font->current()->setColours(TEXT_COLOR_GREYED_SHADOW, TEXT_COLOR_GREYED_FOREGROUND,
TEXT_COLOR_GREYED_HILIGHT);
sprite = sprites[SL_LINE_NORMAL];
break;
default:
case OS_NORMAL:
_vm->_font->setColors(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
_vm->_font->current()->setColours(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
TEXT_COLOR_NORMAL_HILIGHT);
sprite = sprites[SL_LINE_NORMAL];
break;
@ -849,11 +849,11 @@ void MenuSaveLoadText::onRefresh() {
if (_displayValue != 0) {
char tempBuffer[5];
sprintf(tempBuffer, "%02d", _displayValue);
_vm->_font->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1);
_vm->_font->current()->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1);
xp = _bounds.left + 26;
}
_vm->_font->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1);
_vm->_font->current()->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1);
}
}
@ -955,18 +955,18 @@ void MenuTextField::onRefresh() {
// Draw the text
_vm->_font->setFont(FONT_MENU);
_vm->_font->setColors(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
_vm->_font->current()->setColours(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
TEXT_COLOR_NORMAL_HILIGHT);
int xp = _bounds.left + 4;
if (_displayValue != 0) {
char tempBuffer[5];
sprintf(tempBuffer, "%02d", _displayValue);
_vm->_font->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1);
_vm->_font->current()->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1);
xp = _bounds.left + 26;
}
_vm->_font->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1);
_vm->_font->current()->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1);
if (focused) {
// Draw in the cursor
@ -975,7 +975,7 @@ void MenuTextField::onRefresh() {
// Get the width of the string up to the cursor position
char tempCh = *_cursor;
*_cursor = '\0';
int stringWidth = _vm->_font->getWidth(_displayText);
int stringWidth = _vm->_font->current()->getWidth(_displayText);
*_cursor = tempCh;
parent()->setColor(TEXT_COLOR_MOUSEOVER_FOREGROUND);
@ -1015,10 +1015,10 @@ bool MenuTextField::onEvent(M4EventType event, int32 param, int x, int y, MenuOb
tempP = &tempStr[tempLen];
_vm->_font->setFont(FONT_MENU);
tempLen = _vm->_font->getWidth(tempStr);
tempLen = _vm->_font->current()->getWidth(tempStr);
while ((tempP != &tempStr[0]) && (tempLen > x - _bounds.left - 26)) {
*--tempP = '\0';
tempLen = _vm->_font->getWidth(tempStr);
tempLen = _vm->_font->current()->getWidth(tempStr);
}
_cursor = &_displayText[tempP - &tempStr[0]];
@ -1098,7 +1098,7 @@ bool MenuTextField::onEvent(M4EventType event, int32 param, int x, int y, MenuOb
parent()->_deleteSaveDesc = false;
_vm->_font->setFont(FONT_MENU);
tempLen = _vm->_font->getWidth(_displayText);
tempLen = _vm->_font->current()->getWidth(_displayText);
if ((strlen(_displayText) < MAX_SAVEGAME_NAME - 1) &&
(tempLen < _pixelWidth - 12) && (param >= 32) && (param <= 127)) {
@ -1140,9 +1140,9 @@ GUITextField::GUITextField(View *owner, const Common::Rect &bounds): GUIRect(own
void GUITextField::onRefresh() {
_parent->fillRect(_bounds, _vm->_palette->BLACK);
_vm->_font->setColors(3, 3, 3);
_vm->_font->current()->setColours(3, 3, 3);
_vm->_font->setFont(FONT_INTERFACE);
_vm->_font->writeString(_parent, _text.c_str(), _bounds.left, _bounds.top, 0, 1);
_vm->_font->current()->writeString(_parent, _text.c_str(), _bounds.left, _bounds.top, 0, 1);
}
//--------------------------------------------------------------------------

View File

@ -145,7 +145,6 @@ MadsM4Engine::~MadsM4Engine() {
delete _script;
delete _ws;
delete _random;
delete _animation;
delete _palette;
delete _globals;
delete _sound;
@ -174,7 +173,7 @@ Common::Error MadsM4Engine::run() {
_events = new Events(this);
_kernel = new Kernel(this);
_player = new Player(this);
_font = new Font(this);
_font = new FontManager(this);
if (getGameType() == GType_Burger) {
_actor = new Actor(this);
_conversationView = new ConversationView(this);
@ -188,7 +187,6 @@ Common::Error MadsM4Engine::run() {
_sound = new Sound(this, _mixer, 255);
_script = new ScriptInterpreter(this);
_ws = new WoodScript(this);
_animation = new Animation(this);
//_callbacks = new Callbacks(this);
_random = new Common::RandomSource();
g_eventRec.registerRandomSource(*_random, "m4");
@ -557,9 +555,9 @@ Common::Error MadsEngine::run() {
_scene->show();
_font->setFont(FONT_MAIN_MADS);
_font->setColors(2, 1, 3);
_font->writeString(_scene->getBackgroundSurface(), "Testing the M4/MADS ScummVM engine", 5, 160, 310, 2);
_font->writeString(_scene->getBackgroundSurface(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 5, 180, 310, 2);
_font->current()->setColours(2, 1, 3);
_font->current()->writeString(_scene->getBackgroundSurface(), "Testing the M4/MADS ScummVM engine", 5, 160, 310, 2);
_font->current()->writeString(_scene->getBackgroundSurface(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 5, 180, 310, 2);
if (getGameType() == GType_DragonSphere) {
//_scene->showMADSV2TextBox("Test", 10, 10, NULL);
@ -575,8 +573,6 @@ Common::Error MadsEngine::run() {
while (!_events->quitFlag) {
eventHandler();
_animation->updateAnim();
if (g_system->getMillis() >= nextFrame) {
nextFrame = g_system->getMillis() + GAME_FRAME_DELAY;
++_currentTimer;

View File

@ -192,7 +192,7 @@ public:
Player *_player;
Mouse *_mouse;
Events *_events;
Font *_font;
FontManager *_font;
Actor *_actor;
Scene *_scene;
Dialogs *_dialogs;
@ -203,7 +203,6 @@ public:
Rails *_rails;
ScriptInterpreter *_script;
WoodScript *_ws;
Animation *_animation;
Common::RandomSource *_random;
Scene *scene() { return _scene; }

View File

@ -34,7 +34,7 @@ namespace M4 {
GUIInventory::GUIInventory(View *owner, MadsM4Engine *vm, const Common::Rect &bounds, int horizCells,
int vertCells, int cellWidth, int cellHeight, int tag): GUIRect(owner, bounds, tag) {
_vm = vm;
_vm = vm;
_cellCount.x = horizCells;
_cellCount.y = vertCells;
_cellSize.x = cellWidth;

View File

@ -37,7 +37,7 @@ namespace M4 {
TextviewView::TextviewView(MadsM4Engine *vm):
View(vm, Common::Rect(0, 0, vm->_screen->width(), vm->_screen->height())),
_bgSurface(vm->_screen->width(), MADS_SURFACE_HEIGHT),
_textSurface(vm->_screen->width(), MADS_SURFACE_HEIGHT + vm->_font->getHeight() +
_textSurface(vm->_screen->width(), MADS_SURFACE_HEIGHT + vm->_font->current()->getHeight() +
TEXTVIEW_LINE_SPACING) {
_screenType = VIEWID_TEXTVIEW;
@ -60,7 +60,7 @@ TextviewView::TextviewView(MadsM4Engine *vm):
_vm->_palette->setPalette(&palData[0], 4, 3);
_vm->_palette->blockRange(4, 3);
_vm->_font->setColors(5, 6, 4);
_vm->_font->current()->setColours(5, 6, 4);
clear();
_bgSurface.clear();
@ -222,7 +222,7 @@ void TextviewView::updateState() {
}
} else {
// Handling a text row
if (++_lineY == (_vm->_font->getHeight() + TEXTVIEW_LINE_SPACING))
if (++_lineY == (_vm->_font->current()->getHeight() + TEXTVIEW_LINE_SPACING))
processLines();
}
@ -404,7 +404,7 @@ void TextviewView::processText() {
if (!strcmp(_currentLine, "***")) {
// Special signifier for end of script
_scrollCount = _vm->_font->getHeight() * 13;
_scrollCount = _vm->_font->current()->getHeight() * 13;
_lineY = -1;
return;
}
@ -416,7 +416,7 @@ void TextviewView::processText() {
char *centerP = strchr(_currentLine, '@');
if (centerP) {
*centerP = '\0';
xStart = (width() / 2) - _vm->_font->getWidth(_currentLine);
xStart = (width() / 2) - _vm->_font->current()->getWidth(_currentLine);
// Delete the @ character and shift back the remainder of the string
char *p = centerP + 1;
@ -424,16 +424,16 @@ void TextviewView::processText() {
strcpy(centerP, p);
} else {
lineWidth = _vm->_font->getWidth(_currentLine);
lineWidth = _vm->_font->current()->getWidth(_currentLine);
xStart = (width() - lineWidth) / 2;
}
// Copy the text line onto the bottom of the textSurface surface, which will allow it
// to gradually scroll onto the screen
int yp = _textSurface.height() - _vm->_font->getHeight() - TEXTVIEW_LINE_SPACING;
int yp = _textSurface.height() - _vm->_font->current()->getHeight() - TEXTVIEW_LINE_SPACING;
_textSurface.fillRect(Common::Rect(0, yp, _textSurface.width(), _textSurface.height()),
_vm->_palette->BLACK);
_vm->_font->writeString(&_textSurface, _currentLine, xStart, yp);
_vm->_font->current()->writeString(&_textSurface, _currentLine, xStart, yp);
}

View File

@ -617,10 +617,10 @@ void RexDialogView::initialiseLines() {
}
_totalTextEntries = 0;
// Set up a default sprite slot entry
// Set up a default sprite slot entry for a full screen refresh
_spriteSlots.startIndex = 1;
_spriteSlots[0].spriteId = -2;
_spriteSlots[0].timerIndex = -1;
_spriteSlots[0].spriteType = FULL_SCREEN_REFRESH;
_spriteSlots[0].seqIndex = -1;
}
void RexDialogView::initialiseGraphics() {
@ -796,8 +796,8 @@ bool RexDialogView::onEvent(M4EventType eventType, int32 param1, int x, int y, b
void RexDialogView::setFrame(int frameNumber, int depth) {
int slotIndex = _spriteSlots.getIndex();
_spriteSlots[slotIndex].spriteId = 1;
_spriteSlots[slotIndex].timerIndex = 1;
_spriteSlots[slotIndex].spriteType = FOREGROUND_SPRITE;
_spriteSlots[slotIndex].seqIndex = 1;
_spriteSlots[slotIndex].spriteListIndex = 0; //_menuSpritesIndex;
_spriteSlots[slotIndex].frameNumber = frameNumber;
@ -986,15 +986,15 @@ RexGameMenuDialog::RexGameMenuDialog(): RexDialogView() {
void RexGameMenuDialog::addLines() {
// Add the title
int top = MADS_Y_OFFSET - 2 - ((((_vm->_font->getHeight() + 2) * 6) >> 1) - 78);
int top = MADS_Y_OFFSET - 2 - ((((_vm->_font->current()->getHeight() + 2) * 6) >> 1) - 78);
addQuote(_vm->_font, ALIGN_CENTER, 0, top, 10);
addQuote(_vm->_font->current(), ALIGN_CENTER, 0, top, 10);
// Loop for adding the option lines of the dialog
top += 6;
for (int idx = 0; idx < 5; ++idx) {
top += _vm->_font->getHeight() + 1;
addQuote(_vm->_font, ALIGN_CENTER, 0, top, 11 + idx);
top += _vm->_font->current()->getHeight() + 1;
addQuote(_vm->_font->current(), ALIGN_CENTER, 0, top, 11 + idx);
}
}
@ -1070,42 +1070,42 @@ void RexOptionsDialog::reload() {
void RexOptionsDialog::addLines() {
// Add the title
int top = MADS_Y_OFFSET - 2 - ((((_vm->_font->getHeight() + 1) * 9 + 12) >> 1) - 78);
int top = MADS_Y_OFFSET - 2 - ((((_vm->_font->current()->getHeight() + 1) * 9 + 12) >> 1) - 78);
addQuote(_vm->_font, ALIGN_CENTER, 0, top, 16);
addQuote(_vm->_font->current(), ALIGN_CENTER, 0, top, 16);
// Music state line
top += _vm->_font->getHeight() + 1 + 6;
addQuote(_vm->_font, ALIGN_CHAR_CENTER, 0, top, 17, _tempConfig.musicFlag ? 24 : 25);
top += _vm->_font->current()->getHeight() + 1 + 6;
addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 17, _tempConfig.musicFlag ? 24 : 25);
// Sound state line
top += _vm->_font->getHeight() + 1;
addQuote(_vm->_font, ALIGN_CHAR_CENTER, 0, top, 18, _tempConfig.soundFlag ? 26 : 27);
top += _vm->_font->current()->getHeight() + 1;
addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 18, _tempConfig.soundFlag ? 26 : 27);
// Interface easy state line
top += _vm->_font->getHeight() + 1;
addQuote(_vm->_font, ALIGN_CHAR_CENTER, 0, top, 19, _tempConfig.easyMouse ? 29 : 28);
top += _vm->_font->current()->getHeight() + 1;
addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 19, _tempConfig.easyMouse ? 29 : 28);
// Inventory sppinng state line
top += _vm->_font->getHeight() + 1;
addQuote(_vm->_font, ALIGN_CHAR_CENTER, 0, top, 20, _tempConfig.invObjectsStill ? 31 : 30);
top += _vm->_font->current()->getHeight() + 1;
addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 20, _tempConfig.invObjectsStill ? 31 : 30);
// Text window state line
top += _vm->_font->getHeight() + 1;
addQuote(_vm->_font, ALIGN_CHAR_CENTER, 0, top, 21, _tempConfig.textWindowStill ? 33 : 32);
top += _vm->_font->current()->getHeight() + 1;
addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 21, _tempConfig.textWindowStill ? 33 : 32);
// Screen fade state line
top += _vm->_font->getHeight() + 1;
addQuote(_vm->_font, ALIGN_CHAR_CENTER, 0, top, 22, _tempConfig.screenFades + 34);
top += _vm->_font->current()->getHeight() + 1;
addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 22, _tempConfig.screenFades + 34);
// Storyline mode line
top += _vm->_font->getHeight() + 1;
addQuote(_vm->_font, ALIGN_CHAR_CENTER, 0, top, 23, (_tempConfig.storyMode == 1) ? 37 : 38);
top += _vm->_font->current()->getHeight() + 1;
addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 23, (_tempConfig.storyMode == 1) ? 37 : 38);
// Add Done and Cancel button texts
top += _vm->_font->getHeight() + 1 + 6;
addQuote(_vm->_font, ALIGN_CENTER, -54, top, 1, 0);
addQuote(_vm->_font, ALIGN_CENTER, 54, top, 2, 0);
top += _vm->_font->current()->getHeight() + 1 + 6;
addQuote(_vm->_font->current(), ALIGN_CENTER, -54, top, 1, 0);
addQuote(_vm->_font->current(), ALIGN_CENTER, 54, top, 2, 0);
}
bool RexOptionsDialog::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) {

View File

@ -1,286 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "mohawk/video/cinepak.h"
#include "common/system.h"
#include "graphics/conversion.h" // For YUV2RGB
// Code here partially based off of ffmpeg ;)
namespace Mohawk {
#define PUT_PIXEL(offset, lum, u, v) \
Graphics::CPYUV2RGB(lum, u, v, r, g, b); \
if (_pixelFormat.bytesPerPixel == 2) \
*((uint16 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b); \
else \
*((uint32 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b)
CinepakDecoder::CinepakDecoder() : Graphics::Codec() {
_curFrame.surface = NULL;
_curFrame.strips = NULL;
_y = 0;
_pixelFormat = g_system->getScreenFormat();
// We're going to have to dither if we're running in 8bpp.
// We'll take RGBA8888 for best color performance in this case.
if (_pixelFormat.bytesPerPixel == 1)
_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
}
CinepakDecoder::~CinepakDecoder() {
if (_curFrame.surface)
_curFrame.surface->free();
delete[] _curFrame.strips;
}
Graphics::Surface *CinepakDecoder::decodeImage(Common::SeekableReadStream *stream) {
_curFrame.flags = stream->readByte();
_curFrame.length = (stream->readByte() << 16) + stream->readUint16BE();
_curFrame.width = stream->readUint16BE();
_curFrame.height = stream->readUint16BE();
_curFrame.stripCount = stream->readUint16BE();
if (_curFrame.strips == NULL)
_curFrame.strips = new CinepakStrip[_curFrame.stripCount];
debug (4, "Cinepak Frame: Width = %d, Height = %d, Strip Count = %d", _curFrame.width, _curFrame.height, _curFrame.stripCount);
#if 0
// Borrowed from FFMPEG. This should cut out the extra data Cinepak for Sega has (which is useless).
// The theory behind this is that this is here to confuse standard Cinepak decoders. But, we won't let that happen! ;)
if (_curFrame.length != (uint32)stream->size()) {
if (stream->readUint16BE() == 0xFE00)
stream->readUint32BE();
}
#endif
if (!_curFrame.surface) {
_curFrame.surface = new Graphics::Surface();
_curFrame.surface->create(_curFrame.width, _curFrame.height, _pixelFormat.bytesPerPixel);
}
// Reset the y variable.
_y = 0;
for (uint16 i = 0; i < _curFrame.stripCount; i++) {
if (i > 0 && !(_curFrame.flags & 1)) { // Use codebooks from last strip
for (uint16 j = 0; j < 256; j++) {
_curFrame.strips[i].v1_codebook[j] = _curFrame.strips[i - 1].v1_codebook[j];
_curFrame.strips[i].v4_codebook[j] = _curFrame.strips[i - 1].v4_codebook[j];
}
}
_curFrame.strips[i].id = stream->readUint16BE();
_curFrame.strips[i].length = stream->readUint16BE() - 12; // Subtract the 12 byte header
_curFrame.strips[i].rect.top = _y; stream->readUint16BE(); // Ignore, substitute with our own.
_curFrame.strips[i].rect.left = 0; stream->readUint16BE(); // Ignore, substitute with our own
_curFrame.strips[i].rect.bottom = _y + stream->readUint16BE();
_curFrame.strips[i].rect.right = _curFrame.width; stream->readUint16BE(); // Ignore, substitute with our own
//printf ("Left = %d, Top = %d, Right = %d, Bottom = %d\n", _curFrame.strips[i].rect.left, _curFrame.strips[i].rect.top, _curFrame.strips[i].rect.right, _curFrame.strips[i].rect.bottom);
// Sanity check. Because Cinepak is based on 4x4 blocks, the width and height of each strip needs to be divisible by 4.
assert(!(_curFrame.strips[i].rect.width() % 4) && !(_curFrame.strips[i].rect.height() % 4));
uint32 pos = stream->pos();
while ((uint32)stream->pos() < (pos + _curFrame.strips[i].length) && !stream->eos()) {
byte chunkID = stream->readByte();
if (stream->eos())
break;
// Chunk Size is 24-bit, ignore the first 4 bytes
uint32 chunkSize = stream->readByte() << 16;
chunkSize += stream->readUint16BE() - 4;
int32 startPos = stream->pos();
switch (chunkID) {
case 0x20:
case 0x21:
case 0x24:
case 0x25:
loadCodebook(stream, i, 4, chunkID, chunkSize);
break;
case 0x22:
case 0x23:
case 0x26:
case 0x27:
loadCodebook(stream, i, 1, chunkID, chunkSize);
break;
case 0x30:
case 0x31:
case 0x32:
decodeVectors(stream, i, chunkID, chunkSize);
break;
default:
warning("Unknown Cinepak chunk ID %02x", chunkID);
return _curFrame.surface;
}
if (stream->pos() != startPos + (int32)chunkSize)
stream->seek(startPos + chunkSize);
}
_y = _curFrame.strips[i].rect.bottom;
}
return _curFrame.surface;
}
void CinepakDecoder::loadCodebook(Common::SeekableReadStream *stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize) {
CinepakCodebook *codebook = (codebookType == 1) ? _curFrame.strips[strip].v1_codebook : _curFrame.strips[strip].v4_codebook;
int32 startPos = stream->pos();
uint32 flag = 0, mask = 0;
for (uint16 i = 0; i < 256; i++) {
if ((chunkID & 0x01) && !(mask >>= 1)) {
if ((stream->pos() - startPos + 4) > (int32)chunkSize)
break;
flag = stream->readUint32BE();
mask = 0x80000000;
}
if (!(chunkID & 0x01) || (flag & mask)) {
byte n = (chunkID & 0x04) ? 4 : 6;
if ((stream->pos() - startPos + n) > (int32)chunkSize)
break;
for (byte j = 0; j < 4; j++)
codebook[i].y[j] = stream->readByte();
if (n == 6) {
codebook[i].u = stream->readByte() + 128;
codebook[i].v = stream->readByte() + 128;
} else {
/* this codebook type indicates either greyscale or
* palettized video; if palettized, U & V components will
* not be used so it is safe to set them to 128 for the
* benefit of greyscale rendering in YUV420P */
codebook[i].u = 128;
codebook[i].v = 128;
}
}
}
}
void CinepakDecoder::decodeVectors(Common::SeekableReadStream *stream, uint16 strip, byte chunkID, uint32 chunkSize) {
uint32 flag = 0, mask = 0;
uint32 iy[4];
int32 startPos = stream->pos();
byte r = 0, g = 0, b = 0;
for (uint16 y = _curFrame.strips[strip].rect.top; y < _curFrame.strips[strip].rect.bottom; y += 4) {
iy[0] = _curFrame.strips[strip].rect.left + y * _curFrame.width;
iy[1] = iy[0] + _curFrame.width;
iy[2] = iy[1] + _curFrame.width;
iy[3] = iy[2] + _curFrame.width;
for (uint16 x = _curFrame.strips[strip].rect.left; x < _curFrame.strips[strip].rect.right; x += 4) {
if ((chunkID & 0x01) && !(mask >>= 1)) {
if ((stream->pos() - startPos + 4) > (int32)chunkSize)
return;
flag = stream->readUint32BE();
mask = 0x80000000;
}
if (!(chunkID & 0x01) || (flag & mask)) {
if (!(chunkID & 0x02) && !(mask >>= 1)) {
if ((stream->pos() - startPos + 4) > (int32)chunkSize)
return;
flag = stream->readUint32BE();
mask = 0x80000000;
}
if ((chunkID & 0x02) || (~flag & mask)) {
if ((stream->pos() - startPos + 1) > (int32)chunkSize)
return;
// Get the codebook
CinepakCodebook codebook = _curFrame.strips[strip].v1_codebook[stream->readByte()];
PUT_PIXEL(iy[0] + 0, codebook.y[0], codebook.u, codebook.v);
PUT_PIXEL(iy[0] + 1, codebook.y[0], codebook.u, codebook.v);
PUT_PIXEL(iy[1] + 0, codebook.y[0], codebook.u, codebook.v);
PUT_PIXEL(iy[1] + 1, codebook.y[0], codebook.u, codebook.v);
PUT_PIXEL(iy[0] + 2, codebook.y[1], codebook.u, codebook.v);
PUT_PIXEL(iy[0] + 3, codebook.y[1], codebook.u, codebook.v);
PUT_PIXEL(iy[1] + 2, codebook.y[1], codebook.u, codebook.v);
PUT_PIXEL(iy[1] + 3, codebook.y[1], codebook.u, codebook.v);
PUT_PIXEL(iy[2] + 0, codebook.y[2], codebook.u, codebook.v);
PUT_PIXEL(iy[2] + 1, codebook.y[2], codebook.u, codebook.v);
PUT_PIXEL(iy[3] + 0, codebook.y[2], codebook.u, codebook.v);
PUT_PIXEL(iy[3] + 1, codebook.y[2], codebook.u, codebook.v);
PUT_PIXEL(iy[2] + 2, codebook.y[3], codebook.u, codebook.v);
PUT_PIXEL(iy[2] + 3, codebook.y[3], codebook.u, codebook.v);
PUT_PIXEL(iy[3] + 2, codebook.y[3], codebook.u, codebook.v);
PUT_PIXEL(iy[3] + 3, codebook.y[3], codebook.u, codebook.v);
} else if (flag & mask) {
if ((stream->pos() - startPos + 4) > (int32)chunkSize)
return;
CinepakCodebook codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
PUT_PIXEL(iy[0] + 0, codebook.y[0], codebook.u, codebook.v);
PUT_PIXEL(iy[0] + 1, codebook.y[1], codebook.u, codebook.v);
PUT_PIXEL(iy[1] + 0, codebook.y[2], codebook.u, codebook.v);
PUT_PIXEL(iy[1] + 1, codebook.y[3], codebook.u, codebook.v);
codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
PUT_PIXEL(iy[0] + 2, codebook.y[0], codebook.u, codebook.v);
PUT_PIXEL(iy[0] + 3, codebook.y[1], codebook.u, codebook.v);
PUT_PIXEL(iy[1] + 2, codebook.y[2], codebook.u, codebook.v);
PUT_PIXEL(iy[1] + 3, codebook.y[3], codebook.u, codebook.v);
codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
PUT_PIXEL(iy[2] + 0, codebook.y[0], codebook.u, codebook.v);
PUT_PIXEL(iy[2] + 1, codebook.y[1], codebook.u, codebook.v);
PUT_PIXEL(iy[3] + 0, codebook.y[2], codebook.u, codebook.v);
PUT_PIXEL(iy[3] + 1, codebook.y[3], codebook.u, codebook.v);
codebook = _curFrame.strips[strip].v4_codebook[stream->readByte()];
PUT_PIXEL(iy[2] + 2, codebook.y[0], codebook.u, codebook.v);
PUT_PIXEL(iy[2] + 3, codebook.y[1], codebook.u, codebook.v);
PUT_PIXEL(iy[3] + 2, codebook.y[2], codebook.u, codebook.v);
PUT_PIXEL(iy[3] + 3, codebook.y[3], codebook.u, codebook.v);
}
}
for (byte i = 0; i < 4; i++)
iy[i] += 4;
}
}
}
} // End of namespace Mohawk

View File

@ -1,81 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef CINEPAK_H
#define CINEPAK_H
#include "common/scummsys.h"
#include "common/stream.h"
#include "common/rect.h"
#include "graphics/surface.h"
#include "graphics/pixelformat.h"
#include "graphics/video/codecs/codec.h"
namespace Mohawk {
struct CinepakCodebook {
byte y[4];
byte u, v;
};
struct CinepakStrip {
uint16 id;
uint16 length;
Common::Rect rect;
CinepakCodebook v1_codebook[256], v4_codebook[256];
};
struct CinepakFrame {
byte flags;
uint32 length;
uint16 width;
uint16 height;
uint16 stripCount;
CinepakStrip *strips;
Graphics::Surface *surface;
};
class CinepakDecoder : public Graphics::Codec {
public:
CinepakDecoder();
~CinepakDecoder();
Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
private:
CinepakFrame _curFrame;
int32 _y;
Graphics::PixelFormat _pixelFormat;
void loadCodebook(Common::SeekableReadStream *stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize);
void decodeVectors(Common::SeekableReadStream *stream, uint16 strip, byte chunkID, uint32 chunkSize);
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,289 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MOHAWK_VIDEO_QDM2_H
#define MOHAWK_VIDEO_QDM2_H
#include "sound/audiostream.h"
#include "common/array.h"
#include "common/stream.h"
namespace Mohawk {
enum {
SOFTCLIP_THRESHOLD = 27600,
HARDCLIP_THRESHOLD = 35716,
MPA_MAX_CHANNELS = 2,
MPA_FRAME_SIZE = 1152,
FF_INPUT_BUFFER_PADDING_SIZE = 8
};
typedef int8 sb_int8_array[2][30][64];
/* bit input */
/* buffer, buffer_end and size_in_bits must be present and used by every reader */
struct GetBitContext {
const uint8 *buffer, *bufferEnd;
int index;
int sizeInBits;
};
struct QDM2SubPacket {
int type;
unsigned int size;
const uint8 *data; // pointer to subpacket data (points to input data buffer, it's not a private copy)
};
struct QDM2SubPNode {
QDM2SubPacket *packet;
struct QDM2SubPNode *next; // pointer to next packet in the list, NULL if leaf node
};
struct QDM2Complex {
float re;
float im;
};
struct FFTTone {
float level;
QDM2Complex *complex;
const float *table;
int phase;
int phase_shift;
int duration;
short time_index;
short cutoff;
};
struct FFTCoefficient {
int16 sub_packet;
uint8 channel;
int16 offset;
int16 exp;
uint8 phase;
};
struct VLC {
int32 bits;
int16 (*table)[2]; // code, bits
int32 table_size;
int32 table_allocated;
};
#include "common/pack-start.h"
struct QDM2FFT {
QDM2Complex complex[MPA_MAX_CHANNELS][256];
} PACKED_STRUCT;
#include "common/pack-end.h"
enum RDFTransformType {
RDFT,
IRDFT,
RIDFT,
IRIDFT
};
struct FFTComplex {
float re, im;
};
struct FFTContext {
int nbits;
int inverse;
uint16 *revtab;
FFTComplex *exptab;
FFTComplex *tmpBuf;
int mdctSize; // size of MDCT (i.e. number of input data * 2)
int mdctBits; // n = 2^nbits
// pre/post rotation tables
float *tcos;
float *tsin;
void (*fftPermute)(struct FFTContext *s, FFTComplex *z);
void (*fftCalc)(struct FFTContext *s, FFTComplex *z);
void (*imdctCalc)(struct FFTContext *s, float *output, const float *input);
void (*imdctHalf)(struct FFTContext *s, float *output, const float *input);
void (*mdctCalc)(struct FFTContext *s, float *output, const float *input);
int splitRadix;
int permutation;
};
enum {
FF_MDCT_PERM_NONE = 0,
FF_MDCT_PERM_INTERLEAVE = 1
};
struct RDFTContext {
int nbits;
int inverse;
int signConvention;
// pre/post rotation tables
float *tcos;
float *tsin;
FFTContext fft;
};
class QDM2Stream : public Audio::AudioStream {
public:
QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData);
~QDM2Stream();
bool isStereo() const { return _channels == 2; }
bool endOfData() const { return ((_stream->pos() == _stream->size()) && (_outputSamples.size() == 0)); }
int getRate() const { return _sampleRate; }
int readBuffer(int16 *buffer, const int numSamples);
private:
Common::SeekableReadStream *_stream;
// Parameters from codec header, do not change during playback
uint8 _channels;
uint16 _sampleRate;
uint16 _bitRate;
uint16 _blockSize; // Group
uint16 _frameSize; // FFT
uint16 _packetSize; // Checksum
// Parameters built from header parameters, do not change during playback
int _groupOrder; // order of frame group
int _fftOrder; // order of FFT (actually fft order+1)
int _fftFrameSize; // size of fft frame, in components (1 comples = re + im)
int _sFrameSize; // size of data frame
int _frequencyRange;
int _subSampling; // subsampling: 0=25%, 1=50%, 2=100% */
int _coeffPerSbSelect; // selector for "num. of coeffs. per subband" tables. Can be 0, 1, 2
int _cmTableSelect; // selector for "coding method" tables. Can be 0, 1 (from init: 0-4)
// Packets and packet lists
QDM2SubPacket _subPackets[16]; // the packets themselves
QDM2SubPNode _subPacketListA[16]; // list of all packets
QDM2SubPNode _subPacketListB[16]; // FFT packets B are on list
int _subPacketsB; // number of packets on 'B' list
QDM2SubPNode _subPacketListC[16]; // packets with errors?
QDM2SubPNode _subPacketListD[16]; // DCT packets
// FFT and tones
FFTTone _fftTones[1000];
int _fftToneStart;
int _fftToneEnd;
FFTCoefficient _fftCoefs[1000];
int _fftCoefsIndex;
int _fftCoefsMinIndex[5];
int _fftCoefsMaxIndex[5];
int _fftLevelExp[6];
//RDFTContext _rdftCtx;
QDM2FFT _fft;
// I/O data
uint8 *_compressedData;
float _outputBuffer[1024];
Common::Array<int16> _outputSamples;
// Synthesis filter
int16 ff_mpa_synth_window[512];
int16 _synthBuf[MPA_MAX_CHANNELS][512*2];
int _synthBufOffset[MPA_MAX_CHANNELS];
int32 _sbSamples[MPA_MAX_CHANNELS][128][32];
// Mixed temporary data used in decoding
float _toneLevel[MPA_MAX_CHANNELS][30][64];
int8 _codingMethod[MPA_MAX_CHANNELS][30][64];
int8 _quantizedCoeffs[MPA_MAX_CHANNELS][10][8];
int8 _toneLevelIdxBase[MPA_MAX_CHANNELS][30][8];
int8 _toneLevelIdxHi1[MPA_MAX_CHANNELS][3][8][8];
int8 _toneLevelIdxMid[MPA_MAX_CHANNELS][26][8];
int8 _toneLevelIdxHi2[MPA_MAX_CHANNELS][26];
int8 _toneLevelIdx[MPA_MAX_CHANNELS][30][64];
int8 _toneLevelIdxTemp[MPA_MAX_CHANNELS][30][64];
// Flags
bool _hasErrors; // packet has errors
int _superblocktype_2_3; // select fft tables and some algorithm based on superblock type
int _doSynthFilter; // used to perform or skip synthesis filter
uint8 _subPacket; // 0 to 15
int _noiseIdx; // index for dithering noise table
byte _emptyBuffer[FF_INPUT_BUFFER_PADDING_SIZE];
VLC _vlcTabLevel;
VLC _vlcTabDiff;
VLC _vlcTabRun;
VLC _fftLevelExpAltVlc;
VLC _fftLevelExpVlc;
VLC _fftStereoExpVlc;
VLC _fftStereoPhaseVlc;
VLC _vlcTabToneLevelIdxHi1;
VLC _vlcTabToneLevelIdxMid;
VLC _vlcTabToneLevelIdxHi2;
VLC _vlcTabType30;
VLC _vlcTabType34;
VLC _vlcTabFftToneOffset[5];
bool _vlcsInitialized;
void initVlc(void);
uint16 _softclipTable[HARDCLIP_THRESHOLD - SOFTCLIP_THRESHOLD + 1];
void softclipTableInit(void);
float _noiseTable[4096];
byte _randomDequantIndex[256][5];
byte _randomDequantType24[128][3];
void rndTableInit(void);
float _noiseSamples[128];
void initNoiseSamples(void);
RDFTContext _rdftCtx;
void average_quantized_coeffs(void);
void build_sb_samples_from_noise(int sb);
void fix_coding_method_array(int sb, int channels, sb_int8_array coding_method);
void fill_tone_level_array(int flag);
void fill_coding_method_array(sb_int8_array tone_level_idx, sb_int8_array tone_level_idx_temp,
sb_int8_array coding_method, int nb_channels,
int c, int superblocktype_2_3, int cm_table_select);
void synthfilt_build_sb_samples(GetBitContext *gb, int length, int sb_min, int sb_max);
void init_quantized_coeffs_elem0(int8 *quantized_coeffs, GetBitContext *gb, int length);
void init_tone_level_dequantization(GetBitContext *gb, int length);
void process_subpacket_9(QDM2SubPNode *node);
void process_subpacket_10(QDM2SubPNode *node, int length);
void process_subpacket_11(QDM2SubPNode *node, int length);
void process_subpacket_12(QDM2SubPNode *node, int length);
void process_synthesis_subpackets(QDM2SubPNode *list);
void qdm2_decode_super_block(void);
void qdm2_fft_init_coefficient(int sub_packet, int offset, int duration,
int channel, int exp, int phase);
void qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b);
void qdm2_decode_fft_packets(void);
void qdm2_fft_generate_tone(FFTTone *tone);
void qdm2_fft_tone_synthesizer(uint8 sub_packet);
void qdm2_calculate_fft(int channel);
void qdm2_synthesis_filter(uint8 index);
int qdm2_decodeFrame(Common::SeekableReadStream *in);
};
} // End of namespace Mohawk
#endif

View File

@ -1,531 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MOHAWK_VIDEO_QDM2DATA_H
#define MOHAWK_VIDEO_QDM2DATA_H
#include "common/scummsys.h"
namespace Mohawk {
/// VLC TABLES
// values in this table range from -1..23; adjust retrieved value by -1
static const uint16 vlc_tab_level_huffcodes[24] = {
0x037c, 0x0004, 0x003c, 0x004c, 0x003a, 0x002c, 0x001c, 0x001a,
0x0024, 0x0014, 0x0001, 0x0002, 0x0000, 0x0003, 0x0007, 0x0005,
0x0006, 0x0008, 0x0009, 0x000a, 0x000c, 0x00fc, 0x007c, 0x017c
};
static const byte vlc_tab_level_huffbits[24] = {
10, 6, 7, 7, 6, 6, 6, 6, 6, 5, 4, 4, 4, 3, 3, 3, 3, 4, 4, 5, 7, 8, 9, 10
};
// values in this table range from -1..36; adjust retrieved value by -1
static const uint16 vlc_tab_diff_huffcodes[37] = {
0x1c57, 0x0004, 0x0000, 0x0001, 0x0003, 0x0002, 0x000f, 0x000e,
0x0007, 0x0016, 0x0037, 0x0027, 0x0026, 0x0066, 0x0006, 0x0097,
0x0046, 0x01c6, 0x0017, 0x0786, 0x0086, 0x0257, 0x00d7, 0x0357,
0x00c6, 0x0386, 0x0186, 0x0000, 0x0157, 0x0c57, 0x0057, 0x0000,
0x0b86, 0x0000, 0x1457, 0x0000, 0x0457
};
static const byte vlc_tab_diff_huffbits[37] = {
13, 3, 3, 2, 3, 3, 4, 4, 6, 5, 6, 6, 7, 7, 8, 8,
8, 9, 8, 11, 9, 10, 8, 10, 9, 12, 10, 0, 10, 13, 11, 0,
12, 0, 13, 0, 13
};
// values in this table range from -1..5; adjust retrieved value by -1
static const byte vlc_tab_run_huffcodes[6] = {
0x1f, 0x00, 0x01, 0x03, 0x07, 0x0f
};
static const byte vlc_tab_run_huffbits[6] = {
5, 1, 2, 3, 4, 5
};
// values in this table range from -1..19; adjust retrieved value by -1
static const uint16 vlc_tab_tone_level_idx_hi1_huffcodes[20] = {
0x5714, 0x000c, 0x0002, 0x0001, 0x0000, 0x0004, 0x0034, 0x0054,
0x0094, 0x0014, 0x0114, 0x0214, 0x0314, 0x0614, 0x0e14, 0x0f14,
0x2714, 0x0714, 0x1714, 0x3714
};
static const byte vlc_tab_tone_level_idx_hi1_huffbits[20] = {
15, 4, 2, 1, 3, 5, 6, 7, 8, 10, 10, 11, 11, 12, 12, 12, 14, 14, 15, 14
};
// values in this table range from -1..23; adjust retrieved value by -1
static const uint16 vlc_tab_tone_level_idx_mid_huffcodes[24] = {
0x0fea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x03ea, 0x00ea, 0x002a, 0x001a,
0x0006, 0x0001, 0x0000, 0x0002, 0x000a, 0x006a, 0x01ea, 0x07ea
};
static const byte vlc_tab_tone_level_idx_mid_huffbits[24] = {
12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 7, 5, 3, 1, 2, 4, 6, 8, 10, 12
};
// values in this table range from -1..23; adjust retrieved value by -1
static const uint16 vlc_tab_tone_level_idx_hi2_huffcodes[24] = {
0x0664, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0064, 0x00e4,
0x00a4, 0x0068, 0x0004, 0x0008, 0x0014, 0x0018, 0x0000, 0x0001,
0x0002, 0x0003, 0x000c, 0x0028, 0x0024, 0x0164, 0x0000, 0x0264
};
static const byte vlc_tab_tone_level_idx_hi2_huffbits[24] = {
11, 0, 0, 0, 0, 0, 10, 8, 8, 7, 6, 6, 5, 5, 4, 2, 2, 2, 4, 7, 8, 9, 0, 11
};
// values in this table range from -1..8; adjust retrieved value by -1
static const byte vlc_tab_type30_huffcodes[9] = {
0x3c, 0x06, 0x00, 0x01, 0x03, 0x02, 0x04, 0x0c, 0x1c
};
static const byte vlc_tab_type30_huffbits[9] = {
6, 3, 3, 2, 2, 3, 4, 5, 6
};
// values in this table range from -1..9; adjust retrieved value by -1
static const byte vlc_tab_type34_huffcodes[10] = {
0x18, 0x00, 0x01, 0x04, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08
};
static const byte vlc_tab_type34_huffbits[10] = {
5, 4, 3, 3, 3, 3, 3, 3, 3, 5
};
// values in this table range from -1..22; adjust retrieved value by -1
static const uint16 vlc_tab_fft_tone_offset_0_huffcodes[23] = {
0x038e, 0x0001, 0x0000, 0x0022, 0x000a, 0x0006, 0x0012, 0x0002,
0x001e, 0x003e, 0x0056, 0x0016, 0x000e, 0x0032, 0x0072, 0x0042,
0x008e, 0x004e, 0x00f2, 0x002e, 0x0036, 0x00c2, 0x018e
};
static const byte vlc_tab_fft_tone_offset_0_huffbits[23] = {
10, 1, 2, 6, 4, 5, 6, 7, 6, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 6, 6, 8, 10
};
// values in this table range from -1..27; adjust retrieved value by -1
static const uint16 vlc_tab_fft_tone_offset_1_huffcodes[28] = {
0x07a4, 0x0001, 0x0020, 0x0012, 0x001c, 0x0008, 0x0006, 0x0010,
0x0000, 0x0014, 0x0004, 0x0032, 0x0070, 0x000c, 0x0002, 0x003a,
0x001a, 0x002c, 0x002a, 0x0022, 0x0024, 0x000a, 0x0064, 0x0030,
0x0062, 0x00a4, 0x01a4, 0x03a4
};
static const byte vlc_tab_fft_tone_offset_1_huffbits[28] = {
11, 1, 6, 6, 5, 4, 3, 6, 6, 5, 6, 6, 7, 6, 6, 6,
6, 6, 6, 7, 8, 6, 7, 7, 7, 9, 10, 11
};
// values in this table range from -1..31; adjust retrieved value by -1
static const uint16 vlc_tab_fft_tone_offset_2_huffcodes[32] = {
0x1760, 0x0001, 0x0000, 0x0082, 0x000c, 0x0006, 0x0003, 0x0007,
0x0008, 0x0004, 0x0010, 0x0012, 0x0022, 0x001a, 0x0000, 0x0020,
0x000a, 0x0040, 0x004a, 0x006a, 0x002a, 0x0042, 0x0002, 0x0060,
0x00aa, 0x00e0, 0x00c2, 0x01c2, 0x0160, 0x0360, 0x0760, 0x0f60
};
static const byte vlc_tab_fft_tone_offset_2_huffbits[32] = {
13, 2, 0, 8, 4, 3, 3, 3, 4, 4, 5, 5, 6, 5, 7, 7,
7, 7, 7, 7, 8, 8, 8, 9, 8, 8, 9, 9, 10, 11, 13, 12
};
// values in this table range from -1..34; adjust retrieved value by -1
static const uint16 vlc_tab_fft_tone_offset_3_huffcodes[35] = {
0x33ea, 0x0005, 0x0000, 0x000c, 0x0000, 0x0006, 0x0003, 0x0008,
0x0002, 0x0001, 0x0004, 0x0007, 0x001a, 0x000f, 0x001c, 0x002c,
0x000a, 0x001d, 0x002d, 0x002a, 0x000d, 0x004c, 0x008c, 0x006a,
0x00cd, 0x004d, 0x00ea, 0x020c, 0x030c, 0x010c, 0x01ea, 0x07ea,
0x0bea, 0x03ea, 0x13ea
};
static const byte vlc_tab_fft_tone_offset_3_huffbits[35] = {
14, 4, 0, 10, 4, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6,
6, 5, 6, 7, 7, 7, 8, 8, 8, 8, 9, 10, 10, 10, 10, 11,
12, 13, 14
};
// values in this table range from -1..37; adjust retrieved value by -1
static const uint16 vlc_tab_fft_tone_offset_4_huffcodes[38] = {
0x5282, 0x0016, 0x0000, 0x0136, 0x0004, 0x0000, 0x0007, 0x000a,
0x000e, 0x0003, 0x0001, 0x000d, 0x0006, 0x0009, 0x0012, 0x0005,
0x0025, 0x0022, 0x0015, 0x0002, 0x0076, 0x0035, 0x0042, 0x00c2,
0x0182, 0x00b6, 0x0036, 0x03c2, 0x0482, 0x01c2, 0x0682, 0x0882,
0x0a82, 0x0082, 0x0282, 0x1282, 0x3282, 0x2282
};
static const byte vlc_tab_fft_tone_offset_4_huffbits[38] = {
15, 6, 0, 9, 3, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6,
6, 6, 6, 8, 7, 6, 8, 9, 9, 8, 9, 10, 11, 10, 11, 12,
12, 12, 14, 15, 14, 14
};
/// FFT TABLES
// values in this table range from -1..27; adjust retrieved value by -1
static const uint16 fft_level_exp_alt_huffcodes[28] = {
0x1ec6, 0x0006, 0x00c2, 0x0142, 0x0242, 0x0246, 0x00c6, 0x0046,
0x0042, 0x0146, 0x00a2, 0x0062, 0x0026, 0x0016, 0x000e, 0x0005,
0x0004, 0x0003, 0x0000, 0x0001, 0x000a, 0x0012, 0x0002, 0x0022,
0x01c6, 0x02c6, 0x06c6, 0x0ec6
};
static const byte fft_level_exp_alt_huffbits[28] = {
13, 7, 8, 9, 10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3,
3, 2, 3, 3, 4, 5, 7, 8, 9, 11, 12, 13
};
// values in this table range from -1..19; adjust retrieved value by -1
static const uint16 fft_level_exp_huffcodes[20] = {
0x0f24, 0x0001, 0x0002, 0x0000, 0x0006, 0x0005, 0x0007, 0x000c,
0x000b, 0x0014, 0x0013, 0x0004, 0x0003, 0x0023, 0x0064, 0x00a4,
0x0024, 0x0124, 0x0324, 0x0724
};
static const byte fft_level_exp_huffbits[20] = {
12, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 10, 11, 12
};
// values in this table range from -1..6; adjust retrieved value by -1
static const byte fft_stereo_exp_huffcodes[7] = {
0x3e, 0x01, 0x00, 0x02, 0x06, 0x0e, 0x1e
};
static const byte fft_stereo_exp_huffbits[7] = {
6, 1, 2, 3, 4, 5, 6
};
// values in this table range from -1..8; adjust retrieved value by -1
static const byte fft_stereo_phase_huffcodes[9] = {
0x35, 0x02, 0x00, 0x01, 0x0d, 0x15, 0x05, 0x09, 0x03
};
static const byte fft_stereo_phase_huffbits[9] = {
6, 2, 2, 4, 4, 6, 5, 4, 2
};
static const int fft_cutoff_index_table[4][2] = {
{ 1, 2 }, {-1, 0 }, {-1,-2 }, { 0, 0 }
};
static const int16 fft_level_index_table[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
};
static const byte last_coeff[3] = {
4, 7, 10
};
static const byte coeff_per_sb_for_avg[3][30] = {
{ 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
{ 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
{ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9 }
};
static const uint32 dequant_table[3][10][30] = {
{ { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 256, 256, 205, 154, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 51, 102, 154, 205, 256, 238, 219, 201, 183, 165, 146, 128, 110, 91, 73, 55, 37, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 18, 37, 55, 73, 91, 110, 128, 146, 165, 183, 201, 219, 238, 256, 228, 199, 171, 142, 114, 85, 57, 28 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
{ { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 85, 171, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 85, 171, 256, 219, 183, 146, 110, 73, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 73, 110, 146, 183, 219, 256, 228, 199, 171, 142, 114, 85, 57, 28, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 57, 85, 114, 142, 171, 199, 228, 256, 213, 171, 128, 85, 43 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
{ { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 85, 171, 256, 192, 128, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 128, 192, 256, 205, 154, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 102, 154, 205, 256, 213, 171, 128, 85, 43, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 85, 128, 171, 213, 256, 213, 171, 128, 85, 43 } }
};
static const byte coeff_per_sb_for_dequant[3][30] = {
{ 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
{ 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 },
{ 0, 1, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9 }
};
// first index is subband, 2nd index is 0, 1 or 3 (2 is unused)
static const int8 tone_level_idx_offset_table[30][4] = {
{ -50, -50, 0, -50 },
{ -50, -50, 0, -50 },
{ -50, -9, 0, -19 },
{ -16, -6, 0, -12 },
{ -11, -4, 0, -8 },
{ -8, -3, 0, -6 },
{ -7, -3, 0, -5 },
{ -6, -2, 0, -4 },
{ -5, -2, 0, -3 },
{ -4, -1, 0, -3 },
{ -4, -1, 0, -2 },
{ -3, -1, 0, -2 },
{ -3, -1, 0, -2 },
{ -3, -1, 0, -2 },
{ -2, -1, 0, -1 },
{ -2, -1, 0, -1 },
{ -2, -1, 0, -1 },
{ -2, 0, 0, -1 },
{ -2, 0, 0, -1 },
{ -1, 0, 0, -1 },
{ -1, 0, 0, -1 },
{ -1, 0, 0, -1 },
{ -1, 0, 0, -1 },
{ -1, 0, 0, -1 },
{ -1, 0, 0, -1 },
{ -1, 0, 0, -1 },
{ -1, 0, 0, 0 },
{ -1, 0, 0, 0 },
{ -1, 0, 0, 0 },
{ -1, 0, 0, 0 }
};
/* all my samples have 1st index 0 or 1 */
/* second index is subband, only indexes 0-29 seem to be used */
static const int8 coding_method_table[5][30] = {
{ 34, 30, 24, 24, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
},
{ 34, 30, 24, 24, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
},
{ 34, 30, 30, 30, 24, 24, 16, 16, 16, 16, 16, 16, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
},
{ 34, 34, 30, 30, 24, 24, 24, 24, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10, 10
},
{ 34, 34, 30, 30, 30, 30, 30, 30, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
},
};
static const int vlc_stage3_values[60] = {
0, 1, 2, 3, 4, 6, 8, 10, 12, 16, 20, 24,
28, 36, 44, 52, 60, 76, 92, 108, 124, 156, 188, 220,
252, 316, 380, 444, 508, 636, 764, 892, 1020, 1276, 1532, 1788,
2044, 2556, 3068, 3580, 4092, 5116, 6140, 7164, 8188, 10236, 12284, 14332,
16380, 20476, 24572, 28668, 32764, 40956, 49148, 57340, 65532, 81916, 98300,114684
};
static const float fft_tone_sample_table[4][16][5] = {
{ { .0100000000f,-.0037037037f,-.0020000000f,-.0069444444f,-.0018416207f },
{ .0416666667f, .0000000000f, .0000000000f,-.0208333333f,-.0123456791f },
{ .1250000000f, .0558035709f, .0330687836f,-.0164473690f,-.0097465888f },
{ .1562500000f, .0625000000f, .0370370370f,-.0062500000f,-.0037037037f },
{ .1996007860f, .0781250000f, .0462962948f, .0022727272f, .0013468013f },
{ .2000000000f, .0625000000f, .0370370373f, .0208333333f, .0074074073f },
{ .2127659619f, .0555555556f, .0329218097f, .0208333333f, .0123456791f },
{ .2173913121f, .0473484844f, .0280583613f, .0347222239f, .0205761325f },
{ .2173913121f, .0347222239f, .0205761325f, .0473484844f, .0280583613f },
{ .2127659619f, .0208333333f, .0123456791f, .0555555556f, .0329218097f },
{ .2000000000f, .0208333333f, .0074074073f, .0625000000f, .0370370370f },
{ .1996007860f, .0022727272f, .0013468013f, .0781250000f, .0462962948f },
{ .1562500000f,-.0062500000f,-.0037037037f, .0625000000f, .0370370370f },
{ .1250000000f,-.0164473690f,-.0097465888f, .0558035709f, .0330687836f },
{ .0416666667f,-.0208333333f,-.0123456791f, .0000000000f, .0000000000f },
{ .0100000000f,-.0069444444f,-.0018416207f,-.0037037037f,-.0020000000f } },
{ { .0050000000f,-.0200000000f, .0125000000f,-.3030303030f, .0020000000f },
{ .1041666642f, .0400000000f,-.0250000000f, .0333333333f,-.0200000000f },
{ .1250000000f, .0100000000f, .0142857144f,-.0500000007f,-.0200000000f },
{ .1562500000f,-.0006250000f,-.00049382716f,-.000625000f,-.00049382716f },
{ .1562500000f,-.0006250000f,-.00049382716f,-.000625000f,-.00049382716f },
{ .1250000000f,-.0500000000f,-.0200000000f, .0100000000f, .0142857144f },
{ .1041666667f, .0333333333f,-.0200000000f, .0400000000f,-.0250000000f },
{ .0050000000f,-.3030303030f, .0020000001f,-.0200000000f, .0125000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } },
{ { .1428571492f, .1250000000f,-.0285714287f,-.0357142873f, .0208333333f },
{ .1818181818f, .0588235296f, .0333333333f, .0212765951f, .0100000000f },
{ .1818181818f, .0212765951f, .0100000000f, .0588235296f, .0333333333f },
{ .1428571492f,-.0357142873f, .0208333333f, .1250000000f,-.0285714287f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } },
{ { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f },
{ .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } }
};
static const float fft_tone_level_table[2][64] = { {
// pow ~ (i > 46) ? 0 : (((((i & 1) ? 431 : 304) << (i >> 1))) / 1024.0);
0.17677669f, 0.42677650f, 0.60355347f, 0.85355347f,
1.20710683f, 1.68359375f, 2.37500000f, 3.36718750f,
4.75000000f, 6.73437500f, 9.50000000f, 13.4687500f,
19.0000000f, 26.9375000f, 38.0000000f, 53.8750000f,
76.0000000f, 107.750000f, 152.000000f, 215.500000f,
304.000000f, 431.000000f, 608.000000f, 862.000000f,
1216.00000f, 1724.00000f, 2432.00000f, 3448.00000f,
4864.00000f, 6896.00000f, 9728.00000f, 13792.0000f,
19456.0000f, 27584.0000f, 38912.0000f, 55168.0000f,
77824.0000f, 110336.000f, 155648.000f, 220672.000f,
311296.000f, 441344.000f, 622592.000f, 882688.000f,
1245184.00f, 1765376.00f, 2490368.00f, 0.00000000f,
0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
}, {
// pow = (i > 45) ? 0 : ((((i & 1) ? 431 : 304) << (i >> 1)) / 512.0);
0.59375000f, 0.84179688f, 1.18750000f, 1.68359375f,
2.37500000f, 3.36718750f, 4.75000000f, 6.73437500f,
9.50000000f, 13.4687500f, 19.0000000f, 26.9375000f,
38.0000000f, 53.8750000f, 76.0000000f, 107.750000f,
152.000000f, 215.500000f, 304.000000f, 431.000000f,
608.000000f, 862.000000f, 1216.00000f, 1724.00000f,
2432.00000f, 3448.00000f, 4864.00000f, 6896.00000f,
9728.00000f, 13792.0000f, 19456.0000f, 27584.0000f,
38912.0000f, 55168.0000f, 77824.0000f, 110336.000f,
155648.000f, 220672.000f, 311296.000f, 441344.000f,
622592.000f, 882688.000f, 1245184.00f, 1765376.00f,
2490368.00f, 3530752.00f, 0.00000000f, 0.00000000f,
0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f
} };
static const float fft_tone_envelope_table[4][31] = {
{ .009607375f, .038060248f, .084265202f, .146446645f, .222214907f, .308658302f,
.402454883f, .500000060f, .597545207f, .691341758f, .777785182f, .853553414f,
.915734828f, .961939812f, .990392685f, 1.00000000f, .990392625f, .961939752f,
.915734768f, .853553295f, .777785063f, .691341639f, .597545087f, .500000000f,
.402454853f, .308658272f, .222214878f, .146446615f, .084265172f, .038060218f,
.009607345f },
{ .038060248f, .146446645f, .308658302f, .500000060f, .691341758f, .853553414f,
.961939812f, 1.00000000f, .961939752f, .853553295f, .691341639f, .500000000f,
.308658272f, .146446615f, .038060218f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f },
{ .146446645f, .500000060f, .853553414f, 1.00000000f, .853553295f, .500000000f,
.146446615f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f },
{ .500000060f, 1.00000000f, .500000000f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f,
.000000000f }
};
static const float sb_noise_attenuation[32] = {
0.0f, 0.0f, 0.3f, 0.4f, 0.5f, 0.7f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
};
static const byte fft_subpackets[32] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0
};
// first index is joined_stereo, second index is 0 or 2 (1 is unused)
static const float dequant_1bit[2][3] = {
{-0.920000f, 0.000000f, 0.920000f },
{-0.890000f, 0.000000f, 0.890000f }
};
static const float type30_dequant[8] = {
-1.0f,-0.625f,-0.291666656732559f,0.0f,
0.25f,0.5f,0.75f,1.0f,
};
static const float type34_delta[10] = { // FIXME: covers 8 entries..
-1.0f,-0.60947573184967f,-0.333333343267441f,-0.138071194291115f,0.0f,
0.138071194291115f,0.333333343267441f,0.60947573184967f,1.0f,0.0f,
};
} // End of namespace Mohawk
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,282 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
//
// Heavily based on ffmpeg code.
//
// Copyright (c) 2001 Fabrice Bellard.
// First version by Francois Revol revol@free.fr
// Seek function by Gael Chardon gael.dev@4now.net
//
#ifndef MOHAWK_QT_PLAYER_H
#define MOHAWK_QT_PLAYER_H
#include "common/scummsys.h"
#include "common/queue.h"
#include "graphics/video/video_decoder.h"
#include "graphics/video/codecs/codec.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
namespace Common {
class File;
}
namespace Mohawk {
enum ScaleMode {
kScaleNormal = 1,
kScaleHalf = 2,
kScaleQuarter = 4
};
class QTPlayer : public Graphics::RewindableVideoDecoder {
public:
QTPlayer();
virtual ~QTPlayer();
/**
* Returns the width of the video
* @return the width of the video
*/
uint16 getWidth() const;
/**
* Returns the height of the video
* @return the height of the video
*/
uint16 getHeight() const;
/**
* Returns the amount of frames in the video
* @return the amount of frames in the video
*/
uint32 getFrameCount() const;
/**
* Load a QuickTime video file from a SeekableReadStream
* @param stream the stream to load
*/
bool load(Common::SeekableReadStream &stream);
/**
* Close a QuickTime encoded video file
*/
void close();
/**
* Returns the palette of the video
* @return the palette of the video
*/
byte *getPalette() { _dirtyPalette = false; return _palette; }
bool hasDirtyPalette() const { return _dirtyPalette; }
/**
* Set the beginning offset of the video so we can modify the offsets in the stco
* atom of videos inside the Mohawk archives
* @param the beginning offset of the video
*/
void setChunkBeginOffset(uint32 offset) { _beginOffset = offset; }
bool isVideoLoaded() const { return _fd != 0; }
Graphics::Surface *decodeNextFrame();
bool needsUpdate() const;
bool endOfVideo() const;
uint32 getElapsedTime() const;
uint32 getTimeToNextFrame() const;
Graphics::PixelFormat getPixelFormat() const;
// RewindableVideoDecoder API
void rewind();
// TODO: This audio function need to be removed from the public and/or added to
// the VideoDecoder API directly. I plan on replacing this function with something
// that can figure out how much audio is needed instead of constantly keeping two
// chunks in memory.
void updateAudioBuffer();
protected:
// This is the file handle from which data is read from. It can be the actual file handle or a decompressed stream.
Common::SeekableReadStream *_fd;
struct MOVatom {
uint32 type;
uint32 offset;
uint32 size;
};
struct ParseTable {
uint32 type;
int (QTPlayer::*func)(MOVatom atom);
};
struct MOVstts {
int count;
int duration;
};
struct MOVstsc {
uint32 first;
uint32 count;
uint32 id;
};
enum CodecType {
CODEC_TYPE_MOV_OTHER,
CODEC_TYPE_VIDEO,
CODEC_TYPE_AUDIO
};
struct MOVStreamContext {
MOVStreamContext() { memset(this, 0, sizeof(MOVStreamContext)); }
~MOVStreamContext() {
delete[] chunk_offsets;
delete[] stts_data;
delete[] ctts_data;
delete[] sample_to_chunk;
delete[] sample_sizes;
delete[] keyframes;
delete extradata;
}
int ffindex; /* the ffmpeg stream id */
int is_ff_stream; /* Is this stream presented to ffmpeg ? i.e. is this an audio or video stream ? */
uint32 next_chunk;
uint32 chunk_count;
uint32 *chunk_offsets;
int stts_count;
MOVstts *stts_data;
int ctts_count;
MOVstts *ctts_data;
int edit_count; /* number of 'edit' (elst atom) */
uint32 sample_to_chunk_sz;
MOVstsc *sample_to_chunk;
int32 sample_to_chunk_index;
int sample_to_time_index;
uint32 sample_to_time_sample;
uint32 sample_to_time_time;
int sample_to_ctime_index;
int sample_to_ctime_sample;
uint32 sample_size;
uint32 sample_count;
uint32 *sample_sizes;
uint32 keyframe_count;
uint32 *keyframes;
int32 time_scale;
int time_rate;
uint32 current_sample;
uint32 left_in_chunk; /* how many samples before next chunk */
uint16 width;
uint16 height;
int codec_type;
uint32 codec_tag;
char codec_name[32];
uint16 bits_per_sample;
uint16 color_table_id;
bool palettized;
Common::SeekableReadStream *extradata;
uint16 stsd_version;
uint16 channels;
uint16 sample_rate;
uint32 samples_per_frame;
uint32 bytes_per_frame;
uint32 nb_frames;
uint32 duration;
uint32 start_time;
ScaleMode scaleMode;
};
const ParseTable *_parseTable;
bool _foundMOOV;
bool _foundMDAT;
uint32 _timeScale;
uint32 _duration;
uint32 _mdatOffset;
uint32 _mdatSize;
uint32 _next_chunk_offset;
MOVStreamContext *_partial;
uint32 _numStreams;
int _ni;
ScaleMode _scaleMode;
MOVStreamContext *_streams[20];
byte _palette[256 * 3];
bool _dirtyPalette;
uint32 _beginOffset;
void initParseTable();
Audio::AudioStream *createAudioStream(Common::SeekableReadStream *stream);
bool checkAudioCodecSupport(uint32 tag);
Common::SeekableReadStream *getNextFramePacket();
uint32 getFrameDuration();
uint32 getCodecTag();
byte getBitsPerPixel();
Audio::QueuingAudioStream *_audStream;
void startAudio();
void stopAudio();
int8 _audioStreamIndex;
uint _curAudioChunk;
Audio::SoundHandle _audHandle;
Graphics::Codec *createCodec(uint32 codecTag, byte bitsPerPixel);
Graphics::Codec *_videoCodec;
uint32 _nextFrameStartTime;
int8 _videoStreamIndex;
Graphics::Surface *_scaledSurface;
Graphics::Surface *scaleSurface(Graphics::Surface *frame);
ScaleMode getScaleMode() const;
void pauseVideoIntern(bool pause);
int readDefault(MOVatom atom);
int readLeaf(MOVatom atom);
int readELST(MOVatom atom);
int readHDLR(MOVatom atom);
int readMDAT(MOVatom atom);
int readMDHD(MOVatom atom);
int readMOOV(MOVatom atom);
int readMVHD(MOVatom atom);
int readTKHD(MOVatom atom);
int readTRAK(MOVatom atom);
int readSTCO(MOVatom atom);
int readSTSC(MOVatom atom);
int readSTSD(MOVatom atom);
int readSTSS(MOVatom atom);
int readSTSZ(MOVatom atom);
int readSTTS(MOVatom atom);
int readCMOV(MOVatom atom);
int readWAVE(MOVatom atom);
};
} // End of namespace Mohawk
#endif

View File

@ -1,420 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
// QuickTime RLE Decoder
// Based off ffmpeg's QuickTime RLE decoder (written by Mike Melanson)
#include "mohawk/video/qtrle.h"
#include "common/scummsys.h"
#include "common/stream.h"
#include "common/system.h"
#include "graphics/colormasks.h"
#include "graphics/surface.h"
namespace Mohawk {
QTRLEDecoder::QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel) : Graphics::Codec() {
_bitsPerPixel = bitsPerPixel;
_pixelFormat = g_system->getScreenFormat();
// We need to increase the surface size to a multiple of 4
uint16 wMod = width % 4;
if(wMod != 0)
width += 4 - wMod;
debug(2, "QTRLE corrected width: %d", width);
_surface = new Graphics::Surface();
_surface->create(width, height, _bitsPerPixel <= 8 ? 1 : _pixelFormat.bytesPerPixel);
}
#define CHECK_STREAM_PTR(n) \
if ((stream->pos() + n) > stream->size()) { \
warning ("Problem: stream out of bounds (%d >= %d)", stream->pos() + n, stream->size()); \
return; \
}
#define CHECK_PIXEL_PTR(n) \
if ((int32)pixelPtr + n > _surface->w * _surface->h) { \
warning ("Problem: pixel ptr = %d, pixel limit = %d", pixelPtr + n, _surface->w * _surface->h); \
return; \
} \
void QTRLEDecoder::decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
byte *rgb = (byte *)_surface->pixels;
while (linesToChange) {
CHECK_STREAM_PTR(2);
byte skip = stream->readByte();
int8 rleCode = stream->readSByte();
if (rleCode == 0)
break;
if (skip & 0x80) {
linesToChange--;
rowPtr += _surface->w;
pixelPtr = rowPtr + 2 * (skip & 0x7f);
} else
pixelPtr += 2 * skip;
if (rleCode < 0) {
// decode the run length code
rleCode = -rleCode;
// get the next 2 bytes from the stream, treat them as groups of 8 pixels, and output them rleCode times */
CHECK_STREAM_PTR(2);
byte pi0 = stream->readByte();
byte pi1 = stream->readByte();
CHECK_PIXEL_PTR(rleCode * 2);
while (rleCode--) {
rgb[pixelPtr++] = pi0;
rgb[pixelPtr++] = pi1;
}
} else {
// copy the same pixel directly to output 2 times
rleCode *= 2;
CHECK_STREAM_PTR(rleCode);
CHECK_PIXEL_PTR(rleCode);
while (rleCode--)
rgb[pixelPtr++] = stream->readByte();
}
}
}
void QTRLEDecoder::decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp) {
uint32 pixelPtr = 0;
byte *rgb = (byte *)_surface->pixels;
byte numPixels = (bpp == 4) ? 8 : 16;
while (linesToChange--) {
CHECK_STREAM_PTR(2);
pixelPtr = rowPtr + (numPixels * (stream->readByte() - 1));
for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
if (rleCode == 0) {
// there's another skip code in the stream
CHECK_STREAM_PTR(1);
pixelPtr += (numPixels * (stream->readByte() - 1));
} else if (rleCode < 0) {
// decode the run length code
rleCode = -rleCode;
// get the next 4 bytes from the stream, treat them as palette indices, and output them rleCode times */
CHECK_STREAM_PTR(4);
byte pi[16]; // 16 palette indices
for (int8 i = numPixels - 1; i >= 0; i--) {
pi[numPixels - 1 - i] = (stream->readByte() >> ((i * bpp) & 0x07)) & ((1 << bpp) - 1);
// FIXME: Is this right?
//stream_ptr += ((i & ((num_pixels>>2)-1)) == 0);
if ((i & ((numPixels >> 2) - 1)) == 0)
stream->readByte();
}
CHECK_PIXEL_PTR(rleCode * numPixels);
while (rleCode--)
for (byte i = 0; i < numPixels; i++)
rgb[pixelPtr++] = pi[i];
} else {
// copy the same pixel directly to output 4 times
rleCode *= 4;
CHECK_STREAM_PTR(rleCode);
CHECK_PIXEL_PTR(rleCode * (numPixels >> 2));
while (rleCode--) {
byte temp = stream->readByte();
if (bpp == 4) {
rgb[pixelPtr++] = (temp >> 4) & 0x0f;
rgb[pixelPtr++] = temp & 0x0f;
} else {
rgb[pixelPtr++] = (temp >> 6) & 0x03;
rgb[pixelPtr++] = (temp >> 4) & 0x03;
rgb[pixelPtr++] = (temp >> 2) & 0x03;
rgb[pixelPtr++] = temp & 0x03;
}
}
}
}
rowPtr += _surface->w;
}
}
void QTRLEDecoder::decode8(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
byte *rgb = (byte *)_surface->pixels;
while (linesToChange--) {
CHECK_STREAM_PTR(2);
pixelPtr = rowPtr + 4 * (stream->readByte() - 1);
for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
if (rleCode == 0) {
// there's another skip code in the stream
CHECK_STREAM_PTR(1);
pixelPtr += 4 * (stream->readByte() - 1);
} else if (rleCode < 0) {
// decode the run length code
rleCode = -rleCode;
// get the next 4 bytes from the stream, treat them as palette indices, and output them rleCode times
CHECK_STREAM_PTR(4);
byte pi[4]; // 4 palette indexes
for (byte i = 0; i < 4; i++)
pi[i] = stream->readByte();
CHECK_PIXEL_PTR(rleCode * 4);
while (rleCode--)
for (byte i = 0; i < 4; i++)
rgb[pixelPtr++] = pi[i];
} else {
// copy the same pixel directly to output 4 times
rleCode *= 4;
CHECK_STREAM_PTR(rleCode);
CHECK_PIXEL_PTR(rleCode);
while (rleCode--)
rgb[pixelPtr++] = stream->readByte();
}
}
rowPtr += _surface->w;
}
}
void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
OverlayColor *rgb = (OverlayColor *)_surface->pixels;
while (linesToChange--) {
CHECK_STREAM_PTR(2);
pixelPtr = rowPtr + stream->readByte() - 1;
for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
if (rleCode == 0) {
// there's another skip code in the stream
CHECK_STREAM_PTR(1);
pixelPtr += stream->readByte() - 1;
} else if (rleCode < 0) {
// decode the run length code
rleCode = -rleCode;
CHECK_STREAM_PTR(2);
uint16 rgb16 = stream->readUint16BE();
CHECK_PIXEL_PTR(rleCode);
while (rleCode--) {
// Convert from RGB555 to the format specified by the Overlay
byte r = 0, g = 0, b = 0;
Graphics::colorToRGB<Graphics::ColorMasks<555> >(rgb16, r, g, b);
rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
}
} else {
CHECK_STREAM_PTR(rleCode * 2);
CHECK_PIXEL_PTR(rleCode);
// copy pixels directly to output
while (rleCode--) {
uint16 rgb16 = stream->readUint16BE();
// Convert from RGB555 to the format specified by the Overlay
byte r = 0, g = 0, b = 0;
Graphics::colorToRGB<Graphics::ColorMasks<555> >(rgb16, r, g, b);
rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
}
}
}
rowPtr += _surface->w;
}
}
void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
OverlayColor *rgb = (OverlayColor *)_surface->pixels;
while (linesToChange--) {
CHECK_STREAM_PTR(2);
pixelPtr = rowPtr + stream->readByte() - 1;
for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
if (rleCode == 0) {
// there's another skip code in the stream
CHECK_STREAM_PTR(1);
pixelPtr += stream->readByte() - 1;
} else if (rleCode < 0) {
// decode the run length code
rleCode = -rleCode;
CHECK_STREAM_PTR(3);
byte r = stream->readByte();
byte g = stream->readByte();
byte b = stream->readByte();
CHECK_PIXEL_PTR(rleCode);
while (rleCode--)
rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
} else {
CHECK_STREAM_PTR(rleCode * 3);
CHECK_PIXEL_PTR(rleCode);
// copy pixels directly to output
while (rleCode--) {
byte r = stream->readByte();
byte g = stream->readByte();
byte b = stream->readByte();
rgb[pixelPtr++] = _pixelFormat.RGBToColor(r, g, b);
}
}
}
rowPtr += _surface->w;
}
}
void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
OverlayColor *rgb = (OverlayColor *)_surface->pixels;
while (linesToChange--) {
CHECK_STREAM_PTR(2);
pixelPtr = rowPtr + stream->readByte() - 1;
for (int8 rleCode = stream->readSByte(); rleCode != -1; rleCode = stream->readSByte()) {
if (rleCode == 0) {
// there's another skip code in the stream
CHECK_STREAM_PTR(1);
pixelPtr += stream->readByte() - 1;
} else if (rleCode < 0) {
// decode the run length code
rleCode = -rleCode;
CHECK_STREAM_PTR(4);
byte a = stream->readByte();
byte r = stream->readByte();
byte g = stream->readByte();
byte b = stream->readByte();
CHECK_PIXEL_PTR(rleCode);
while (rleCode--)
rgb[pixelPtr++] = _pixelFormat.ARGBToColor(a, r, g, b);
} else {
CHECK_STREAM_PTR(rleCode * 4);
CHECK_PIXEL_PTR(rleCode);
// copy pixels directly to output
while (rleCode--) {
byte a = stream->readByte();
byte r = stream->readByte();
byte g = stream->readByte();
byte b = stream->readByte();
rgb[pixelPtr++] = _pixelFormat.ARGBToColor(a, r, g, b);
}
}
}
rowPtr += _surface->w;
}
}
Graphics::Surface *QTRLEDecoder::decodeImage(Common::SeekableReadStream *stream) {
uint16 start_line = 0;
uint16 height = _surface->h;
// check if this frame is even supposed to change
if (stream->size() < 8)
return _surface;
// start after the chunk size
stream->readUint32BE();
// fetch the header
uint16 header = stream->readUint16BE();
// if a header is present, fetch additional decoding parameters
if (header & 8) {
if(stream->size() < 14)
return _surface;
start_line = stream->readUint16BE();
stream->readUint16BE(); // Unknown
height = stream->readUint16BE();
stream->readUint16BE(); // Unknown
}
uint32 row_ptr = _surface->w * start_line;
switch (_bitsPerPixel) {
case 1:
case 33:
decode1(stream, row_ptr, height);
break;
case 2:
case 34:
decode2_4(stream, row_ptr, height, 2);
break;
case 4:
case 36:
decode2_4(stream, row_ptr, height, 4);
break;
case 8:
case 40:
decode8(stream, row_ptr, height);
break;
case 16:
decode16(stream, row_ptr, height);
break;
case 24:
decode24(stream, row_ptr, height);
break;
case 32:
decode32(stream, row_ptr, height);
break;
default:
error ("Unsupported bits per pixel %d", _bitsPerPixel);
}
return _surface;
}
QTRLEDecoder::~QTRLEDecoder() {
_surface->free();
}
} // End of namespace Mohawk

View File

@ -1,58 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MOHAWK_QTRLE_H
#define MOHAWK_QTRLE_H
#include "graphics/pixelformat.h"
#include "graphics/video/codecs/codec.h"
namespace Mohawk {
class QTRLEDecoder : public Graphics::Codec {
public:
QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel);
~QTRLEDecoder();
Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
private:
byte _bitsPerPixel;
Graphics::Surface *_surface;
Graphics::PixelFormat _pixelFormat;
void decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
void decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp);
void decode8(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
void decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
void decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
void decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange);
};
} // End of namespace Mohawk
#endif

View File

@ -1,208 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
// Based off ffmpeg's RPZA decoder
#include "mohawk/video/rpza.h"
#include "common/system.h"
#include "graphics/colormasks.h"
namespace Mohawk {
RPZADecoder::RPZADecoder(uint16 width, uint16 height) : Graphics::Codec() {
_pixelFormat = g_system->getScreenFormat();
// We need to increase the surface size to a multiple of 4
uint16 wMod = width % 4;
if(wMod != 0)
width += 4 - wMod;
debug(2, "RPZA corrected width: %d", width);
_surface = new Graphics::Surface();
_surface->create(width, height, _pixelFormat.bytesPerPixel);
}
#define ADVANCE_BLOCK() \
pixelPtr += 4; \
if (pixelPtr >= _surface->w) { \
pixelPtr = 0; \
rowPtr += _surface->w * 4; \
} \
totalBlocks--; \
if (totalBlocks < 0) \
error("block counter just went negative (this should not happen)") \
// Convert from RGB555 to the format specified by the screen
#define PUT_PIXEL(color) \
if ((int32)blockPtr < _surface->w * _surface->h) { \
byte r = 0, g = 0, b = 0; \
Graphics::colorToRGB<Graphics::ColorMasks<555> >(color, r, g, b); \
if (_pixelFormat.bytesPerPixel == 2) \
*((uint16 *)_surface->pixels + blockPtr) = _pixelFormat.RGBToColor(r, g, b); \
else \
*((uint32 *)_surface->pixels + blockPtr) = _pixelFormat.RGBToColor(r, g, b); \
} \
blockPtr++
Graphics::Surface *RPZADecoder::decodeImage(Common::SeekableReadStream *stream) {
uint16 colorA = 0, colorB = 0;
uint16 color4[4];
uint32 rowPtr = 0;
uint32 pixelPtr = 0;
uint32 blockPtr = 0;
uint32 rowInc = _surface->w - 4;
uint16 ta;
uint16 tb;
// First byte is always 0xe1. Warn if it's different
byte firstByte = stream->readByte();
if (firstByte != 0xe1)
warning("First RPZA chunk byte is 0x%02x instead of 0xe1", firstByte);
// Get chunk size, ingnoring first byte
uint32 chunkSize = stream->readUint16BE() << 8;
chunkSize += stream->readByte();
// If length mismatch use size from MOV file and try to decode anyway
if (chunkSize != (uint32)stream->size()) {
warning("MOV chunk size != encoded chunk size; using MOV chunk size");
chunkSize = stream->size();
}
// Number of 4x4 blocks in frame
int32 totalBlocks = ((_surface->w + 3) / 4) * ((_surface->h + 3) / 4);
// Process chunk data
while ((uint32)stream->pos() < chunkSize) {
byte opcode = stream->readByte(); // Get opcode
byte numBlocks = (opcode & 0x1f) + 1; // Extract block counter from opcode
// If opcode MSbit is 0, we need more data to decide what to do
if ((opcode & 0x80) == 0) {
colorA = (opcode << 8) | stream->readByte();
opcode = 0;
if (stream->readByte() & 0x80) {
// Must behave as opcode 110xxxxx, using colorA computed
// above. Use fake opcode 0x20 to enter switch block at
// the right place
opcode = 0x20;
numBlocks = 1;
}
stream->seek(-1, SEEK_CUR);
}
switch (opcode & 0xe0) {
case 0x80: // Skip blocks
while (numBlocks--) {
ADVANCE_BLOCK();
}
break;
case 0xa0: // Fill blocks with one color
colorA = stream->readUint16BE();
while (numBlocks--) {
blockPtr = rowPtr + pixelPtr;
for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
for (byte pixel_x = 0; pixel_x < 4; pixel_x++) {
PUT_PIXEL(colorA);
}
blockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
// Fill blocks with 4 colors
case 0xc0:
colorA = stream->readUint16BE();
case 0x20:
colorB = stream->readUint16BE();
// Sort out the colors
color4[0] = colorB;
color4[1] = 0;
color4[2] = 0;
color4[3] = colorA;
// Red components
ta = (colorA >> 10) & 0x1F;
tb = (colorB >> 10) & 0x1F;
color4[1] |= ((11 * ta + 21 * tb) >> 5) << 10;
color4[2] |= ((21 * ta + 11 * tb) >> 5) << 10;
// Green components
ta = (colorA >> 5) & 0x1F;
tb = (colorB >> 5) & 0x1F;
color4[1] |= ((11 * ta + 21 * tb) >> 5) << 5;
color4[2] |= ((21 * ta + 11 * tb) >> 5) << 5;
// Blue components
ta = colorA & 0x1F;
tb = colorB & 0x1F;
color4[1] |= ((11 * ta + 21 * tb) >> 5);
color4[2] |= ((21 * ta + 11 * tb) >> 5);
while (numBlocks--) {
blockPtr = rowPtr + pixelPtr;
for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
byte index = stream->readByte();
for (byte pixel_x = 0; pixel_x < 4; pixel_x++){
byte idx = (index >> (2 * (3 - pixel_x))) & 0x03;
PUT_PIXEL(color4[idx]);
}
blockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
// Fill block with 16 colors
case 0x00:
blockPtr = rowPtr + pixelPtr;
for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
for (byte pixel_x = 0; pixel_x < 4; pixel_x++){
// We already have color of upper left pixel
if (pixel_y != 0 || pixel_x != 0)
colorA = stream->readUint16BE();
PUT_PIXEL(colorA);
}
blockPtr += rowInc;
}
ADVANCE_BLOCK();
break;
// Unknown opcode
default:
error("Unknown opcode %02x in rpza chunk", opcode);
}
}
return _surface;
}
} // End of namespace Mohawk

View File

@ -1,49 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MOHAWK_RPZA_H
#define MOHAWK_RPZA_H
#include "graphics/pixelformat.h"
#include "graphics/video/codecs/codec.h"
namespace Mohawk {
class RPZADecoder : public Graphics::Codec {
public:
RPZADecoder(uint16 width, uint16 height);
~RPZADecoder() { delete _surface; }
Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
private:
Graphics::Surface *_surface;
Graphics::PixelFormat _pixelFormat;
};
} // End of namespace Mohawk
#endif

View File

@ -1,385 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
// Based off ffmpeg's SMC decoder
#include "mohawk/video/smc.h"
namespace Mohawk {
#define GET_BLOCK_COUNT() \
(opcode & 0x10) ? (1 + stream->readByte()) : 1 + (opcode & 0x0F);
#define ADVANCE_BLOCK() \
{ \
pixelPtr += 4; \
if (pixelPtr >= _surface->w) { \
pixelPtr = 0; \
rowPtr += _surface->w * 4; \
} \
totalBlocks--; \
if (totalBlocks < 0) { \
warning("block counter just went negative (this should not happen)"); \
return _surface; \
} \
}
SMCDecoder::SMCDecoder(uint16 width, uint16 height) {
_surface = new Graphics::Surface();
_surface->create(width, height, 1);
}
Graphics::Surface *SMCDecoder::decodeImage(Common::SeekableReadStream *stream) {
byte *pixels = (byte *)_surface->pixels;
uint32 numBlocks = 0;
uint32 colorFlags = 0;
uint32 colorFlagsA = 0;
uint32 colorFlagsB = 0;
const uint16 rowInc = _surface->w - 4;
int32 rowPtr = 0;
int32 pixelPtr = 0;
uint32 blockPtr = 0;
uint32 prevBlockPtr = 0;
uint32 prevBlockPtr1 = 0, prevBlockPtr2 = 0;
byte prevBlockFlag = false;
byte pixel = 0;
uint32 colorPairIndex = 0;
uint32 colorQuadIndex = 0;
uint32 colorOctetIndex = 0;
uint32 colorTableIndex = 0; // indices to color pair, quad, or octet tables
int32 chunkSize = stream->readUint32BE() & 0x00FFFFFF;
if (chunkSize != stream->size())
warning("MOV chunk size != SMC chunk size (%d != %d); ignoring SMC chunk size", chunkSize, stream->size());
int32 totalBlocks = ((_surface->w + 3) / 4) * ((_surface->h + 3) / 4);
// traverse through the blocks
while (totalBlocks != 0) {
// sanity checks
// make sure stream ptr hasn't gone out of bounds
if (stream->pos() > stream->size()) {
warning("SMC decoder just went out of bounds (stream ptr = %d, chunk size = %d)", stream->pos(), stream->size());
return _surface;
}
// make sure the row pointer hasn't gone wild
if (rowPtr >= _surface->w * _surface->h) {
warning("SMC decoder just went out of bounds (row ptr = %d, size = %d)", rowPtr, _surface->w * _surface->h);
return _surface;
}
byte opcode = stream->readByte();
switch (opcode & 0xF0) {
// skip n blocks
case 0x00:
case 0x10:
numBlocks = GET_BLOCK_COUNT();
while (numBlocks--) {
ADVANCE_BLOCK();
}
break;
// repeat last block n times
case 0x20:
case 0x30:
numBlocks = GET_BLOCK_COUNT();
// sanity check
if (rowPtr == 0 && pixelPtr == 0) {
warning("encountered repeat block opcode (%02X) but no blocks rendered yet", opcode & 0xF0);
break;
}
// figure out where the previous block started
if (pixelPtr == 0)
prevBlockPtr1 = (rowPtr - _surface->w * 4) + _surface->w - 4;
else
prevBlockPtr1 = rowPtr + pixelPtr - 4;
while (numBlocks--) {
blockPtr = rowPtr + pixelPtr;
prevBlockPtr = prevBlockPtr1;
for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++)
pixels[blockPtr++] = pixels[prevBlockPtr++];
blockPtr += rowInc;
prevBlockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
// repeat previous pair of blocks n times
case 0x40:
case 0x50:
numBlocks = GET_BLOCK_COUNT();
numBlocks *= 2;
// sanity check
if (rowPtr == 0 && pixelPtr < 2 * 4) {
warning("encountered repeat block opcode (%02X) but not enough blocks rendered yet", opcode & 0xF0);
break;
}
// figure out where the previous 2 blocks started
if (pixelPtr == 0)
prevBlockPtr1 = (rowPtr - _surface->w * 4) + _surface->w - 4 * 2;
else if (pixelPtr == 4)
prevBlockPtr1 = (rowPtr - _surface->w * 4) + rowInc;
else
prevBlockPtr1 = rowPtr + pixelPtr - 4 * 2;
if (pixelPtr == 0)
prevBlockPtr2 = (rowPtr - _surface->w * 4) + rowInc;
else
prevBlockPtr2 = rowPtr + pixelPtr - 4;
prevBlockFlag = 0;
while (numBlocks--) {
blockPtr = rowPtr + pixelPtr;
if (prevBlockFlag)
prevBlockPtr = prevBlockPtr2;
else
prevBlockPtr = prevBlockPtr1;
prevBlockFlag = !prevBlockFlag;
for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++)
pixels[blockPtr++] = pixels[prevBlockPtr++];
blockPtr += rowInc;
prevBlockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
// 1-color block encoding
case 0x60:
case 0x70:
numBlocks = GET_BLOCK_COUNT();
pixel = stream->readByte();
while (numBlocks--) {
blockPtr = rowPtr + pixelPtr;
for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++)
pixels[blockPtr++] = pixel;
blockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
// 2-color block encoding
case 0x80:
case 0x90:
numBlocks = (opcode & 0x0F) + 1;
// figure out which color pair to use to paint the 2-color block
if ((opcode & 0xF0) == 0x80) {
// fetch the next 2 colors from bytestream and store in next
// available entry in the color pair table
for (byte i = 0; i < CPAIR; i++) {
pixel = stream->readByte();
colorTableIndex = CPAIR * colorPairIndex + i;
_colorPairs[colorTableIndex] = pixel;
}
// this is the base index to use for this block
colorTableIndex = CPAIR * colorPairIndex;
colorPairIndex++;
// wraparound
if (colorPairIndex == COLORS_PER_TABLE)
colorPairIndex = 0;
} else
colorTableIndex = CPAIR * stream->readByte();
while (numBlocks--) {
colorFlags = stream->readUint16BE();
uint16 flagMask = 0x8000;
blockPtr = rowPtr + pixelPtr;
for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++) {
if (colorFlags & flagMask)
pixel = colorTableIndex + 1;
else
pixel = colorTableIndex;
flagMask >>= 1;
pixels[blockPtr++] = _colorPairs[pixel];
}
blockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
// 4-color block encoding
case 0xA0:
case 0xB0:
numBlocks = (opcode & 0x0F) + 1;
// figure out which color quad to use to paint the 4-color block
if ((opcode & 0xF0) == 0xA0) {
// fetch the next 4 colors from bytestream and store in next
// available entry in the color quad table
for (byte i = 0; i < CQUAD; i++) {
pixel = stream->readByte();
colorTableIndex = CQUAD * colorQuadIndex + i;
_colorQuads[colorTableIndex] = pixel;
}
// this is the base index to use for this block
colorTableIndex = CQUAD * colorQuadIndex;
colorQuadIndex++;
// wraparound
if (colorQuadIndex == COLORS_PER_TABLE)
colorQuadIndex = 0;
} else
colorTableIndex = CQUAD * stream->readByte();
while (numBlocks--) {
colorFlags = stream->readUint32BE();
// flag mask actually acts as a bit shift count here
byte flagMask = 30;
blockPtr = rowPtr + pixelPtr;
for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++) {
pixel = colorTableIndex + ((colorFlags >> flagMask) & 0x03);
flagMask -= 2;
pixels[blockPtr++] = _colorQuads[pixel];
}
blockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
// 8-color block encoding
case 0xC0:
case 0xD0:
numBlocks = (opcode & 0x0F) + 1;
// figure out which color octet to use to paint the 8-color block
if ((opcode & 0xF0) == 0xC0) {
// fetch the next 8 colors from bytestream and store in next
// available entry in the color octet table
for (byte i = 0; i < COCTET; i++) {
pixel = stream->readByte();
colorTableIndex = COCTET * colorOctetIndex + i;
_colorOctets[colorTableIndex] = pixel;
}
// this is the base index to use for this block
colorTableIndex = COCTET * colorOctetIndex;
colorOctetIndex++;
// wraparound
if (colorOctetIndex == COLORS_PER_TABLE)
colorOctetIndex = 0;
} else
colorTableIndex = COCTET * stream->readByte();
while (numBlocks--) {
/*
For this input of 6 hex bytes:
01 23 45 67 89 AB
Mangle it to this output:
flags_a = xx012456, flags_b = xx89A37B
*/
// build the color flags
byte flagData[6];
stream->read(flagData, 6);
colorFlagsA = ((READ_BE_UINT16(flagData) & 0xFFF0) << 8) | (READ_BE_UINT16(flagData + 2) >> 4);
colorFlagsB = ((READ_BE_UINT16(flagData + 4) & 0xFFF0) << 8) | ((flagData[1] & 0xF) << 8) |
((flagData[3] & 0xF) << 4) | (flagData[5] & 0xf);
colorFlags = colorFlagsA;
// flag mask actually acts as a bit shift count here
byte flagMask = 21;
blockPtr = rowPtr + pixelPtr;
for (byte y = 0; y < 4; y++) {
// reload flags at third row (iteration y == 2)
if (y == 2) {
colorFlags = colorFlagsB;
flagMask = 21;
}
for (byte x = 0; x < 4; x++) {
pixel = colorTableIndex + ((colorFlags >> flagMask) & 0x07);
flagMask -= 3;
pixels[blockPtr++] = _colorOctets[pixel];
}
blockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
// 16-color block encoding (every pixel is a different color)
case 0xE0:
numBlocks = (opcode & 0x0F) + 1;
while (numBlocks--) {
blockPtr = rowPtr + pixelPtr;
for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++)
pixels[blockPtr++] = stream->readByte();
blockPtr += rowInc;
}
ADVANCE_BLOCK();
}
break;
case 0xF0:
warning("0xF0 opcode seen in SMC chunk (contact the developers)");
break;
}
}
return _surface;
}
} // End of namespace Mohawk

View File

@ -1,59 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MOHAWK_VIDEO_SMC_H
#define MOHAWK_VIDEO_SMC_H
#include "graphics/video/codecs/codec.h"
namespace Mohawk {
enum {
CPAIR = 2,
CQUAD = 4,
COCTET = 8,
COLORS_PER_TABLE = 256
};
class SMCDecoder : public Graphics::Codec {
public:
SMCDecoder(uint16 width, uint16 height);
~SMCDecoder() { delete _surface; }
Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
private:
Graphics::Surface *_surface;
// SMC color tables
byte _colorPairs[COLORS_PER_TABLE * CPAIR];
byte _colorQuads[COLORS_PER_TABLE * CQUAD];
byte _colorOctets[COLORS_PER_TABLE * COCTET];
};
} // End of namespace Mohawk
#endif

View File

@ -1,377 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "mohawk/resource.h"
#include "mohawk/video/video.h"
#include "mohawk/video/qt_player.h"
#include "common/events.h"
namespace Mohawk {
VideoManager::VideoManager(MohawkEngine* vm) : _vm(vm) {
}
VideoManager::~VideoManager() {
_mlstRecords.clear();
stopVideos();
}
void VideoManager::pauseVideos() {
for (uint16 i = 0; i < _videoStreams.size(); i++)
_videoStreams[i]->pauseVideo(true);
}
void VideoManager::resumeVideos() {
for (uint16 i = 0; i < _videoStreams.size(); i++)
_videoStreams[i]->pauseVideo(false);
}
void VideoManager::stopVideos() {
for (uint16 i = 0; i < _videoStreams.size(); i++)
delete _videoStreams[i].video;
_videoStreams.clear();
}
void VideoManager::playMovie(Common::String filename, uint16 x, uint16 y, bool clearScreen) {
VideoHandle videoHandle = createVideoHandle(filename, x, y, false);
if (videoHandle == NULL_VID_HANDLE)
return;
// Clear screen if requested
if (clearScreen) {
_vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
_vm->_system->updateScreen();
}
waitUntilMovieEnds(videoHandle);
}
void VideoManager::playMovieCentered(Common::String filename, bool clearScreen) {
VideoHandle videoHandle = createVideoHandle(filename, 0, 0, false);
if (videoHandle == NULL_VID_HANDLE)
return;
// Clear screen if requested
if (clearScreen) {
_vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
_vm->_system->updateScreen();
}
_videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
_videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
waitUntilMovieEnds(videoHandle);
}
void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) {
bool continuePlaying = true;
while (!_videoStreams[videoHandle]->endOfVideo() && !_vm->shouldQuit() && continuePlaying) {
if (updateBackgroundMovies())
_vm->_system->updateScreen();
Common::Event event;
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
continuePlaying = false;
break;
case Common::EVENT_KEYDOWN:
switch (event.kbd.keycode) {
case Common::KEYCODE_SPACE:
_vm->pauseGame();
break;
case Common::KEYCODE_ESCAPE:
continuePlaying = false;
break;
default:
break;
}
default:
break;
}
}
// Cut down on CPU usage
_vm->_system->delayMillis(10);
}
_videoStreams[videoHandle]->close();
_videoStreams.clear();
}
void VideoManager::playBackgroundMovie(Common::String filename, int16 x, int16 y, bool loop) {
VideoHandle videoHandle = createVideoHandle(filename, x, y, loop);
if (videoHandle == NULL_VID_HANDLE)
return;
// Center x if requested
if (x < 0)
_videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
// Center y if requested
if (y < 0)
_videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
}
bool VideoManager::updateBackgroundMovies() {
bool updateScreen = false;
for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) {
// Skip deleted videos
if (!_videoStreams[i].video)
continue;
// Remove any videos that are over
if (_videoStreams[i]->endOfVideo()) {
if (_videoStreams[i].loop) {
_videoStreams[i]->rewind();
} else {
delete _videoStreams[i].video;
memset(&_videoStreams[i], 0, sizeof(VideoEntry));
_videoStreams[i].video = NULL;
continue;
}
}
// Check if we need to draw a frame
if (_videoStreams[i]->needsUpdate()) {
Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
bool deleteFrame = false;
if (frame && _videoStreams[i].enabled) {
// Convert from 8bpp to the current screen format if necessary
if (frame->bytesPerPixel == 1) {
Graphics::Surface *newFrame = new Graphics::Surface();
Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();
byte *palette = _videoStreams[i]->getPalette();
assert(palette);
newFrame->create(frame->w, frame->h, pixelFormat.bytesPerPixel);
for (uint16 j = 0; j < frame->h; j++) {
for (uint16 k = 0; k < frame->w; k++) {
byte palIndex = *((byte *)frame->getBasePtr(k, j));
byte r = palette[palIndex * 3];
byte g = palette[palIndex * 3 + 1];
byte b = palette[palIndex * 3 + 2];
if (pixelFormat.bytesPerPixel == 2)
*((uint16 *)newFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
else
*((uint32 *)newFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
}
}
frame = newFrame;
deleteFrame = true;
}
// Clip the width/height to make sure we stay on the screen (Myst does this a few times)
uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);
_vm->_system->copyRectToScreen((byte*)frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
// We've drawn something to the screen, make sure we update it
updateScreen = true;
// Delete the frame if we're using the buffer from the 8bpp conversion
if (deleteFrame) {
frame->free();
delete frame;
}
}
}
// Update the audio buffer too
_videoStreams[i]->updateAudioBuffer();
}
// Return true if we need to update the screen
return updateScreen;
}
void VideoManager::activateMLST(uint16 mlstId, uint16 card) {
Common::SeekableReadStream *mlstStream = _vm->getRawData(ID_MLST, card);
uint16 recordCount = mlstStream->readUint16BE();
for (uint16 i = 0; i < recordCount; i++) {
MLSTRecord mlstRecord;
mlstRecord.index = mlstStream->readUint16BE();
mlstRecord.movieID = mlstStream->readUint16BE();
mlstRecord.code = mlstStream->readUint16BE();
mlstRecord.left = mlstStream->readUint16BE();
mlstRecord.top = mlstStream->readUint16BE();
for (byte j = 0; j < 2; j++)
if (mlstStream->readUint16BE() != 0)
warning("u0[%d] in MLST non-zero", j);
if (mlstStream->readUint16BE() != 0xFFFF)
warning("u0[2] in MLST not 0xFFFF");
mlstRecord.loop = mlstStream->readUint16BE();
mlstRecord.volume = mlstStream->readUint16BE();
mlstRecord.u1 = mlstStream->readUint16BE();
if (mlstRecord.u1 != 1)
warning("mlstRecord.u1 not 1");
if (mlstRecord.index == mlstId) {
_mlstRecords.push_back(mlstRecord);
break;
}
}
delete mlstStream;
}
void VideoManager::playMovie(uint16 id) {
for (uint16 i = 0; i < _mlstRecords.size(); i++)
if (_mlstRecords[i].code == id) {
debug(1, "Play tMOV %d (non-blocking) at (%d, %d) %s", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0 ? "looping" : "non-looping");
createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0);
return;
}
}
void VideoManager::playMovieBlocking(uint16 id) {
for (uint16 i = 0; i < _mlstRecords.size(); i++)
if (_mlstRecords[i].code == id) {
debug(1, "Play tMOV %d (blocking) at (%d, %d)", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top);
VideoHandle videoHandle = createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, false);
waitUntilMovieEnds(videoHandle);
return;
}
}
void VideoManager::stopMovie(uint16 id) {
debug(2, "Stopping movie %d", id);
for (uint16 i = 0; i < _mlstRecords.size(); i++)
if (_mlstRecords[i].code == id)
for (uint16 j = 0; j < _videoStreams.size(); j++)
if (_mlstRecords[i].movieID == _videoStreams[j].id) {
delete _videoStreams[i].video;
memset(&_videoStreams[i].video, 0, sizeof(VideoEntry));
return;
}
}
void VideoManager::enableMovie(uint16 id) {
debug(2, "Enabling movie %d", id);
for (uint16 i = 0; i < _mlstRecords.size(); i++)
if (_mlstRecords[i].code == id)
for (uint16 j = 0; j < _videoStreams.size(); j++)
if (_mlstRecords[i].movieID == _videoStreams[j].id) {
_videoStreams[j].enabled = true;
return;
}
}
void VideoManager::disableMovie(uint16 id) {
debug(2, "Disabling movie %d", id);
for (uint16 i = 0; i < _mlstRecords.size(); i++)
if (_mlstRecords[i].code == id)
for (uint16 j = 0; j < _videoStreams.size(); j++)
if (_mlstRecords[i].movieID == _videoStreams[j].id) {
_videoStreams[j].enabled = false;
return;
}
}
void VideoManager::disableAllMovies() {
debug(2, "Disabling all movies");
for (uint16 i = 0; i < _videoStreams.size(); i++)
_videoStreams[i].enabled = false;
}
VideoHandle VideoManager::createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop) {
// First, check to see if that video is already playing
for (uint32 i = 0; i < _videoStreams.size(); i++)
if (_videoStreams[i].id == id)
return i;
// Otherwise, create a new entry
VideoEntry entry;
entry.video = new QTPlayer();
entry.x = x;
entry.y = y;
entry.filename = "";
entry.id = id;
entry.loop = loop;
entry.enabled = true;
entry->setChunkBeginOffset(_vm->getResourceOffset(ID_TMOV, id));
entry->load(*_vm->getRawData(ID_TMOV, id));
// Search for any deleted videos so we can take a formerly used slot
for (uint32 i = 0; i < _videoStreams.size(); i++)
if (!_videoStreams[i].video) {
_videoStreams[i] = entry;
return i;
}
// Otherwise, just add it to the list
_videoStreams.push_back(entry);
return _videoStreams.size() - 1;
}
VideoHandle VideoManager::createVideoHandle(Common::String filename, uint16 x, uint16 y, bool loop) {
// First, check to see if that video is already playing
for (uint32 i = 0; i < _videoStreams.size(); i++)
if (_videoStreams[i].filename == filename)
return i;
// Otherwise, create a new entry
VideoEntry entry;
entry.video = new QTPlayer();
entry.x = x;
entry.y = y;
entry.filename = filename;
entry.id = 0;
entry.loop = loop;
entry.enabled = true;
Common::File *file = new Common::File();
if (!file->open(filename)) {
delete file;
return NULL_VID_HANDLE;
}
entry->load(*file);
// Search for any deleted videos so we can take a formerly used slot
for (uint32 i = 0; i < _videoStreams.size(); i++)
if (!_videoStreams[i].video) {
_videoStreams[i] = entry;
return i;
}
// Otherwise, just add it to the list
_videoStreams.push_back(entry);
return _videoStreams.size() - 1;
}
} // End of namespace Mohawk

View File

@ -1,107 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MOHAWK_VIDEO_H
#define MOHAWK_VIDEO_H
#include "graphics/pixelformat.h"
namespace Mohawk {
class MohawkEngine;
struct MLSTRecord {
uint16 index;
uint16 movieID;
uint16 code;
uint16 left;
uint16 top;
uint16 u0[3];
uint16 loop;
uint16 volume;
uint16 u1;
};
class QTPlayer;
struct VideoEntry {
QTPlayer *video;
uint16 x;
uint16 y;
bool loop;
Common::String filename;
uint16 id; // Riven only
bool enabled;
QTPlayer *operator->() const { assert(video); return video; }
};
typedef int32 VideoHandle;
enum {
NULL_VID_HANDLE = -1
};
class VideoManager {
public:
VideoManager(MohawkEngine *vm);
~VideoManager();
// Generic movie functions
void playMovie(Common::String filename, uint16 x = 0, uint16 y = 0, bool clearScreen = false);
void playMovieCentered(Common::String filename, bool clearScreen = true);
void playBackgroundMovie(Common::String filename, int16 x = -1, int16 y = -1, bool loop = false);
bool updateBackgroundMovies();
void pauseVideos();
void resumeVideos();
void stopVideos();
// Riven-related functions
void activateMLST(uint16 mlstId, uint16 card);
void enableMovie(uint16 id);
void disableMovie(uint16 id);
void disableAllMovies();
void playMovie(uint16 id);
void stopMovie(uint16 id);
void playMovieBlocking(uint16 id);
// Riven-related variables
Common::Array<MLSTRecord> _mlstRecords;
private:
MohawkEngine *_vm;
void waitUntilMovieEnds(VideoHandle videoHandle);
// Keep tabs on any videos playing
Common::Array<VideoEntry> _videoStreams;
VideoHandle createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop);
VideoHandle createVideoHandle(Common::String filename, uint16 x, uint16 y, bool loop);
};
} // End of namespace Mohawk
#endif

View File

@ -42,6 +42,7 @@ Debugger::Debugger(Parallaction *vm)
DCmd_Register("zones", WRAP_METHOD(Debugger, Cmd_Zones));
DCmd_Register("animations", WRAP_METHOD(Debugger, Cmd_Animations));
DCmd_Register("globalflags",WRAP_METHOD(Debugger, Cmd_GlobalFlags));
DCmd_Register("toggleglobalflag",WRAP_METHOD(Debugger, Cmd_ToggleGlobalFlag));
DCmd_Register("localflags", WRAP_METHOD(Debugger, Cmd_LocalFlags));
DCmd_Register("locations", WRAP_METHOD(Debugger, Cmd_Locations));
DCmd_Register("gfxobjects", WRAP_METHOD(Debugger, Cmd_GfxObjects));
@ -117,6 +118,32 @@ bool Debugger::Cmd_GlobalFlags(int argc, const char **argv) {
return true;
}
bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) {
int i;
switch (argc) {
case 2:
i = _vm->_globalFlagsNames->lookup(argv[1]);
if (i == Table::notFound) {
DebugPrintf("invalid flag '%s'\n", argv[1]);
} else {
i--;
if ((_globalFlags & (1 << i)) == 0)
_globalFlags |= (1 << i);
else
_globalFlags &= ~(1 << i);
}
break;
default:
DebugPrintf("toggleglobalflag <flag name>\n");
}
return true;
}
bool Debugger::Cmd_LocalFlags(int argc, const char **argv) {
uint32 flags = _vm->getLocationFlags();

View File

@ -28,6 +28,7 @@ protected:
bool Cmd_Animations(int argc, const char **argv);
bool Cmd_LocalFlags(int argc, const char **argv);
bool Cmd_GlobalFlags(int argc, const char **argv);
bool Cmd_ToggleGlobalFlag(int argc, const char **argv);
bool Cmd_Locations(int argc, const char **argv);
bool Cmd_GfxObjects(int argc, const char **argv);
bool Cmd_Programs(int argc, const char** argv);

View File

@ -461,6 +461,10 @@ public:
void Parallaction::enterDialogueMode(ZonePtr z) {
if (!z->u._speakDialogue) {
return;
}
debugC(1, kDebugDialogue, "Parallaction::enterDialogueMode(%s)", z->u._filename.c_str());
_dialogueMan = createDialogueManager(z);
assert(_dialogueMan);

View File

@ -337,7 +337,7 @@ DECLARE_COMMAND_OPCODE(speak) {
return;
}
if (ACTIONTYPE(ctxt._cmd->_zone) == kZoneSpeak) {
if (ACTIONTYPE(ctxt._cmd->_zone) == kZoneSpeak && ctxt._cmd->_zone->u._speakDialogue) {
_vm->enterDialogueMode(ctxt._cmd->_zone);
} else {
_vm->_activeZone = ctxt._cmd->_zone;

View File

@ -538,12 +538,12 @@ GfxObj *Gfx::renderFloatingLabel(Font *font, char *text) {
setupLabelSurface(*cnv, w, h);
font->setColor((_vm->getGameType() == GType_BRA) ? 0 : 7);
font->setColor((_gameType == GType_BRA) ? 0 : 7);
font->drawString((byte*)cnv->pixels + 1, cnv->w, text);
font->drawString((byte*)cnv->pixels + 1 + cnv->w * 2, cnv->w, text);
font->drawString((byte*)cnv->pixels + cnv->w, cnv->w, text);
font->drawString((byte*)cnv->pixels + 2 + cnv->w, cnv->w, text);
font->setColor((_vm->getGameType() == GType_BRA) ? 11 : 1);
font->setColor((_gameType == GType_BRA) ? 11 : 1);
font->drawString((byte*)cnv->pixels + 1 + cnv->w, cnv->w, text);
} else {
w = font->getStringWidth(text);
@ -835,7 +835,7 @@ void Gfx::setBackground(uint type, BackgroundInfo *info) {
// The PC version of BRA needs the entries 20-31 of the palette to be constant, but
// the background resource files are screwed up. The right colors come from an unused
// bitmap (pointer.bmp). Nothing is known about the Amiga version so far.
if ((_vm->getGameType() == GType_BRA) && (_vm->getPlatform() == Common::kPlatformPC)) {
if ((_gameType == GType_BRA) && (_vm->getPlatform() == Common::kPlatformPC)) {
int r, g, b;
for (uint i = 16; i < 32; i++) {
_backupPal.getEntry(i, r, g, b);

View File

@ -203,13 +203,13 @@ int Input::updateGameInput() {
return event;
}
if (_vm->getGameType() == GType_Nippon) {
if (_gameType == GType_Nippon) {
if (_hasKeyPressEvent && (_vm->getFeatures() & GF_DEMO) == 0) {
if (_keyPressed.keycode == Common::KEYCODE_l) event = kEvLoadGame;
if (_keyPressed.keycode == Common::KEYCODE_s) event = kEvSaveGame;
}
} else
if (_vm->getGameType() == GType_BRA) {
if (_gameType == GType_BRA) {
if (_hasKeyPressEvent && (_vm->getFeatures() & GF_DEMO) == 0) {
if (_keyPressed.keycode == Common::KEYCODE_F5) event = kEvIngameMenu;
}
@ -325,8 +325,13 @@ bool Input::translateGameInput() {
if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || (ACTIONTYPE(z) == kZoneCommand))) {
if (z->_flags & kFlagsNoWalk) {
// character doesn't need to walk to take specified action
bool noWalk = z->_flags & kFlagsNoWalk; // check the explicit no-walk flag
if (_gameType == GType_BRA) {
// action performed on object marked for self-use do not need walk in BRA
noWalk |= ((z->_flags & kFlagsYourself) != 0);
}
if (noWalk) {
takeAction(z);
} else {
// action delayed: if Zone defined a moveto position the character is programmed to move there,
@ -351,7 +356,7 @@ bool Input::translateGameInput() {
void Input::enterInventoryMode() {
Common::Point mousePos;
getCursorPos(mousePos);
getAbsoluteCursorPos(mousePos);
bool hitCharacter = _vm->hitZone(kZoneYou, mousePos.x, mousePos.y);
if (hitCharacter) {

View File

@ -88,9 +88,9 @@ enum ZoneFlags {
kFlagsNoWalk = 0x800, // Zone: character doesn't need to walk towards object to interact
// BRA specific
kFlagsYourself = 0x1000,
kFlagsYourself = 0x1000, // BRA: marks zones used by the character on him/herself
kFlagsScaled = 0x2000,
kFlagsSelfuse = 0x4000,
kFlagsSelfuse = 0x4000, // BRA: marks zones to be preserved across location changes (see Parallaction::freeZones)
kFlagsIsAnimation = 0x1000000, // BRA: used in walk code (trap check), to tell is a Zone is an Animation
kFlagsAnimLinked = 0x2000000
};

View File

@ -102,7 +102,8 @@ Parallaction::~Parallaction() {
Common::Error Parallaction::init() {
_gameType = getGameType();
_engineFlags = 0;
_objectsNames = NULL;
_globalFlagsNames = NULL;
@ -408,7 +409,7 @@ void Parallaction::drawAnimation(AnimationPtr anim) {
uint16 layer = LAYER_FOREGROUND;
uint16 scale = 100;
switch (getGameType()) {
switch (_gameType) {
case GType_Nippon:
if ((anim->_flags & kFlagsNoMasked) == 0) {
// Layer in NS depends on where the animation is on the screen, for each animation.
@ -523,7 +524,7 @@ void Parallaction::enterCommentMode(ZonePtr z) {
}
// TODO: move this balloons stuff into DialogueManager and BalloonManager
if (getGameType() == GType_Nippon) {
if (_gameType == GType_Nippon) {
if (!data->_filename.empty()) {
if (data->_gfxobj == 0) {
data->_gfxobj = _disk->loadStatic(data->_filename.c_str());
@ -540,7 +541,7 @@ void Parallaction::enterCommentMode(ZonePtr z) {
_gfx->setItem(_char._talk, 190, 80);
}
} else
if (getGameType() == GType_BRA) {
if (_gameType == GType_BRA) {
_balloonMan->setSingleBalloon(data->_examineText.c_str(), 0, 0, 1, BalloonManager::kNormalColor);
_gfx->setItem(_char._talk, 10, 80);
}
@ -651,13 +652,21 @@ bool Parallaction::pickupItem(ZonePtr z) {
return (slot != -1);
}
// FIXME: input coordinates must be offseted to handle scrolling!
bool Parallaction::checkSpecialZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
// not a special zone
if ((z->getX() != -2) && (z->getX() != -3)) {
return false;
// check if really a special zone
if (_gameType == GType_Nippon) {
// so-called special zones in NS have special x coordinates
if ((z->getX() != -2) && (z->getX() != -3)) {
return false;
}
}
if (_gameType == GType_BRA) {
// so far, special zones in BRA are only merge zones
if (ACTIONTYPE(z) != kZoneMerge) {
return false;
}
}
// WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
// instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
// but we need to check it separately here. The same workaround is applied in freeZones.
@ -681,28 +690,25 @@ bool Parallaction::checkSpecialZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
return false;
}
// FIXME: input coordinates must be offseted to handle scrolling!
bool Parallaction::checkZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
if (z->_flags & kFlagsRemove)
return false;
debugC(5, kDebugExec, "checkZoneBox for %s (type = %x, x = %i, y = %i)", z->_name, type, x, y);
if (!z->hitRect(x, y)) {
// check for special zones (items defined in common.loc)
if (checkSpecialZoneBox(z, type, x, y))
return true;
if (z->getX() != -1)
return false;
if (!_char._ani->hitFrameRect(x, y))
return false;
bool Parallaction::checkZoneType(ZonePtr z, uint32 type) {
if (_gameType == GType_Nippon) {
if ((type == 0) && (ITEMTYPE(z) == 0))
return true;
}
if (_gameType == GType_BRA) {
if (type == 0) {
if (ITEMTYPE(z) == 0) {
if (ACTIONTYPE(z) != kZonePath) {
return true;
}
}
if (ACTIONTYPE(z) == kZoneDoor) {
return true;
}
}
}
// normal Zone
if ((type == 0) && (ITEMTYPE(z) == 0))
return true;
if (z->_type == type)
return true;
if (ITEMTYPE(z) == type)
@ -711,7 +717,37 @@ bool Parallaction::checkZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
return false;
}
// FIXME: input coordinates must be offseted to handle scrolling!
bool Parallaction::checkZoneBox(ZonePtr z, uint32 type, uint x, uint y) {
if (z->_flags & kFlagsRemove)
return false;
debugC(5, kDebugExec, "checkZoneBox for %s (type = %x, x = %i, y = %i)", z->_name, type, x, y);
if (!z->hitRect(x, y)) {
// check for special zones (items defined in common.loc)
if (checkSpecialZoneBox(z, type, x, y))
return true;
// check if self-use zone (nothing to do with kFlagsSelfuse)
if (_gameType == GType_Nippon) {
if (z->getX() != -1) { // no explicit self-use flag in NS
return false;
}
}
if (_gameType == GType_BRA) {
if (!(z->_flags & kFlagsYourself)) {
return false;
}
}
if (!_char._ani->hitFrameRect(x, y)) {
return false;
}
// we get here only if (x,y) hits the character and the zone is marked as self-use
}
return checkZoneType(z, type);
}
bool Parallaction::checkLinkedAnimBox(ZonePtr z, uint32 type, uint x, uint y) {
if (z->_flags & kFlagsRemove)
return false;
@ -727,18 +763,14 @@ bool Parallaction::checkLinkedAnimBox(ZonePtr z, uint32 type, uint x, uint y) {
return false;
}
// NOTE: the implementation of the following lines is a different in the
// original... it is working so far, though
if ((type == 0) && (ITEMTYPE(z) == 0))
return true;
if (z->_type == type)
return true;
if (ITEMTYPE(z) == type)
return true;
return false;
return checkZoneType(z, type);
}
/* NOTE: hitZone needs to be passed absolute game coordinates to work.
When type is kZoneMerge, then x and y are the identifiers of the objects to merge,
and the above requirement does not apply.
*/
ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
uint16 _di = y;
uint16 _si = x;
@ -752,14 +784,20 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
}
}
int16 _a, _b, _c, _d;
bool _ef;
for (AnimationList::iterator ait = _location._animations.begin(); ait != _location._animations.end(); ++ait) {
AnimationPtr a = *ait;
_a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation
_a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation
if (!_a) {
if (_gameType == GType_BRA && ACTIONTYPE(a) != kZoneTrap) {
continue;
}
}
_ef = a->hitFrameRect(_si, _di);
_b = ((type != 0) || (a->_type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character)
@ -951,7 +989,7 @@ bool CharacterName::dummy() const {
}
void Parallaction::beep() {
if (getGameType() == GType_Nippon) {
if (_gameType == GType_Nippon) {
_soundMan->execute(SC_SETSFXCHANNEL, 3);
_soundMan->execute(SC_SETSFXVOLUME, 127);
_soundMan->execute(SC_SETSFXLOOPING, (int32)0);

View File

@ -280,6 +280,7 @@ public:
int32 _screenWidth;
int32 _screenHeight;
int32 _screenSize;
int _gameType;
// subsystems
Gfx *_gfx;
@ -360,6 +361,7 @@ public:
uint32 getLocationFlags();
bool checkSpecialZoneBox(ZonePtr z, uint32 type, uint x, uint y);
bool checkZoneBox(ZonePtr z, uint32 type, uint x, uint y);
bool checkZoneType(ZonePtr z, uint32 type);
bool checkLinkedAnimBox(ZonePtr z, uint32 type, uint x, uint y);
ZonePtr hitZone(uint32 type, uint16 x, uint16 y);
void runZone(ZonePtr z);

View File

@ -196,7 +196,7 @@ void Parallaction_br::runPendingZones() {
if (_activeZone) {
z = _activeZone; // speak Zone or sound
_activeZone.reset();
if (ACTIONTYPE(z) == kZoneSpeak) {
if (ACTIONTYPE(z) == kZoneSpeak && z->u._speakDialogue) {
enterDialogueMode(z);
} else {
runZone(z); // FIXME: BRA doesn't handle sound yet
@ -206,7 +206,7 @@ void Parallaction_br::runPendingZones() {
if (_activeZone2) {
z = _activeZone2; // speak Zone or sound
_activeZone2.reset();
if (ACTIONTYPE(z) == kZoneSpeak) {
if (ACTIONTYPE(z) == kZoneSpeak && z->u._speakDialogue) {
enterDialogueMode(z);
} else {
runZone(z); // FIXME: BRA doesn't handle sound yet

View File

@ -44,8 +44,10 @@ Script::~Script() {
/*
* readLineIntern read a text line and prepares it for
* parsing, by stripping the leading whitespace and
* changing tabs to spaces. It will stop on a CR or LF,
* and return an empty string (length = 0) when a line
* changing tabs to spaces. It will stop on a CR, LF, or
* SUB (0x1A), which may all occur at the end of a script
* line.
* Returns an empty string (length = 0) when a line
* has no printable text in it.
*/
char *Script::readLineIntern(char *buf, size_t bufSize) {
@ -54,7 +56,8 @@ char *Script::readLineIntern(char *buf, size_t bufSize) {
char c = _input->readSByte();
if (_input->eos())
break;
if (c == '\n' || c == '\r')
// break if EOL
if (c == '\n' || c == '\r' || c == (char)0x1A)
break;
if (c == '\t')
c = ' ';

View File

@ -286,6 +286,7 @@ void LocationParser_ns::parseAnimation(AnimationList &list, char *name) {
debugC(5, kDebugParser, "parseAnimation(name: %s)", name);
if (_vm->_location.findAnimation(name)) {
_zoneProg++;
_script->skip("endanimation");
return;
}
@ -1305,6 +1306,7 @@ void LocationParser_ns::parseZone(ZoneList &list, char *name) {
debugC(5, kDebugParser, "parseZone(name: %s)", name);
if (_vm->_location.findZone(name)) {
_zoneProg++;
_script->skip("endzone");
return;
}

View File

@ -172,11 +172,11 @@ bool MidiParser_MSC::loadMusic(byte *data, uint32 size) {
byte *pos = data;
uint32 signature = read4high(pos);
if (memcmp("tCSM", &signature, 4)) {
if (memcmp("MSCt", pos, 4)) {
warning("Expected header not found in music file.");
return false;
}
pos += 4;
_beats = read1(pos);
_ppqn = read2low(pos);

View File

@ -316,20 +316,6 @@ Common::Error SagaEngine::run() {
syncSoundSettings();
#if 0
// FIXME: Disabled this code for now. We want to get rid of OSystem::kFeatureAutoComputeDirtyRects
// and this is the last place to make use of it. We need to find out whether doing
// so causes any regressions. If it does, we can reenable it, if not, we can remove
// this code in 0.13.0.
// FIXME: This is the ugly way of reducing redraw overhead. It works
// well for 320x200 but it's unclear how well it will work for
// 640x480.
if (getGameId() == GID_ITE)
_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true);
#endif
int msec = 0;
_previousTicks = _system->getMillis();

View File

@ -332,6 +332,8 @@ uint16 Script::validateExportFunc(int pubfunct) {
if (offset == 0) {
// Check if the game has a second export table (e.g. script 912 in Camelot)
// Fixes bug #3039785
if (g_sci->getGameId() == GID_ECOQUEST) // cheap fix in here for eco quest 1, [md5] plz look into this TODO FIXME
return offset;
const uint16 *secondExportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS, 0);
if (secondExportTable) {

View File

@ -51,8 +51,72 @@ struct SciScriptSignature {
// - if not EOS, an adjust offset and the actual bytes
// - rinse and repeat
// stayAndHelp::changeState (0) is called when ego swims to the left or right
// boundaries of room 660. Normally a textbox is supposed to get on screen
// but the call is wrong, so not only do we get an error message the script
// is also hanging because the cue won't get sent out
// This also happens in sierra sci - ffs. bug #3038387
const byte ecoquest1SignatureStayAndHelp[] = {
40,
0x3f, 0x01, // link 01
0x87, 0x01, // lap param[1]
0x65, 0x14, // aTop state
0x36, // push
0x3c, // dup
0x35, 0x00, // ldi 00
0x1a, // eq?
0x31, 0x1c, // bnt [next state]
0x76, // push0
0x45, 0x01, 0x00, // callb export1 from script 0 (switching control off)
0x38, 0x22, 0x01, // pushi 0122
0x78, // push1
0x76, // push0
0x81, 0x00, // lag global[0]
0x4a, 0x06, // send 06 - ego::setMotion(0)
0x39, 0x6e, // pushi 6e (selector init)
0x39, 0x04, // pushi 04
0x76, // push0
0x76, // push0
0x39, 0x17, // pushi 17
0x7c, // pushSelf
0x51, 0x82, // class EcoNarrator
0x4a, 0x0c, // send 0c - EcoNarrator::init(0, 0, 23, self) (BADLY BROKEN!)
0x33, // jmp [end]
0
};
// daySixBeignet::changeState is called when the cop goes out and sets cycles to 220.
const uint16 ecoquest1PatchStayAndHelp[] = {
0x87, 0x01, // lap param[1]
0x65, 0x14, // aTop state
0x36, // push
0x2f, 0x22, // bt [next state] (this optimization saves 6 bytes)
0x39, 0x00, // pushi 0 (wasting 1 byte here)
0x45, 0x01, 0x00, // callb export1 from script 0 (switching control off)
0x38, 0x22, 0x01, // pushi 0122
0x78, // push1
0x76, // push0
0x81, 0x00, // lag global[0]
0x4a, 0x06, // send 06 - ego::setMotion(0)
0x39, 0x6e, // pushi 6e (selector init)
0x39, 0x06, // pushi 06
0x39, 0x02, // pushi 02 (additional 2 bytes)
0x76, // push0
0x76, // push0
0x39, 0x17, // pushi 17
0x7c, // pushSelf
0x38, 0x80, 0x02, // pushi 280 (additional 3 bytes)
0x51, 0x82, // class EcoNarrator
0x4a, 0x10, // send 10 - EcoNarrator::init(2, 0, 0, 23, self, 640)
PATCH_END
};
// script, description, magic DWORD, adjust
const SciScriptSignature ecoquest1Signatures[] = {
{ 660, "CD: bad messagebox and freeze", PATCH_MAGICDWORD(0x38, 0x22, 0x01, 0x78), -17, ecoquest1SignatureStayAndHelp, ecoquest1PatchStayAndHelp },
{ 0, NULL, 0, 0, NULL, NULL }
};
// daySixBeignet::changeState (4) is called when the cop goes out and sets cycles to 220.
// this is not enough time to get to the door, so we patch that to 23 seconds
const byte gk1SignatureDay6PoliceBeignet[] = {
4,
@ -78,12 +142,14 @@ const uint16 gk1PatchDay6PoliceBeignet[] = {
PATCH_END
};
// sargSleeping::changeState (8) is called when the cop falls asleep and sets cycles to 220.
// this is not enough time to get to the door, so we patch it to 42 seconds
const byte gk1SignatureDay6PoliceSleep[] = {
4,
0x35, 0x08, // ldi 08
0x1a, // eq?
0x31, // bnt [next state check]
+1, 5, // [skip 1 byte, offset of bnt]
+1, 6, // [skip 1 byte, offset of bnt]
0x34, 0xdc, 0x00, // ldi 220
0x65, 0x1a, // aTop cycles
0x32, // jmp [end]
@ -97,8 +163,27 @@ const uint16 gk1PatchDay6PoliceSleep[] = {
PATCH_END
};
// startOfDay5::changeState (20h) - when gabriel goes to the phone the script will hang
const byte gk1SignatureDay5PhoneFreeze[] = {
5,
0x35, 0x03, // ldi 03
0x65, 0x1a, // aTop cycles
0x32, // jmp [end]
+2, 3, // [skip 2 bytes, offset of jmp]
0x3c, // dup
0x35, 0x21, // ldi 21
0
};
const uint16 gk1PatchDay5PhoneFreeze[] = {
0x35, 0x06, // ldi 06
0x65, 0x20, // aTop ticks
PATCH_END
};
// script, description, magic DWORD, adjust
const SciScriptSignature gk1Signatures[] = {
{ 212, "day 5 phone freeze", PATCH_MAGICDWORD(0x35, 0x03, 0x65, 0x1a), 0, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze },
{ 230, "day 6 police beignet timer issue", PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -16, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet },
{ 230, "day 6 police sleep timer issue", PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -5, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep },
{ 0, NULL, 0, 0, NULL, NULL }
@ -325,6 +410,8 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr
void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
const SciScriptSignature *signatureTable = NULL;
if (g_sci->getGameId() == GID_ECOQUEST)
signatureTable = ecoquest1Signatures;
if (g_sci->getGameId() == GID_GK1)
signatureTable = gk1Signatures;
// hoyle4 now works due workaround inside GfxPorts
@ -341,7 +428,7 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
int32 foundOffset = findSignature(signatureTable, scriptData, scriptSize);
if (foundOffset != -1) {
// found, so apply the patch
warning("matched %s on script %d offset %d", signatureTable->description, scriptNr, foundOffset);
warning("matched and patched %s on script %d offset %d", signatureTable->description, scriptNr, foundOffset);
applyPatch(signatureTable->patch, scriptData, scriptSize, foundOffset);
}
}

View File

@ -114,6 +114,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_JONES, 764, 255, 0, "", "export 0", -1, 14, { WORKAROUND_FAKE, 0 } }, // jones/ega&vga only - called when the game starts
{ GID_KQ5, -1, 0, 0, "", "export 29", -1, 3, { WORKAROUND_FAKE, 0 } }, // called when playing harp for the harpies or when aborting dialog in toy shop, is used for kDoAudio - bug #3034700
{ GID_KQ5, 25, 25, 0, "rm025", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // inside witch forest, when going to the room where the walking rock is
{ GID_KQ5, 55, 55, 0, "helpScript", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // when giving the tambourine to the monster in the labyrinth (only happens at one of the locations) - bug #3041262
{ GID_KQ6, -1, 30, 0, "rats", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // rats in the catacombs (temps 1 - 5) - bugs #3034597, #3035495, #3035824
{ GID_KQ6, 210, 210, 0, "rm210", "scriptCheck", -1, 0, { WORKAROUND_FAKE, 1 } }, // using inventory in that room - bug #3034565
{ GID_KQ6, 500, 500, 0, "rm500", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to island of the beast
@ -124,8 +125,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up (initial bug #3034985)
{ GID_LAURABOW2, -1, 24, 0, "gcWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu
{ GID_LAURABOW2, -1, 21, 0, "dropCluesCode", "doit", -1, 1, { WORKAROUND_FAKE, 0x7fff } }, // when asking some questions (e.g. the reporter about the burglary, or the policeman about Ziggy). Must be big, as the game scripts perform lt on it and start deleting journal entries - bugs #3035068, #3036274
{ GID_LAURABOW2, -1, 90, 0, "aTut", "init", -1, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum (bug #3041257)
{ GID_LAURABOW2, -1, 90, 0, "aZiggy", "init", -1, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum (bug #3041257)
{ GID_LAURABOW2, -1, 90, 1, "MuseumActor", "init", -1, 6, { WORKAROUND_FAKE, 0 } }, // Random actors in museum (bug #3041257)
{ GID_LAURABOW2, 240, 240, 0, "sSteveAnimates", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // Steve Dorian's idle animation at the docks - bug #3036291
{ GID_LONGBOW, -1, 213, 0, "clear", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // When giving an answer using the druid hand sign code in any room
{ GID_LONGBOW, -1, 213, 0, "letter", "handleEvent", 0xa8, 1, { WORKAROUND_FAKE, 0 } }, // When using the druid hand sign code in any room - bug #3036601
@ -155,6 +155,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #3036390, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #3039774, temp 1)
{ GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #3040624
{ GID_QFG3, 470, 470, -1, "rm470", "notify", -1, 0, { WORKAROUND_FAKE, 0 } }, // closing the character screen in the Simbani village in the room with the bridge, bug #3040565
{ GID_QFG3, 490, 490, -1, "computersMove", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // when finishing awari game, bug #3040579
{ GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen
{ GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu
{ GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happen sometimes in fights

View File

@ -243,6 +243,8 @@ void GfxAnimate::fill(byte &old_picNotValid) {
}
}
//warning("%s", _s->_segMan->getObjectName(curObject));
if (!view->isScaleable()) {
// Laura Bow 2 (especially floppy) depends on this, some views are not supposed to be scaleable
// this "feature" was removed in later versions of SCI1.1
@ -516,6 +518,19 @@ void GfxAnimate::reAnimate(Common::Rect rect) {
}
}
void GfxAnimate::preprocessAddToPicList() {
AnimateList::iterator it;
const AnimateList::iterator end = _list.end();
for (it = _list.begin(); it != end; ++it) {
if (it->priority == -1)
it->priority = _ports->kernelCoordinateToPriority(it->y);
// Do not allow priority to get changed by fill()
it->signal |= kSignalFixedPriority;
}
}
void GfxAnimate::addToPicDrawCels() {
reg_t curObject;
GfxView *view = NULL;
@ -525,17 +540,11 @@ void GfxAnimate::addToPicDrawCels() {
for (it = _list.begin(); it != end; ++it) {
curObject = it->object;
if (it->priority == -1)
it->priority = _ports->kernelCoordinateToPriority(it->y);
// Get the corresponding view
view = _cache->getView(it->viewId);
// Create rect according to coordinates and given cel
view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
// draw corresponding cel
_paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo);
_paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
if ((it->signal & kSignalIgnoreActor) == 0) {
it->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, it->celRect.top, it->celRect.bottom - 1);
_paint16->fillRect(it->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
@ -679,6 +688,7 @@ void GfxAnimate::addToPicSetPicNotValid() {
void GfxAnimate::kernelAddToPicList(reg_t listReference, int argc, reg_t *argv) {
List *list;
byte tempPicNotValid = 0;
_ports->setPort((Port *)_ports->_picWind);
@ -687,6 +697,8 @@ void GfxAnimate::kernelAddToPicList(reg_t listReference, int argc, reg_t *argv)
error("kAddToPic called with non-list as parameter");
makeSortedList(list);
preprocessAddToPicList();
fill(tempPicNotValid);
addToPicDrawCels();
addToPicSetPicNotValid();

View File

@ -100,6 +100,7 @@ public:
void updateScreen(byte oldPicNotValid);
void restoreAndDelete(int argc, reg_t *argv);
void reAnimate(Common::Rect rect);
void preprocessAddToPicList();
void addToPicDrawCels();
void addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control);

View File

@ -256,6 +256,8 @@ void GfxView::initData(GuiResourceId resourceId) {
cel->scriptHeight = cel->height = READ_SCI11ENDIAN_UINT16(celData + 2);
cel->displaceX = READ_SCI11ENDIAN_UINT16(celData + 4);
cel->displaceY = READ_SCI11ENDIAN_UINT16(celData + 6);
if (cel->displaceY < 0)
cel->displaceY += 255; // sierra did this adjust in their sci1.1 getCelRect() - not sure about sci32
assert(cel->width && cel->height);

File diff suppressed because it is too large Load Diff

View File

@ -1,209 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
/* Sound engine */
#ifndef SCI_SFX_CORE_H
#define SCI_SFX_CORE_H
#include "common/error.h"
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/songlib.h"
#include "sci/resource.h"
namespace Sci {
class SfxPlayer;
class SongIterator;
struct fade_params_t;
#define SFX_TICKS_PER_SEC 60 /* MIDI ticks per second */
#define SFX_STATE_FLAG_MULTIPLAY (1 << 0) /* More than one song playable
** simultaneously ? */
#define SFX_STATE_FLAG_NOSOUND (1 << 1) /* Completely disable sound playing */
class SfxState {
private:
SfxPlayer *_player;
public: // FIXME, make private
SongIterator *_it; /**< The song iterator at the heart of things */
uint _flags; /**< SFX_STATE_FLAG_* */
SongLibrary _songlib; /**< Song library */
Song *_song; /**< Active song, or start of active song chain */
bool _suspended; /**< Whether we are suspended */
ResourceManager *_resMan;
public:
SfxState();
~SfxState();
/***********/
/* General */
/***********/
/* Initializes the sound engine
** Parameters: (ResourceManager *) resMan: Resource manager for initialization
** (int) flags: SFX_STATE_FLAG_*
*/
void sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion);
/** Deinitializes the sound subsystem. */
void sfx_exit();
/* Suspends/unsuspends the sound sybsystem
** Parameters: (int) suspend: Whether to suspend (non-null) or to unsuspend
*/
void sfx_suspend(bool suspend);
/* Polls the sound server for cues etc.
** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise
** (SongHandle) *handle: The affected handle
** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP)
*/
int sfx_poll(SongHandle *handle, int *cue);
/* Polls the sound server for cues etc.
** Parameters: (SongHandle) handle: The handle to poll
** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise
** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP)
*/
int sfx_poll_specific(SongHandle handle, int *cue);
/* Determines the current global volume settings
** Returns : (int) The global volume, between 0 (silent) and 127 (max. volume)
*/
int sfx_getVolume();
/* Determines the current global volume settings
** Parameters: (int) volume: The new global volume, between 0 and 127 (see above)
*/
void sfx_setVolume(int volume);
/* Stops all songs currently playing, purges song library
*/
void sfx_all_stop();
/*****************/
/* Song basics */
/*****************/
/* Adds a song to the internal sound library
** Parameters: (SongIterator *) it: The iterator describing the song
** (int) priority: Initial song priority (higher <-> more important)
** (SongHandle) handle: The handle to associate with the song
*/
void sfx_add_song(SongIterator *it, int priority, SongHandle handle, int resnum);
/* Deletes a song and its associated song iterator from the song queue
** Parameters: (SongHandle) handle: The song to remove
*/
void sfx_remove_song(SongHandle handle);
/**********************/
/* Song modifications */
/**********************/
/* Sets the song status, i.e. whether it is playing, suspended, or stopped.
** Parameters: (SongHandle) handle: Handle of the song to modify
** (int) status: The song status the song should assume
** WAITING and PLAYING are set implicitly and essentially describe the same state
** as far as this function is concerned.
*/
void sfx_song_set_status(SongHandle handle, int status);
/* Sets the new song priority
** Parameters: (SongHandle) handle: The handle to modify
** (int) priority: The priority to set
*/
void sfx_song_renice(SongHandle handle, int priority);
/* Sets the number of loops for the specified song
** Parameters: (SongHandle) handle: The song handle to reference
** (int) loops: Number of loops to set
*/
void sfx_song_set_loops(SongHandle handle, int loops);
/* Sets the number of loops for the specified song
** Parameters: (SongHandle) handle: The song handle to reference
** (int) hold: Number of loops to setn
*/
void sfx_song_set_hold(SongHandle handle, int hold);
/* Instructs a song to be faded out
** Parameters: (SongHandle) handle: The song handle to reference
** (fade_params_t *) fade_setup: The precise fade-out configuration to use
*/
void sfx_song_set_fade(SongHandle handle, fade_params_t *fade_setup);
// Previously undocumented:
Common::Error sfx_send_midi(SongHandle handle, int channel,
int command, int arg1, int arg2);
// misc
/**
* Determines the polyphony of the player in use.
* @return Number of voices the active player can emit
*/
int sfx_get_player_polyphony();
/**
* Tells the player to stop its internal iterator.
*/
void sfx_reset_player();
/**
* Pass a raw MIDI event to the synth of the player.
* @param argc Length of buffer holding the midi event
* @param argv The buffer itself
*/
void sfx_player_tell_synth(int buf_nr, byte *buf);
protected:
void freezeTime();
void thawTime();
bool isPlaying(Song *song);
void setSongStatus(Song *song, int status);
void updateSingleSong();
void updateMultiSong();
void update();
};
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS
#endif // SCI_SFX_CORE_H

File diff suppressed because it is too large Load Diff

View File

@ -1,326 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
/* Song iterator declarations */
#ifndef SCI_SFX_SFX_ITERATOR_H
#define SCI_SFX_SFX_ITERATOR_H
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/drivers/mididriver.h"
namespace Audio {
class AudioStream;
}
namespace Sci {
enum SongIteratorStatus {
SI_FINISHED = -1, /**< Song finished playing */
SI_LOOP = -2, /**< Song just looped */
SI_ABSOLUTE_CUE = -3, /**< Found a song cue (absolute) */
SI_RELATIVE_CUE = -4, /**< Found a song cue (relative) */
SI_PCM = -5, /**< Found a PCM */
SI_IGNORE = -6, /**< This event got edited out by the remapper */
SI_MORPH = -255 /**< Song iterator requested self-morph. */
};
#define FADE_ACTION_NONE 0
#define FADE_ACTION_FADE_AND_STOP 1
#define FADE_ACTION_FADE_AND_CONT 2
struct fade_params_t {
int ticks_per_step;
int final_volume;
int step_size;
int action;
};
/* Helper defs for messages */
enum {
_SIMSG_BASE, /* Any base decoder */
_SIMSG_PLASTICWRAP /* Any "Plastic" (discardable) wrapper decoder */
};
/* Base messages */
enum {
_SIMSG_BASEMSG_SET_LOOPS, /* Set loops */
_SIMSG_BASEMSG_SET_PLAYMASK, /* Set the current playmask for filtering */
_SIMSG_BASEMSG_SET_RHYTHM, /* Activate/deactivate rhythm channel */
_SIMSG_BASEMSG_ACK_MORPH, /* Acknowledge self-morph */
_SIMSG_BASEMSG_STOP, /* Stop iterator */
_SIMSG_BASEMSG_PRINT, /* Print self to stderr, after printing param1 tabs */
_SIMSG_BASEMSG_SET_HOLD, /* Set value of hold parameter to expect */
_SIMSG_BASEMSG_SET_FADE /* Set fade parameters */
};
/* "Plastic" (discardable) wrapper messages */
enum {
_SIMSG_PLASTICWRAP_ACK_MORPH = _SIMSG_BASEMSG_ACK_MORPH /* Acknowledge self-morph */
};
/* Messages */
#define SIMSG_SET_LOOPS(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_LOOPS,(x)
#define SIMSG_SET_PLAYMASK(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_PLAYMASK,(x)
#define SIMSG_SET_RHYTHM(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_RHYTHM,(x)
#define SIMSG_ACK_MORPH _SIMSG_PLASTICWRAP,_SIMSG_PLASTICWRAP_ACK_MORPH,0
#define SIMSG_STOP _SIMSG_BASE,_SIMSG_BASEMSG_STOP,0
#define SIMSG_PRINT(indentation) _SIMSG_BASE,_SIMSG_BASEMSG_PRINT,(indentation)
#define SIMSG_SET_HOLD(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_HOLD,(x)
/* Message transmission macro: Takes song reference, message reference */
#define SIMSG_SEND(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, m))
#define SIMSG_SEND_FADE(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, _SIMSG_BASE, _SIMSG_BASEMSG_SET_FADE, m))
typedef unsigned long songit_id_t;
#define SONGIT_MAX_LISTENERS 2
class TeeSongIterator;
class SongIterator {
public:
struct Message {
songit_id_t ID;
uint _class; /* Type of iterator supposed to receive this */
uint _type;
union {
uint i;
void *p;
} _arg;
Message() : ID(0), _class(0xFFFF), _type(0xFFFF) {}
/**
* Create a song iterator message.
*
* @param id: song ID the message is targeted to
* @param recipient_class: Message recipient class
* @param type message type
* @param a argument
*
* @note You should only use this with the SIMSG_* macros
*/
Message(songit_id_t id, int recipient_class, int type, int a)
: ID(id), _class(recipient_class), _type(type) {
_arg.i = a;
}
/**
* Create a song iterator message, wherein the first parameter is a pointer.
*
* @param id: song ID the message is targeted to
* @param recipient_class: Message recipient class
* @param type message type
* @param a argument
*
* @note You should only use this with the SIMSG_* macros
*/
Message(songit_id_t id, int recipient_class, int type, void *a)
: ID(id), _class(recipient_class), _type(type) {
_arg.p = a;
}
};
public:
songit_id_t ID;
uint16 channel_mask; /* Bitmask of all channels this iterator will use */
fade_params_t fade;
int priority;
/* Death listeners */
/* These are not reset during initialisation */
TeeSongIterator *_deathListeners[SONGIT_MAX_LISTENERS];
/* See songit_* for the constructor and non-virtual member functions */
byte channel_remap[MIDI_CHANNELS]; ///< Remapping for channels
public:
SongIterator();
SongIterator(const SongIterator &);
virtual ~SongIterator();
/**
* Resets/initializes the sound iterator.
*/
virtual void init() {}
/**
* Reads the next MIDI operation _or_ delta time.
* @param buf The buffer to write to (needs to be able to store at least 4 bytes)
* @param result Number of bytes written to the buffer
* (equals the number of bytes that need to be passed
* to the lower layers) for 0, the cue value for SI_CUE,
* or the number of loops remaining for SI_LOOP.
* @return zero if a MIDI operation was written, SI_FINISHED
* if the song has finished playing, SI_LOOP if looping
* (after updating the loop variable), SI_CUE if we found
* a cue, SI_PCM if a PCM was found, or the number of ticks
* to wait before this function should be called next.
*
* @note If SI_PCM is returned, get_pcm() may be used to retrieve the associated
* PCM, but this must be done before any subsequent calls to next().
*
* @todo The actual buffer size should either be specified or passed in, so that
* we can detect buffer overruns.
*/
virtual int nextCommand(byte *buf, int *result) = 0;
/**
Checks for the presence of a pcm sample.
* @return NULL if no PCM data was found, an AudioStream otherwise.
*/
virtual Audio::AudioStream *getAudioStream() = 0;
/**
* Handles a message to the song iterator.
* @param msg the message to handle
* @return NULL if the message was not understood,
* this if the message could be handled, or a new song iterator
* if the current iterator had to be morphed (but the message could
* still be handled)
*
* @note This function is not supposed to be called directly; use
* songit_handle_message() instead. It should not recurse, since songit_handle_message()
* takes care of that and makes sure that its delegate received the message (and
* was morphed) before self.
*/
virtual SongIterator *handleMessage(Message msg) = 0;
/**
* Gets the song position to store in a savegame.
*/
virtual int getTimepos() = 0;
/**
* Clone this song iterator.
* @param delta number of ticks that still need to elapse until the
* next item should be read from the song iterator
*/
virtual SongIterator *clone(int delta) = 0;
private:
// Make the assignment operator unreachable, just in case...
SongIterator& operator=(const SongIterator&);
};
/********************************/
/*-- Song iterator operations --*/
/********************************/
enum SongIteratorType {
SCI_SONG_ITERATOR_TYPE_SCI0 = 0,
SCI_SONG_ITERATOR_TYPE_SCI1 = 1
};
#define IT_READER_MASK_MIDI (1 << 0)
#define IT_READER_MASK_DELAY (1 << 1)
#define IT_READER_MASK_LOOP (1 << 2)
#define IT_READER_MASK_CUE (1 << 3)
#define IT_READER_MASK_PCM (1 << 4)
#define IT_READER_MAY_FREE (1 << 10) /* Free SI_FINISHED iterators */
#define IT_READER_MAY_CLEAN (1 << 11)
/* MAY_CLEAN: May instantiate cleanup iterators
** (use for players; this closes open channels at the end of a song) */
#define IT_READER_MASK_ALL ( IT_READER_MASK_MIDI \
| IT_READER_MASK_DELAY \
| IT_READER_MASK_LOOP \
| IT_READER_MASK_CUE \
| IT_READER_MASK_PCM )
/* Convenience wrapper around it->next
** Parameters: (SongIterator **it) Reference to the iterator to access
** (byte *) buf: The buffer to write to (needs to be able to
** store at least 4 bytes)
** (int) mask: IT_READER_MASK options specifying the events to
** listen for
** Returns : (int) zero if a MIDI operation was written, SI_FINISHED
** if the song has finished playing, SI_LOOP if looping
** (after updating the loop variable), SI_CUE if we found
** a cue, SI_PCM if a PCM was found, or the number of ticks
** to wait before this function should be called next.
** (int) *result: Number of bytes written to the buffer
** (equals the number of bytes that need to be passed
** to the lower layers) for 0, the cue value for SI_CUE,
** or the number of loops remaining for SI_LOOP.
*/
int songit_next(SongIterator **it, byte *buf, int *result, int mask);
/* Constructs a new song iterator object
** Parameters: (byte *) data: The song data to iterate over
** (uint) size: Number of bytes in the song
** (int) type: One of the SCI_SONG_ITERATOR_TYPEs
** (songit_id_t) id: An ID for addressing the song iterator
** Returns : (SongIterator *) A newly allocated but uninitialized song
** iterator, or NULL if 'type' was invalid or unsupported
*/
SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id);
/* Constructs a new song timer iterator object
** Parameters: (int) delta: The delta after which to fire SI_FINISHED
** Returns : (SongIterator *) A newly allocated but uninitialized song
** iterator
*/
SongIterator *new_timer_iterator(int delta);
/* Handles a message to the song iterator
** Parameters: (SongIterator **): A reference to the variable storing the song iterator
** Returns : (int) Non-zero if the message was understood
** The song iterator may polymorph as result of msg, so a writeable reference is required.
*/
int songit_handle_message(SongIterator **it_reg, SongIterator::Message msg);
/* Creates a new song iterator which fast-forwards
** Parameters: (SongIterator *) it: The iterator to wrap
** (int) delta: The number of ticks to skip
** Returns : (SongIterator) A newly created song iterator
** which skips all delta times
** until 'delta' has been used up
*/
SongIterator *new_fast_forward_iterator(SongIterator *it, int delta);
/* Combines two song iterators into one
** Parameters: (sfx_iterator_t *) it1: One of the two iterators, or NULL
** (sfx_iterator_t *) it2: The other iterator, or NULL
** Returns : (sfx_iterator_t *) A combined iterator
** If a combined iterator is returned, it will be flagged to be allowed to
** dispose of 'it1' and 'it2', where applicable. This means that this
** call should be used by song players, but not by the core sound system
*/
SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2);
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS
#endif // SCI_SFX_SFX_ITERATOR_H

View File

@ -1,276 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef SCI_SFX_SFX_ITERATOR_INTERNAL
#define SCI_SFX_SFX_ITERATOR_INTERNAL
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/iterator.h"
#include "sci/sound/drivers/mididriver.h"
#include "common/array.h"
#include "common/list.h"
namespace Sci {
/* Iterator types */
enum {
SI_STATE_UNINITIALISED = -1,
SI_STATE_DELTA_TIME = 0, ///< Now at a delta time
SI_STATE_COMMAND = 1, ///< Now at a MIDI operation
SI_STATE_PENDING = 2, ///< Pending for loop
SI_STATE_FINISHED = 3, ///< End of song
SI_STATE_PCM = 4, ///< Should report a PCM next (-> DELTA_TIME)
SI_STATE_PCM_MAGIC_DELTA = 5 ///< Should report a ``magic'' one tick delta time next (goes on to FINISHED)
};
struct SongIteratorChannel {
int state; ///< State of this song iterator channel
int offset; ///< Offset into the data chunk */
int end; ///< Last allowed byte in track */
int id; ///< Some channel ID */
/**
* Number of ticks before the specified channel is next used, or
* CHANNEL_DELAY_MISSING to indicate that the delay has not yet
* been read.
*/
int delay;
/* Two additional offsets for recovering: */
int loop_offset;
int initial_offset;
int playmask; ///< Active playmask (MIDI channels to play in here) */
int loop_timepos; ///< Total delay for this channel's loop marker */
int total_timepos; ///< Number of ticks since the beginning, ignoring loops */
int timepos_increment; ///< Number of ticks until the next command (to add) */
byte last_cmd; ///< Last operation executed, for running status */
public:
void init(int id, int offset, int end);
void resetSynthChannels();
};
class BaseSongIterator : public SongIterator {
public:
int _polyphony[MIDI_CHANNELS]; ///< # of simultaneous notes on each
int _ccc; ///< Cumulative cue counter, for those who need it
byte _resetflag; ///< for 0x4C -- on DoSound StopSound, do we return to start?
int _deviceId; ///< ID of the device we generating events for
int _numActiveChannels; ///< Number of active channels
Common::Array<byte> _data; ///< Song data
int _loops; ///< Number of loops remaining
public:
BaseSongIterator(byte *data, uint size, songit_id_t id);
protected:
int parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags);
int processMidi(byte *buf, int *result, SongIteratorChannel *channel, int flags);
};
/********************************/
/*--------- SCI 0 --------------*/
/********************************/
class Sci0SongIterator : public BaseSongIterator {
public:
SongIteratorChannel _channel;
public:
Sci0SongIterator(byte *data, uint size, songit_id_t id);
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream();
SongIterator *handleMessage(Message msg);
void init();
int getTimepos();
SongIterator *clone(int delta);
};
/********************************/
/*--------- SCI 1 --------------*/
/********************************/
struct Sci1Sample {
/**
* Time left-- initially, this is 'Sample point 1'.
* After initialisation, it is 'sample point 1 minus the sample
* point of the previous sample'
*/
int delta;
int size;
bool announced; /* Announced for download (SI_PCM) */
int rate;
byte *_data;
};
class Sci1SongIterator : public BaseSongIterator {
public:
SongIteratorChannel _channels[MIDI_CHANNELS];
/* Invariant: Whenever channels[i].delay == CHANNEL_DELAY_MISSING,
** channel_offset[i] points to a delta time object. */
bool _initialised; /**!< Whether the MIDI channel setup has been initialised */
int _numChannels; /**!< Number of channels actually used */
Common::List<Sci1Sample> _samples;
int _numLoopedChannels; /**!< Number of channels that are ready to loop */
int _delayRemaining; /**!< Number of ticks that haven't been polled yet */
int _hold;
public:
Sci1SongIterator(byte *data, uint size, songit_id_t id);
~Sci1SongIterator();
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream();
SongIterator *handleMessage(Message msg);
void init();
int getTimepos();
SongIterator *clone(int delta);
private:
int initSample(const int offset);
int initSong();
int getSmallestDelta() const;
void updateDelta(int delta);
/** Checks that none of the channels is waiting for its delta to be read */
bool noDeltaTime() const;
/** Determine the channel # of the next active event, or -1 */
int getCommandIndex() const;
};
#define PLAYMASK_NONE 0x0
/***************************/
/*--------- Timer ---------*/
/***************************/
/**
* A song iterator which waits a specified time and then fires
* SI_FINISHED. Used by DoSound, where audio resources are played (SCI1)
*/
class TimerSongIterator : public SongIterator {
protected:
int _delta; /**!< Remaining time */
public:
TimerSongIterator(int delta) : _delta(delta) {}
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream() { return NULL; }
SongIterator *handleMessage(Message msg) { return NULL; }
int getTimepos() { return 0; }
SongIterator *clone(int delta) { return new TimerSongIterator(*this); }
};
/**********************************/
/*--------- Fast Forward ---------*/
/**********************************/
/**
* A song iterator which fast-forwards another iterator.
* Skips all delta times until a specified 'delta' has been used up.
*/
class FastForwardSongIterator : public SongIterator {
protected:
SongIterator *_delegate;
int _delta; /**!< Remaining time */
public:
FastForwardSongIterator(SongIterator *capsit, int delta);
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream();
SongIterator *handleMessage(Message msg);
int getTimepos();
SongIterator *clone(int delta);
};
/**********************************/
/*--------- Tee iterator ---------*/
/**********************************/
enum {
TEE_LEFT = 0,
TEE_RIGHT = 1,
TEE_LEFT_ACTIVE = (1<<0),
TEE_RIGHT_ACTIVE = (1<<1),
TEE_LEFT_READY = (1<<2), /**!< left result is ready */
TEE_RIGHT_READY = (1<<3), /**!< right result is ready */
TEE_LEFT_PCM = (1<<4),
TEE_RIGHT_PCM = (1<<5)
};
/**
* This iterator combines two iterators, returns the next event available from either.
*/
class TeeSongIterator : public SongIterator {
public:
int _status;
bool _readyToMorph; /**!< One of TEE_MORPH_* above */
struct {
SongIterator *it;
byte buf[4];
int result;
int retval;
} _children[2];
public:
TeeSongIterator(SongIterator *left, SongIterator *right);
~TeeSongIterator();
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream();
SongIterator *handleMessage(Message msg);
void init();
int getTimepos() { return 0; }
SongIterator *clone(int delta);
};
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS
#endif // SCI_SFX_SFX_ITERATOR_INTERNAL

View File

@ -1,189 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/core.h"
#include "sci/sound/iterator/iterator.h"
namespace Sci {
#define debug_stream stderr
Song::Song() : _wakeupTime(0, SFX_TICKS_PER_SEC) {
_handle = 0;
_resourceNum = 0;
_priority = 0;
_status = SOUND_STATUS_STOPPED;
_restoreBehavior = RESTORE_BEHAVIOR_CONTINUE;
_restoreTime = 0;
_loops = 0;
_hold = 0;
_it = 0;
_delay = 0;
_next = NULL;
_nextPlaying = NULL;
_nextStopping = NULL;
}
Song::Song(SongHandle handle, SongIterator *it, int priority) : _wakeupTime(0, SFX_TICKS_PER_SEC) {
_handle = handle;
_resourceNum = 0;
_priority = priority;
_status = SOUND_STATUS_STOPPED;
_restoreBehavior = RESTORE_BEHAVIOR_CONTINUE;
_restoreTime = 0;
_loops = 0;
_hold = 0;
_it = it;
_delay = 0;
_next = NULL;
_nextPlaying = NULL;
_nextStopping = NULL;
}
void SongLibrary::addSong(Song *song) {
Song **seeker = NULL;
int pri = song->_priority;
if (NULL == song) {
warning("addSong(): NULL passed for song");
return;
}
seeker = &_lib;
while (*seeker && ((*seeker)->_priority > pri))
seeker = &((*seeker)->_next);
song->_next = *seeker;
*seeker = song;
}
void SongLibrary::freeSounds() {
Song *next = _lib;
while (next) {
Song *song = next;
delete song->_it;
song->_it = NULL;
next = song->_next;
delete song;
}
_lib = NULL;
}
Song *SongLibrary::findSong(SongHandle handle) {
Song *seeker = _lib;
while (seeker) {
if (seeker->_handle == handle)
break;
seeker = seeker->_next;
}
return seeker;
}
Song *SongLibrary::findNextActive(Song *other) {
Song *seeker = other ? other->_next : _lib;
while (seeker) {
if ((seeker->_status == SOUND_STATUS_WAITING) ||
(seeker->_status == SOUND_STATUS_PLAYING))
break;
seeker = seeker->_next;
}
/* Only return songs that have equal priority */
if (other && seeker && other->_priority > seeker->_priority)
return NULL;
return seeker;
}
Song *SongLibrary::findFirstActive() {
return findNextActive(NULL);
}
int SongLibrary::removeSong(SongHandle handle) {
int retval;
Song *goner = _lib;
if (!goner)
return -1;
if (goner->_handle == handle)
_lib = goner->_next;
else {
while ((goner->_next) && (goner->_next->_handle != handle))
goner = goner->_next;
if (goner->_next) { /* Found him? */
Song *oldnext = goner->_next;
goner->_next = goner->_next->_next;
goner = oldnext;
} else return -1; /* No. */
}
retval = goner->_status;
delete goner->_it;
delete goner;
return retval;
}
int SongLibrary::countSongs() {
Song *seeker = _lib;
int retval = 0;
while (seeker) {
retval++;
seeker = seeker->_next;
}
return retval;
}
void SongLibrary::setSongRestoreBehavior(SongHandle handle, RESTORE_BEHAVIOR action) {
Song *seeker = findSong(handle);
seeker->_restoreBehavior = action;
}
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS

View File

@ -1,171 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
/* Song library */
#ifndef SCI_SFX_SFX_SONGLIB_H
#define SCI_SFX_SFX_SONGLIB_H
#include "common/scummsys.h"
#include "sound/timestamp.h"
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
namespace Sci {
class SongIterator;
#define SOUND_STATUS_STOPPED 0
#define SOUND_STATUS_PLAYING 1
#define SOUND_STATUS_SUSPENDED 2
/* suspended: only if ordered from kernel space */
#define SOUND_STATUS_WAITING 3
/* "waiting" means "tagged for playing, but not active right now" */
typedef unsigned long SongHandle;
enum RESTORE_BEHAVIOR {
RESTORE_BEHAVIOR_CONTINUE, /* restart a song when restored from
a saved game */
RESTORE_BEHAVIOR_RESTART /* continue it from where it was */
};
class Song {
public:
SongHandle _handle;
int _resourceNum; /**<! Resource number */
int _priority; /**!< Song priority (more important if priority is higher) */
int _status; /* See above */
int _restoreBehavior;
int _restoreTime;
/* Grabbed from the sound iterator, for save/restore purposes */
int _loops;
int _hold;
SongIterator *_it;
int _delay; /**!< Delay before accessing the iterator, in ticks */
Audio::Timestamp _wakeupTime; /**!< Timestamp indicating the next MIDI event */
Song *_next; /**!< Next song or NULL if this is the last one */
/**
* Next playing song. Used by the core song system.
*/
Song *_nextPlaying;
/**
* Next song pending stopping. Used exclusively by the core song system's
* _update_multi_song()
*/
Song *_nextStopping;
public:
Song();
/**
* Initializes a new song.
* @param handle the sound handle
* @param it the song
* @param priority the song's priority
* @return a freshly allocated song
*/
Song(SongHandle handle, SongIterator *it, int priority);
};
class SongLibrary {
public:
Song *_lib;
public:
SongLibrary() : _lib(0) {}
/** Frees a song library. */
void freeSounds();
/**
* Adds a song to a song library.
* @param song song to add
*/
void addSong(Song *song);
/**
* Looks up the song with the specified handle.
* @param handle sound handle to look for
* @return the song or NULL if it wasn't found
*/
Song *findSong(SongHandle handle);
/**
* Finds the first song playing with the highest priority.
* @return the song that should be played next, or NULL if there is none
*/
Song *findFirstActive();
/**
* Finds the next song playing with the highest priority.
*
* The functions 'findFirstActive' and 'findNextActive'
* allow to iterate over all songs that satisfy the requirement of
* being 'playable'.
*
* @param song a song previously returned from the song library
* @return the next song to play relative to 'song', or NULL if none are left
*/
Song *findNextActive(Song *song);
/**
* Removes a song from the library.
* @param handle handle of the song to remove
* @return the status of the song that was removed
*/
int removeSong(SongHandle handle);
/**
* Counts the number of songs in a song library.
* @return the number of songs
*/
int countSongs();
/**
* Determines what should be done with the song "handle" when restoring
* it from a saved game.
* @param handle sound handle being restored
* @param action desired action
*/
void setSongRestoreBehavior(SongHandle handle,
RESTORE_BEHAVIOR action);
};
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS
#endif // SCI_SSFX_SFX_SONGLIB_H

View File

@ -1,423 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "iterator.h"
#include "iterator_internal.h"
#include <stdarg.h>
#include <stdio.h>
using namespace Sci;
#define ASSERT_S(x) if (!(x)) { error("Failed assertion in L%d: " #x, __LINE__); return; }
#define ASSERT(x) ASSERT_S(x)
/* Tests the song iterators */
int errors = 0;
void error(char *fmt, ...) {
va_list ap;
fprintf(stderr, "[ERROR] ");
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
++errors;
}
/* The simple iterator will finish after a fixed amount of time. Before that,
** it emits (absolute) cues in ascending order. */
struct simple_iterator : public SongIterator {
int lifetime_remaining;
char *cues;
int cue_counter;
int cue_progress;
int cues_nr;
};
int simple_it_next(SongIterator *_self, unsigned char *buf, int *result) {
simple_iterator *self = (simple_iterator *)_self;
if (self->lifetime_remaining == -1) {
error("Song iterator called post mortem");
return SI_FINISHED;
}
if (self->lifetime_remaining) {
if (self->cue_counter < self->cues_nr) {
int time_to_cue = self->cues[self->cue_counter];
if (self->cue_progress == time_to_cue) {
++self->cue_counter;
self->cue_progress = 0;
*result = self->cue_counter;
return SI_ABSOLUTE_CUE;
} else {
int retval = time_to_cue - self->cue_progress;
self->cue_progress = time_to_cue;
if (retval > self->lifetime_remaining) {
retval = self->lifetime_remaining;
self->lifetime_remaining = 0;
self->cue_progress = retval;
return retval;
}
self->lifetime_remaining -= retval;
return retval;
}
} else {
int retval = self->lifetime_remaining;
self->lifetime_remaining = 0;
return retval;
}
} else {
self->lifetime_remaining = -1;
return SI_FINISHED;
}
}
Audio::AudioStream *simple_it_pcm_feed(SongIterator *_self) {
error("No PCM feed");
return NULL;
}
void simple_it_init(SongIterator *_self) {
}
SongIterator *simple_it_handle_message(SongIterator *_self, SongIterator::Message msg) {
return NULL;
}
void simple_it_cleanup(SongIterator *_self) {
}
/* Initialises the simple iterator.
** Parameters: (int) delay: Number of ticks until the iterator finishes
** (int *) cues: An array of cue delays (cue values are [1,2...])
** (int) cues_nr: Number of cues in ``cues''
** The first cue is emitted after cues[0] ticks, and it is 1. After cues[1] additional ticks
** the next cue is emitted, and so on. */
SongIterator *setup_simple_iterator(int delay, char *cues, int cues_nr) {
simple_iterator.lifetime_remaining = delay;
simple_iterator.cues = cues;
simple_iterator.cue_counter = 0;
simple_iterator.cues_nr = cues_nr;
simple_iterator.cue_progress = 0;
simple_iterator.ID = 42;
simple_iterator.channel_mask = 0x004f;
simple_iterator.flags = 0;
simple_iterator.priority = 1;
simple_iterator.death_listeners_nr = 0;
simple_iterator.cleanup = simple_it_cleanup;
simple_iterator.init = simple_it_init;
simple_iterator.handle_message = simple_it_handle_message;
simple_iterator.get_pcm_feed = simple_it_pcm_feed;
simple_iterator.next = simple_it_next;
return (SongIterator *) &simple_iterator;
}
#define ASSERT_SIT ASSERT(it == simple_it)
#define ASSERT_FFIT ASSERT(it == ff_it)
#define ASSERT_NEXT(n) ASSERT(songit_next(&it, data, &result, IT_READER_MASK_ALL) == n)
#define ASSERT_RESULT(n) ASSERT(result == n)
#define ASSERT_CUE(n) ASSERT_NEXT(SI_ABSOLUTE_CUE); ASSERT_RESULT(n)
void test_simple_it() {
SongIterator *it;
SongIterator *simple_it = (SongIterator *) & simple_iterator;
unsigned char data[4];
int result;
puts("[TEST] simple iterator (test artifact)");
it = setup_simple_iterator(42, NULL, 0);
ASSERT_SIT;
ASSERT_NEXT(42);
ASSERT_SIT;
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, "\003\004", 2);
ASSERT_SIT;
ASSERT_NEXT(3);
ASSERT_CUE(1);
ASSERT_SIT;
ASSERT_NEXT(4);
ASSERT_CUE(2);
ASSERT_SIT;
// warning("XXX => %d", songit_next(&it, data, &result, IT_READER_MASK_ALL));
ASSERT_NEXT(35);
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
puts("[TEST] Test OK.");
}
void test_fastforward() {
SongIterator *it;
SongIterator *simple_it = (SongIterator *) & simple_iterator;
SongIterator *ff_it;
unsigned char data[4];
int result;
puts("[TEST] fast-forward iterator");
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 0);
ASSERT_FFIT;
ASSERT_NEXT(42);
ASSERT_SIT; /* Must have morphed back */
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 1);
ASSERT_FFIT;
ASSERT_NEXT(41);
/* May or may not have morphed back here */
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 41);
ASSERT_FFIT;
ASSERT_NEXT(1);
/* May or may not have morphed back here */
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 42);
ASSERT_NEXT(SI_FINISHED);
/* May or may not have morphed back here */
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 10000);
ASSERT_NEXT(SI_FINISHED);
/* May or may not have morphed back here */
it = setup_simple_iterator(42, "\003\004", 2);
ff_it = it = new_fast_forward_iterator(it, 2);
ASSERT_FFIT;
ASSERT_NEXT(1);
ASSERT_CUE(1);
ASSERT_SIT;
ASSERT_NEXT(4);
ASSERT_CUE(2);
ASSERT_SIT;
ASSERT_NEXT(35);
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, "\003\004", 2);
ff_it = it = new_fast_forward_iterator(it, 5);
ASSERT_FFIT;
ASSERT_CUE(1);
ASSERT_FFIT;
ASSERT_NEXT(2);
ASSERT_CUE(2);
ASSERT_SIT;
ASSERT_NEXT(35);
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, "\003\004", 2);
ff_it = it = new_fast_forward_iterator(it, 41);
ASSERT_FFIT;
ASSERT_CUE(1);
ASSERT_FFIT;
ASSERT_CUE(2);
ASSERT_FFIT;
ASSERT_NEXT(1);
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
puts("[TEST] Test OK.");
}
#define SIMPLE_SONG_SIZE 50
static unsigned char simple_song[SIMPLE_SONG_SIZE] = {
0x00, /* Regular song */
/* Only use channel 0 for all devices */
0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Song begins here */
42, 0x90, 60, 0x7f, /* Play C after 42 ticks */
02, 64, 0x42, /* Play E after 2 more ticks, using running status mode */
0xf8, 10, 0x80, 60, 0x02, /* Stop C after 250 ticks */
0, 64, 0x00, /* Stop E immediately */
00, 0xfc /* Stop song */
};
#define ASSERT_MIDI3(cmd, arg0, arg1) \
ASSERT(data[0] == cmd); \
ASSERT(data[1] == arg0); \
ASSERT(data[2] == arg1);
void test_iterator_sci0() {
SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
unsigned char data[4];
int result;
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
puts("[TEST] SCI0-style song");
ASSERT_NEXT(42);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 60, 0x7f);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(250);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 60, 0x02);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
ASSERT_NEXT(SI_FINISHED);
puts("[TEST] Test OK.");
}
void test_iterator_sci0_loop() {
SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
unsigned char data[4];
int result;
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
SIMSG_SEND(it, SIMSG_SET_LOOPS(2)); /* Loop one additional time */
puts("[TEST] SCI0-style song with looping");
ASSERT_NEXT(42);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 60, 0x7f);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(250);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 60, 0x02);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
ASSERT_NEXT(SI_LOOP);
ASSERT_NEXT(42);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 60, 0x7f);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(250);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 60, 0x02);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
ASSERT_NEXT(SI_FINISHED);
puts("[TEST] Test OK.");
}
#define LOOP_SONG_SIZE 54
unsigned char loop_song[LOOP_SONG_SIZE] = {
0x00, /* Regular song song */
/* Only use channel 0 for all devices */
0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Song begins here */
42, 0x90, 60, 0x7f, /* Play C after 42 ticks */
13, 0x80, 60, 0x00, /* Stop C after 13 ticks */
00, 0xCF, 0x7f, /* Set loop point */
02, 0x90, 64, 0x42, /* Play E after 2 more ticks, using running status mode */
03, 0x80, 64, 0x00, /* Stop E after 3 ticks */
00, 0xfc /* Stop song/loop */
};
void test_iterator_sci0_mark_loop() {
SongIterator *it = songit_new(loop_song, LOOP_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
unsigned char data[4];
int result;
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
SIMSG_SEND(it, SIMSG_SET_LOOPS(3)); /* Loop once more */
puts("[TEST] SCI0-style song with loop mark, looping");
ASSERT_NEXT(42);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 60, 0x7f);
ASSERT_NEXT(13);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 60, 0x00);
/* Loop point here: we don't observe that in the iterator interface yet, though */
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(3);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
/* Now we loop back to the loop pont */
ASSERT_NEXT(SI_LOOP);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(3);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
/* ...and one final time */
ASSERT_NEXT(SI_LOOP);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(3);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
ASSERT_NEXT(SI_FINISHED);
puts("[TEST] Test OK.");
}
int main(int argc, char **argv) {
test_simple_it();
test_fastforward();
test_iterator_sci0();
test_iterator_sci0_loop();
test_iterator_sci0_mark_loop();
if (errors != 0)
warning("[ERROR] %d errors total", errors);
return (errors != 0);
}

View File

@ -844,7 +844,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
offsX = offsY = 0;
} else {
uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
assert(charOffs < 0x10000);
assert(charOffs < 0x14000);
if (!charOffs)
return;
charPtr = _fontPtr + charOffs;

View File

@ -868,7 +868,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) {
detach();
} else {
DebugPrintf("Use 'passcode <SEGA CD Passcode>'\n");
DebugPrintf("Current Passcode is %d \nUse 'passcode <SEGA CD Passcode>'\n",_vm->_scummVars[411]);
return true;
}
return false;

View File

@ -234,19 +234,6 @@ protected:
#endif
class ConfigDialog : public GUI::OptionsDialog {
protected:
#ifdef SMALL_SCREEN_DEVICE
GUI::Dialog *_keysDialog;
#endif
public:
ConfigDialog();
~ConfigDialog();
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
};
#pragma mark -
ScummDialog::ScummDialog(int x, int y, int w, int h) : GUI::Dialog(x, y, w, h) {
@ -259,220 +246,28 @@ ScummDialog::ScummDialog(String name) : GUI::Dialog(name) {
#pragma mark -
enum {
kSaveCmd = 'SAVE',
kLoadCmd = 'LOAD',
kPlayCmd = 'PLAY',
kOptionsCmd = 'OPTN',
kHelpCmd = 'HELP',
kAboutCmd = 'ABOU',
kQuitCmd = 'QUIT',
kChooseCmd = 'CHOS'
};
#ifndef DISABLE_HELP
ScummMenuDialog::ScummMenuDialog(ScummEngine *scumm)
: ScummDialog("ScummMain"), _vm(scumm) {
new GUI::ButtonWidget(this, "ScummMain.Resume", "Resume", kPlayCmd, 'P');
_loadButton = new GUI::ButtonWidget(this, "ScummMain.Load", "Load", kLoadCmd, 'L');
_saveButton = new GUI::ButtonWidget(this, "ScummMain.Save", "Save", kSaveCmd, 'S');
new GUI::ButtonWidget(this, "ScummMain.Options", "Options", kOptionsCmd, 'O');
#ifndef DISABLE_HELP
new GUI::ButtonWidget(this, "ScummMain.Help", "Help", kHelpCmd, 'H');
#endif
new GUI::ButtonWidget(this, "ScummMain.About", "About", kAboutCmd, 'A');
new GUI::ButtonWidget(this, "ScummMain.Quit", "Quit", kQuitCmd, 'Q');
//
// Create the sub dialog(s)
//
_aboutDialog = new GUI::AboutDialog();
_optionsDialog = new ConfigDialog();
#ifndef DISABLE_HELP
: MainMenuDialog(scumm) {
_helpDialog = new HelpDialog(scumm->_game);
#endif
_saveDialog = new GUI::SaveLoadChooser("Save game:", "Save");
_saveDialog->setSaveMode(true);
_loadDialog = new GUI::SaveLoadChooser("Load game:", "Load");
_loadDialog->setSaveMode(false);
_helpButton->setEnabled(true);
}
ScummMenuDialog::~ScummMenuDialog() {
delete _aboutDialog;
delete _optionsDialog;
#ifndef DISABLE_HELP
delete _helpDialog;
#endif
delete _saveDialog;
delete _loadDialog;
}
int ScummMenuDialog::runModal() {
_loadButton->setEnabled(_vm->canLoadGameStateCurrently());
_saveButton->setEnabled(_vm->canSaveGameStateCurrently());
return ScummDialog::runModal();
}
void ScummMenuDialog::reflowLayout() {
_loadButton->setEnabled(_vm->canLoadGameStateCurrently());
_saveButton->setEnabled(_vm->canSaveGameStateCurrently());
Dialog::reflowLayout();
}
void ScummMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kSaveCmd:
save();
break;
case kLoadCmd:
load();
break;
case kPlayCmd:
close();
break;
case kOptionsCmd:
_optionsDialog->runModal();
break;
case kAboutCmd:
_aboutDialog->runModal();
break;
#ifndef DISABLE_HELP
case kHelpCmd:
_helpDialog->runModal();
break;
#endif
case kQuitCmd:
_vm->quitGame();
close();
break;
default:
ScummDialog::handleCommand(sender, cmd, data);
MainMenuDialog::handleCommand(sender, cmd, data);
}
}
void ScummMenuDialog::save() {
Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0;
EngineMan.findGame(gameId, &plugin);
int idx = _saveDialog->runModal(plugin, ConfMan.getActiveDomainName());
if (idx >= 0) {
String result(_saveDialog->getResultString());
char buffer[20];
const char *str;
if (result.empty()) {
// If the user was lazy and entered no save name, come up with a default name.
sprintf(buffer, "Save %d", idx);
str = buffer;
} else
str = result.c_str();
_vm->requestSave(idx, str);
close();
}
}
void ScummMenuDialog::load() {
Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0;
EngineMan.findGame(gameId, &plugin);
int idx = _loadDialog->runModal(plugin, ConfMan.getActiveDomainName());
if (idx >= 0) {
_vm->requestLoad(idx);
close();
}
}
#pragma mark -
enum {
kKeysCmd = 'KEYS'
};
// FIXME: We use the empty string as domain name here. This tells the
// ConfigManager to use the 'default' domain for all its actions. We do that
// to get as close as possible to editing the 'active' settings.
//
// However, that requires bad & evil hacks in the ConfigManager code,
// and even then still doesn't work quite correctly.
// For example, if the transient domain contains 'false' for the 'fullscreen'
// flag, but the user used a hotkey to switch to windowed mode, then the dialog
// will display the wrong value anyway.
//
// Proposed solution consisting of multiple steps:
// 1) Add special code to the open() code that reads out everything stored
// in the transient domain that is controlled by this dialog, and updates
// the dialog accordingly.
// 2) Even more code is added to query the backend for current settings, like
// the fullscreen mode flag etc., and also updates the dialog accordingly.
// 3) The domain being edited is set to the active game domain.
// 4) If the dialog is closed with the "OK" button, then we remove everything
// stored in the transient domain (or at least everything corresponding to
// switches in this dialog.
// If OTOH the dialog is closed with "Cancel" we do no such thing.
//
// These changes will achieve two things at once: Allow us to get rid of using
// "" as value for the domain, and in fact provide a somewhat better user
// experience at the same time.
ConfigDialog::ConfigDialog()
: GUI::OptionsDialog("", "ScummConfig") {
//
// Sound controllers
//
addVolumeControls(this, "ScummConfig.");
//
// Some misc options
//
// SCUMM has a talkspeed range of 0-9
addSubtitleControls(this, "ScummConfig.", 9);
//
// Add the buttons
//
new GUI::ButtonWidget(this, "ScummConfig.Ok", "OK", GUI::kOKCmd, 'O');
new GUI::ButtonWidget(this, "ScummConfig.Cancel", "Cancel", GUI::kCloseCmd, 'C');
#ifdef SMALL_SCREEN_DEVICE
new GUI::ButtonWidget(this, "ScummConfig.Keys", "Keys", kKeysCmd, 'K');
_keysDialog = NULL;
#endif
}
ConfigDialog::~ConfigDialog() {
#ifdef SMALL_SCREEN_DEVICE
delete _keysDialog;
#endif
}
void ConfigDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kKeysCmd:
#ifdef SMALL_SCREEN_DEVICE
//
// Create the sub dialog(s)
//
_keysDialog = new GUI::KeysDialog();
_keysDialog->runModal();
delete _keysDialog;
_keysDialog = NULL;
#endif
break;
default:
GUI::OptionsDialog::handleCommand (sender, cmd, data);
}
}
#ifndef DISABLE_HELP
#pragma mark -
enum {

View File

@ -27,9 +27,8 @@
#include "common/str.h"
#include "gui/dialog.h"
#include "gui/options.h"
#include "gui/widget.h"
#include "gui/saveload.h"
#include "engines/dialogs.h"
#include "scumm/detection.h"
@ -52,32 +51,17 @@ protected:
typedef Common::String String;
};
class ScummMenuDialog : public ScummDialog {
#ifndef DISABLE_HELP
class ScummMenuDialog : public MainMenuDialog {
public:
ScummMenuDialog(ScummEngine *scumm);
~ScummMenuDialog();
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
virtual void reflowLayout();
int runModal();
protected:
ScummEngine *_vm;
GUI::Dialog *_aboutDialog;
GUI::Dialog *_optionsDialog;
#ifndef DISABLE_HELP
GUI::Dialog *_helpDialog;
#endif
GUI::SaveLoadChooser *_saveDialog;
GUI::SaveLoadChooser *_loadDialog;
GUI::ButtonWidget *_loadButton;
GUI::ButtonWidget *_saveButton;
void save();
void load();
};
#endif
/**
* A dialog which displays an arbitrary message to the user and returns

View File

@ -633,8 +633,10 @@ Win32ResExtractor::WinResource *Win32ResExtractor::list_pe_resources(WinLibrary
wr[c].children = fi->first_resource + (FROM_LE_32(dirent[c].offset_to_data) & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY);
/* fill in wr->id, wr->numeric_id */
if (!decode_pe_resource_id(fi, wr + c, FROM_LE_32(dirent[c].name)))
if (!decode_pe_resource_id(fi, wr + c, FROM_LE_32(dirent[c].name))) {
free(wr);
return NULL;
}
}
return wr;

View File

@ -508,7 +508,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, 0);
scummMenuDialog(); // Display GUI
openMainMenuDialog(); // Display global main menu
if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT2), 0, 0, 0);

View File

@ -108,7 +108,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_language(dr.language),
_debugger(0),
_currentScript(0xFF), // Let debug() work on init stage
_messageDialog(0), _pauseDialog(0), _scummMenuDialog(0), _versionDialog(0) {
_messageDialog(0), _pauseDialog(0), _versionDialog(0) {
if (_game.platform == Common::kPlatformNES) {
_gdi = new GdiNES(this);
@ -140,7 +140,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_fileHandle = 0;
// Init all vars
_v0ObjectIndex = false;
_v0ObjectInInventory = false;
@ -152,7 +151,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_sound = NULL;
memset(&vm, 0, sizeof(vm));
_pauseDialog = NULL;
_scummMenuDialog = NULL;
_versionDialog = NULL;
_fastMode = 0;
_actors = NULL;
@ -552,6 +550,12 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
for (int i = 0; i < ARRAYSIZE(debugChannels); ++i)
DebugMan.addDebugChannel(debugChannels[i].flag, debugChannels[i].channel, debugChannels[i].desc);
#ifndef DISABLE_HELP
// Create custom GMM dialog providing a help subdialog
assert(!_mainMenuDialog);
_mainMenuDialog = new ScummMenuDialog(this);
#endif
g_eventRec.registerRandomSource(_rnd, "scumm");
}
@ -572,7 +576,6 @@ ScummEngine::~ScummEngine() {
delete _charset;
delete _messageDialog;
delete _pauseDialog;
delete _scummMenuDialog;
delete _versionDialog;
delete _fileHandle;
@ -2444,13 +2447,6 @@ void ScummEngine::versionDialog() {
runDialog(*_versionDialog);
}
void ScummEngine::scummMenuDialog() {
if (!_scummMenuDialog)
_scummMenuDialog = new ScummMenuDialog(this);
runDialog(*_scummMenuDialog);
syncSoundSettings();
}
void ScummEngine::confirmExitDialog() {
ConfirmDialog d(this, 6);

View File

@ -530,7 +530,6 @@ protected:
Dialog *_pauseDialog;
Dialog *_messageDialog;
Dialog *_versionDialog;
Dialog *_scummMenuDialog;
virtual int runDialog(Dialog &dialog);
void confirmExitDialog();
@ -538,7 +537,6 @@ protected:
void pauseDialog();
void messageDialog(const char *message);
void versionDialog();
void scummMenuDialog();
char displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4);

View File

@ -23,7 +23,6 @@
*
*/
#include "common/file.h"
#include "sword1/sword1.h"
#include "sword1/animation.h"
@ -72,6 +71,9 @@ MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSys
_bgSoundStream = NULL;
_decoderType = decoderType;
_decoder = decoder;
_white = 255;
_black = 0;
}
MoviePlayer::~MoviePlayer() {
@ -254,9 +256,35 @@ bool MoviePlayer::playVideo() {
if (frame)
_vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
if (_decoder->hasDirtyPalette())
if (_decoder->hasDirtyPalette()) {
_decoder->setSystemPalette();
uint32 maxWeight = 0;
uint32 minWeight = 0xFFFFFFFF;
uint32 weight;
byte r, g, b;
byte *palette = _decoder->getPalette();
for (int i = 0; i < 256; i++) {
r = *palette++;
g = *palette++;
b = *palette++;
weight = 3 * r * r + 6 * g * g + 2 * b * b;
if (weight >= maxWeight) {
maxWeight = weight;
_white = i;
}
if (weight <= minWeight) {
minWeight = weight;
_black = i;
}
}
}
Graphics::Surface *screen = _vm->_system->lockScreen();
performPostProcessing((byte *)screen->pixels);
_vm->_system->unlockScreen();
@ -267,17 +295,19 @@ bool MoviePlayer::playVideo() {
while (_vm->_system->getEventManager()->pollEvent(event))
if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
return false;
_vm->_system->delayMillis(10);
}
return !_vm->shouldQuit();
}
byte MoviePlayer::findBlackPalIndex() {
return 0;
return _black;
}
byte MoviePlayer::findWhitePalIndex() {
return 0xff;
return _white;
}
DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)

View File

@ -85,6 +85,7 @@ protected:
OSystem *_system;
Common::Array<MovieText *> _movieTexts;
int _textX, _textY, _textWidth, _textHeight;
byte _white, _black;
DecoderType _decoderType;
Graphics::VideoDecoder *_decoder;

View File

@ -51,6 +51,9 @@ MoviePlayer::MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, A
_bgSoundStream = NULL;
_decoderType = decoderType;
_decoder = decoder;
_white = 255;
_black = 0;
}
MoviePlayer:: ~MoviePlayer() {
@ -280,9 +283,35 @@ bool MoviePlayer::playVideo() {
if (frame)
_vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
if (_decoder->hasDirtyPalette())
if (_decoder->hasDirtyPalette()) {
_decoder->setSystemPalette();
uint32 maxWeight = 0;
uint32 minWeight = 0xFFFFFFFF;
uint32 weight;
byte r, g, b;
byte *palette = _decoder->getPalette();
for (int i = 0; i < 256; i++) {
r = *palette++;
g = *palette++;
b = *palette++;
weight = 3 * r * r + 6 * g * g + 2 * b * b;
if (weight >= maxWeight) {
maxWeight = weight;
_white = i;
}
if (weight <= minWeight) {
minWeight = weight;
_black = i;
}
}
}
Graphics::Surface *screen = _vm->_system->lockScreen();
performPostProcessing((byte *)screen->pixels);
_vm->_system->unlockScreen();
@ -293,17 +322,19 @@ bool MoviePlayer::playVideo() {
while (_vm->_system->getEventManager()->pollEvent(event))
if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
return false;
_vm->_system->delayMillis(10);
}
return !_vm->shouldQuit();
}
byte MoviePlayer::findBlackPalIndex() {
return 0;
return _black;
}
byte MoviePlayer::findWhitePalIndex() {
return 0xff;
return _white;
}
DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)

View File

@ -87,6 +87,7 @@ protected:
uint32 _currentMovieText;
byte *_textSurface;
int _textX, _textY;
byte _white, _black;
DecoderType _decoderType;
Graphics::VideoDecoder *_decoder;

View File

@ -284,7 +284,8 @@ void LoadFile(MEMHANDLE *pH) {
}
// extract and zero terminate the filename
Common::strlcpy(szFilename, pH->szName, sizeof(pH->szName));
memcpy(szFilename, pH->szName, sizeof(pH->szName));
szFilename[sizeof(pH->szName)] = 0;
if (f.open(szFilename)) {
// read the data