mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-26 12:48:16 +00:00
KYRA: (EOB/SegaCD) - fix decorations and monster animations
This commit is contained in:
parent
5da41b3e11
commit
b59d201873
@ -56,6 +56,7 @@ EoBEngine::EoBEngine(OSystem *system, const GameFlags &flags)
|
||||
_seqPlayer = 0;
|
||||
_sres = 0;
|
||||
_levelCurTrack = 0;
|
||||
_dcrResCur = -1;
|
||||
}
|
||||
|
||||
EoBEngine::~EoBEngine() {
|
||||
@ -448,7 +449,7 @@ void EoBEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool h
|
||||
assert(size <= 18);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
_monsterShapes[monsterIndex + i] = _screen->sega_encodeShape(pos, enc[0], enc[1], 2);
|
||||
_monsterShapes[monsterIndex + i] = _screen->sega_convertShape(pos, enc[0], enc[1], 2);
|
||||
pos += ((enc[0] * enc[1]) >> 1);
|
||||
enc += 2;
|
||||
}
|
||||
@ -563,6 +564,7 @@ const uint8 *EoBEngine::getBlockFileData(int level) {
|
||||
Common::SeekableReadStream *s = _sres->resStream(6);
|
||||
_screen->loadFileDataToPage(s, 15, s->size());
|
||||
delete s;
|
||||
_dcrResCur = -1;
|
||||
return _screen->getCPagePtr(15);
|
||||
}
|
||||
|
||||
@ -574,13 +576,18 @@ Common::SeekableReadStreamEndian *EoBEngine::getDecDefinitions(const char *decFi
|
||||
}
|
||||
|
||||
void EoBEngine::loadDecShapesToPage3(const char *shpFile) {
|
||||
if (_flags.platform != Common::kPlatformSegaCD)
|
||||
return EoBCoreEngine::loadDecShapesToPage3(shpFile);
|
||||
_sres->loadContainer(Common::String::format("L%d", _currentLevel));
|
||||
Common::SeekableReadStream *s = _sres->resStream(2);
|
||||
_screen->loadFileDataToPage(s, 3, s->size());
|
||||
_dcrShpDataPos = _screen->getCPagePtr(3);
|
||||
delete s;
|
||||
if (_flags.platform != Common::kPlatformSegaCD) {
|
||||
EoBCoreEngine::loadDecShapesToPage3(shpFile);
|
||||
return;
|
||||
}
|
||||
if (_dcrResCur != _currentLevel) {
|
||||
_sres->loadContainer(Common::String::format("L%d", _currentLevel));
|
||||
Common::SeekableReadStream *s = _sres->resStream(2);
|
||||
_screen->loadFileDataToPage(s, 3, s->size());
|
||||
_dcrShpDataPos = _screen->getCPagePtr(3);
|
||||
_dcrResCur = _currentLevel;
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
void EoBEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) {
|
||||
@ -606,9 +613,9 @@ void EoBEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s
|
||||
if (_flags.platform == Common::kPlatformSegaCD) {
|
||||
int offs = lvlIndex[_currentLevel] * 6 + shapeId[a] + i;
|
||||
const uint8 *enc = &_doorShapeEncodeDefs[offs << 2];
|
||||
_doorShapes[shapeId[a] + i] = _screen->sega_encodeShape(_doorShapesSrc[offs], enc[0] << 3, enc[1] << 3, 0);
|
||||
_doorShapes[shapeId[a] + i] = _screen->sega_convertShape(_doorShapesSrc[offs], enc[0] << 3, enc[1] << 3, 0);
|
||||
enc = &_doorSwitchShapeEncodeDefs[(offs << 2) - shapeId[a]];
|
||||
_doorSwitches[shapeId[a] + i].shp = _screen->sega_encodeShape(_doorSwitchShapesSrc[offs], enc[0] << 3, enc[1] << 3, 0);
|
||||
_doorSwitches[shapeId[a] + i].shp = _screen->sega_convertShape(_doorSwitchShapesSrc[offs], enc[0] << 3, enc[1] << 3, 0);
|
||||
} else {
|
||||
const uint8 *enc = &_doorShapeEncodeDefs[(doorType[a] * 3 + i) << 2];
|
||||
_doorShapes[shapeId[a] + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, _cgaLevelMappingIndex ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
|
||||
|
@ -155,6 +155,8 @@ private:
|
||||
const uint8 *const *_doorShapesSrc;
|
||||
const uint8 *const *_doorSwitchShapesSrc;
|
||||
|
||||
int _dcrResCur;
|
||||
|
||||
// Fight
|
||||
static const uint8 _monsterAcHitChanceTbl1[];
|
||||
static const uint8 _monsterAcHitChanceTbl2[];
|
||||
|
@ -56,8 +56,10 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) : KyraRpgE
|
||||
|
||||
_enableHiResDithering = false;
|
||||
|
||||
_tickLength = 55;
|
||||
_envAudioTimer = 0;
|
||||
_flashShapeTimer = 0;
|
||||
_flashShapeTimerIntv = (_flags.platform == Common::kPlatformSegaCD ? 16 : _tickLength) * 8;
|
||||
_drawSceneTimer = 0;
|
||||
_vcnFilePattern = "%s.VCN";
|
||||
_vmpFilePattern = "%s.VMP";
|
||||
@ -372,10 +374,6 @@ Common::KeymapArray EoBCoreEngine::initKeymaps(const Common::String &gameId) {
|
||||
}
|
||||
|
||||
Common::Error EoBCoreEngine::init() {
|
||||
// In EOB the timer proc is directly invoked via interrupt 0x1C, 18.2 times per second.
|
||||
// This makes a tick length of 54.94.
|
||||
_tickLength = 55;
|
||||
|
||||
if (ConfMan.hasKey("render_mode"))
|
||||
_configRenderMode = Common::parseRenderMode(ConfMan.get("render_mode"));
|
||||
|
||||
|
@ -202,6 +202,8 @@ struct EoBMonsterInPlay {
|
||||
int8 mode;
|
||||
int8 stray;
|
||||
int8 curAttackFrame;
|
||||
uint8 animProgress;
|
||||
uint8 animType;
|
||||
int8 spellStatusLeft;
|
||||
int16 hitPointsMax;
|
||||
int16 hitPointsCur;
|
||||
@ -646,6 +648,7 @@ protected:
|
||||
|
||||
uint32 _drawSceneTimer;
|
||||
uint32 _flashShapeTimer;
|
||||
uint32 _flashShapeTimerIntv;
|
||||
uint32 _envAudioTimer;
|
||||
uint16 _teleporterPulse;
|
||||
|
||||
|
@ -490,7 +490,7 @@ void EoBCoreEngine::assignWallsAndDecorations(int wallIndex, int vmpIndex, int d
|
||||
error("Error trying to make decoration %d (x: %d, y: %d, w: %d, h: %d)", decIndex, r->x, r->y, r->w, r->h);
|
||||
|
||||
if (_flags.platform == Common::kPlatformSegaCD) {
|
||||
_levelDecorationShapes[t] = _screen->sega_encodeShape(_dcrShpDataPos, r->w << 3, r->h, 0);
|
||||
_levelDecorationShapes[t] = _screen->sega_convertShape(_dcrShpDataPos, r->w << 3, r->h, 0);
|
||||
_dcrShpDataPos += ((r->w << 2) * r->h);
|
||||
} else {
|
||||
_levelDecorationShapes[t] = _screen->encodeShape(r->x, r->y, r->w, r->h, false, _cgaLevelMappingIndex ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
|
||||
@ -582,7 +582,7 @@ void EoBCoreEngine::drawScene(int refresh) {
|
||||
_screen->updateScreen();
|
||||
|
||||
if (_sceneDefaultUpdate) {
|
||||
_sceneDefaultUpdate = false;
|
||||
_sceneDefaultUpdate = 0;
|
||||
_drawSceneTimer = _system->getMillis() + 4 * _tickLength;
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,13 @@ void EoBCoreEngine::releaseMonsterShapes(int first, int num) {
|
||||
}
|
||||
|
||||
const uint8 *EoBCoreEngine::loadActiveMonsterData(const uint8 *data, int level) {
|
||||
static const uint8 intervals[4] = { 35, 30, 25, 0 };
|
||||
for (uint8 p = *data++; p != 0xFF; p = *data++) {
|
||||
uint8 v = *data++;
|
||||
if (_flags.platform == Common::kPlatformSegaCD) {
|
||||
assert(v < ARRAYSIZE(intervals));
|
||||
v = intervals[v];
|
||||
}
|
||||
_timer->setCountdown(0x20 + (p << 1), v);
|
||||
_timer->setCountdown(0x21 + (p << 1), v);
|
||||
}
|
||||
@ -459,75 +464,91 @@ void EoBCoreEngine::drawMonsters(int index) {
|
||||
int subFrame = ABS(f);
|
||||
int shpIndex = d->shpIndex ? 18 : 0;
|
||||
int palIndex = d->palette ? ((((shpIndex == 18) ? subFrame + 5 : subFrame - 1) << 1) + (d->palette - 1)) : -1;
|
||||
|
||||
if (_flags.platform == Common::kPlatformSegaCD) {
|
||||
if (d->curAttackFrame == -1)
|
||||
subFrame = 5;
|
||||
else if (f == 3)
|
||||
subFrame = 2;
|
||||
else if (f == -3)
|
||||
subFrame = 4;
|
||||
else if (f == 4)
|
||||
subFrame = 3;
|
||||
else if (f == -4)
|
||||
subFrame = -3;
|
||||
}
|
||||
|
||||
const uint8 *shp = _screen->scaleShape(_monsterShapes[subFrame + shpIndex - 1], blockDistance);
|
||||
int shpOffs = subFrame + shpIndex - 1;
|
||||
int xAdd2 = 0;
|
||||
int yAdd2 = 0;
|
||||
|
||||
int v30 = (subFrame == 1 || subFrame > 3) ? 1 : 0;
|
||||
int v1e = (d->pos == 4) ? 4 : _dscItemPosIndex[cDirOffs + d->pos];
|
||||
int posIndex = (index * 5 + v1e) << 1;
|
||||
int posOffs = (d->pos == 4) ? 4 : _dscItemPosIndex[cDirOffs + d->pos];
|
||||
int posIndex = (index * 5 + posOffs) << 1;
|
||||
|
||||
int x = _dscShapeCoords[posIndex] + 88;
|
||||
int y = _dscShapeCoords[posIndex + 1] + 127;
|
||||
if (_flags.platform == Common::kPlatformSegaCD) {
|
||||
if (d->curAttackFrame < 0)
|
||||
subFrame = 5;
|
||||
else if (subFrame >= 3)
|
||||
subFrame--;
|
||||
|
||||
if (p->u30 == 1) {
|
||||
if (v30) {
|
||||
if (_flags.gameID == GI_EOB2)
|
||||
posIndex = ((posIndex >> 1) - v1e) << 1;
|
||||
y = _dscShapeCoords[posIndex + 1] + 127 + yAdd[blockDistance + ((v1e == 4 || _flags.gameID == GI_EOB1) ? 0 : 3)];
|
||||
} else {
|
||||
if (_flags.gameID == GI_EOB2)
|
||||
posIndex = ((posIndex >> 1) - v1e + 4) << 1;
|
||||
x = _dscShapeCoords[posIndex] + 88;
|
||||
if (d->animType != subFrame) {
|
||||
d->animType = subFrame;
|
||||
d->animProgress = 0;
|
||||
}
|
||||
} else if (d->curAttackFrame < 0) {
|
||||
d->curAttackFrame++;
|
||||
}
|
||||
|
||||
int w = shp[2] << 3;
|
||||
int h = shp[1];
|
||||
for (int numFrames = 1; numFrames; --numFrames) {
|
||||
if (_flags.platform == Common::kPlatformSegaCD) {
|
||||
int temp = 0;
|
||||
const uint8 *frm = _staticres->loadRawData(kEoB1MonsterAnimFrames00 + d->type * 5 + subFrame - 1, temp) + ((d->animProgress++) << 2);
|
||||
shpOffs = shpIndex + (frm[0] & 0x3F);
|
||||
numFrames += ((frm[0] >> 6) & 1);
|
||||
xAdd2 = (int8)frm[1];
|
||||
yAdd2 = (int8)frm[2];
|
||||
if (frm[4] == 0xFE)
|
||||
d->animProgress = 0;
|
||||
else if (frm[4] == 0xFF)
|
||||
d->curAttackFrame = 0;
|
||||
}
|
||||
|
||||
x = x - (w >> 1) + (d->idleAnimState >> 4);
|
||||
y = y - h + (d->idleAnimState & 0x0F);
|
||||
const uint8 *shp = _screen->scaleShape(_monsterShapes[shpOffs], blockDistance);
|
||||
|
||||
drawMonsterShape(shp, x, y, f >= 0 ? 0 : 1, d->flags, palIndex);
|
||||
int x = _dscShapeCoords[posIndex] + 88;
|
||||
int y = _dscShapeCoords[posIndex + 1] + 127;
|
||||
|
||||
if (_flags.gameID == GI_EOB1) {
|
||||
if (p->u30 == 1) {
|
||||
if (v30) {
|
||||
if (_flags.gameID == GI_EOB2)
|
||||
posIndex = ((posIndex >> 1) - posOffs) << 1;
|
||||
y = _dscShapeCoords[posIndex + 1] + 127 + yAdd[blockDistance + ((posOffs == 4 || _flags.gameID == GI_EOB1) ? 0 : 3)];
|
||||
} else {
|
||||
if (_flags.gameID == GI_EOB2)
|
||||
posIndex = ((posIndex >> 1) - posOffs + 4) << 1;
|
||||
x = _dscShapeCoords[posIndex] + 88;
|
||||
}
|
||||
}
|
||||
|
||||
int w = shp[2] << 3;
|
||||
int h = shp[1];
|
||||
|
||||
x = x - (w >> 1) + (d->idleAnimState >> 4) + xAdd2;
|
||||
y = y - h + (d->idleAnimState & 0x0F) + yAdd2;
|
||||
|
||||
drawMonsterShape(shp, x, y, f >= 0 ? 0 : 1, d->flags, palIndex);
|
||||
|
||||
if (_flags.gameID == GI_EOB2) {
|
||||
for (int ii = 0; ii < 3; ii++) {
|
||||
if (!p->decorations[ii])
|
||||
continue;
|
||||
|
||||
SpriteDecoration *dcr = &_monsterDecorations[(p->decorations[ii] - 1) * 6 + subFrame + shpIndex - 1];
|
||||
|
||||
if (!dcr->shp)
|
||||
continue;
|
||||
|
||||
shp = _screen->scaleShape(dcr->shp, blockDistance);
|
||||
int dx = dcr->x;
|
||||
int dy = dcr->y;
|
||||
|
||||
for (int iii = 0; iii < blockDistance; iii++) {
|
||||
dx = (dx << 1) / 3;
|
||||
dy = (dy << 1) / 3;
|
||||
}
|
||||
|
||||
drawMonsterShape(shp, x + ((f < 0) ? (w - dx - (shp[2] << 3)) : dx), y + dy, f >= 0 ? 0 : 1, d->flags, -1);
|
||||
}
|
||||
}
|
||||
_screen->setShapeFadingLevel(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int ii = 0; ii < 3; ii++) {
|
||||
if (!p->decorations[ii])
|
||||
continue;
|
||||
|
||||
SpriteDecoration *dcr = &_monsterDecorations[(p->decorations[ii] - 1) * 6 + subFrame + shpIndex - 1];
|
||||
|
||||
if (!dcr->shp)
|
||||
continue;
|
||||
|
||||
shp = _screen->scaleShape(dcr->shp, blockDistance);
|
||||
int dx = dcr->x;
|
||||
int dy = dcr->y;
|
||||
|
||||
for (int iii = 0; iii < blockDistance; iii++) {
|
||||
dx = (dx << 1) / 3;
|
||||
dy = (dy << 1) / 3;
|
||||
}
|
||||
|
||||
drawMonsterShape(shp, x + ((f < 0) ? (w - dx - (shp[2] << 3)) : dx), y + dy, f >= 0 ? 0 : 1, d->flags, -1);
|
||||
}
|
||||
_screen->setShapeFadingLevel(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1009,16 +1030,19 @@ bool EoBCoreEngine::updateMonsterTryCloseAttack(EoBMonsterInPlay *m, int block)
|
||||
|
||||
if (facing) {
|
||||
disableSysTimer(2);
|
||||
if (m->type == 4)
|
||||
if ((_flags.platform == Common::kPlatformSegaCD) == (m->type != 4))
|
||||
snd_updateEnvironmentalSfx(_monsterProps[m->type].sound1);
|
||||
m->curAttackFrame = -2;
|
||||
|
||||
_flashShapeTimer = 0;
|
||||
drawScene(1);
|
||||
m->curAttackFrame = -1;
|
||||
if (m->type != 4)
|
||||
snd_updateEnvironmentalSfx(_monsterProps[m->type].sound1);
|
||||
_flashShapeTimer = _system->getMillis() + 8 * _tickLength;
|
||||
drawScene(1);
|
||||
m->curAttackFrame = -2;
|
||||
|
||||
for (int i = 0; i < 16 && m->curAttackFrame < 0; ++i) {
|
||||
if (m->type != 4 && m->curAttackFrame == -1)
|
||||
snd_updateEnvironmentalSfx(_monsterProps[m->type].sound1);
|
||||
drawScene(1);
|
||||
_flashShapeTimer = _system->getMillis() + _flashShapeTimerIntv;
|
||||
}
|
||||
|
||||
} else {
|
||||
snd_updateEnvironmentalSfx(_monsterProps[m->type].sound1);
|
||||
}
|
||||
@ -1030,7 +1054,7 @@ bool EoBCoreEngine::updateMonsterTryCloseAttack(EoBMonsterInPlay *m, int block)
|
||||
m->animStep ^= 1;
|
||||
_sceneUpdateRequired = 1;
|
||||
enableSysTimer(2);
|
||||
_flashShapeTimer = _system->getMillis() + 8 * _tickLength;
|
||||
_flashShapeTimer = _system->getMillis() + _flashShapeTimerIntv;
|
||||
}
|
||||
} else {
|
||||
int b = m->block;
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
void sega_loadTextBufferToVRAM(uint16 srcOffset, uint16 addr, int size);
|
||||
void sega_gfxScale(uint8 *out, uint16 w, uint16 h, uint16 pitch, const uint8 *in, const uint16 *stampMap, const uint16 *traceVectors);
|
||||
void sega_drawClippedLine(uint8 *dst, int pW, int pH, int x, int y, int w, int h, uint8 color);
|
||||
uint8 *sega_encodeShape(const uint8 *src, int w, int h, int pal);
|
||||
uint8 *sega_convertShape(const uint8 *src, int w, int h, int pal);
|
||||
void sega_encodeShapesFromSprites(const uint8 **dst, const uint8 *src, int numShapes, int w, int h, int pal);
|
||||
|
||||
SegaRenderer *sega_getRenderer() const { return _segaRenderer; }
|
||||
|
@ -289,7 +289,7 @@ void Screen_EoB::sega_drawClippedLine(uint8 *dst, int pW, int pH, int x, int y,
|
||||
}
|
||||
}
|
||||
|
||||
uint8 *Screen_EoB::sega_encodeShape(const uint8 *src, int w, int h, int pal) {
|
||||
uint8 *Screen_EoB::sega_convertShape(const uint8 *src, int w, int h, int pal) {
|
||||
uint8 *shp = new uint8[(w >> 1) * h + 20];
|
||||
uint8 *dst = shp;
|
||||
*dst++ = 2;
|
||||
|
@ -249,6 +249,8 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
|
||||
m->directionChanged = in.readByte();
|
||||
m->stepsTillRemoteAttack = in.readByte();
|
||||
m->sub = in.readByte();
|
||||
m->animType = 0;
|
||||
m->animProgress = 0;
|
||||
}
|
||||
|
||||
for (int ii = 0; ii < _numFlyingObjects; ii++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user