mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-05 09:10:29 +00:00
64b5f32e81
svn-id: r19170
459 lines
13 KiB
C++
459 lines
13 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2004-2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* $Header$
|
|
*
|
|
*/
|
|
|
|
#include "common/stdafx.h"
|
|
#include "common/stream.h"
|
|
#include "common/util.h"
|
|
#include "common/system.h"
|
|
#include "kyra/screen.h"
|
|
#include "kyra/kyra.h"
|
|
#include "kyra/sprites.h"
|
|
#include "kyra/resource.h"
|
|
|
|
namespace Kyra {
|
|
|
|
Sprites::Sprites(KyraEngine *engine, OSystem *system) {
|
|
_engine = engine;
|
|
_res = engine->resource();
|
|
_screen = engine->screen();
|
|
_system = system;
|
|
_dat = 0;
|
|
memset(_anims, 0, sizeof(_anims));
|
|
_animDelay = 16;
|
|
}
|
|
|
|
Sprites::~Sprites() {
|
|
delete[] _dat;
|
|
}
|
|
|
|
Sprite Sprites::getSprite(uint8 spriteID) {
|
|
assert( spriteID < MAX_NUM_SPRITES);
|
|
return _sprites[spriteID];
|
|
}
|
|
|
|
void Sprites::drawSprites(uint8 srcPage, uint8 dstPage) {
|
|
int flags;
|
|
|
|
for (int i = 0; i < MAX_NUM_ANIMS; i++) {
|
|
if (_anims[i].script == 0 || !_anims[i].play)
|
|
break;
|
|
if (_anims[i].sprite >= 0) {
|
|
assert( _anims[i].sprite < MAX_NUM_SPRITES);
|
|
Sprite sprite = _sprites[_anims[i].sprite];
|
|
|
|
//debug(1, "Drawing from X %i, Y %i, to X %i, Y %i, width %i, height %i, srcPage %i, dstPage %i",
|
|
// sprite.x, sprite.y, _anims[i].x, _anims[i].y, sprite.width, sprite.height, srcPage, dstPage);
|
|
flags = Screen::CR_CLIPPED;
|
|
if (_anims[i].flipX)
|
|
flags |= Screen::CR_X_FLIPPED;
|
|
|
|
_screen->copyRegion(sprite.x, sprite.y, _anims[i].x, _anims[i].y, sprite.width, sprite.height, srcPage, dstPage, flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Sprites::doAnims() {
|
|
uint32 currTime = _system->getMillis();
|
|
for (int i = 0; i < MAX_NUM_ANIMS; i++) {
|
|
if (_anims[i].script == 0 || !_anims[i].play || _anims[i].nextRun != 0 && _anims[i].nextRun > currTime)
|
|
continue;
|
|
|
|
uint8 *data;
|
|
|
|
if (_anims[i].reentry == 0) {
|
|
data = _anims[i].script;
|
|
|
|
//debug(1, "---Start of anim script---");
|
|
assert( READ_LE_UINT16(data) == 0xFF86 );
|
|
data += 2;
|
|
|
|
//debug(1, "Default X of sprite: %i", READ_LE_UINT16(data + 0x12) );
|
|
_anims[i].x = READ_LE_UINT16(data + 0x12);
|
|
//debug(1, "Default Y of sprite: %i", READ_LE_UINT16(data + 0x16) );
|
|
_anims[i].y = READ_LE_UINT16(data + 0x16);
|
|
|
|
//debug(1, "Anim %i flags: 22h: %i, 1ah: %i", i, READ_LE_UINT16(data + 0x22), READ_LE_UINT16(data + 0x1a));
|
|
|
|
/*
|
|
debug(1, "Anim %i data: 0h: %i, 2h: %i,4h: %i,6h: %i,8h: %i,ah: %i,ch: %i", i, READ_LE_UINT16(data + 0x0),
|
|
READ_LE_UINT16(data + 0x2), READ_LE_UINT16(data + 0x4),READ_LE_UINT16(data + 0x6),READ_LE_UINT16(data + 0x8),
|
|
READ_LE_UINT16(data + 0xa),READ_LE_UINT16(data + 0xc));
|
|
|
|
debug(1, "Anim %i data: eh: %i, 10h: %i,12h: %i,14h: %i,16h: %i,18h: %i,1ah: %i", i, READ_LE_UINT16(data + 0xe),
|
|
READ_LE_UINT16(data + 0x10), READ_LE_UINT16(data + 0x12),READ_LE_UINT16(data + 0x14),READ_LE_UINT16(data + 0x16),
|
|
READ_LE_UINT16(data + 0x18),READ_LE_UINT16(data + 0x1a));
|
|
|
|
debug(1, "Anim %i data: 1ch: %i, 1fh: %i,22h: %i,24h: %i,26h: %i,28h: %i,2ah: %i", i, READ_LE_UINT16(data + 0x1c),
|
|
READ_LE_UINT16(data + 0x1f), READ_LE_UINT16(data + 0x22),READ_LE_UINT16(data + 0x24),READ_LE_UINT16(data + 0x26),
|
|
READ_LE_UINT16(data + 0x28),READ_LE_UINT16(data + 0x2a));
|
|
*/
|
|
|
|
|
|
// TODO: Find out what the rest of this data (next 38h bytes) does.
|
|
data += 0x38;
|
|
} else {
|
|
data = _anims[i].reentry;
|
|
_anims[i].reentry = 0;
|
|
}
|
|
|
|
bool endLoop = false;
|
|
|
|
while (READ_LE_UINT16(data) != 0xFF87 && !endLoop) {
|
|
uint16 rndNr;
|
|
uint16 anim;
|
|
assert((data - _anims[i].script) < _anims[i].length);
|
|
switch (READ_LE_UINT16(data)) {
|
|
case 0xFF88:
|
|
data += 2;
|
|
debug(5, "func: Set sprite image.");
|
|
debug(5, "Sprite index %i", READ_LE_UINT16(data));
|
|
_anims[i].sprite = READ_LE_UINT16(data);
|
|
data += 2;
|
|
//debug(5, "Unused %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
debug(5, "X %i", READ_LE_UINT16(data));
|
|
_anims[i].x = READ_LE_UINT16(data);
|
|
data += 2;
|
|
debug(5, "Y %i", READ_LE_UINT16(data));
|
|
_anims[i].y = READ_LE_UINT16(data);
|
|
data += 2;
|
|
_anims[i].flipX = false;
|
|
break;
|
|
case 0xFF8D:
|
|
data += 2;
|
|
debug(5, "func: Set sprite image, flipped.");
|
|
debug(5, "Sprite index %i", READ_LE_UINT16(data));
|
|
_anims[i].sprite = READ_LE_UINT16(data);
|
|
data += 2;
|
|
//debug(9, "Unused %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
debug(5, "X %i", READ_LE_UINT16(data));
|
|
_anims[i].x = READ_LE_UINT16(data);
|
|
data += 2;
|
|
debug(5, "Y %i", READ_LE_UINT16(data));
|
|
_anims[i].y = READ_LE_UINT16(data);
|
|
data += 2;
|
|
_anims[i].flipX = true;
|
|
break;
|
|
case 0xFF8A:
|
|
data += 2;
|
|
debug(5, "func: Set time to wait");
|
|
debug(5, "Time %i", READ_LE_UINT16(data));
|
|
_anims[i].nextRun = _system->getMillis() + READ_LE_UINT16(data) * _animDelay;
|
|
data += 2;
|
|
break;
|
|
case 0xFFB3:
|
|
data += 2;
|
|
debug(5, "func: Set time to wait to random value");
|
|
rndNr = READ_LE_UINT16(data) + _rnd.getRandomNumber( READ_LE_UINT16(data) + 2);
|
|
debug(5, "Minimum time %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
debug(5, "Maximum time %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
_anims[i].nextRun = _system->getMillis() + rndNr * _animDelay;
|
|
break;
|
|
case 0xFF8C:
|
|
data += 2;
|
|
debug(5, "func: Wait until wait time has elapsed");
|
|
_anims[i].reentry = data;
|
|
endLoop = true;
|
|
//assert( _anims[i].nextRun > _system->getMillis());
|
|
break;
|
|
case 0xFF99:
|
|
data += 2;
|
|
debug(1, "TODO func: Set value of animation property 32h to 1");
|
|
break;
|
|
case 0xFF9A:
|
|
data += 2;
|
|
debug(1, "TODO func: Set value of animation property 32h to 0");
|
|
break;
|
|
case 0xFF97:
|
|
data += 2;
|
|
debug(5, "func: Set default X coordinate of sprite");
|
|
debug(5, "X %i", READ_LE_UINT16(data));
|
|
_anims[i].x = READ_LE_UINT16(data);
|
|
data += 2;
|
|
break;
|
|
case 0xFF98:
|
|
data += 2;
|
|
debug(5, "func: Set default Y coordinate of sprite");
|
|
debug(5, "Y %i", READ_LE_UINT16(data));
|
|
_anims[i].y = READ_LE_UINT16(data);
|
|
data += 2;
|
|
break;
|
|
case 0xFF8B:
|
|
debug(5, "func: Jump to start of script section");
|
|
//data = scriptStart;
|
|
_anims[i].nextRun = _system->getMillis();
|
|
endLoop = true;
|
|
break;
|
|
case 0xFF8E:
|
|
data += 2;
|
|
debug(5, "func: Begin for () loop");
|
|
debug(5, "Iterations: %i", READ_LE_UINT16(data));
|
|
_anims[i].loopsLeft = READ_LE_UINT16(data);
|
|
data += 2;
|
|
_anims[i].loopStart = data;
|
|
break;
|
|
case 0xFF8F:
|
|
data += 2;
|
|
debug(5, "func: End for () loop");
|
|
if (_anims[i].loopsLeft > 0) {
|
|
_anims[i].loopsLeft--;
|
|
data = _anims[i].loopStart;
|
|
}
|
|
break;
|
|
case 0xFF90:
|
|
data += 2;
|
|
debug(5, "func: Set sprite image using default X and Y");
|
|
debug(5, "Sprite index %i", READ_LE_UINT16(data));
|
|
_anims[i].sprite = READ_LE_UINT16(data);
|
|
_anims[i].flipX = false;
|
|
data += 2;
|
|
break;
|
|
case 0xFF91:
|
|
data += 2;
|
|
debug(5, "func: Set sprite image using default X and Y, flipped.");
|
|
debug(5, "Sprite index %i", READ_LE_UINT16(data));
|
|
_anims[i].sprite = READ_LE_UINT16(data);
|
|
_anims[i].flipX = true;
|
|
data += 2;
|
|
break;
|
|
case 0xFF92:
|
|
data += 2;
|
|
debug(5, "func: Increase value of default X-coordinate");
|
|
debug(5, "Increment %i", READ_LE_UINT16(data));
|
|
_anims[i].x += READ_LE_UINT16(data);
|
|
data += 2;
|
|
break;
|
|
case 0xFF93:
|
|
data += 2;
|
|
debug(5, "func: Increase value of default Y-coordinate");
|
|
debug(5, "Increment %i", READ_LE_UINT16(data));
|
|
_anims[i].y += READ_LE_UINT16(data);
|
|
data += 2;
|
|
break;
|
|
case 0xFF94:
|
|
data += 2;
|
|
debug(5, "func: Decrease value of default X-coordinate");
|
|
debug(5, "Decrement %i", READ_LE_UINT16(data));
|
|
_anims[i].x -= READ_LE_UINT16(data);
|
|
data += 2;
|
|
break;
|
|
case 0xFF95:
|
|
data += 2;
|
|
debug(5, "func: Decrease value of default Y-coordinate");
|
|
debug(5, "Decrement %i", READ_LE_UINT16(data));
|
|
_anims[i].y -= READ_LE_UINT16(data);
|
|
data += 2;
|
|
break;
|
|
case 0xFF96:
|
|
data += 2;
|
|
debug(9, "func: Stop animation");
|
|
debug(9, "Animation index %i", READ_LE_UINT16(data));
|
|
anim = READ_LE_UINT16(data);
|
|
data += 2;
|
|
_anims[anim].play = false;
|
|
_anims[anim].sprite = -1;
|
|
//debug(1, "Arg2 %i", READ_LE_UINT16(data));
|
|
//data += 2;
|
|
break;
|
|
/* case 0xFF97:
|
|
data += 2;
|
|
debug(1, "func: Set value of animation property 34h to 0");
|
|
break;*/
|
|
case 0xFFAD:
|
|
data += 2;
|
|
debug(1, "TODO func: Set Brandon's X coordinate");
|
|
debug(1, "X %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
break;
|
|
case 0xFFAE:
|
|
data += 2;
|
|
debug(1, "TODO func: Set Brandon's Y coordinate");
|
|
debug(1, "Y %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
break;
|
|
case 0xFFAF:
|
|
data += 2;
|
|
debug(1, "TODO func: Set Brandon's X sprite");
|
|
debug(1, "Sprite %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
break;
|
|
case 0xFFAA:
|
|
data += 2;
|
|
debug(1, "TODO func: Reset Brandon's sprite");
|
|
break;
|
|
case 0xFFAB:
|
|
data += 2;
|
|
debug(1, "TODO func: Update Brandon's sprite");
|
|
break;
|
|
case 0xFFB0:
|
|
data += 2;
|
|
debug(1, "TODO func: Play sound");
|
|
debug(1, "Sound index %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
break;
|
|
case 0xFFB1:
|
|
data += 2;
|
|
debug(1, "TODO func: Set unknown global bit");
|
|
break;
|
|
case 0xFFB2:
|
|
data += 2;
|
|
debug(1, "TODO func: Reset unknown global bit");
|
|
break;
|
|
case 0xFFB4:
|
|
data += 2;
|
|
debug(1, "TODO func: Play (at random) a certain sound at a certain percentage of time");
|
|
debug(1, "Sound index %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
debug(1, "Percentage %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
break;
|
|
case 0xFFA7:
|
|
data += 2;
|
|
debug(1, "TODO func: Unknown FFA7");
|
|
debug(1, " %i", READ_LE_UINT16(data));
|
|
data += 2;
|
|
break;
|
|
default:
|
|
debug(1, "Unsupported anim command %X", READ_LE_UINT16(data));
|
|
//endLoop = true;
|
|
data += 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (READ_LE_UINT16(data) == 0xFF87)
|
|
_anims[i].play = false;
|
|
|
|
//debug(1, "---End of anim script---");
|
|
}
|
|
}
|
|
|
|
void Sprites::loadDAT(const char *filename) {
|
|
debug(9, "Sprites::loadDat('%s')", filename);
|
|
uint32 fileSize;
|
|
uint8 spritesLoaded = 0;
|
|
|
|
delete[] _dat;
|
|
|
|
_dat = _res->fileData(filename, &fileSize);
|
|
|
|
memset(_anims, 0, sizeof(Anim) * MAX_NUM_ANIMS);
|
|
uint8 nextAnim = 0;
|
|
|
|
assert(fileSize > 0x6D);
|
|
|
|
memcpy(_screen->_currentPalette + 745 - 0x3D, _dat + 0x17, 0x3D);
|
|
_screen->setScreenPalette(_screen->_currentPalette);
|
|
uint8 *data = _dat + 0x6B;
|
|
|
|
uint16 length = READ_LE_UINT16(data);
|
|
data += 2;
|
|
|
|
//debug(1, "DAT body length: %i, filesize %i, current spot %i", length, fileSize, data - _dat);
|
|
|
|
if (length > 2) {
|
|
assert( length < fileSize);
|
|
uint8 *animstart;
|
|
uint8 *start = data;
|
|
|
|
while (1) {
|
|
if (((uint16)(data - _dat) >= fileSize) || (data - start) >= length)
|
|
break;
|
|
|
|
if (READ_LE_UINT16(data) == 0xFF83) {
|
|
//debug(1, "Body section end.");
|
|
data += 2;
|
|
break;
|
|
}
|
|
|
|
switch (READ_LE_UINT16(data)) {
|
|
case 0xFF81:
|
|
data += 2;
|
|
//debug(1, "Body section start");
|
|
break;
|
|
case 0xFF82:
|
|
data += 2;
|
|
//debug(1, "Unknown 0xFF82 section");
|
|
break;
|
|
case 0xFF84:
|
|
data += 2;
|
|
while (READ_LE_UINT16(data) != 0xFF85) {
|
|
uint16 spriteNum = READ_LE_UINT16(data);
|
|
//debug(1, "Spritenum: %i", spriteNum);
|
|
assert(spriteNum < MAX_NUM_SPRITES);
|
|
data += 2;
|
|
_sprites[spriteNum].x = READ_LE_UINT16(data) * 8;
|
|
data += 2;
|
|
_sprites[spriteNum].y = READ_LE_UINT16(data);
|
|
data += 2;
|
|
_sprites[spriteNum].width = READ_LE_UINT16(data) * 8;
|
|
data += 2;
|
|
_sprites[spriteNum].height = READ_LE_UINT16(data);
|
|
data += 2;
|
|
spritesLoaded++;
|
|
//debug(1, "Got sprite index: %i", spriteNum);
|
|
//debug(1, "X: %i", _sprites[spriteNum].x);
|
|
//debug(1, "Y: %i", _sprites[spriteNum].y);
|
|
//debug(1, "Width: %i", _sprites[spriteNum].width);
|
|
//debug(1, "Height: %i", _sprites[spriteNum].height);
|
|
}
|
|
//debug(1, "End of sprite images.");
|
|
data += 2;
|
|
break;
|
|
case 0xFF86:
|
|
assert(nextAnim < MAX_NUM_ANIMS);
|
|
_anims[nextAnim].script = data;
|
|
_anims[nextAnim].sprite = -1;
|
|
_anims[nextAnim].play = true;
|
|
animstart = data;
|
|
data += 2;
|
|
while (READ_LE_UINT16(data) != 0xFF87) {
|
|
assert((uint16)(data - _dat) < fileSize);
|
|
data += 2;
|
|
}
|
|
_anims[nextAnim].length = data - animstart;
|
|
//debug(1, "Found an anim script of length %i!", _anims[nextAnim].length);
|
|
nextAnim++;
|
|
data += 2;
|
|
break;
|
|
default:
|
|
debug(1, "Unknown code in DAT file: %x", READ_LE_UINT16(data));
|
|
data += 2;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
data += 2;
|
|
}
|
|
|
|
debug(1, "Room DAT file loaded. Found %i sprite and %i animation scripts.", spritesLoaded, nextAnim);
|
|
|
|
//debug(1, "Remainder after script: %i", fileSize - (data - _dat));
|
|
assert(fileSize - (data - _dat) == 0xC);
|
|
|
|
//TODO: Read in character entry coords here
|
|
}
|
|
|
|
} // end of namespace Kyra
|