Added proper names for some of the previous unknown timer fields, and bugfixes for the sequence list methods

svn-id: r48875
This commit is contained in:
Paul Gilbert 2010-04-30 11:27:42 +00:00
parent df4400d223
commit e11afdeab5
9 changed files with 111 additions and 62 deletions

View File

@ -227,7 +227,7 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre
frame.w = spriteStream->readUint16LE();
frame.h = spriteStream->readUint16LE();
if (curFrame == 0)
printf("%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h);
debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h);
frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false);
_frames.push_back(frame);

View File

@ -115,6 +115,7 @@ MadsM4Engine::MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc) :
SearchMan.addSubDirectoryMatching(_gameDataDir, "resource");
DebugMan.addDebugChannel(kDebugScript, "script", "Script debug level");
DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics debug level");
DebugMan.addDebugChannel(kDebugConversations, "conversations", "Conversations debugging");
_resourceManager = NULL;

View File

@ -113,7 +113,8 @@ enum {
enum {
kDebugScript = 1 << 0,
kDebugConversations = 2 << 0
kDebugConversations = 1 << 1,
kDebugGraphics = 1 << 2
};
#define MESSAGE_BASIC 1

View File

@ -83,16 +83,16 @@ uint16 MadsSceneLogic::startSpriteSequence(uint16 srcSpriteIdx, int v0, int numT
spriteFrame->y + (spriteFrame->height() / 2));
return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0,
-1, 100, (int)pixel - 1, 1, 1, 0, 0);
-1, 100, (int)pixel - 1, 1, ANIMTYPE_SINGLE_DIRECTION, 0, 0);
}
uint16 MadsSceneLogic::startSpriteSequence2(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks) {
uint16 MadsSceneLogic::startCycledSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks) {
M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(1);
uint8 pixel = *_madsVm->scene()->getWalkSurface()->getBasePtr(spriteFrame->x + (spriteFrame->width() / 2),
spriteFrame->y + (spriteFrame->height() / 2));
return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0,
-1, 100, (int)pixel - 1, 1, 2, 0, 0);
-1, 100, (int)pixel - 1, 1, ANIMTYPE_CYCLED, 0, 0);
}
uint16 MadsSceneLogic::startSpriteSequence3(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks) {
@ -101,7 +101,7 @@ uint16 MadsSceneLogic::startSpriteSequence3(uint16 srcSpriteIdx, int v0, int num
spriteFrame->y + (spriteFrame->height() / 2));
return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0,
-1, 100, (int)pixel - 1, -1, 1, 0, 0);
-1, 100, (int)pixel - 1, -1, ANIMTYPE_SINGLE_DIRECTION, 0, 0);
}
void MadsSceneLogic::activateHotspot(int idx, bool active) {
@ -165,7 +165,7 @@ void MadsSceneLogic::selectScene(int sceneNum) {
void MadsSceneLogic::setupScene() {
// FIXME: This is the hardcoded logic for Rex scene 101 only
const char *animName = formAnimName('A', -1);
warning("anim - %s\n", animName);
// sub_1e754(animName, 3);
getSceneSpriteSet();
@ -189,7 +189,7 @@ void MadsSceneLogic::enterScene() {
_madsVm->scene()->_sequenceList.unk2(0, 2, 7, 0x46);
_spriteIndexes[18] = startSpriteSequence2(_spriteIndexes[3], 0, 10, 0, 0, 60);
_spriteIndexes[18] = startCycledSpriteSequence(_spriteIndexes[3], 0, 10, 0, 0, 60);
_spriteIndexes[19] = startSpriteSequence(_spriteIndexes[4], 0, 5, 0, 1, 0);
_spriteIndexes[20] = startSpriteSequence(_spriteIndexes[5], 0, 10, 0, 2, 0);
_spriteIndexes[21] = startSpriteSequence(_spriteIndexes[6], 0, 6, 0, 0, 0);

View File

@ -36,7 +36,7 @@ private:
// Library interface methods
uint16 loadSpriteSet(uint16 suffixNum, uint16 sepChar);
uint16 startSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks);
uint16 startSpriteSequence2(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks);
uint16 startCycledSpriteSequence(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks);
uint16 startSpriteSequence3(uint16 srcSpriteIdx, int v0, int numTicks, int fld24, int timeoutTicks, int extraTicks);
void activateHotspot(int idx, bool active);
void lowRoomsEntrySound();

View File

@ -697,7 +697,7 @@ void RexDialogView::onRefresh(RectList *rects, M4Surface *destSurface) {
refreshText();
// Handle the drawing of the various Mads elements
refresh(rects);
refresh();
View::onRefresh(rects, destSurface);
}

View File

@ -263,26 +263,10 @@ void MadsScene::setAction(int action, int objectId) {
* Draws all the elements of the scene
*/
void MadsScene::drawElements() {
// Display animations
_spriteSlots.draw(this);
// Text display
_textDisplay.draw(this);
refresh();
// Copy the user interface surface onto the surface
_interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height());
/*
// Some kind of copying over of slot entries
for (int idx = 0, idx2 = 0; idx < _spriteSlotsStart; ++idx) {
if (_spriteSlots[idx].spriteId >= 0) {
if (idx != idx2) {
// Copy over the slot entry
_spriteSlots[idx2] = _spriteSlots[idx];
}
++idx2;
}
}*/
}

View File

@ -36,14 +36,26 @@
namespace M4 {
static const int INV_ANIM_FRAME_SPEED = 8;
static const int INV_ANIM_FRAME_SPEED = 2;
static const int INVENTORY_X = 160;
static const int INVENTORY_Y = 159;
static const int SCROLLER_DELAY = 200;
//--------------------------------------------------------------------------
MadsSpriteSlots::MadsSpriteSlots() {
for (int i = 0; i < SPRITE_SLOTS_SIZE; ++i) {
MadsSpriteSlot rec;
_entries.push_back(rec);
}
startIndex = 0;
}
int MadsSpriteSlots::getIndex() {
if (startIndex == SPRITE_SLOTS_SIZE)
error("Run out of sprite slots");
return startIndex++;
}
@ -97,7 +109,7 @@ void MadsSpriteSlots::draw(View *view) {
// Sort the list in order of the depth
Common::sort(depthList.begin(), depthList.end(), sortHelper);
// Loop through each of the objectes
// Loop through each of the objects
DepthList::iterator i;
for (i = depthList.begin(); i != depthList.end(); ++i) {
DepthEntry &de = *i;
@ -131,6 +143,29 @@ void MadsSpriteSlots::draw(View *view) {
}
}
/**
* Removes any sprite slots that are no longer needed
*/
void MadsSpriteSlots::cleanUp() {
// Delete any entries that aren't needed
int idx = 0;
while (idx < startIndex) {
if (_entries[idx].spriteId >= 0) {
_entries.remove_at(idx);
--startIndex;
} else {
++idx;
}
}
// Original engine sprite slot list was a fixed array, so to keep the engine similiar, for
// now I'm adding in new entries to make up the original fixed total again
while (_entries.size() < SPRITE_SLOTS_SIZE) {
MadsSpriteSlot rec;
_entries.push_back(rec);
}
}
//--------------------------------------------------------------------------
MadsTextDisplay::MadsTextDisplay() {
@ -191,6 +226,18 @@ void MadsTextDisplay::draw(View *view) {
}
}
/**
* Deactivates any text display entries that are finished
*/
void MadsTextDisplay::cleanUp() {
for (uint idx = 0; idx < _entries.size(); ++idx) {
if (_entries[idx].expire < 0) {
_entries[idx].active = false;
_entries[idx].expire = 0;
}
}
}
//--------------------------------------------------------------------------
/**
@ -341,8 +388,8 @@ bool MadsSequenceList::unk2(int index, int v1, int v2, int v3) {
}
int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, char field_24, int timeoutTicks, int extraTicks, int numTicks,
int height, int width, char field_12, char scale, char depth, int frameStart, int field_A, int numSprites,
int spriteNum) {
int height, int width, char field_12, char scale, char depth, int frameInc, SpriteAnimType animType, int numSprites,
int frameStart) {
// Find a free slot
uint timerIndex = 0;
@ -351,22 +398,22 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, char fiel
if (timerIndex == _entries.size())
error("TimerList full");
if (spriteNum <= 0)
spriteNum = 1;
if (frameStart <= 0)
frameStart = 1;
if (numSprites == 0)
numSprites = _madsVm->scene()->_spriteSlots.getSprite(spriteListIndex).getCount();
if (spriteNum == numSprites)
frameStart = 0;
if (frameStart == numSprites)
frameInc = 0;
// Set the list entry fields
_entries[timerIndex].active = true;
_entries[timerIndex].spriteListIndex = spriteListIndex;
_entries[timerIndex].field_2 = v0;
_entries[timerIndex].frameIndex = frameIndex;
_entries[timerIndex].spriteNum = spriteNum;
_entries[timerIndex].numSprites = numSprites;
_entries[timerIndex].field_A = field_A;
_entries[timerIndex].frameStart = frameStart;
_entries[timerIndex].numSprites = numSprites;
_entries[timerIndex].animType = animType;
_entries[timerIndex].frameInc = frameInc;
_entries[timerIndex].depth = depth;
_entries[timerIndex].scale = scale;
_entries[timerIndex].field_12 = field_12;
@ -405,7 +452,7 @@ void MadsSequenceList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot)
SpriteAsset &sprite = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex);
// TODO: Figure out logic for spriteId value based on SPRITE_SLOT.field_0
spriteSlot.spriteId = (0 /*field 0*/ == 1) ? 0xFFFC : 1;
spriteSlot.spriteId = (0 /*field 0*/ == 1) ? -4 : 1;
spriteSlot.timerIndex = timerIndex;
spriteSlot.spriteListIndex = timerEntry.spriteListIndex;
spriteSlot.frameNumber = ((timerEntry.field_2 == 1) ? 0x8000 : 0) | timerEntry.frameIndex;
@ -416,8 +463,8 @@ void MadsSequenceList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot)
spriteSlot.xp = timerEntry.width;
spriteSlot.yp = timerEntry.height;
} else {
spriteSlot.xp = sprite.getFrame(timerEntry.frameIndex)->x;
spriteSlot.yp = sprite.getFrame(timerEntry.frameIndex)->y;
spriteSlot.xp = sprite.getFrame(timerEntry.frameIndex - 1)->x;
spriteSlot.yp = sprite.getFrame(timerEntry.frameIndex - 1)->y;
}
}
@ -443,7 +490,7 @@ bool MadsSequenceList::loadSprites(int timerIndex) {
if ((timerEntry.field_13 != 0) || (timerEntry.dynamicHotspotIndex >= 0)) {
SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex);
M4Sprite *frame = spriteSet.getFrame(timerEntry.frameIndex);
M4Sprite *frame = spriteSet.getFrame(timerEntry.frameIndex - 1);
int width = frame->width() * timerEntry.scale / 200;
int height = frame->height() * timerEntry.scale / 100;
@ -464,26 +511,32 @@ bool MadsSequenceList::loadSprites(int timerIndex) {
}
// Frame adjustments
if (timerEntry.numSprites != timerEntry.spriteNum)
timerEntry.frameIndex += timerEntry.frameStart;
if (timerEntry.frameStart != timerEntry.numSprites)
timerEntry.frameIndex += timerEntry.frameInc;
if (timerEntry.frameIndex >= timerEntry.spriteNum) {
if (timerEntry.frameIndex >= timerEntry.frameStart) {
if (timerEntry.frameIndex > timerEntry.numSprites) {
result = true;
if (timerEntry.field_A != 2) {
timerEntry.frameIndex = timerEntry.spriteNum;
if (timerEntry.animType != ANIMTYPE_CYCLED) {
// Keep index from exceeding maximum allowed
timerEntry.frameIndex = timerEntry.frameStart;
} else {
// Switch into reverse
timerEntry.frameIndex = timerEntry.numSprites - 1;
timerEntry.frameStart = -1;
timerEntry.frameInc = -1;
}
}
} else {
// Currently in reverse mode
result = true;
if (timerEntry.field_A == 2) {
timerEntry.frameIndex = timerEntry.spriteNum + 1;
timerEntry.frameStart = 1;
if (timerEntry.animType == ANIMTYPE_CYCLED)
{
// Switch back to forward direction again
timerEntry.frameIndex = timerEntry.frameStart + 1;
timerEntry.frameInc = 1;
} else {
// Otherwise reset back to last sprite for further reverse animating
timerEntry.frameIndex = timerEntry.numSprites;
}
}
@ -511,7 +564,7 @@ bool MadsSequenceList::loadSprites(int timerIndex) {
}
if (idx >= 0) {
_owner._abortTimers = timerEntry.fld36[idx];
//_owner._abortTimers = timerEntry.fld36[idx];
// TODO: Figure out word_84208, timerEntry.field_3B[]
}
@ -558,12 +611,18 @@ MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceL
_abortTimers2 = 0;
}
void MadsView::refresh(RectList *rects) {
void MadsView::refresh() {
// Draw any sprites
_spriteSlots.draw(_view);
// Draw text elements onto the view
_textDisplay.draw(_view);
// Remove any sprite slots that are no longer needed
_spriteSlots.cleanUp();
// Deactivate any text display entries that are no longer needed
_textDisplay.cleanUp();
}
/*--------------------------------------------------------------------------

View File

@ -60,12 +60,12 @@ typedef Common::Array<Common::SharedPtr<SpriteAsset> > SpriteList;
class MadsSpriteSlots {
private:
MadsSpriteSlot _entries[SPRITE_SLOTS_SIZE];
Common::Array<MadsSpriteSlot> _entries;
SpriteList _sprites;
public:
int startIndex;
MadsSpriteSlots() { startIndex = 0; }
MadsSpriteSlots();
MadsSpriteSlot &operator[](int idx) {
assert(idx < SPRITE_SLOTS_SIZE);
@ -85,6 +85,7 @@ public:
void deleteTimer(int timerIndex);
void draw(View *view);
void cleanUp();
};
class MadsTextDisplayEntry {
@ -122,6 +123,7 @@ public:
int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font);
void clear();
void draw(View *view);
void cleanUp();
};
class ScreenObjectEntry {
@ -191,6 +193,8 @@ public:
#define TIMER_ENTRY_SUBSET_MAX 5
enum SpriteAnimType {ANIMTYPE_SINGLE_DIRECTION = 1, ANIMTYPE_CYCLED = 2};
struct MadsSequenceEntry {
int8 active;
int8 spriteListIndex;
@ -198,11 +202,11 @@ struct MadsSequenceEntry {
int field_2;
int frameIndex;
int spriteNum;
int frameStart;
int numSprites;
int field_A;
int frameStart;
SpriteAnimType animType;
int frameInc;
int depth;
int scale;
@ -240,8 +244,8 @@ public:
MadsSequenceEntry &operator[](int index) { return _entries[index]; }
bool unk2(int index, int v1, int v2, int v3);
int add(int spriteListIndex, int v0, int v1, char field_24, int timeoutTicks, int extraTicks, int numTicks,
int height, int width, char field_12, char scale, char depth, int frameStart, int field_A,
int numSprites, int spriteNum);
int height, int width, char field_12, char scale, char depth, int frameInc, SpriteAnimType animType,
int numSprites, int frameStart);
void remove(int timerIndex);
void setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot);
bool loadSprites(int timerIndex);
@ -264,7 +268,7 @@ public:
public:
MadsView(View *view);
void refresh(RectList *rects);
void refresh();
};
#define CHEAT_SEQUENCE_MAX 8