[Scummvm-cvs-logs] CVS: scummvm/scumm/smush smush_font.cpp,NONE,1.1 smush_font.h,NONE,1.1 smush_mixer.cpp,NONE,1.1 smush_mixer.h,NONE,1.1 smush_player.cpp,NONE,1.1 smush_player.h,NONE,1.1 channel.h,1.9,1.10 chunk.cpp,1.10,1.11 chunk.h,1.7,1.8 codec1.cpp,1.8,1.9 codec37.cpp,1.17,1.18 codec37.h,1.10,1.11 codec47.cpp,1.44,1.45 codec47.h,1.13,1.14 imuse_channel.cpp,1.13,1.14 saud_channel.cpp,1.10,1.11 brenderer.cpp,1.6,NONE brenderer.h,1.10,NONE codec1.h,1.6,NONE codec44.cpp,1.9,NONE codec44.h,1.8,NONE color.cpp,1.4,NONE color.h,1.6,NONE config.h,1.6,NONE decoder.h,1.8,NONE frenderer.cpp,1.18,NONE frenderer.h,1.13,NONE mixer.h,1.5,NONE palette.h,1.6,NONE player.cpp,1.43,NONE player.h,1.15,NONE renderer.h,1.8,NONE scumm_renderer.cpp,1.30,NONE scumm_renderer.h,1.14,NONE
Pawel Kolodziejski
aquadran at users.sourceforge.net
Mon Mar 17 04:30:35 CET 2003
- Previous message: [Scummvm-cvs-logs] CVS: web/docs todo.xml,1.17,1.18
- Next message: [Scummvm-cvs-logs] CVS: scummvm/scumm script_v6.cpp,1.80,1.81 script_v8.cpp,2.143,2.144 scumm.h,1.159,1.160 scummvm.cpp,2.61,2.62
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/scummvm/scummvm/scumm/smush
In directory sc8-pr-cvs1:/tmp/cvs-serv7190
Modified Files:
channel.h chunk.cpp chunk.h codec1.cpp codec37.cpp codec37.h
codec47.cpp codec47.h imuse_channel.cpp saud_channel.cpp
Added Files:
smush_font.cpp smush_font.h smush_mixer.cpp smush_mixer.h
smush_player.cpp smush_player.h
Removed Files:
brenderer.cpp brenderer.h codec1.h codec44.cpp codec44.h
color.cpp color.h config.h decoder.h frenderer.cpp frenderer.h
mixer.h palette.h player.cpp player.h renderer.h
scumm_renderer.cpp scumm_renderer.h
Log Message:
reorg/clenup, changed main loop in smush code
--- NEW FILE: smush_font.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2003 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/scumm/smush/smush_font.cpp,v 1.1 2003/03/17 12:28:50 aquadran Exp $
*
*/
#include <stdafx.h>
#include "common/util.h"
#include "common/engine.h"
#include "common/file.h"
#include "scumm/scumm.h"
#include "smush_font.h"
SmushFont::SmushFont(bool use_original_colors, bool new_colors) :
_nbChars(0),
_color(-1),
_new_colors(new_colors),
_original(use_original_colors) {
for(int i = 0; i < 256; i++)
_chars[i].chr = NULL;
}
SmushFont::~SmushFont() {
for(int i = 0; i < _nbChars; i++) {
if(_chars[i].chr)
delete []_chars[i].chr;
}
}
bool SmushFont::loadFont(const char *filename, const char *directory) {
debug(2, "SmushFont::loadFont() called");
File file;
file.open(filename, directory);
if (file.isOpen() == false) {
warning("SmushFont::loadFont() Can't open font file: %s/%s", directory, filename);
return false;
}
uint32 tag = file.readUint32BE();
if (tag != 'ANIM') {
debug(2, "SmushFont::loadFont() there is no ANIM chunk in font header");
return false;
}
if (_dataSrc != NULL) {
free(_dataSrc);
_dataSrc = NULL;
}
uint32 length = file.readUint32BE();
_dataSrc = (byte *)malloc(length);
file.read(_dataSrc, length);
file.close();
if (READ_BE_UINT32(_dataSrc) != 'AHDR') {
debug(2, "SmushFont::loadFont() there is no AHDR chunk in font header");
free(_dataSrc);
_dataSrc = NULL;
return false;
}
_nbChars = READ_LE_UINT16(_dataSrc + 10);
int32 offset = READ_BE_UINT32(_dataSrc + 4) + 8;
for (int l = 0; l < _nbChars; l++) {
if (READ_BE_UINT32(_dataSrc + offset) == 'FRME') {
offset += 8;
if (READ_BE_UINT32(_dataSrc + offset) == 'FOBJ') {
_chars[l].width = READ_LE_UINT16(_dataSrc + offset + 14);
_chars[l].height = READ_LE_UINT16(_dataSrc + offset + 16);
_chars[l].chr = new byte[_chars[l].width * _chars[l].height + 1000];
decodeCodec(_chars[l].chr, _dataSrc + offset + 22, READ_BE_UINT32(_dataSrc + offset + 4) - 14);
offset += READ_BE_UINT32(_dataSrc + offset + 4) + 8;
} else {
debug(2, "SmushFont::loadFont(%s, %s) there is no FOBJ chunk in FRME chunk %d (offset %x)", filename, directory, l, offset);
break;
}
} else {
debug(2, "SmushFont::loadFont(%s, %s) there is no FRME chunk %d (offset %x)", filename, directory, l, offset);
break;
}
}
free(_dataSrc);
_dataSrc = NULL;
return true;
}
int SmushFont::getCharWidth(byte v) {
if(v >= _nbChars)
error("invalid character in SmushFont::charWidth : %d (%d)", v, _nbChars);
return _chars[v].width;
}
int SmushFont::getCharHeight(byte v) {
if(v >= _nbChars)
error("invalid character in SmushFont::charHeight : %d (%d)", v, _nbChars);
return _chars[v].height;
}
int SmushFont::getStringWidth(char *str) {
int ret = 0;
while(*str) {
ret += getCharWidth(*str++);
}
return ret;
}
int SmushFont::getStringHeight(char *str) {
int ret = 0;
for(int i = 0; str[i] != 0; i++) {
int h = getCharHeight(str[i]);
ret = MAX(ret, h);
}
return ret;
}
void SmushFont::decodeCodec(byte *dst, byte *src, int length) {
int size_line, num;
byte *src2 = src;
byte *dst2 = dst;
byte val;
do {
size_line = READ_LE_UINT16(src2);
src2 += 2;
length -= 2;
while (size_line != 0) {
num = *src2++;
val = *src2++;
memset(dst2, val, num);
dst2 += num;
length -= 2;
size_line -= 2;
if (size_line != 0) {
num = READ_LE_UINT16(src2) + 1;
src2 += 2;
memcpy(dst2, src2, num);
dst2 += num;
src2 += num;
length -= num + 2;
size_line -= num + 2;
}
}
dst2--;
} while (length > 1);
}
int SmushFont::drawChar(byte *buffer, int dst_width, int x, int y, byte chr) {
int w = _chars[chr].width;
int h = _chars[chr].height;
byte *src = _chars[chr].chr;
byte *dst = buffer + dst_width * y + x;
if(_original) {
for(int32 j = 0; j < h; j++) {
for(int32 i = 0; i < w; i++) {
char value = *src++;
if(value) dst[i] = value;
}
dst += dst_width;
}
} else {
char color = (_color != -1) ? _color : 1;
if (_new_colors == true) {
for(int j = 0; j < h; j++) {
for(int i = 0; i < w; i++) {
char value = *src++;
if(value == -color) {
dst[i] = 0xFF;
} else if(value == -31) {
dst[i] = 0;
} else if(value) {
dst[i] = value;
}
}
dst += dst_width;
}
} else {
for(int j = 0; j < h; j++) {
for(int i = 0; i < w; i++) {
char value = *src++;
if(value == 1) {
dst[i] = color;
} else if(value) {
dst[i] = 0;
}
}
dst += dst_width;
}
}
}
return w;
}
static char **split(char *str, char sep) {
char **ret = new char *[62];
int n = 0;
const char *i = str;
char *j = strchr(i, sep);
while(j != NULL) {
assert(n < 60);
ret[n] = new char[j - i + 1];
memcpy(ret[n], i, j - i);
ret[n++][j - i] = 0;
i = j + 1;
j = strchr(i, sep);
}
ret[n] = new char[strlen(i) + 1];
memcpy(ret[n], i, strlen(i));
ret[n++][strlen(i)] = 0;
ret[n] = 0;
return ret;
}
void SmushFont::drawSubstring(char *str, byte *buffer, int dst_width, int x, int y) {
for(int i = 0; str[i] != 0; i++)
x += drawChar(buffer, dst_width, x, y, str[i]);
}
void SmushFont::drawStringAbsolute(char *str, byte *buffer, int dst_width, int x, int y) {
debug(9, "SmushFont::drawStringAbsolute(%s, %d, %d)", str, x, y);
while(str) {
char line[256];
char *pos = strchr(str, '\n');
if(pos) {
memcpy(line, str, pos - str - 1);
line[pos - str - 1] = 0;
str = pos + 1;
} else {
strcpy(line, str);
str = 0;
}
drawSubstring(line, buffer, dst_width, x, y);
y += getStringHeight(line);
}
}
void SmushFont::drawStringCentered(char *str, byte *buffer, int dst_width, int dst_height, int y, int xmin, int width, int offset) {
debug(9, "SmushFont::drawStringCentered(%s, %d, %d)", str, xmin, y);
if ((strchr(str, '\n') != 0)) {
char *z = strchr(str, '\n');
*z = 0;
}
char **words = split(str, ' ');
int nb_sub = 0;
while(words[nb_sub])
nb_sub++;
int *sizes = new int[nb_sub];
int i = 0, max_width = 0, height = 0, nb_subs = 0;
for(i = 0; i < nb_sub; i++)
sizes[i] = getStringWidth(words[i]);
char **substrings = new char *[nb_sub];
int *substr_widths = new int[nb_sub];
int space_width = getCharWidth(' ');
i = 0;
while(i < nb_sub) {
int substr_width = sizes[i];
char *substr = new char[1000];
strcpy(substr, words[i]);
int j = i + 1;
while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) {
substr_width += sizes[j++] + space_width;
}
for(int k = i + 1; k < j; k++) {
strcat(substr, " ");
strcat(substr, words[k]);
}
substrings[nb_subs] = substr;
substr_widths[nb_subs++] = substr_width;
if(substr_width > max_width)
max_width = substr_width;
i = j;
height += getStringHeight(substr);
}
delete []sizes;
for(i = 0; i < nb_sub; i++) {
delete []words[i];
}
delete []words;
max_width = (max_width + 1) >> 1;
int x = xmin + width / 2;
x += offset - dst_width / 2;
if(x < max_width) x = max_width;
if(x + max_width > dst_width) {
x = dst_width - max_width;
}
if(y + height > dst_height) {
y = dst_height - height;
}
for(i = 0; i < nb_subs; i++) {
int substr_width = substr_widths[i];
drawSubstring(substrings[i], buffer, dst_width, x - substr_width / 2, y);
y += getStringHeight(substrings[i]);
delete []substrings[i];
}
delete []substr_widths;
delete []substrings;
}
void SmushFont::drawStringWrap(char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int width) {
debug(9, "SmushFont::drawStringWrap(%s, %d, %d)", str, x, y);
if ((strchr(str, '\n') != 0)) {
char *z = strchr(str, '\n');
*z = 0;
}
char ** words = split(str, ' ');
int nb_sub = 0;
while(words[nb_sub])
nb_sub++;
int *sizes = new int[nb_sub];
int i = 0, max_width = 0, height = 0, nb_subs = 0, left_x;
for(i = 0; i < nb_sub; i++)
sizes[i] = getStringWidth(words[i]);
char **substrings = new char *[nb_sub];
int *substr_widths = new int[nb_sub];
int space_width = getCharWidth(' ');
i = 0;
while(i < nb_sub) {
int substr_width = sizes[i];
char *substr = new char[1000];
strcpy(substr, words[i]);
int j = i + 1;
while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) {
substr_width += sizes[j++] + space_width;
}
for(int k = i + 1; k < j; k++) {
strcat(substr, " ");
strcat(substr, words[k]);
}
substrings[nb_subs] = substr;
substr_widths[nb_subs++] = substr_width;
i = j;
height += getStringHeight(substr);
}
delete []sizes;
for(i = 0; i < nb_sub; i++) {
delete []words[i];
}
delete []words;
if(y + height > dst_height) {
y = dst_height - height;
}
for(i = 0; i < nb_subs; i++)
max_width = MAX(max_width, substr_widths[i]);
if(max_width + x > dst_width)
left_x = dst_width - max_width + getCharWidth(' ');
else
left_x = x;
if(max_width + left_x > dst_height)
left_x = dst_width - max_width;
for(i = 0; i < nb_subs; i++) {
drawSubstring(substrings[i], buffer, dst_width, left_x, y);
y += getStringHeight(substrings[i]);
delete []substrings[i];
}
delete []substr_widths;
delete []substrings;
}
void SmushFont::drawStringWrapCentered(char *str, byte *buffer, int dst_width, int dst_height, int x, int32 y, int width) {
debug(9, "SmushFont::drawStringWrapCentered(%s, %d, %d)", str, x, y);
int max_substr_width = 0;
if ((strchr(str, '\n') != 0)) {
char *z = strchr(str, '\n');
*z = 0;
}
char **words = split(str, ' ');
int nb_sub = 0;
while(words[nb_sub])
nb_sub++;
int *sizes = new int[nb_sub];
int i = 0, height = 0, nb_subs = 0;
for(i = 0; i < nb_sub; i++)
sizes[i] = getStringWidth(words[i]);
char **substrings = new char *[nb_sub];
int *substr_widths = new int[nb_sub];
int space_width = getCharWidth(' ');
i = 0;
width = MIN(width, dst_width);
while(i < nb_sub) {
int substr_width = sizes[i];
char *substr = new char[1000];
strcpy(substr, words[i]);
int j = i + 1;
while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) {
substr_width += sizes[j++] + space_width;
}
for(int k = i + 1; k < j; k++) {
strcat(substr, " ");
strcat(substr, words[k]);
}
substrings[nb_subs] = substr;
substr_widths[nb_subs++] = substr_width;
max_substr_width = MAX(substr_width, max_substr_width);
i = j;
height += getStringHeight(substr);
}
delete []sizes;
for(i = 0; i < nb_sub; i++) {
delete []words[i];
}
delete []words;
if(y + height > dst_height) {
y = dst_height - height;
}
x = (dst_width - max_substr_width) / 2;
for(i = 0; i < nb_subs; i++) {
int substr_width = substr_widths[i];
drawSubstring(substrings[i], buffer, dst_width, x + (max_substr_width - substr_width) / 2, y);
y += getStringHeight(substrings[i]);
delete []substrings[i];
}
delete []substr_widths;
delete []substrings;
}
--- NEW FILE: smush_font.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2003 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/scumm/smush/smush_font.h,v 1.1 2003/03/17 12:28:50 aquadran Exp $
*
*/
#ifndef SMUSH_FONT_H
#define SMUSH_FONT_H
#include "common/scummsys.h"
class SmushFont {
private:
int _nbChars;
byte _color;
bool _new_colors;
bool _original;
byte *_dataSrc;
struct {
int width;
int height;
byte *chr;
} _chars[256];
public:
SmushFont(bool use_original_colors, bool new_colors);
~SmushFont();
protected:
int getCharWidth(byte c);
int getStringWidth(char *str);
int getCharHeight(byte c);
int getStringHeight(char *str);
int drawChar(byte *buffer, int dst_width, int x, int y, byte chr);
void drawSubstring(char *str, byte *buffer, int dst_width, int x, int y);
void decodeCodec(byte *dst, byte *src, int length);
public:
bool loadFont(const char *filename, const char *directory);
void setColor(byte c) { _color = c; }
void drawStringCentered(char *str, byte *buffer, int dst_width, int dst_height, int y, int xmin, int width, int offset);
void drawStringWrap(char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int width);
void drawStringWrapCentered(char *str, byte *buffer, int dst_width, int dst_height, int x, int32 y, int width);
void drawStringAbsolute(char *str, byte *buffer, int dst_width, int x, int y);
};
#endif
--- NEW FILE: smush_mixer.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2003 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/scumm/smush/smush_mixer.cpp,v 1.1 2003/03/17 12:28:50 aquadran Exp $
*
*/
#include <stdafx.h>
#include "common/util.h"
#include "smush_mixer.h"
#include "channel.h"
#include "sound/mixer.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
#include "scumm/imuse.h"
SmushMixer::SmushMixer(SoundMixer *m) :
_mixer(m),
_soundFrequency(22050),
_nextIndex(_mixer->_beginSlots) {
for(int32 i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) {
_channels[i].id = -1;
_channels[i].chan = NULL;
_channels[i].first = true;
}
}
SmushMixer::~SmushMixer() {
}
SmushChannel *SmushMixer::findChannel(int32 track) {
debug(9, "SmushMixer::findChannel(%d)", track);
for(int32 i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) {
if(_channels[i].id == track)
return _channels[i].chan;
}
return NULL;
}
bool SmushMixer::addChannel(SmushChannel *c) {
int32 track = c->getTrackIdentifier();
int i;
debug(9, "SmushMixer::addChannel(%d)", track);
for(i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) {
if(_channels[i].id == track)
warning("SmushMixer::addChannel(%d) : channel already exist !", track);
}
if(_nextIndex >= SoundMixer::NUM_CHANNELS)
_nextIndex = _mixer->_beginSlots;
for(i = _nextIndex; i < SoundMixer::NUM_CHANNELS; i++) {
if(_channels[i].chan == NULL || _channels[i].id == -1) {
_channels[i].chan = c;
_channels[i].id = track;
_channels[i].first = true;
_nextIndex = i + 1;
return true;
}
}
for(i = _mixer->_beginSlots; i < _nextIndex; i++) {
if(_channels[i].chan == NULL || _channels[i].id == -1) {
_channels[i].chan = c;
_channels[i].id = track;
_channels[i].first = true;
_nextIndex = i + 1;
return true;
}
}
warning("_nextIndex == %d\n", _nextIndex);
for(i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) {
warning("channel %d : %p(%d, %d) %d %d\n", i, (void *)_channels[i].chan,
_channels[i].chan ? _channels[i].chan->getTrackIdentifier() : -1,
_channels[i].chan ? _channels[i].chan->isTerminated() : 1,
_channels[i].first, _channels[i].mixer_index);
}
error("SmushMixer::add_channel() : no more channel available");
return false;
}
bool SmushMixer::handleFrame() {
debug(9, "SmushMixer::handleFrame()");
for(int i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) {
if(_channels[i].id != -1) {
if(_channels[i].chan->isTerminated()) {
delete _channels[i].chan;
_channels[i].id = -1;
_channels[i].chan = NULL;
} else {
int32 rate;
bool stereo, is_short;
_channels[i].chan->getParameters(rate, stereo, is_short);
int32 size = _channels[i].chan->availableSoundData();
int32 flags = stereo ? SoundMixer::FLAG_STEREO : 0;
if(is_short) {
short *data = new int16[size * (stereo ? 2 : 1) * 2];
_channels[i].chan->getSoundData(data, size);
if(_channels[i].chan->getRate() == 11025) size *= 2;
size *= stereo ? 4 : 2;
if(_silentMixer == false) {
if(_channels[i].first) {
_channels[i].mixer_index = _mixer->playStream(NULL, -1, data, size, rate, flags | SoundMixer::FLAG_16BITS);
_channels[i].first = false;
} else {
_mixer->append(_channels[i].mixer_index, data, size, rate, flags | SoundMixer::FLAG_16BITS);
}
}
delete []data;
} else {
int8 *data = new int8[size * (stereo ? 2 : 1) * 2];
_channels[i].chan->getSoundData(data, size);
if(_channels[i].chan->getRate() == 11025) size *= 2;
size *= stereo ? 2 : 1;
if(_silentMixer == false) {
if(_channels[i].first) {
_channels[i].mixer_index = _mixer->playStream(NULL, -1, data, size, rate, flags | SoundMixer::FLAG_UNSIGNED);
_channels[i].first = false;
} else {
_mixer->append(_channels[i].mixer_index, data, size, rate, flags | SoundMixer::FLAG_UNSIGNED);
}
}
delete []data;
}
}
}
}
return true;
}
bool SmushMixer::stop() {
debug(9, "SmushMixer::stop()");
for(int i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) {
if(_channels[i].id != -1) {
delete _channels[i].chan;
_channels[i].id = -1;
_channels[i].chan = NULL;
}
}
return true;
}
--- NEW FILE: smush_mixer.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2003 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/scumm/smush/smush_mixer.h,v 1.1 2003/03/17 12:28:50 aquadran Exp $
*
*/
#include <stdafx.h>
#include "sound/mixer.h"
class SmushChannel;
class SmushMixer {
private:
SoundMixer *_mixer;
struct {
int id;
SmushChannel *chan;
bool first;
int mixer_index;
} _channels[SoundMixer::NUM_CHANNELS];
int _nextIndex;
int _soundFrequency;
public:
SmushMixer(SoundMixer *);
virtual ~SmushMixer();
SmushChannel *findChannel(int32 track);
bool addChannel(SmushChannel *c);
bool handleFrame();
bool stop();
bool update();
bool _silentMixer;
};
--- NEW FILE: smush_player.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2003 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/scumm/smush/smush_player.cpp,v 1.1 2003/03/17 12:28:50 aquadran Exp $
*
*/
#include <stdafx.h>
#include "common/file.h"
#include "common/util.h"
#include "common/engine.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
#include "scumm/imuse.h"
#include "sound/mixer.h"
#include "smush_player.h"
#include "smush_mixer.h"
#include "smush_font.h"
#include "channel.h"
#include "chunk.h"
#include "chunk_type.h"
const int MAX_STRINGS = 200;
class StringResource {
private:
struct {
int id;
char *string;
} _strings[MAX_STRINGS];
int _nbStrings;
int _lastId;
char *_lastString;
public:
StringResource() :
_nbStrings(0),
_lastId(-1) {
};
~StringResource() {
for(int32 i = 0; i < _nbStrings; i++) {
delete []_strings[i].string;
}
}
bool init(char *buffer, int32 length) {
char *def_start = strchr(buffer, '#');
while(def_start != NULL) {
char *def_end = strchr(def_start, '\n');
assert(def_end != NULL);
char *id_end = def_end;
while(id_end >= def_start && !isdigit(*(id_end-1))) {
id_end--;
}
assert(id_end > def_start);
char *id_start = id_end;
while(isdigit(*(id_start - 1))) {
id_start--;
}
char idstring[32];
memcpy(idstring, id_start, id_end - id_start);
idstring[id_end - id_start] = 0;
int32 id = atoi(idstring);
char *data_start = def_end;
while(*data_start == '\n' || *data_start == '\r') {
data_start++;
}
char *data_end = data_start;
while(1) {
if(data_end[-2] == '\r' && data_end[1] == '\n' && data_end[-1] == '\n' && data_end[0] == '\r') {
break;
}
data_end++;
if(data_end >= buffer + length) {
data_end = buffer + length;
break;
}
}
data_end -= 2;
assert(data_end > data_start);
char *value = new char[data_end - data_start + 1];
assert(value);
memcpy(value, data_start, data_end - data_start);
value[data_end - data_start] = 0;
char *line_start = value;
char *line_end;
while ((line_end = strchr(line_start, '\n'))) {
line_start = line_end+1;
if (line_start[0] == '/' && line_start[1] == '/') {
line_start += 2;
if (line_end[-1] == '\r')
line_end[-1] = ' ';
else
*line_end++ = ' ';
memmove(line_end, line_start, strlen(line_start)+1);
}
}
_strings[_nbStrings].id = id;
_strings[_nbStrings].string = value;
_nbStrings ++;
def_start = strchr(data_end + 2, '#');
}
return true;
}
char *get(int id) {
if(id == _lastId) {
return _lastString;
}
for(int i = 0; i < _nbStrings; i++) {
if(_strings[i].id == id) {
_lastId = id;
_lastString = _strings[i].string;
return _strings[i].string;
}
}
warning("invalid string id : %d", id);
_lastId = -1;
_lastString = "unknown string";
return _lastString;
}
};
static StringResource *getStrings(const char *file, const char *directory, bool is_encoded) {
debug(7, "trying to read text ressources from %s", file);
File theFile;
theFile.open(file, directory);
if (!theFile.isOpen()) {
return 0;
}
int32 length = theFile.size();
char *filebuffer = new char [length + 1];
assert(filebuffer);
theFile.read(filebuffer, length);
filebuffer[length] = 0;
if(is_encoded) {
static const int32 ETRS_HEADER_LENGTH = 16;
assert(length > ETRS_HEADER_LENGTH);
Chunk::type type = READ_BE_UINT32(filebuffer);
if(type != TYPE_ETRS) {
delete [] filebuffer;
return getStrings(file, directory, false);
}
char *old = filebuffer;
filebuffer = new char[length - ETRS_HEADER_LENGTH + 1];
for(int32 i = ETRS_HEADER_LENGTH; i < length; i++) {
filebuffer[i - ETRS_HEADER_LENGTH] = old[i] ^ 0xCC;
}
filebuffer[length - ETRS_HEADER_LENGTH] = '\0';
delete []old;
length -= ETRS_HEADER_LENGTH;
}
StringResource *sr = new StringResource;
assert(sr);
sr->init(filebuffer, length);
delete []filebuffer;
return sr;
}
SmushPlayer *player;
void smush_callback(void *ptr) {
player->_smushProcessFrame = true;
player->parseNextFrame();
player->_smushProcessFrame = false;
}
SmushPlayer::SmushPlayer(Scumm *scumm, int speed, bool subtitles) {
player = this;
_version = -1;
_nbframes = 0;
_smixer = 0;
_strings = NULL;
_skipNext = false;
_data = NULL;
_storeFrame = false;
_width = 0;
_height = 0;
_frameBuffer = NULL;
_sf[0] = NULL;
_sf[1] = NULL;
_sf[2] = NULL;
_sf[3] = NULL;
_sf[4] = NULL;
_scumm = scumm;
_IACTchannel = -1,
_IACTpos = 0;
_soundFrequency = 22050;
_speed = speed;
_subtitles = subtitles;
_smushProcessFrame = false;
}
SmushPlayer::~SmushPlayer() {
deinit();
}
void SmushPlayer::init() {
_frame = 0;
_scumm->_sound->pauseBundleMusic(true);
if (_scumm->_imuseDigital) {
_scumm->_imuseDigital->pause(true);
}
_scumm->_videoFinished = false;
_scumm->_insaneState = true;
_smixer = new SmushMixer(_scumm->_mixer);
_scumm->setDirtyColors(0, 255);
_smixer->_silentMixer = _scumm->_silentDigitalImuse;
_scumm->_smushPlay = true;
_data = _scumm->virtscr[0].screenPtr + _scumm->virtscr[0].xstart;
_scumm->_timer->installProcedure(&smush_callback, _speed);
_alreadyInit = false;
}
void SmushPlayer::deinit() {
_scumm->_smushPlay = false;
_scumm->_timer->releaseProcedure(&smush_callback);
while (_smushProcessFrame) {}
for(int i = 0; i < 5; i++) {
if (_sf[i]) {
delete _sf[i];
_sf[i] = NULL;
}
}
if(_strings) {
delete _strings;
_strings = NULL;
}
if(_smixer) {
_smixer->stop();
delete _smixer;
_smixer = NULL;
}
_scumm->_insaneState = false;
_scumm->exitCutscene();
if (_scumm->_imuseDigital) {
_scumm->_imuseDigital->pause(false);
}
_scumm->_sound->pauseBundleMusic(false);
_scumm->_fullRedraw = 1;
}
void SmushPlayer::checkBlock(const Chunk &b, Chunk::type type_expected, uint32 min_size) {
if(type_expected != b.getType()) {
error("Chunk type is different from expected : %d != %d", b.getType(), type_expected);
}
if(min_size > b.getSize()) {
error("Chunk size is inferior than minimum required size : %d < %d", b.getSize(), min_size);
}
}
void SmushPlayer::handleSoundBuffer(int32 track_id, int32 index, int32 max_frames, int32 flags, int32 vol, int32 bal, Chunk &b, int32 size) {
debug(6, "SmushPlayer::handleSoundBuffer(%d)", track_id);
// if((flags & 128) == 128) {
// return;
// }
// if((flags & 64) == 64) {
// return;
// }
SmushChannel *c = _smixer->findChannel(track_id);
if(c == NULL) {
c = new SaudChannel(track_id, _soundFrequency);
_smixer->addChannel(c);
}
if(index == 0) {
c->setParameters(max_frames, flags, vol, bal);
} else {
c->checkParameters(index, max_frames, flags, vol, bal);
}
c->appendData(b, size);
}
void SmushPlayer::handleSoundFrame(Chunk &b) {
checkBlock(b, TYPE_PSAD);
debug(6, "SmushPlayer::handleSoundFrame()");
int32 track_id = b.getWord();
int32 index = b.getWord();
int32 max_frames = b.getWord();
int32 flags = b.getWord();
int32 vol = b.getByte();
int32 bal = b.getChar();
#ifdef DEBUG
if(index == 0) {
debug(5, "track_id == %d, max_frames == %d, %d, %d, %d", track_id, max_frames, flags, vol, bal);
}
#endif
int32 size = b.getSize() - 10;
handleSoundBuffer(track_id, index, max_frames, flags, vol, bal, b, size);
}
void SmushPlayer::handleSkip(Chunk &b) {
checkBlock(b, TYPE_SKIP, 4);
int32 code = b.getDword();
debug(6, "SmushPlayer::handleSkip(%d)", code);
if(code >= 0 && code < 37)
_skipNext = _skips[code];
else
_skipNext = true;
}
void SmushPlayer::handleStore(Chunk &b) {
debug(6, "SmushPlayer::handleStore()");
checkBlock(b, TYPE_STOR, 4);
_storeFrame = true;
}
void SmushPlayer::handleFetch(Chunk &b) {
debug(6, "SmushPlayer::handleFetch()");
checkBlock(b, TYPE_FTCH, 6);
if (_frameBuffer != NULL) {
memcpy(_data, _frameBuffer, _width * _height);
}
}
void SmushPlayer::handleImuseBuffer(int32 track_id, int32 index, int32 nbframes, int32 size, int32 unk1, int32 track_flags, Chunk &b, int32 bsize) {
int32 track = (track_flags << 16) | track_id;
SmushChannel *c = _smixer->findChannel(track);
if(c == 0) {
c = new ImuseChannel(track, _soundFrequency);
_smixer->addChannel(c);
}
if(index == 0)
c->setParameters(nbframes, size, track_flags, unk1);
else
c->checkParameters(index, nbframes, size, track_flags, unk1);
c->appendData(b, bsize);
}
void SmushPlayer::handleImuseAction(Chunk &b) {
checkBlock(b, TYPE_IACT, 8);
debug(6, "SmushPlayer::handleImuseAction()");
int code = b.getWord();
int flags = b.getWord();
int unknown = b.getShort();
int track_flags = b.getWord();
assert(flags == 46 && unknown == 0);
int track_id = b.getWord();
int index = b.getWord();
int nbframes = b.getWord();
int32 size = b.getDword();
int32 bsize = b.getSize() - 18;
if (g_scumm->_gameId != GID_CMI) {
handleImuseBuffer(track_id, index, nbframes, size, unknown, track_flags, b, bsize);
} else {
byte output_data[4096];
byte *src = (byte *)malloc(bsize);
b.read(src, bsize);
byte *d_src = src;
byte value;
do {
if (bsize == 0)
break;
if (_IACTpos >= 2) {
int32 len = READ_BE_UINT16(_IACToutput) + 2;
len -= _IACTpos;
if (len > bsize) {
memcpy(_IACToutput + _IACTpos, d_src, bsize);
_IACTpos += bsize;
bsize = 0;
} else {
memcpy(_IACToutput + _IACTpos, d_src, len);
byte *dst = output_data;
byte *d_src2 = _IACToutput;
d_src2 += 2;
int32 count = 1024;
byte variable1 = *d_src2++;
byte variable2 = variable1 >> 4;
variable1 &= 0x0f;
do {
value = *(d_src2++);
if (value == 0x80) {
*dst++ = *d_src2++;
*dst++ = *d_src2++;
} else {
int16 val = (int8)value << variable2;
*dst++ = val>> 8;
*dst++ = (byte)(val);
}
value = *(d_src2++);
if (value == 0x80) {
*dst++ = *d_src2++;
*dst++ = *d_src2++;
} else {
int16 val = (int8)value << variable1;
*dst++ = val>> 8;
*dst++ = (byte)(val);
}
} while (--count);
if (_IACTchannel == -1) {
_IACTchannel = _scumm->_mixer->playStream(NULL, -1, output_data, 0x1000, 22050,
SoundMixer::FLAG_STEREO | SoundMixer::FLAG_16BITS, -1, 200000);
} else {
_scumm->_mixer->append(_IACTchannel, output_data, 0x1000, 22050,
SoundMixer::FLAG_STEREO | SoundMixer::FLAG_16BITS);
}
bsize -= len;
d_src += len;
_IACTpos = 0;
}
} else {
if (bsize == 1) {
if (_IACTpos != 0) {
*(_IACToutput + 1) = *d_src++;
_IACTpos = 2;
bsize--;
continue;
}
bsize = 0;
*(_IACToutput + 0) = *d_src;
_IACTpos = 1;
continue;
} else if (_IACTpos == 0) {
*(_IACToutput + 0) = *d_src++;
bsize--;
}
*(_IACToutput + 1) = *d_src++;
_IACTpos = 2;
bsize--;
}
} while (bsize != 0);
free(src);
}
}
void SmushPlayer::handleTextResource(Chunk &b) {
int pos_x = b.getShort();
int pos_y = b.getShort();
int flags = b.getShort();
int left = b.getShort();
int top = b.getShort();
int width = b.getShort();
/*int32 height =*/ b.getShort();
/*int32 unk2 =*/ b.getWord();
char *str, *string = NULL, *string2 = NULL;
if (b.getType() == TYPE_TEXT) {
string = (char *)malloc(b.getSize() - 16);
str = string;
b.read(string, b.getSize() - 16);
} else {
int string_id = b.getWord();
if(!_strings)
return;
str = _strings->get(string_id);
}
// if subtitles disabled and bit 3 is set, then do not draw
if((!_subtitles) && ((flags & 8) == 8))
return;
SmushFont *sf = _sf[0];
int color = 15;
while(*str == '/') {
str++; // For Full Throttle text resources
}
if (_scumm->_gameId == GID_CMI) {
_scumm->translateText((byte*)str - 1, _scumm->_transText);
while(*str++ != '/');
string2 = (char *)_scumm->_transText;
// If string2 contains formatting information there probably
// wasn't any translation for it in the language.tab file. In
// that case, pretend there is no string2.
if (string2[0] == '^')
string2[0] = 0;
}
while(str[0] == '^') {
switch(str[1]) {
case 'f':
{
int id = str[3] - '0';
str += 4;
sf = _sf[id];
}
break;
case 'c':
{
color = str[4] - '0' + 10 *(str[3] - '0');
str += 5;
}
break;
default:
error("invalid escape code in text string");
}
}
assert(sf != NULL);
sf->setColor(color);
if (_scumm->_gameId != GID_CMI) {
string2 = str;
}
if (_scumm->_gameId == GID_CMI) {
if (string2[0] == 0) {
string2 = str;
}
}
// flags:
// bit 0 - center 1
// bit 1 - not used 2
// bit 2 - ??? 4
// bit 3 - wrap around 8
switch (flags) {
case 0:
sf->drawStringAbsolute(string2, _data, _width, pos_x, pos_y);
break;
case 1:
sf->drawStringCentered(string2, _data, _width, _height, MAX(pos_y, top), left, width, pos_x);
break;
case 4:
sf->drawStringAbsolute(string2, _data, _width, pos_x, pos_y);
break;
case 5:
sf->drawStringCentered(string2, _data, _width, _height, MAX(pos_y, top), left, width, pos_x);
break;
case 8:
sf->drawStringWrap(string2, _data, _width, _height, pos_x, MAX(pos_y, top), width);
break;
case 9:
sf->drawStringCentered(string2, _data, _width, _height, MAX(pos_y, top), left, width, pos_x);
break;
case 12:
sf->drawStringWrap(string2, _data, _width, _height, pos_x, MAX(pos_y, top), width);
break;
case 13:
sf->drawStringWrapCentered(string2, _data, _width, _height, pos_x, MAX(pos_y, top), width);
break;
default:
warning("SmushPlayer::handleTextResource. Not handled flags: %d\n", flags);
}
if (string != NULL) {
free (string);
}
}
bool SmushPlayer::readString(const char *file, const char *directory) {
const char *i = strrchr(file, '.');
if(i == NULL) {
error("invalid filename : %s", file);
}
char fname[260];
memcpy(fname, file, i - file);
strcpy(fname + (i - file), ".trs");
if((_strings = getStrings(fname, directory, false)) != 0) {
return true;
}
if((_strings = getStrings("digtxt.trs", directory, true)) != 0) {
return true;
}
return false;
}
void SmushPlayer::readPalette(byte *out, Chunk &in) {
in.read(out, 0x300);
}
static byte delta_color(byte org_color, int16 delta_color) {
int16 t;
t = (((int32)(org_color) << 7) + org_color + delta_color) >> 7;
if (t > 255)
t = 255;
if (t < 0)
t = 0;
return (byte)t;
}
void SmushPlayer::handleDeltaPalette(Chunk &b) {
checkBlock(b, TYPE_XPAL);
debug(6, "SmushPlayer::handleDeltaPalette()");
if(b.getSize() == 0x300 * 3 + 4) {
b.getWord();
b.getWord();
for(int i = 0; i < 0x300; i++) {
_deltaPal[i] = b.getWord();
}
readPalette(_pal, b);
setPalette(_pal);
} else if(b.getSize() == 6) {
b.getWord();
b.getWord();
b.getWord();
for(int i = 0; i < 0x300; i++) {
_pal[i] = delta_color(_pal[i], _deltaPal[i]);
}
setPalette(_pal);
} else {
error("SmushPlayer::handleDeltaPalette() Wrong size for DeltaPalette");
}
}
void SmushPlayer::handleNewPalette(Chunk &b) {
checkBlock(b, TYPE_NPAL, 0x300);
debug(6, "SmushPlayer::handleNewPalette()");
readPalette(_pal, b);
setPalette(_pal);
}
void SmushPlayer::initCodecs() {
}
extern void smush_decode_codec1(byte *dst, byte *src, int height);
void SmushPlayer::handleFrameObject(Chunk &b) {
checkBlock(b, TYPE_FOBJ, 14);
if(_skipNext) {
_skipNext = false;
return;
}
int codec = b.getWord();
b.getWord(); // left
b.getWord(); // top
int width = b.getWord();
int height = b.getWord();
// hack for spontanic changing resolution
// differ than width scumm screen, and pass only one width 384x242
if((height != _scumm->_realHeight) && (height != 242))
return;
if (height == 242)
return;
if((width != _scumm->_realWidth) && (width != 384))
return;
if (width == 384)
return;
if(_alreadyInit == false) {
_codec37.init(width, height);
_codec47.init(width, height);
_alreadyInit = true;
}
_width = width;
_height = height;
b.getWord();
b.getWord();
int32 chunk_size = b.getSize() - 14;
byte *chunk_buffer = (byte *)malloc(chunk_size);
assert(chunk_buffer);
b.read(chunk_buffer, chunk_size);
switch (codec) {
case 1:
case 3:
smush_decode_codec1(_data, chunk_buffer, _height);
break;
case 37:
_codec37.decode(_data, chunk_buffer);
break;
case 47:
_codec47.decode(_data, chunk_buffer);
break;
default:
error("Invalid codec for frame object : %d", (int)codec);
}
if (_storeFrame == true) {
if (_frameBuffer == NULL) {
_frameBuffer = (byte *)malloc(_width * _height);
}
memcpy(_frameBuffer, _data, _width * _height);
_storeFrame = false;
}
free(chunk_buffer);
}
void SmushPlayer::handleFrame(Chunk &b) {
checkBlock(b, TYPE_FRME);
debug(6, "SmushPlayer::handleFrame(%d)", _frame);
_skipNext = false;
uint32 start_time, curr_time, start_update, end_update;
start_time = _scumm->_system->get_msecs();
while(!b.eof()) {
Chunk *sub = b.subBlock();
if(sub->getSize() & 1) b.seek(1);
switch(sub->getType()) {
case TYPE_NPAL:
handleNewPalette(*sub);
break;
case TYPE_FOBJ:
handleFrameObject(*sub);
break;
case TYPE_PSAD:
handleSoundFrame(*sub);
break;
case TYPE_TRES:
handleTextResource(*sub);
break;
case TYPE_XPAL:
handleDeltaPalette(*sub);
break;
case TYPE_IACT:
handleImuseAction(*sub);
break;
case TYPE_STOR:
handleStore(*sub);
break;
case TYPE_FTCH:
handleFetch(*sub);
break;
case TYPE_SKIP:
handleSkip(*sub);
break;
case TYPE_TEXT:
handleTextResource(*sub);
break;
default:
error("Unknown frame subChunk found : %s, %d", Chunk::ChunkString(sub->getType()), sub->getSize());
}
delete sub;
}
curr_time = _scumm->_system->get_msecs();
_smixer->handleFrame();
start_update = _scumm->_system->get_msecs();
if (curr_time < (start_time + _speed / 1000)) {
updateScreen();
} else {
warning("SmushPlayer: skipping update frame %d", _frame);
}
end_update = _scumm->_system->get_msecs();
debug(0, "Smush stats: FRME( %03d ),GFX_update( %03d ),FRME+GFX+SFX( %03d ),Limit(%d)",
curr_time - start_time, end_update - start_update,
end_update - start_time, _speed / 1000);
_frame++;
}
void SmushPlayer::handleAnimHeader(Chunk &b) {
checkBlock(b, TYPE_AHDR, 0x300 + 6);
debug(6, "SmushPlayer::handleAnimHeader()");
_version = b.getWord();
_nbframes = b.getWord();
b.getWord();
readPalette(_pal, b);
setPalette(_pal);
}
void SmushPlayer::setupAnim(const char *file, const char *directory) {
_base = new FileChunk(file, directory);
Chunk *sub = _base->subBlock();
checkBlock(*sub, TYPE_AHDR);
handleAnimHeader(*sub);
readString(file, directory);
if (_scumm->_gameId == GID_FT) {
_sf[0] = new SmushFont(true, false);
_sf[2] = new SmushFont(true, false);
_sf[0]->loadFont("scummfnt.nut", directory);
_sf[2]->loadFont("titlfnt.nut", directory);
} else if (_scumm->_gameId == GID_DIG) {
for(int i = 0; i < 4; i++) {
char file_font[11];
sprintf((char *)&file_font, "font%d.nut", i);
_sf[i] = new SmushFont(i != 0, false);
_sf[i]->loadFont(file_font, directory);
}
} else if (_scumm->_gameId == GID_CMI) {
for(int i = 0; i < 5; i++) {
char file_font[11];
sprintf((char *)&file_font, "font%d.nut", i);
_sf[i] = new SmushFont(false, true);
_sf[i]->loadFont(file_font, directory);
}
} else {
error("SmushPlayer::init() Unknown font setup for game");
}
delete sub;
}
void SmushPlayer::parseNextFrame() {
if (_scumm->_smushPlay == false)
return;
Chunk *sub = _base->subBlock();
if (_base->eof()) {
_scumm->_videoFinished = true;
return;
}
switch(sub->getType()) {
case TYPE_FRME:
handleFrame(*sub);
break;
default:
error("Unknown Chunk found : %d, %d", sub->getType(), sub->getSize());
}
delete sub;
}
void SmushPlayer::setPalette(byte *palette) {
byte palette_colors[1024];
byte *p = palette_colors;
byte *data = palette;
for (int i = 0; i != 256; i++, data += 3, p += 4) {
p[0] = data[0]; // red
p[1] = data[1]; // green
p[2] = data[2]; // blue
p[3] = 0;
}
_scumm->_system->set_palette(palette_colors, 0, 256);
}
void SmushPlayer::updateScreen() {
int width = MIN(_width, _scumm->_realWidth);
int height = MIN(_height, _scumm->_realHeight);
_scumm->parseEvents();
_scumm->_system->copy_rect(_data, _width, 0, 0, width, height);
_scumm->_system->update_screen();
}
void SmushPlayer::play(const char *filename, const char *directory) {
setupAnim(filename, directory);
init();
while (true) {
_scumm->processKbd();
_scumm->_system->delay_msecs(10);
if (_scumm->_videoFinished == true)
break;
if (_scumm->_saveLoadFlag)
break;
};
deinit();
}
--- NEW FILE: smush_player.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2003 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/scumm/smush/smush_player.h,v 1.1 2003/03/17 12:28:50 aquadran Exp $
*
*/
#ifndef SMUSH_PLAYER_H
#define SMUSH_PLAYER_H
#include "common/util.h"
#include "chunk.h"
#include "codec37.h"
#include "codec47.h"
class SmushFont;
class SmushMixer;
class StringResource;
class SmushPlayer {
private:
Scumm *_scumm;
int _version;
int32 _nbframes;
SmushMixer *_smixer;
int16 _deltaPal[0x300];
byte _pal[0x300];
StringResource *_strings;
SmushFont *_sf[5];
Codec37Decoder _codec37;
Codec47Decoder _codec47;
int dst_width, dst_height;
FileChunk *_base;
byte *_frameBuffer;
bool _codec37Called;
bool _skipNext;
bool _subtitles;
bool _skips[37];
int32 _frame;
int _IACTchannel;
byte _IACToutput[4096];
int32 _IACTpos;
bool _storeFrame;
int _soundFrequency;
bool _alreadyInit;
int _speed;
bool _outputSound;
public:
int _width, _height;
byte *_data;
bool _smushProcessFrame;
SmushPlayer(Scumm *, int, bool);
~SmushPlayer();
void updatePalette(void);
void parseNextFrame();
void init();
void deinit();
void setupAnim(const char *file, const char *directory);
void initCodecs();
void updateScreen();
void play(const char *filename, const char *directory);
void setPalette(byte *palette);
protected:
bool readString(const char *file, const char *directory);
void clean();
void checkBlock(const Chunk &, Chunk::type, uint32 = 0);
void handleAnimHeader(Chunk &);
void handleFrame(Chunk &);
void handleNewPalette(Chunk &);
void handleFrameObject(Chunk &);
void handleSoundBuffer(int32, int32, int32, int32, int32, int32, Chunk &, int32);
void handleImuseBuffer(int32, int32, int32, int32, int32, int32, Chunk &, int32);
void handleSoundFrame(Chunk &);
void handleSkip(Chunk &);
void handleStore(Chunk &);
void handleFetch(Chunk &);
void handleImuseAction(Chunk &);
void handleTextResource(Chunk &);
void handleDeltaPalette(Chunk &);
void readPalette(byte *, Chunk &);
};
#endif
Index: channel.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/channel.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- channel.h 6 Mar 2003 21:46:35 -0000 1.9
+++ channel.h 17 Mar 2003 12:28:49 -0000 1.10
@@ -19,63 +19,47 @@
*
*/
-#ifndef CHANNEL_H
-#define CHANNEL_H
-
-#include "config.h"
-#include "common/engine.h" // for debug, warning, error
+#ifndef SMUSH_CHANNEL_H
+#define SMUSH_CHANNEL_H
-#ifdef DEBUG
-# ifndef NO_DEBUG_CHANNEL
-# define DEBUG_CHANNEL
-# endif
-#else
-# ifdef DEBUG_CHANNEL
-# error DEBUG_CHANNEL defined without DEBUG
-# endif
-#endif
+#include "common/engine.h"
class Chunk;
class ContChunk;
-/*! @brief int32erface for a sound channel (a track)
-
- This is the int32erface for sound channels.
-*/
-class _Channel {
+class SmushChannel {
public:
- virtual ~_Channel() {};
- // called by the smush_player
+
+ virtual ~SmushChannel() {};
virtual bool appendData(Chunk &b, int32 size) = 0;
virtual bool setParameters(int32, int32, int32, int32) = 0;
virtual bool checkParameters(int32, int32, int32, int32, int32) = 0;
- // called by the mixer
virtual bool isTerminated() const = 0;
virtual int32 availableSoundData() const = 0;
- virtual void getSoundData(int16 *sound_buffer, int32 size) = 0; // size is in sample
+ virtual void getSoundData(int16 *sound_buffer, int32 size) = 0;
virtual void getSoundData(int8 *sound_buffer, int32 size) = 0;
virtual int32 getRate() = 0;
virtual bool getParameters(int32 &rate, bool &stereo, bool &is_16bit) = 0;
virtual int32 getTrackIdentifier() const = 0;
};
-class SaudChannel : public _Channel {
+class SaudChannel : public SmushChannel {
private:
- int32 _track; //!< The track identifier
- int32 _nbframes; //!< number of frames of the track (unused)
- int32 _dataSize; //!< the size of the sound buffer
- int32 _frequency; //!< the frequency target of the track (always 22050)
- bool _inData; //!< are we processing data ?
- bool _markReached; //!< set to \c true when the SMRK tag is reached
- int32 _flags; //!< current flags of the track (unused)
- int32 _volume; //!< the current track volume
- int32 _balance; //!< the current track balance
- int32 _index; //!< the current PSAD index (for coherency checking)
- int16 _voltable[2][256]; //!< the precalculated volume table (stereo 16 bits)
- byte *_tbuffer; //!< data temporary buffer
- int32 _tbufferSize; //!< temporary buffer size
- byte *_sbuffer; //!< sound buffer
- int32 _sbufferSize; //!< sound buffer size
+ int32 _track;
+ int32 _nbframes;
+ int32 _dataSize;
+ int32 _frequency;
+ bool _inData;
+ bool _markReached;
+ int32 _flags;
+ int32 _volume;
+ int32 _balance;
+ int32 _index;
+ int16 _voltable[2][256];
+ byte *_tbuffer;
+ int32 _tbufferSize;
+ byte *_sbuffer;
+ int32 _sbufferSize;
protected:
void handleStrk(Chunk &c);
@@ -105,13 +89,7 @@
virtual int32 getTrackIdentifier() const { return _track; };
};
-/*! @brief class for a IACT sound ::channel (a The Dig track)
-
- This class implements a channel specifically for The Dig.
-
- \bug for unknown reason, some sound have a too long duration, or repeat themselves.
-*/
-class ImuseChannel : public _Channel {
+class ImuseChannel : public SmushChannel {
private:
int32 _track; //!< the track number
byte *_tbuffer; //!< data temporary buffer
Index: chunk.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/chunk.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- chunk.cpp 6 Mar 2003 21:46:36 -0000 1.10
+++ chunk.cpp 17 Mar 2003 12:28:49 -0000 1.11
@@ -22,35 +22,34 @@
#include <stdafx.h>
#include "chunk.h"
-#include "common/engine.h" // for debug, warning, error
+#include "common/engine.h"
#include "common/file.h"
#include "common/str.h"
-#include <stdio.h> // for FILE, fopen, fclose, fseek and ftell
-#include <string.h> // for memcpy
-
-/*! @brief very small and fast wrapper for a ifstream.
-
- implements reference counting, so that ::file_Chunk does not leak memory !
-*/
class FilePtr {
ScummVM::String _filename;
File _ifs;
int32 _refcount;
int32 _curPos;
public:
- FilePtr(const char *fname, const char *directory) : _filename(fname), _refcount(1), _curPos(0) {
- debug(9, "FilePtr created for %s", fname);
- _ifs.open(fname, directory);
- if(_ifs.isOpen() == false) error("FilePtr unable to read file %s", fname);
- }
+ FilePtr(const char *fname, const char *directory) :
+ _filename(fname),
+ _refcount(1),
+ _curPos(0) {
+ debug(9, "FilePtr created for %s", fname);
+ _ifs.open(fname, directory);
+ if(_ifs.isOpen() == false) error("FilePtr unable to read file %s", fname);
+ }
+
~FilePtr() {
debug(9, "FilePtr destroyed for %s", _filename.c_str());
_ifs.close();
}
+
int32 tell() {
return _curPos;
}
+
bool seek(int32 pos) {
if(pos != _curPos) {
_ifs.seek(pos, SEEK_SET);
@@ -58,14 +57,17 @@
}
return true;
}
+
bool read(void *ptr, int32 size) {
_ifs.read(ptr, size);
_curPos += size;
return true;
}
+
void incRef() {
_refcount++;
}
+
void decRef() {
if(--_refcount == 0)
delete this;
@@ -82,11 +84,16 @@
return data;
}
-FileChunk::FileChunk() : _data(0), _type(0), _size(0), _curPos(0) {
+FileChunk::FileChunk() :
+ _data(0),
+ _type(0),
+ _size(0),
+ _curPos(0) {
}
FileChunk::~FileChunk() {
- if(_data) _data->decRef();
+ if(_data)
+ _data->decRef();
}
FileChunk::FileChunk(const char *fname, const char *directory) {
@@ -137,11 +144,15 @@
_curPos += delta;
break;
case seek_start:
- if(delta < 0) error("invalid seek request");
+ if(delta < 0)
+ error("invalid seek request");
+
_curPos = (uint32)delta;
break;
case seek_end:
- if(delta > 0 || (_size + delta) < 0) error("invalid seek request");
+ if(delta > 0 || (_size + delta) < 0)
+ error("invalid seek request");
+
_curPos = (uint32)(_size + delta);
break;
}
@@ -154,6 +165,7 @@
bool FileChunk::read(void *buffer, uint32 size) {
if(size <= 0 || (_curPos + size) > _size)
error("invalid buffer read request");
+
_data->seek(_offset + _curPos);
_data->read(buffer, size);
_curPos += size;
@@ -163,6 +175,7 @@
int8 FileChunk::getChar() {
if(_curPos >= _size)
error("invalid char read request");
+
_data->seek(_offset + _curPos);
int8 buffer;
_data->read(&buffer, sizeof(buffer));
@@ -173,6 +186,7 @@
byte FileChunk::getByte() {
if(_curPos >= _size)
error("invalid byte read request");
+
_data->seek(_offset + _curPos);
byte buffer;
_data->read(&buffer, sizeof(buffer));
@@ -188,6 +202,7 @@
uint16 FileChunk::getWord() {
if(_curPos >= _size - 1)
error("invalid word read request");
+
_data->seek(_offset + _curPos);
uint16 buffer;
_data->read(&buffer, sizeof(buffer));
@@ -198,6 +213,7 @@
uint32 FileChunk::getDword() {
if(_curPos >= _size - 3)
error("invalid dword read request");
+
_data->seek(_offset + _curPos);
uint32 buffer;
_data->read(&buffer, sizeof(buffer));
@@ -207,7 +223,8 @@
ContChunk::ContChunk(byte *data) {
if(data == 0)
- error("Chunk() called with NULL point32er");
+ error("Chunk() called with NULL pointer");
+
_type = (Chunk::type)READ_BE_UINT32(data);
_size = READ_BE_UINT32(data + 4);
_data = data + sizeof(Chunk::type) + sizeof(uint32);
@@ -257,39 +274,51 @@
}
bool ContChunk::read(void *buffer, uint32 size) {
- if(size <= 0 || (_curPos + size) > _size) error("invalid buffer read request");
+ if(size <= 0 || (_curPos + size) > _size)
+ error("invalid buffer read request");
+
memcpy(buffer, _data + _curPos, size);
_curPos += size;
return true;
}
int8 ContChunk::getChar() {
- if(_curPos >= _size) error("invalid char read request");
+ if(_curPos >= _size)
+ error("invalid char read request");
+
return _data[_curPos++];
}
byte ContChunk::getByte() {
- if(_curPos >= _size) error("invalid byte read request");
+ if(_curPos >= _size)
+ error("invalid byte read request");
+
byte *ptr = (byte *)(_data + _curPos);
_curPos += 1;
return *ptr;
}
int16 ContChunk::getShort() {
- if(_curPos >= _size - 1) error("invalid int16 read request");
+ if(_curPos >= _size - 1)
+ error("invalid int16 read request");
+
int16 buffer = getWord();
return *((int16 *)&buffer);
}
uint16 ContChunk::getWord() {
- if(_curPos >= _size - 1) error("invalid word read request");
+ if(_curPos >= _size - 1)
+ error("invalid word read request");
+
uint16 *ptr = (uint16 *)(_data + _curPos);
_curPos += 2;
return READ_LE_UINT16(ptr);
}
uint32 ContChunk::getDword() {
- if(_curPos >= _size - 3) error("invalid dword read request");
+ if(_curPos >= _size - 3)
+ error("invalid dword read request");
+
uint32 *ptr = (uint32 *)(_data + _curPos);
_curPos += 4;
return READ_LE_UINT32(ptr);
Index: chunk.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/chunk.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- chunk.h 6 Mar 2003 21:46:37 -0000 1.7
+++ chunk.h 17 Mar 2003 12:28:49 -0000 1.8
@@ -22,69 +22,54 @@
#ifndef CHUNK_H
#define CHUNK_H
-#include "config.h"
-
-/*! @brief Interface for Chunk handling
-
- This class is an interface for reading from a Chunk.
+#include "common/scummsys.h"
- \todo handle big endian system.
-*/
class Chunk {
public:
- enum seek_type { seek_start, seek_end, seek_cur };
- virtual ~Chunk() {};
- typedef uint32 type; //!< type of a Chunk (i.e. The first 4byte field of the Chunk structure).
- /*! @brief convert a type to a string
-
- Utility function that convert a type to a string.
-
- @param t the type to convert to a string
-
- @return the converted string
- */
- static const char * ChunkString(type t);
- virtual type getType() const = 0; //!< return the type of the Chunk
- virtual uint32 getSize() const = 0; //!< return the size of the Chunk
- virtual Chunk * subBlock() = 0; //!< extract a subChunk from the current read position
- virtual bool eof() const = 0; //!< is the Chunk completely read ?
- virtual uint32 tell() const = 0; //!< get the Chunk current read position
- virtual bool seek(int32 delta, seek_type dir = seek_cur) = 0; //!< move the current read position inside the Chunk
- virtual bool read(void * buffer, uint32 size) = 0; //!< read some data for the current read position
- virtual int8 getChar() = 0; //!< extract the character at the current read position
- virtual byte getByte() = 0; //!< extract the byte at the current read position
- virtual int16 getShort() = 0; //!< extract the short at the current read position
- virtual uint16 getWord() = 0; //!< extract the word at the current read position
- virtual uint32 getDword()= 0; //!< extract the dword at the current read position
+ virtual ~Chunk() {};
+ enum seek_type { seek_start, seek_end, seek_cur };
+ typedef uint32 type;
+ static const char *ChunkString(type t);
+ virtual type getType() const = 0;
+ virtual uint32 getSize() const = 0;
+ virtual Chunk *subBlock() = 0;
+ virtual bool eof() const = 0;
+ virtual uint32 tell() const = 0;
+ virtual bool seek(int32 delta, seek_type dir = seek_cur) = 0;
+ virtual bool read(void *buffer, uint32 size) = 0;
+ virtual int8 getChar() = 0;
+ virtual byte getByte() = 0;
+ virtual int16 getShort() = 0;
+ virtual uint16 getWord() = 0;
+ virtual uint32 getDword()= 0;
};
class FilePtr;
-/*! @brief file based ::Chunk
-
- This class is an implementation of ::Chunk that handles file.
-
-*/
class FileChunk : public Chunk {
private:
- FilePtr * _data;
+ FilePtr *_data;
type _type;
uint32 _size;
uint32 _offset;
uint32 _curPos;
+
protected:
+
FileChunk();
+
public:
- FileChunk(const char * fname, const char * directory);
+
+ FileChunk(const char *fname, const char *directory);
virtual ~FileChunk();
type getType() const;
uint32 getSize() const;
- Chunk * subBlock();
+ Chunk *subBlock();
bool eof() const;
uint32 tell() const;
bool seek(int32 delta, seek_type dir = seek_cur);
- bool read(void * buffer, uint32 size);
+ bool read(void *buffer, uint32 size);
int8 getChar();
byte getByte();
short getShort();
@@ -92,17 +77,16 @@
uint32 getDword();
};
-/*! @brief memory based ::Chunk
-
- This class is an implementation of ::Chunk that handles a memory buffer.
-*/
class ContChunk : public Chunk {
private:
+
byte *_data;
Chunk::type _type;
uint32 _size;
uint32 _curPos;
+
public:
+
ContChunk(byte *data);
Chunk::type getType() const;
uint32 getSize() const;
Index: codec1.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/codec1.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- codec1.cpp 13 Mar 2003 01:24:02 -0000 1.8
+++ codec1.cpp 17 Mar 2003 12:28:49 -0000 1.9
@@ -20,44 +20,28 @@
*/
#include <stdafx.h>
-#include "codec1.h"
-
-Codec1Decoder::~Codec1Decoder() {
-}
+#include "common/scummsys.h"
-bool Codec1Decoder::decode(byte *dst, const byte *src, int) {
- byte val;
- int32 size_line;
- int32 code, length;
- int32 h, height = getRect().height();
+void smush_decode_codec1(byte *dst, byte *src, int height) {
+ byte val, code;
+ int32 length;
+ int h = height, size_line;
for(h = 0; h < height; h++) {
- size_line = READ_LE_UINT16(src); // size of compressed line !
+ size_line = READ_LE_UINT16(src);
src += 2;
-#ifdef DEBUG_CODEC1
- debug(7, "codec1 : h == %d, size_line == %d", h, size_line);
-#endif
while(size_line > 0) {
code = *src++;
size_line--;
length = (code >> 1) + 1;
-#ifdef DEBUG_CODEC1
- debug(7, "codec1 : length == %d", length);
-#endif
if(code & 1) {
val = *src++;
size_line--;
if (val)
memset(dst, val, length);
dst += length;
-#ifdef DEBUG_CODEC1
- debug(7, "codec1 : blitting %d times %d", length, val);
-#endif
} else {
size_line -= length;
-#ifdef DEBUG_CODEC1
- debug(7, "codec1 : blitting %d entries", length);
-#endif
while(length--) {
val = *src++;
if (val)
@@ -67,5 +51,4 @@
}
}
}
- return true;
}
Index: codec37.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/codec37.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- codec37.cpp 13 Mar 2003 01:24:02 -0000 1.17
+++ codec37.cpp 17 Mar 2003 12:28:49 -0000 1.18
@@ -24,35 +24,24 @@
#include "common/engine.h"
-#include <assert.h>
-#include <string.h>
-
-bool Codec37Decoder::initSize(const Point &p, const Rect &r) {
- if(r.width() != getRect().width() && r.height() != getRect().height()) {
- if(
- (r.width() != 320 || r.height() != 200) &&
- (r.width() != 384 || r.height() != 242) &&
- (r.width() != 640 || r.height() != 480)
- )
- return false;
- Decoder::initSize(p, r);
- clean();
- int32 frame_size = getRect().width() * getRect().height();
- _deltaSize = frame_size * 3 + 0x13600;
- _deltaBuf = new byte[_deltaSize];
- memset(_deltaBuf, 0, _deltaSize);
- if(_deltaBuf == 0) error("unable to allocate decoder buffer");
- _deltaBufs[0] = _deltaBuf + 0x4D80;
- _deltaBufs[1] = _deltaBuf + 0xE880 + frame_size;
- _offsetTable = new int16[255];
- _curtable = 0;
- if(_offsetTable == 0)
- error("unable to allocate decoder offset table");
- _tableLastPitch = -1;
- _tableLastIndex = -1;
- return true;
- }
- return false;
+void Codec37Decoder::init(int width, int height) {
+ deinit();
+ _width = width;
+ _height = height;
+ _frameSize = _width * _height;
+ _deltaSize = _frameSize * 3 + 0x13600;
+ _deltaBuf = new byte[_deltaSize];
+ memset(_deltaBuf, 0, _deltaSize);
+ if(_deltaBuf == 0)
+ error("unable to allocate decoder buffer");
+ _deltaBufs[0] = _deltaBuf + 0x4D80;
+ _deltaBufs[1] = _deltaBuf + 0xE880 + _frameSize;
+ _offsetTable = new int16[255];
+ _curtable = 0;
+ if(_offsetTable == 0)
+ error("unable to allocate decoder offset table");
+ _tableLastPitch = -1;
+ _tableLastIndex = -1;
}
Codec37Decoder::Codec37Decoder() {
@@ -67,7 +56,7 @@
_prevSeqNb = 0;
}
-void Codec37Decoder::clean() {
+void Codec37Decoder::deinit() {
if(_offsetTable) {
delete []_offsetTable;
_offsetTable = 0;
@@ -84,10 +73,10 @@
}
Codec37Decoder::~Codec37Decoder() {
- clean();
+ deinit();
}
-void Codec37Decoder::maketable(int32 pitch, int32 index) {
+void Codec37Decoder::maketable(int pitch, int index) {
static const int8 maketable_bytes[] = {
0, 0, 1, 0, 2, 0, 3, 0, 5, 0,
8, 0, 13, 0, 21, 0, -1, 0, -2, 0,
@@ -246,6 +235,7 @@
if (_tableLastPitch == pitch && _tableLastIndex == index)
return;
+
_tableLastPitch = pitch;
_tableLastIndex = index;
index *= 255;
@@ -368,7 +358,7 @@
dst += 4; \
} while(0)
-void Codec37Decoder::proc3WithFDFE(byte *dst, const byte *src, int32 next_offs, int32 bw, int32 bh, int32 pitch, int16 *offset_table) {
+void Codec37Decoder::proc3WithFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) {
do {
int32 i = bw;
do {
@@ -388,7 +378,7 @@
} while (--bh);
}
-void Codec37Decoder::proc3WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int32 bw, int32 bh, int32 pitch, int16 *offset_table) {
+void Codec37Decoder::proc3WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) {
do {
int32 i = bw;
do {
@@ -404,7 +394,7 @@
} while (--bh);
}
-void Codec37Decoder::proc4WithFDFE(byte *dst, const byte *src, int32 next_offs, int32 bw, int32 bh, int32 pitch, int16 *offset_table) {
+void Codec37Decoder::proc4WithFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) {
do {
int32 i = bw;
do {
@@ -440,7 +430,7 @@
} while (--bh);
}
-void Codec37Decoder::proc4WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int32 bw, int32 bh, int32 pitch, int16 *offset_table) {
+void Codec37Decoder::proc4WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) {
do {
int32 i = bw;
do {
@@ -472,10 +462,8 @@
} while (--bh);
}
-bool Codec37Decoder::decode(byte *dst, const byte *src, int length) {
- int32 width = getRect().width();
- int32 height = getRect().height();
- int32 bw = (width + 3) >> 2, bh = (height + 3) >> 2;
+void Codec37Decoder::decode(byte *dst, const byte *src) {
+ int32 bw = (_width + 3) >> 2, bh = (_height + 3) >> 2;
int32 pitch = bw << 2;
int16 seq_nb = READ_LE_UINT16(src + 2);
@@ -543,8 +531,6 @@
}
_prevSeqNb = seq_nb;
- memcpy(dst, _deltaBufs[_curtable], width * height);
-
- return true;
+ memcpy(dst, _deltaBufs[_curtable], _frameSize);
}
Index: codec37.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/codec37.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- codec37.h 13 Mar 2003 01:24:02 -0000 1.10
+++ codec37.h 17 Mar 2003 12:28:49 -0000 1.11
@@ -19,36 +19,39 @@
*
*/
-#ifndef CODEC37_H
-#define CODEC37_H
+#ifndef SMUSH_CODEC37_H
+#define SMUSH_CODEC37_H
-#include "decoder.h"
+#include "common/scummsys.h"
-class Codec37Decoder : public Decoder {
+class Codec37Decoder {
private:
+
int32 _deltaSize;
byte *_deltaBufs[2];
byte *_deltaBuf;
int16 *_offsetTable;
- int32 _curtable;
+ int _curtable;
uint16 _prevSeqNb;
- int32 _tableLastPitch;
- int32 _tableLastIndex;
+ int _tableLastPitch;
+ int _tableLastIndex;
+ int32 _frameSize;
+ int _width, _height;
public:
- bool initSize(const Point &, const Rect &);
Codec37Decoder();
- void clean();
- virtual ~Codec37Decoder();
+ ~Codec37Decoder();
+ void init(int width, int height);
+ void deinit();
protected:
- void maketable(int32, int32);
+ void maketable(int, int);
void bompDecode(byte *dst, const byte *src, int len);
- void proc3WithFDFE(byte *dst, const byte *src, int32, int32, int32, int32, int16 *);
- void proc3WithoutFDFE(byte *dst, const byte *src, int32, int32, int32, int32, int16 *);
- void proc4WithFDFE(byte *dst, const byte *src, int32, int32, int32, int32, int16 *);
- void proc4WithoutFDFE(byte *dst, const byte *src, int32, int32, int32, int32, int16 *);
+ void proc3WithFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *);
+ void proc3WithoutFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *);
+ void proc4WithFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *);
+ void proc4WithoutFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *);
public:
- bool decode(byte *dst, const byte *src, int length);
+ void decode(byte *dst, const byte *src);
};
#endif
Index: codec47.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/codec47.cpp,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- codec47.cpp 13 Mar 2003 06:37:07 -0000 1.44
+++ codec47.cpp 17 Mar 2003 12:28:49 -0000 1.45
@@ -601,16 +601,16 @@
}
}
-void Codec47Decoder::decode2(byte *dst, const byte *src, int32 width, int32 height, const byte *param_ptr) {
+void Codec47Decoder::decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr) {
_d_src = src;
_paramPtr = param_ptr - 0xf8;
- int32 bw = (width + 7) >> 3;
- int32 bh = (height + 7) >> 3;
- int32 next_line = width * 7;
+ int bw = (width + 7) >> 3;
+ int bh = (height + 7) >> 3;
+ int next_line = width * 7;
_d_pitch = width;
do {
- int32 tmp_bw = bw;
+ int tmp_bw = bw;
do {
level1(dst);
dst += 8;
@@ -619,35 +619,26 @@
} while (--bh);
}
-bool Codec47Decoder::initSize(const Point &p, const Rect &r) {
- if(r.width() != getRect().width() && r.height() != getRect().height()) {
- if(
- (r.width() != 640 || r.height() != 480)
- )
- return false;
- Decoder::initSize(p, r);
- clean();
-
- makeTables37(4);
- makeTables37(8);
-
- int32 frame_size = getRect().width() * getRect().height();
- _deltaSize = frame_size * 3;
- _deltaBuf = new byte[_deltaSize];
- _deltaBufs[0] = _deltaBuf;
- _deltaBufs[1] = _deltaBuf + frame_size;
- _curBuf = _deltaBuf + frame_size * 2;
+void Codec47Decoder::init(int width, int height) {
+ deinit();
+ _width = width;
+ _height = height;
+ makeTables37(4);
+ makeTables37(8);
- return true;
- }
- return false;
+ _frameSize = _width * _height;
+ _deltaSize = _frameSize * 3;
+ _deltaBuf = new byte[_deltaSize];
+ _deltaBufs[0] = _deltaBuf;
+ _deltaBufs[1] = _deltaBuf + _frameSize;
+ _curBuf = _deltaBuf + _frameSize * 2;
}
Codec47Decoder::Codec47Decoder() {
_deltaBuf = 0;
}
-void Codec47Decoder::clean() {
+void Codec47Decoder::deinit() {
_lastTableWidth = -1;
if(_deltaBuf) {
delete []_deltaBuf;
@@ -659,12 +650,10 @@
}
Codec47Decoder::~Codec47Decoder() {
- clean();
+ deinit();
}
-bool Codec47Decoder::decode(byte *dst, const byte *src, int length) {
- int32 width = getRect().width();
- int32 height = getRect().height();
+bool Codec47Decoder::decode(byte *dst, const byte *src) {
_offset1 = _deltaBufs[1] - _curBuf;
_offset2 = _deltaBufs[0] - _curBuf;
@@ -674,9 +663,9 @@
byte *tmp_ptr;
if (seq_nb == 0) {
- makeTables47(width);
- memset(_deltaBufs[0], src[12], width * height);
- memset(_deltaBufs[1], src[13], width * height);
+ makeTables47(_width);
+ memset(_deltaBufs[0], src[12], _frameSize);
+ memset(_deltaBufs[1], src[13], _frameSize);
_prevSeqNb = -1;
}
@@ -686,28 +675,28 @@
switch(src[2]) {
case 0:
- memcpy(_curBuf, gfx_data, width * height);
+ memcpy(_curBuf, gfx_data, _frameSize);
break;
case 1:
warning("codec47: not implemented decode1 proc");
break;
case 2:
if (seq_nb == _prevSeqNb + 1) {
- decode2(_curBuf, gfx_data, width, height, src + 8);
+ decode2(_curBuf, gfx_data, _width, _height, src + 8);
}
break;
case 3:
- memcpy(_curBuf, _deltaBufs[1], width * height);
+ memcpy(_curBuf, _deltaBufs[1], _frameSize);
break;
case 4:
- memcpy(_curBuf, _deltaBufs[0], width * height);
+ memcpy(_curBuf, _deltaBufs[0], _frameSize);
break;
case 5:
bompDecode(_curBuf, gfx_data, READ_LE_UINT32(src + 14));
break;
}
- memcpy(dst, _curBuf, width * height);
+ memcpy(dst, _curBuf, _frameSize);
if (seq_nb == _prevSeqNb + 1) {
if (src[3] == 1) {
Index: codec47.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/codec47.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- codec47.h 13 Mar 2003 01:24:02 -0000 1.13
+++ codec47.h 17 Mar 2003 12:28:50 -0000 1.14
@@ -19,27 +19,28 @@
*
*/
-#ifndef CODEC_47_H
-#define CODEC_47_H
-
-#include "config.h"
+#ifndef SMUSH_CODEC_47_H
+#define SMUSH_CODEC_47_H
-#include "decoder.h"
+#include "common/scummsys.h"
-class Codec47Decoder : public Decoder {
+class Codec47Decoder {
private:
+
int32 _deltaSize;
byte *_deltaBufs[2];
byte *_deltaBuf;
byte *_curBuf;
int32 _prevSeqNb;
- int32 _lastTableWidth;
+ int _lastTableWidth;
const byte *_d_src, *_paramPtr;
- int32 _d_pitch;
+ int _d_pitch;
int32 _offset1, _offset2;
byte _tableBig[99328];
byte _tableSmall[32768];
int16 _table[256];
+ int32 _frameSize;
+ int _width, _height;
void makeTables47(int32 width);
void makeTables37(int32 param);
@@ -47,14 +48,14 @@
void level1(byte *d_dst);
void level2(byte *d_dst);
void level3(byte *d_dst);
- void decode2(byte *dst, const byte *src, int32 width, int32 height, const byte *param_ptr);
+ void decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr);
public:
Codec47Decoder();
- virtual ~Codec47Decoder();
- bool initSize(const Point &, const Rect &);
- void clean();
- bool decode(byte *dst, const byte *src, int length);
+ ~Codec47Decoder();
+ void init(int width, int height);
+ void deinit();
+ bool decode(byte *dst, const byte *src);
};
#endif
Index: imuse_channel.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/imuse_channel.cpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- imuse_channel.cpp 6 Mar 2003 21:46:44 -0000 1.13
+++ imuse_channel.cpp 17 Mar 2003 12:28:50 -0000 1.14
@@ -24,9 +24,6 @@
#include "chunk.h"
#include "chunk_type.h"
-#include <assert.h>
-#include <string.h>
-
ImuseChannel::ImuseChannel(int32 track, int32 freq) :
_track(track),
_tbuffer(0),
@@ -73,7 +70,7 @@
}
bool ImuseChannel::appendData(Chunk &b, int32 size) {
- if(_dataSize == -1) { // First call
+ if(_dataSize == -1) {
assert(size > 8);
Chunk::type imus_type = b.getDword(); imus_type = SWAP_BYTES(imus_type);
uint32 imus_size = b.getDword(); imus_size = SWAP_BYTES(imus_size);
@@ -86,9 +83,9 @@
if(!_tbuffer)
error("imuse_channel failed to allocate memory");
b.read(_tbuffer, size);
- _dataSize = -2; // even if _in_data does not get set, this won't be called again
+ _dataSize = -2;
} else {
- if(_tbuffer) { // remaining from last call
+ if(_tbuffer) {
byte *old = _tbuffer;
int32 new_size = size + _tbufferSize;
_tbuffer = new byte[new_size];
@@ -223,7 +220,7 @@
handleMap(c);
}
break;
- case TYPE_DATA: // Sound data !!!
+ case TYPE_DATA:
_inData = true;
_dataSize = size;
offset += 8;
@@ -254,7 +251,6 @@
}
bool ImuseChannel::processBuffer() {
- // see comments in saud_channel::processBuffer for an explanation
assert(_tbuffer != 0);
assert(_tbufferSize != 0);
assert(_sbuffer == 0);
@@ -266,7 +262,7 @@
while(handleSubTags(offset));
_sbufferSize = _dataSize;
_sbuffer = _tbuffer;
- if(offset < _tbufferSize) { // there is still some unprocessed data
+ if(offset < _tbufferSize) {
int32 new_size = _tbufferSize - offset;
_tbuffer = new byte[new_size];
if(!_tbuffer) error("imuse_channel failed to allocate memory");
@@ -277,12 +273,10 @@
_tbufferSize = 0;
}
if(_sbufferSize == 0) {
- // this never happened yet, but who knows
delete []_sbuffer;
_sbuffer = 0;
}
} else {
- // easy, swap the buffer
_sbufferSize = _tbufferSize;
_sbuffer = _tbuffer;
_tbufferSize = 0;
@@ -301,7 +295,7 @@
_tbuffer = 0;
_tbufferSize = 0;
} else {
- if(offset) { // maybe I should assert() this to avoid a lock...
+ if(offset) {
byte * old = _tbuffer;
int32 new_size = _tbufferSize - offset;
_tbuffer = new byte[new_size];
Index: saud_channel.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/smush/saud_channel.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- saud_channel.cpp 6 Mar 2003 21:46:45 -0000 1.10
+++ saud_channel.cpp 17 Mar 2003 12:28:50 -0000 1.11
@@ -25,9 +25,6 @@
#include "chunk.h"
#include "chunk_type.h"
-#include <assert.h>
-#include <string.h>
-
void SaudChannel::handleStrk(Chunk &b) {
int32 size = b.getSize();
if(size != 14 && size != 10) {
@@ -41,7 +38,8 @@
void SaudChannel::handleShdr(Chunk &b) {
int32 size = b.getSize();
- if(size != 4) warning("SMRK has a invalid size : %d", size);
+ if(size != 4)
+ warning("SMRK has a invalid size : %d", size);
}
bool SaudChannel::handleSubTags(int32 &offset) {
@@ -93,12 +91,6 @@
}
bool SaudChannel::processBuffer() {
- // At the start of this function, we have _tbuffer[0.._tbuffersize] containing possible data...
- // and _sbuffer is 0
- // At the end we have :
- // if(sound data) _sbuffer[0.._sbuffer_size] contains the sound data
- // the unprocessed data is kept in _tbuffer[0.._tbuffersize] (which may have changed)
- // if no unprocessed data, then _tbuffer is 0
assert(_tbuffer != 0);
assert(_tbufferSize != 0);
assert(_sbuffer == 0);
@@ -106,12 +98,11 @@
if(_inData) {
if(_dataSize < _tbufferSize) {
- // I can't assume that the channel is finished after data is received... (this assumption failed in realride.san)
int32 offset = _dataSize;
while(handleSubTags(offset));
_sbufferSize = _dataSize;
_sbuffer = _tbuffer;
- if(offset < _tbufferSize) { // there is still some unprocessed data
+ if(offset < _tbufferSize) {
int new_size = _tbufferSize - offset;
_tbuffer = new byte[new_size];
if(!_tbuffer) error("SaudChannel failed to allocate memory");
@@ -122,12 +113,10 @@
_tbufferSize = 0;
}
if(_sbufferSize == 0) {
- // this never happened yet, but who knows
delete []_sbuffer;
_sbuffer = 0;
}
} else {
- // easy, swap the buffer
_sbufferSize = _tbufferSize;
_sbuffer = _tbuffer;
_tbufferSize = 0;
@@ -140,17 +129,19 @@
_sbufferSize = _tbufferSize - offset;
assert(_sbufferSize);
_sbuffer = new byte[_sbufferSize];
- if(!_sbuffer) error("saud_channel failed to allocate memory");
+ if(!_sbuffer)
+ error("saud_channel failed to allocate memory");
memcpy(_sbuffer, _tbuffer + offset, _sbufferSize);
delete []_tbuffer;
_tbuffer = 0;
_tbufferSize = 0;
} else {
- if(offset) { // maybe I should assert() this to avoid a lock...
- unsigned char *old = _tbuffer;
+ if(offset) {
+ byte *old = _tbuffer;
int32 new_size = _tbufferSize - offset;
_tbuffer = new byte[new_size];
- if(!_tbuffer) error("SaudChannel failed to allocate memory");
+ if(!_tbuffer)
+ error("SaudChannel failed to allocate memory");
memcpy(_tbuffer, old + offset, new_size);
_tbufferSize = new_size;
delete []old;
@@ -197,10 +188,14 @@
int32 right_multiplier = MAX_BALANCE + _balance;
volume_left = _volume * left_multiplier / (MAX_BALANCE * 2);
volume_right = _volume * right_multiplier / (MAX_BALANCE * 2);
- if(volume_left < 0) volume_left = 0;
- if(volume_left > 128) volume_left = 128;
- if(volume_right < 0) volume_right = 0;
- if(volume_right > 128) volume_right = 128;
+ if(volume_left < 0)
+ volume_left = 0;
+ if(volume_left > 128)
+ volume_left = 128;
+ if(volume_right < 0)
+ volume_right = 0;
+ if(volume_right > 128)
+ volume_right = 128;
for(int32 i = 0; i < 256; i++) {
int16 value = volume_left * (int8)i;
_voltable[0][i] = TO_BE_16(value);
@@ -220,9 +215,12 @@
}
bool SaudChannel::checkParameters(int32 index, int32 nb, int32 flags, int32 volume, int32 balance) {
- if(++_index != index) error("invalid index in SaudChannel::checkParameters()");
- if(_nbframes != nb) error("invalid duration in SaudChannel::checkParameters()");
- if(_flags != flags) error("invalid flags in SaudChannel::checkParameters()");
+ if(++_index != index)
+ error("invalid index in SaudChannel::checkParameters()");
+ if(_nbframes != nb)
+ error("invalid duration in SaudChannel::checkParameters()");
+ if(_flags != flags)
+ error("invalid flags in SaudChannel::checkParameters()");
if(_volume != volume || _balance != balance) {
_volume = volume;
_balance = balance;
@@ -232,13 +230,13 @@
}
bool SaudChannel::appendData(Chunk &b, int32 size) {
- if(_dataSize == -1) { // First call
+ if(_dataSize == -1) {
assert(size > 8);
Chunk::type saud_type = b.getDword(); saud_type = SWAP_BYTES(saud_type);
uint32 saud_size = b.getDword(); saud_size = SWAP_BYTES(saud_size);
if(saud_type != TYPE_SAUD) error("Invalid Chunk for SaudChannel : %X", saud_type);
size -= 8;
- _dataSize = -2; // We don't get here again...
+ _dataSize = -2;
}
if(_tbuffer) {
byte *old = _tbuffer;
--- brenderer.cpp DELETED ---
--- brenderer.h DELETED ---
--- codec1.h DELETED ---
--- codec44.cpp DELETED ---
--- codec44.h DELETED ---
--- color.cpp DELETED ---
--- color.h DELETED ---
--- config.h DELETED ---
--- decoder.h DELETED ---
--- frenderer.cpp DELETED ---
--- frenderer.h DELETED ---
--- mixer.h DELETED ---
--- palette.h DELETED ---
--- player.cpp DELETED ---
--- player.h DELETED ---
--- renderer.h DELETED ---
--- scumm_renderer.cpp DELETED ---
--- scumm_renderer.h DELETED ---
- Previous message: [Scummvm-cvs-logs] CVS: web/docs todo.xml,1.17,1.18
- Next message: [Scummvm-cvs-logs] CVS: scummvm/scumm script_v6.cpp,1.80,1.81 script_v8.cpp,2.143,2.144 scumm.h,1.159,1.160 scummvm.cpp,2.61,2.62
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Scummvm-git-logs
mailing list