mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-30 07:23:05 +00:00
In progress work implementing the animation player
svn-id: r49347
This commit is contained in:
parent
3f4302214c
commit
088e6456ea
@ -31,177 +31,397 @@ namespace M4 {
|
||||
|
||||
// TODO: this code needs cleanup
|
||||
|
||||
Animation::Animation(MadsM4Engine *vm) {
|
||||
_vm = vm;
|
||||
MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _view(view) {
|
||||
_playing = false;
|
||||
_font = NULL;
|
||||
_unk1 = 0;
|
||||
_skipLoad = false;
|
||||
_unkIndex = -1;
|
||||
_messageCtr= 0;
|
||||
}
|
||||
|
||||
void Animation::loadFullScreen(const char *filename) {
|
||||
_vm->_palette->deleteAllRanges();
|
||||
load(filename);
|
||||
MadsAnimation::~MadsAnimation() {
|
||||
delete _font;
|
||||
}
|
||||
|
||||
void Animation::load(const char *filename) {
|
||||
MadsPack anim(filename, _vm);
|
||||
void MadsAnimation::load(const Common::String &filename) {
|
||||
MadsPack anim(filename.c_str(), _vm);
|
||||
bool madsRes = filename[0] == '*';
|
||||
char buffer[20];
|
||||
int streamIndex = 1;
|
||||
|
||||
// Chunk 1: header
|
||||
// header
|
||||
// TODO: there are some unknown fields here, plus we don't read
|
||||
// the entire chunk
|
||||
|
||||
Common::SeekableReadStream *animStream = anim.getItemStream(0);
|
||||
Common::SeekableReadStream *spriteSeriesStream;
|
||||
//printf("Chunk 0, size %i\n", animStream->size());
|
||||
_seriesCount = animStream->readUint16LE();
|
||||
_frameCount = animStream->readUint16LE();
|
||||
_frameEntryCount = animStream->readUint16LE();
|
||||
|
||||
// Unknown
|
||||
for (int i = 0; i < 43; i++)
|
||||
animStream->readByte();
|
||||
int spriteListCount = animStream->readUint16LE();
|
||||
int miscEntriesCount = animStream->readUint16LE();
|
||||
int frameEntryCount = animStream->readUint16LE();
|
||||
int messagesCount = animStream->readUint16LE();
|
||||
animStream->skip(1);
|
||||
_flags = animStream->readByte();
|
||||
|
||||
_spriteSeriesNames = new Common::String[_seriesCount];
|
||||
printf("%i sprite series\n", _seriesCount);
|
||||
animStream->skip(2);
|
||||
_animMode = animStream->readUint16LE();
|
||||
assert(_animMode != 4);
|
||||
_roomNumber = animStream->readUint16LE();
|
||||
_field12 = animStream->readUint16LE() != 0;
|
||||
animStream->skip(4);
|
||||
_spriteListIndex = animStream->readUint16LE();
|
||||
_scrollX = animStream->readUint16LE();
|
||||
_scrollY = animStream->readSint16LE();
|
||||
animStream->skip(10);
|
||||
|
||||
animStream->read(buffer, 13);
|
||||
_field24 = Common::String(buffer, 13);
|
||||
|
||||
// TODO: for now, we only load the first sprite series
|
||||
if (_seriesCount > 1)
|
||||
printf("TODO: Anim has %i sprite series, for now, we only load the first one\n", _seriesCount);
|
||||
_seriesCount = 1; // TODO
|
||||
|
||||
for (int i = 0; i < _seriesCount; i++) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
animStream->read(buffer, 13);
|
||||
_spriteSeriesNames[i] = Common::String(buffer);
|
||||
//printf("%03d: %s\n", i, _spriteSeriesNames[i].c_str());
|
||||
_spriteSetNames[i] = Common::String(buffer, 13);
|
||||
}
|
||||
|
||||
spriteSeriesStream = _vm->res()->get(_spriteSeriesNames[i].c_str());
|
||||
_spriteSeries = new SpriteAsset(_vm, spriteSeriesStream,
|
||||
spriteSeriesStream->size(), _spriteSeriesNames[i].c_str());
|
||||
_vm->res()->toss(_spriteSeriesNames[i].c_str());
|
||||
animStream->skip(81);
|
||||
animStream->read(buffer, 13);
|
||||
_lbmFilename = Common::String(buffer, 13);
|
||||
animStream->read(buffer, 13);
|
||||
_spritesFilename = Common::String(buffer, 13);
|
||||
animStream->skip(48);
|
||||
animStream->read(buffer, 13);
|
||||
_soundName = Common::String(buffer, 13);
|
||||
animStream->skip(26);
|
||||
animStream->read(buffer, 13);
|
||||
Common::String fontResource(buffer, 13);
|
||||
|
||||
// Adjust the palette of the sprites in the sprite series
|
||||
// so that they can be displayed on screen correctly
|
||||
RGBList *palData = new RGBList(_spriteSeries->getColorCount(), _spriteSeries->getPalette(), true);
|
||||
_vm->_palette->addRange(palData);
|
||||
// TODO: Based on a weird usage of a flags word, a secondary method gets called here.
|
||||
// Figure out secondary method, and when/if it's called
|
||||
|
||||
for (int k = 0; k < _spriteSeries->getCount(); k++) {
|
||||
M4Sprite *spr = _spriteSeries->getFrame(k);
|
||||
spr->translate(palData); // sprite pixel translation
|
||||
// Initialise the reference list
|
||||
for (int i = 0; i < spriteListCount; ++i)
|
||||
_spriteListIndexes.push_back(-1);
|
||||
|
||||
delete animStream;
|
||||
|
||||
if (messagesCount > 0) {
|
||||
// Chunk 2
|
||||
// Following is a list of any messages for the animation
|
||||
|
||||
Common::SeekableReadStream *animStream = anim.getItemStream(streamIndex++);
|
||||
|
||||
for (int i = 0; i < messagesCount; ++i) {
|
||||
AnimMessage rec;
|
||||
animStream->read(rec.msg, 70);
|
||||
rec.pos.x = animStream->readUint16LE();
|
||||
rec.pos.y = animStream->readUint16LE();
|
||||
animStream->readUint16LE();
|
||||
rec.rgb1.r = animStream->readByte();
|
||||
rec.rgb1.g = animStream->readByte();
|
||||
rec.rgb1.b = animStream->readByte();
|
||||
rec.rgb2.r = animStream->readByte();
|
||||
rec.rgb2.g = animStream->readByte();
|
||||
rec.rgb2.b = animStream->readByte();
|
||||
rec.kernelMsgIndex = animStream->readUint16LE();
|
||||
animStream->skip(6);
|
||||
rec.startFrame = animStream->readUint16LE();
|
||||
rec.endFrame = animStream->readUint16LE();
|
||||
animStream->readUint16LE();
|
||||
|
||||
_messages.push_back(rec);
|
||||
}
|
||||
|
||||
delete animStream;
|
||||
}
|
||||
|
||||
//printf("End pos: %i\n", animStream->pos());
|
||||
if (frameEntryCount > 0) {
|
||||
// Chunk 3: animation frame info
|
||||
animStream = anim.getItemStream(streamIndex++);
|
||||
|
||||
delete animStream;
|
||||
for (int i = 0; i < frameEntryCount; i++) {
|
||||
AnimFrameEntry rec;
|
||||
rec.frameNumber = animStream->readUint16LE();
|
||||
rec.seqIndex = animStream->readByte();
|
||||
rec.spriteSlot.frameNumber = animStream->readUint16LE();
|
||||
rec.spriteSlot.xp = animStream->readUint16LE();
|
||||
rec.spriteSlot.yp = animStream->readUint16LE();
|
||||
rec.spriteSlot.depth = animStream->readUint16LE();
|
||||
rec.spriteSlot.scale = animStream->readUint16LE();
|
||||
|
||||
// ------------------
|
||||
_frameEntries.push_back(rec);
|
||||
}
|
||||
|
||||
// Chunk 2: anim info
|
||||
AnimationFrame frame;
|
||||
animStream = anim.getItemStream(1);
|
||||
//printf("Chunk 1, size %i\n", animStream->size());
|
||||
|
||||
_frameEntries = new AnimationFrame[_frameEntryCount];
|
||||
|
||||
for (int i = 0; i < _frameEntryCount; i++) {
|
||||
|
||||
frame.animFrameIndex = animStream->readUint16LE();
|
||||
frame.u = animStream->readByte();
|
||||
frame.seriesIndex = animStream->readByte();
|
||||
frame.seriesFrameIndex = animStream->readUint16LE();
|
||||
frame.x = animStream->readUint16LE();
|
||||
frame.y = animStream->readUint16LE();
|
||||
frame.v = animStream->readByte();
|
||||
frame.w = animStream->readByte();
|
||||
|
||||
_frameEntries[i] = frame;
|
||||
|
||||
/*
|
||||
printf(
|
||||
"animFrameIndex = %4d, "
|
||||
"u = %3d, "
|
||||
"seriesIndex = %3d, "
|
||||
"seriesFrameIndex = %6d, "
|
||||
"x = %3d, "
|
||||
"y = %3d, "
|
||||
"v = %3d, "
|
||||
"w = %3d\n",
|
||||
|
||||
frame.animFrameIndex,
|
||||
frame.u,
|
||||
frame.seriesIndex,
|
||||
frame.seriesFrameIndex,
|
||||
frame.x,
|
||||
frame.y,
|
||||
frame.v,
|
||||
frame.w
|
||||
);
|
||||
*/
|
||||
delete animStream;
|
||||
}
|
||||
//printf("End pos: %i\n", animStream->pos());
|
||||
|
||||
delete animStream;
|
||||
if (miscEntriesCount > 0) {
|
||||
// Chunk 4: Misc Data
|
||||
animStream = anim.getItemStream(streamIndex);
|
||||
|
||||
// Chunk 3: unknown (seems to be sound data?)
|
||||
// TODO
|
||||
for (int i = 0; i < miscEntriesCount; ++i) {
|
||||
AnimMiscEntry rec;
|
||||
rec.soundNum = animStream->readUint16LE();
|
||||
rec.numTicks = animStream->readUint16LE();
|
||||
rec.posAdjust.x = animStream->readUint16LE();
|
||||
rec.posAdjust.y = animStream->readUint16LE();
|
||||
animStream->readUint16LE();
|
||||
|
||||
_miscEntries.push_back(rec);
|
||||
}
|
||||
|
||||
delete animStream;
|
||||
}
|
||||
|
||||
// If the animation specifies a font, then load it for access
|
||||
if (_flags & ANIM_CUSTOM_FONT) {
|
||||
Common::String fontName;
|
||||
if (madsRes)
|
||||
fontName += "*";
|
||||
fontName += fontResource;
|
||||
|
||||
_font = _vm->_font->getFont(fontName);
|
||||
}
|
||||
|
||||
// Load all the sprite sets for the animation
|
||||
for (int i = 0; i < spriteListCount; ++i) {
|
||||
_spriteListIndexes[i] = _view->_spriteSlots.addSprites(_spriteSetNames[i].c_str());
|
||||
}
|
||||
|
||||
|
||||
if (_field12) {
|
||||
Common::String resName;
|
||||
if (madsRes)
|
||||
resName += "*";
|
||||
resName += _spriteSetNames[_spriteListIndex];
|
||||
|
||||
_spriteListIndexes[_spriteListIndex] = _view->_spriteSlots.addSprites(resName.c_str());
|
||||
}
|
||||
|
||||
// TODO: Unknown section about handling palette entries - I think it's adjusting sprite sets
|
||||
// to the palette of the game screen
|
||||
|
||||
// Process the sprite list indexes to remap them to the actual sprite list indexes
|
||||
|
||||
}
|
||||
|
||||
Animation::~Animation() {
|
||||
//delete[] _spriteSeriesNames;
|
||||
//delete[] _spriteSeries;
|
||||
//delete[] _frameEntries;
|
||||
}
|
||||
|
||||
void Animation::start() {
|
||||
_curFrame = 0;
|
||||
_curFrameEntry = 0;
|
||||
void MadsAnimation::start() {
|
||||
_currentFrame = 0;
|
||||
_oldFrameEntry = 0;
|
||||
//for (int i = 0; i < _seriesCount; i++) {
|
||||
//_spriteSeries[i] = new SpriteSeries((char*)_spriteSeriesNames[i].c_str());
|
||||
//}
|
||||
_playing = true;
|
||||
updateAnim();
|
||||
update();
|
||||
}
|
||||
|
||||
bool Animation::updateAnim() {
|
||||
bool MadsAnimation::update() {
|
||||
if (!_playing)
|
||||
return true;
|
||||
|
||||
// Get the scene background surface
|
||||
M4Surface *bg = _vm->_scene->getBackgroundSurface();
|
||||
if (_field12) {
|
||||
int spriteListIndex = _spriteListIndexes[_spriteListIndex];
|
||||
int newIndex = -1;
|
||||
|
||||
for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) {
|
||||
if (_frameEntries[idx].frameNumber > _currentFrame)
|
||||
break;
|
||||
if (_frameEntries[idx].spriteSlot.spriteListIndex == spriteListIndex)
|
||||
newIndex = _frameEntries[idx].spriteSlot.frameNumber;
|
||||
}
|
||||
|
||||
while (_frameEntries[_curFrameEntry].animFrameIndex == _curFrame) {
|
||||
AnimationFrame *frame = &_frameEntries[_curFrameEntry];
|
||||
int seriesFrameIndex = (frame->seriesFrameIndex & 0x7FFF) - 1;
|
||||
|
||||
// Write the sprite onto the screen
|
||||
M4Sprite *spr = _spriteSeries->getFrame(seriesFrameIndex);
|
||||
|
||||
// FIXME: correct x, y
|
||||
spr->copyTo(bg, frame->x, frame->y, (int)spr->getTransparentColor());
|
||||
|
||||
// HACK: wait a bit
|
||||
g_system->delayMillis(100);
|
||||
|
||||
//printf("_curFrameEntry = %d\n", _curFrameEntry);
|
||||
_curFrameEntry++;
|
||||
if (newIndex >= 0)
|
||||
load1(newIndex);
|
||||
}
|
||||
|
||||
//printf("_curFrame = %d\n", _curFrame);
|
||||
// If it's not time for the next frame, then exit
|
||||
if (_madsVm->_currentTimer < _nextFrameTimer)
|
||||
return false;
|
||||
|
||||
_curFrame++;
|
||||
if (_curFrame >= _frameCount) // anim done
|
||||
// Loop checks for any prior animation sprite slots to be expired
|
||||
for (int slotIndex = 0; slotIndex < _view->_spriteSlots.startIndex; ++slotIndex) {
|
||||
if ((_view->_spriteSlots[slotIndex].seqIndex >= 0x80) &&
|
||||
(_view->_spriteSlots[slotIndex].seqIndex <= 0xFD)) {
|
||||
// Flag the frame as animation sprite slot
|
||||
_view->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the current frame
|
||||
if (_currentFrame > (int)_miscEntries.size()) {
|
||||
// Is the animation allowed to be repeated?
|
||||
if (_resetFlag) {
|
||||
_currentFrame = 0;
|
||||
_oldFrameEntry = 0;
|
||||
} else {
|
||||
_unk1 = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle starting any sound for this frame
|
||||
AnimMiscEntry &misc = _miscEntries[_currentFrame];
|
||||
if (misc.soundNum)
|
||||
_vm->_sound->playSound(misc.soundNum);
|
||||
|
||||
bool screenChanged = false;
|
||||
|
||||
// Handle any scrolling of the screen surface
|
||||
if ((_scrollX != 0) || (_scrollY != 0)) {
|
||||
_view->_bgSurface->scrollX(_scrollX);
|
||||
_view->_bgSurface->scrollY(_scrollY);
|
||||
|
||||
screenChanged = true;
|
||||
}
|
||||
|
||||
// Handle any offset adjustment for sprites as of this frame
|
||||
if (_view->_posAdjust.x != misc.posAdjust.x) {
|
||||
misc.posAdjust.x = _view->_posAdjust.x;
|
||||
screenChanged = true;
|
||||
}
|
||||
if (_view->_posAdjust.y != misc.posAdjust.y) {
|
||||
misc.posAdjust.y = _view->_posAdjust.y;
|
||||
screenChanged = true;
|
||||
}
|
||||
if (screenChanged) {
|
||||
// Signal the entire screen needs refreshing
|
||||
_view->_spriteSlots.fullRefresh();
|
||||
}
|
||||
|
||||
int spriteSlotsMax = _view->_spriteSlots.startIndex;
|
||||
|
||||
// Main frame animation loop - frames get animated by being placed, as necessary, into the
|
||||
// main sprite slot array
|
||||
while ((uint)_oldFrameEntry < _frameEntries.size()) {
|
||||
if (_frameEntries[_oldFrameEntry].frameNumber > _currentFrame)
|
||||
break;
|
||||
else if (_frameEntries[_oldFrameEntry].frameNumber == _currentFrame) {
|
||||
// Found the correct frame
|
||||
int spriteSlotIndex = 0;
|
||||
int index = 0;
|
||||
|
||||
for (;;) {
|
||||
if ((spriteSlotIndex == 0) && (index < spriteSlotsMax)) {
|
||||
int seqIndex = _frameEntries[_oldFrameEntry].seqIndex - _view->_spriteSlots[index].seqIndex;
|
||||
if (seqIndex == 0x80) {
|
||||
if (_view->_spriteSlots[index] == _frameEntries[_oldFrameEntry].spriteSlot)
|
||||
_view->_spriteSlots[index].spriteType = SPRITE_ZERO;
|
||||
}
|
||||
++index;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spriteSlotIndex == 0) {
|
||||
int slotIndex = _view->_spriteSlots.getIndex();
|
||||
_view->_spriteSlots[slotIndex].copy(_frameEntries[_oldFrameEntry].spriteSlot);
|
||||
_view->_spriteSlots[slotIndex].seqIndex += 0x80;
|
||||
|
||||
SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(
|
||||
_view->_spriteSlots[slotIndex].spriteListIndex);
|
||||
|
||||
_view->_spriteSlots[slotIndex].spriteType = (spriteSet.getAssetType() == 0) ?
|
||||
SPRITE_FOUR : SPRITE_ZERO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++_oldFrameEntry;
|
||||
}
|
||||
|
||||
// Handle the display of any messages
|
||||
for (uint idx = 0; idx < _messages.size(); ++idx) {
|
||||
if (_messages[idx].kernelMsgIndex >= 0) {
|
||||
// Handle currently active message
|
||||
if ((_currentFrame < _messages[idx].startFrame) || (_currentFrame > _messages[idx].endFrame)) {
|
||||
_view->_kernelMessages.remove(_messages[idx].kernelMsgIndex);
|
||||
_messages[idx].kernelMsgIndex = -1;
|
||||
--_messageCtr;
|
||||
}
|
||||
} else if ((_currentFrame >= _messages[idx].startFrame) && (_currentFrame <= _messages[idx].endFrame)) {
|
||||
// Start displaying the message
|
||||
AnimMessage &me = _messages[idx];
|
||||
|
||||
// The colour index to use is dependant on how many messages are currently on-screen
|
||||
uint8 colIndex;
|
||||
switch (_messageCtr) {
|
||||
case 1:
|
||||
colIndex = 252;
|
||||
break;
|
||||
case 2:
|
||||
colIndex = 16;
|
||||
break;
|
||||
default:
|
||||
colIndex = 250;
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_palette->setEntry(colIndex, me.rgb1.r, me.rgb1.g, me.rgb1.b);
|
||||
_vm->_palette->setEntry(colIndex + 1, me.rgb2.r, me.rgb2.g, me.rgb2.b);
|
||||
|
||||
// Add a kernel message to display the given text
|
||||
me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 101, 0, 0, INDEFINITE_TIMEOUT, me.msg);
|
||||
++_messageCtr;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next frame
|
||||
_currentFrame++;
|
||||
if (_currentFrame >= (int)_miscEntries.size()) {
|
||||
// Animation is complete
|
||||
stop();
|
||||
|
||||
return _curFrame >= _frameCount;
|
||||
if (_abortTimers != 0) {
|
||||
_view->_abortTimers = _abortTimers;
|
||||
_view->_abortTimersMode = _abortMode;
|
||||
|
||||
if (_abortMode != ABORTMODE_1) {
|
||||
// Copy the noun list
|
||||
for (int i = 0; i < 3; ++i)
|
||||
_madsVm->scene()->actionNouns[i] = _actionNouns[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1);
|
||||
_nextFrameTimer = _madsVm->_currentTimer + _miscEntries[frameNum].numTicks;
|
||||
|
||||
return _currentFrame >= (int)_miscEntries.size();
|
||||
}
|
||||
|
||||
void Animation::stop() {
|
||||
void MadsAnimation::stop() {
|
||||
_playing = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _seriesCount; i++) {
|
||||
// TODO: cleanup
|
||||
//delete _spriteSeries[i];
|
||||
//_spriteSeries[i] = NULL;
|
||||
void MadsAnimation::setCurrentFrame(int frameNumber) {
|
||||
_currentFrame = frameNumber;
|
||||
_oldFrameEntry = 0;
|
||||
_unk1 = 0;
|
||||
}
|
||||
|
||||
void MadsAnimation::load1(int frameNumber) {
|
||||
if (_skipLoad)
|
||||
return;
|
||||
|
||||
Common::Point pt;
|
||||
int listIndex = _spriteListIndexes[_spriteListIndex];
|
||||
SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex);
|
||||
|
||||
if (_unkIndex < 0) {
|
||||
M4Surface *frame = spriteSet.getFrame(0);
|
||||
pt.x = frame->bounds().left;
|
||||
pt.y = frame->bounds().top;
|
||||
} else {
|
||||
pt.x = _unkList[_unkIndex].x;
|
||||
pt.y = _unkList[_unkIndex].y;
|
||||
_unkIndex = 1 - _unkIndex;
|
||||
}
|
||||
|
||||
if (proc1(spriteSet, pt, frameNumber))
|
||||
error("proc1 failure");
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
|
@ -29,39 +29,90 @@
|
||||
#include "m4/m4.h"
|
||||
#include "m4/graphics.h"
|
||||
#include "m4/assets.h"
|
||||
#include "m4/mads_views.h"
|
||||
#include "common/array.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
struct AnimationFrame {
|
||||
uint16 animFrameIndex;
|
||||
byte u;
|
||||
byte seriesIndex;
|
||||
uint16 seriesFrameIndex;
|
||||
uint16 x, y;
|
||||
byte v, w;
|
||||
class MadsView;
|
||||
class SpriteSlotSubset;
|
||||
|
||||
class AnimMessage {
|
||||
public:
|
||||
char msg[70];
|
||||
Common::Point pos;
|
||||
RGB8 rgb1, rgb2;
|
||||
int kernelMsgIndex;
|
||||
|
||||
int startFrame, endFrame;
|
||||
};
|
||||
|
||||
class Animation {
|
||||
public:
|
||||
Animation(MadsM4Engine *vm);
|
||||
~Animation();
|
||||
class AnimFrameEntry {
|
||||
public:
|
||||
int frameNumber;
|
||||
int seqIndex;
|
||||
SpriteSlotSubset spriteSlot;
|
||||
};
|
||||
|
||||
void load(const char *filename);
|
||||
void loadFullScreen(const char *filename);
|
||||
void start();
|
||||
bool updateAnim();
|
||||
void stop();
|
||||
class AnimMiscEntry {
|
||||
public:
|
||||
int soundNum;
|
||||
int numTicks;
|
||||
Common::Point posAdjust;
|
||||
};
|
||||
|
||||
private:
|
||||
bool _playing;
|
||||
MadsM4Engine *_vm;
|
||||
int _seriesCount;
|
||||
int _frameCount;
|
||||
int _frameEntryCount;
|
||||
AnimationFrame *_frameEntries;
|
||||
Common::String *_spriteSeriesNames;
|
||||
SpriteAsset *_spriteSeries;
|
||||
int _curFrame, _curFrameEntry;
|
||||
#define ANIM_SPRITE_SET_SIZE 50
|
||||
|
||||
enum MadsAnimationFlags {ANIM_CUSTOM_FONT = 0x20};
|
||||
|
||||
class MadsAnimation: public Animation {
|
||||
private:
|
||||
bool _playing;
|
||||
MadsView *_view;
|
||||
|
||||
int _spriteListCount;
|
||||
Common::Array<AnimMessage> _messages;
|
||||
Common::Array<AnimFrameEntry> _frameEntries;
|
||||
Common::Array<AnimMiscEntry> _miscEntries;
|
||||
Font *_font;
|
||||
|
||||
uint8 _flags;
|
||||
int _animMode;
|
||||
int _roomNumber;
|
||||
bool _field12;
|
||||
int _spriteListIndex;
|
||||
int _scrollX;
|
||||
int _scrollY;
|
||||
Common::String _field24;
|
||||
Common::String _spriteSetNames[10];
|
||||
Common::String _lbmFilename;
|
||||
Common::String _spritesFilename;
|
||||
Common::String _soundName;
|
||||
Common::Array<int> _spriteListIndexes;
|
||||
|
||||
int _currentFrame, _oldFrameEntry;
|
||||
bool _resetFlag;
|
||||
int _unk1;
|
||||
bool _skipLoad;
|
||||
int _unkIndex;
|
||||
Common::Point _unkList[2];
|
||||
uint32 _nextFrameTimer;
|
||||
int _messageCtr;
|
||||
int _abortTimers;
|
||||
AbortTimerMode _abortMode;
|
||||
uint16 _actionNouns[3];
|
||||
|
||||
void load1(int frameNumber);
|
||||
bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber);
|
||||
public:
|
||||
MadsAnimation(MadsM4Engine *vm, MadsView *view);
|
||||
~MadsAnimation();
|
||||
|
||||
virtual void load(const Common::String &filename);
|
||||
virtual void start();
|
||||
virtual bool update();
|
||||
virtual void stop();
|
||||
virtual void setCurrentFrame(int frameNumber);
|
||||
};
|
||||
|
||||
} // End of namespace M4
|
||||
|
@ -30,13 +30,13 @@
|
||||
|
||||
namespace M4 {
|
||||
|
||||
BaseAsset::BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : _vm(vm) {
|
||||
BaseAsset::BaseAsset(MadsM4Engine *vm) : _vm(vm) {
|
||||
}
|
||||
|
||||
BaseAsset::~BaseAsset() {
|
||||
}
|
||||
|
||||
MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
|
||||
MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
|
||||
uint32 stateCount = stream->readUint32LE();
|
||||
for (uint32 curState = 0; curState < stateCount; curState++) {
|
||||
uint32 stateOffset = stream->readUint32LE();
|
||||
@ -61,7 +61,7 @@ uint32 MachineAsset::getStateOffset(uint32 state) {
|
||||
return _stateTable[state];
|
||||
}
|
||||
|
||||
SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
|
||||
SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
|
||||
_localVarCount = stream->readUint32LE();
|
||||
_codeSize = size - 4;
|
||||
_code = new byte[_codeSize];
|
||||
@ -78,7 +78,7 @@ void SequenceAsset::getCode(byte *&code, uint32 &codeSize) {
|
||||
}
|
||||
|
||||
|
||||
DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
|
||||
DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
|
||||
|
||||
_recCount = stream->readUint32LE();
|
||||
_recSize = stream->readUint32LE();
|
||||
@ -98,7 +98,8 @@ long *DataAsset::getRow(int index) {
|
||||
return &_data[_recSize * index];
|
||||
}
|
||||
|
||||
SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) : BaseAsset(vm, stream, size, name) {
|
||||
SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) :
|
||||
BaseAsset(vm) {
|
||||
_stream = stream;
|
||||
_palInterface = NULL;
|
||||
_paletteData = NULL;
|
||||
@ -110,6 +111,20 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, i
|
||||
}
|
||||
}
|
||||
|
||||
SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) {
|
||||
_stream = vm->res()->get(name);
|
||||
_palInterface = NULL;
|
||||
_paletteData = NULL;
|
||||
|
||||
if (_vm->isM4()) {
|
||||
loadM4SpriteAsset(vm, _stream, true);
|
||||
} else {
|
||||
loadMadsSpriteAsset(vm, _stream);
|
||||
}
|
||||
|
||||
vm->res()->toss(name);
|
||||
}
|
||||
|
||||
SpriteAsset::~SpriteAsset() {
|
||||
if (_palInterface) {
|
||||
// Internally stored palette translation data, so release it
|
||||
|
@ -49,7 +49,7 @@ class Palette;
|
||||
|
||||
class BaseAsset {
|
||||
public:
|
||||
BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name);
|
||||
BaseAsset(MadsM4Engine *vm);
|
||||
~BaseAsset();
|
||||
const Common::String getName() const { return _name; }
|
||||
protected:
|
||||
@ -103,6 +103,7 @@ struct SpriteAssetFrame {
|
||||
class SpriteAsset : public BaseAsset {
|
||||
public:
|
||||
SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream = false);
|
||||
SpriteAsset(MadsM4Engine *vm, const char *name);
|
||||
~SpriteAsset();
|
||||
void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream);
|
||||
void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream);
|
||||
|
@ -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,34 @@ 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->scene()->_sceneAnimation.loadFullScreen(resourceName);
|
||||
else
|
||||
_madsVm->scene()->_sceneAnimation.load(resourceName);
|
||||
_madsVm->scene()->_sceneAnimation.start();
|
||||
|
||||
view->restore(0, 0, view->width(), view->height());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
M4Console::M4Console(M4Engine *vm): Console(vm) {
|
||||
|
@ -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() {}
|
||||
|
@ -145,7 +145,6 @@ MadsM4Engine::~MadsM4Engine() {
|
||||
delete _script;
|
||||
delete _ws;
|
||||
delete _random;
|
||||
delete _animation;
|
||||
delete _palette;
|
||||
}
|
||||
|
||||
@ -184,7 +183,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");
|
||||
@ -581,8 +579,6 @@ Common::Error MadsEngine::run() {
|
||||
while (!_events->quitFlag) {
|
||||
eventHandler();
|
||||
|
||||
_animation->updateAnim();
|
||||
|
||||
if (g_system->getMillis() >= nextFrame) {
|
||||
nextFrame = g_system->getMillis() + GAME_FRAME_DELAY;
|
||||
++_currentTimer;
|
||||
|
@ -200,7 +200,6 @@ public:
|
||||
Rails *_rails;
|
||||
ScriptInterpreter *_script;
|
||||
WoodScript *_ws;
|
||||
Animation *_animation;
|
||||
Common::RandomSource *_random;
|
||||
|
||||
Scene *scene() { return _scene; }
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include "m4/m4_views.h"
|
||||
#include "m4/animation.h"
|
||||
#include "m4/dialogs.h"
|
||||
#include "m4/events.h"
|
||||
#include "m4/font.h"
|
||||
@ -43,6 +44,22 @@ static const int SCROLLER_DELAY = 200;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool MadsSpriteSlot::operator==(const SpriteSlotSubset &other) const {
|
||||
return (spriteListIndex == other.spriteListIndex) && (frameNumber == other.frameNumber) &&
|
||||
(xp == other.xp) && (yp == other.yp) && (depth == other.depth) && (scale == other.scale);
|
||||
}
|
||||
|
||||
void MadsSpriteSlot::copy(const SpriteSlotSubset &other) {
|
||||
spriteListIndex = other.spriteListIndex;
|
||||
frameNumber = other.frameNumber;
|
||||
xp = other.xp;
|
||||
yp = other.yp;
|
||||
depth = other.depth;
|
||||
scale = other.scale;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
MadsSpriteSlots::MadsSpriteSlots(MadsView &owner): _owner(owner) {
|
||||
for (int i = 0; i < SPRITE_SLOTS_SIZE; ++i) {
|
||||
MadsSpriteSlot rec;
|
||||
@ -74,6 +91,7 @@ int MadsSpriteSlots::addSprites(const char *resName) {
|
||||
Common::SeekableReadStream *data = _vm->res()->get(resName);
|
||||
SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName);
|
||||
spriteSet->translate(_madsVm->_palette);
|
||||
assert(spriteSet != NULL);
|
||||
|
||||
_sprites.push_back(SpriteList::value_type(spriteSet));
|
||||
_vm->res()->toss(resName);
|
||||
@ -1125,8 +1143,20 @@ void MadsSequenceList::setAnimRange(int seqIndex, int startVal, int endVal) {
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Animation::Animation(MadsM4Engine *vm): _vm(vm) {
|
||||
}
|
||||
|
||||
void Animation::loadFullScreen(const Common::String &filename) {
|
||||
_vm->_palette->deleteAllRanges();
|
||||
load(filename);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this),
|
||||
_kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) {
|
||||
_kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this),
|
||||
// FIXME: There's probably a cleaner way to do this, and I don't think the destructor is ever called
|
||||
_sceneAnimation(*new MadsAnimation(_vm, this)) {
|
||||
_textSpacing = -1;
|
||||
_ticksAmount = 3;
|
||||
_newTimeout = 0;
|
||||
|
@ -43,6 +43,16 @@ class MadsView;
|
||||
|
||||
enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2};
|
||||
|
||||
class SpriteSlotSubset {
|
||||
public:
|
||||
int spriteListIndex;
|
||||
int frameNumber;
|
||||
int xp;
|
||||
int yp;
|
||||
int depth;
|
||||
int scale;
|
||||
};
|
||||
|
||||
class MadsSpriteSlot {
|
||||
public:
|
||||
int spriteType;
|
||||
@ -55,12 +65,16 @@ public:
|
||||
int scale;
|
||||
|
||||
MadsSpriteSlot() { }
|
||||
|
||||
bool operator==(const SpriteSlotSubset &other) const;
|
||||
void copy(const SpriteSlotSubset &other);
|
||||
};
|
||||
|
||||
#define SPRITE_SLOTS_SIZE 50
|
||||
|
||||
enum SpriteIdSpecial {
|
||||
BACKGROUND_SPRITE = -4, FULL_SCREEN_REFRESH = -2, FOREGROUND_SPRITE = 1, EXPIRED_SPRITE = -1
|
||||
BACKGROUND_SPRITE = -4, FULL_SCREEN_REFRESH = -2, EXPIRED_SPRITE = -1, SPRITE_ZERO = 0, FOREGROUND_SPRITE = 1,
|
||||
SPRITE_FOUR = 4
|
||||
};
|
||||
|
||||
typedef Common::Array<Common::SharedPtr<SpriteAsset> > SpriteList;
|
||||
@ -138,7 +152,7 @@ public:
|
||||
};
|
||||
|
||||
#define TIMED_TEXT_SIZE 10
|
||||
#define TEXT_4A_SIZE 30
|
||||
#define INDEFINITE_TIMEOUT 9999999
|
||||
|
||||
enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_OWNER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10,
|
||||
KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, KMSG_ACTIVE = 0x80};
|
||||
@ -352,10 +366,26 @@ public:
|
||||
void setAnimRange(int seqIndex, int startVal, int endVal);
|
||||
};
|
||||
|
||||
class Animation {
|
||||
protected:
|
||||
MadsM4Engine *_vm;
|
||||
public:
|
||||
Animation(MadsM4Engine *vm);
|
||||
void loadFullScreen(const Common::String &filename);
|
||||
|
||||
virtual void load(const Common::String &filename) = 0;
|
||||
virtual void start() = 0;
|
||||
virtual bool update() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void setCurrentFrame(int frameNumber) = 0;
|
||||
};
|
||||
|
||||
|
||||
class MadsView {
|
||||
private:
|
||||
View *_view;
|
||||
public:
|
||||
Animation &_sceneAnimation;
|
||||
MadsSpriteSlots _spriteSlots;
|
||||
MadsTextDisplay _textDisplay;
|
||||
MadsKernelMessageList _kernelMessages;
|
||||
|
Loading…
x
Reference in New Issue
Block a user