diff options
| author | Matthew Stewart | 2018-05-11 02:17:57 -0400 | 
|---|---|---|
| committer | Eugene Sandulenko | 2018-08-09 08:37:30 +0200 | 
| commit | d375429abef0109a483970975b053292efa4bd6e (patch) | |
| tree | 448bd50bc330010834b3e1f655903bf1b2d7e93e | |
| parent | fde5f22f9783c557c74d0267d8118c1a0c6d498e (diff) | |
| download | scummvm-rg350-d375429abef0109a483970975b053292efa4bd6e.tar.gz scummvm-rg350-d375429abef0109a483970975b053292efa4bd6e.tar.bz2 scummvm-rg350-d375429abef0109a483970975b053292efa4bd6e.zip | |
STARTREK: Objects and animations.
Testing them with the transporter room.
| -rw-r--r-- | engines/startrek/filestream.h | 2 | ||||
| -rw-r--r-- | engines/startrek/font.cpp | 2 | ||||
| -rw-r--r-- | engines/startrek/graphics.cpp | 121 | ||||
| -rw-r--r-- | engines/startrek/graphics.h | 20 | ||||
| -rw-r--r-- | engines/startrek/module.mk | 1 | ||||
| -rw-r--r-- | engines/startrek/object.cpp | 27 | ||||
| -rw-r--r-- | engines/startrek/object.h | 83 | ||||
| -rw-r--r-- | engines/startrek/room.cpp | 2 | ||||
| -rw-r--r-- | engines/startrek/sound.cpp | 7 | ||||
| -rw-r--r-- | engines/startrek/sound.h | 5 | ||||
| -rw-r--r-- | engines/startrek/sprite.h | 12 | ||||
| -rw-r--r-- | engines/startrek/startrek.cpp | 517 | ||||
| -rw-r--r-- | engines/startrek/startrek.h | 61 | ||||
| -rw-r--r-- | engines/startrek/text.cpp | 8 | 
14 files changed, 700 insertions, 168 deletions
| diff --git a/engines/startrek/filestream.h b/engines/startrek/filestream.h index 475bbcfeea..dcc806043c 100644 --- a/engines/startrek/filestream.h +++ b/engines/startrek/filestream.h @@ -39,7 +39,7 @@ private:  public:  	// ReadStream functions  	virtual bool eos() const; -	virtual uint32 read(void* dataPtr, uint32 dataSize); +	virtual uint32 read(void *dataPtr, uint32 dataSize);  	// SeekableReadStream functions  	virtual int32 pos() const; diff --git a/engines/startrek/font.cpp b/engines/startrek/font.cpp index db310425a0..8463841ece 100644 --- a/engines/startrek/font.cpp +++ b/engines/startrek/font.cpp @@ -31,7 +31,7 @@ static const byte CHARACTER_COUNT = 0x80;  static const byte CHARACTER_SIZE = 0x40;  Font::Font(StarTrekEngine *vm) : _vm(vm) { -	SharedPtr<Common::SeekableReadStream> fontStream = _vm->openFile("FONT.FNT"); +	SharedPtr<Common::SeekableReadStream> fontStream = _vm->loadFile("FONT.FNT");  	_characters = new Character[CHARACTER_COUNT]; diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp index ced8d82edb..457313cd51 100644 --- a/engines/startrek/graphics.cpp +++ b/engines/startrek/graphics.cpp @@ -33,9 +33,7 @@ namespace StarTrek {  Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {  	_font = nullptr; -  	_egaData = nullptr; -	_priData = nullptr;  	_lutData = nullptr;  	_screenRect = Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT); @@ -50,6 +48,9 @@ Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {  	_numSprites = 0;  	_textDisplayMode = TEXTDISPLAY_WAIT; +	_textboxVar2 = 0; +	_textboxVar6 = 0; +	_textboxHasMultipleChoices = false;  	setMouseCursor(loadBitmap("pushbtn"));  	CursorMan.showMouse(true); @@ -57,58 +58,22 @@ Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {  Graphics::~Graphics() {  	delete[] _egaData; -	delete[] _priData;  	delete[] _lutData;  	delete _font;  } -void Graphics::loadEGAData(const char *filename) { -	// Load EGA palette data -	if (!_egaMode) -		return; - -	if (!_egaData) -		_egaData = new byte[256]; - -	SharedPtr<Common::SeekableReadStream> egaStream = _vm->openFile(filename); -	egaStream->read(_egaData, 256); +void Graphics::setBackgroundImage(SharedPtr<Bitmap> bitmap) { +	_backgroundImage = bitmap;  } -void Graphics::drawBackgroundImage(const char *filename) { -	// Draw an stjr BGD image (palette built-in) - -	SharedPtr<Common::SeekableReadStream> imageStream = _vm->openFile(filename); -	byte *palette = new byte[256 * 3]; -	imageStream->read(palette, 256 * 3); - -	// Expand color components -	for (uint16 i = 0; i < 256 * 3; i++) -		palette[i] <<= 2; - -	uint16 xoffset = imageStream->readUint16LE(); -	uint16 yoffset = imageStream->readUint16LE(); -	uint16 width = imageStream->readUint16LE(); -	uint16 height = imageStream->readUint16LE(); - -	byte *pixels = new byte[width * height]; -	imageStream->read(pixels, width * height); - -	_vm->_system->getPaletteManager()->setPalette(palette, 0, 256); -	_vm->_system->copyRectToScreen(pixels, width, xoffset, yoffset, width, height); -	_vm->_system->updateScreen(); - -	delete[] palette; -} - -  void Graphics::loadPalette(const Common::String &paletteName) {  	// Set the palette from a PAL file  	Common::String palFile = paletteName + ".PAL";  	Common::String lutFile = paletteName + ".LUT"; -	SharedPtr<Common::SeekableReadStream> palStream = _vm->openFile(palFile.c_str()); +	SharedPtr<Common::SeekableReadStream> palStream = _vm->loadFile(palFile.c_str());  	byte *palette = new byte[256 * 3];  	palStream->read(palette, 256 * 3); @@ -122,7 +87,7 @@ void Graphics::loadPalette(const Common::String &paletteName) {  	delete[] palette;  	// Load LUT file -	SharedPtr<Common::SeekableReadStream> lutStream = _vm->openFile(lutFile.c_str()); +	SharedPtr<Common::SeekableReadStream> lutStream = _vm->loadFile(lutFile.c_str());  	delete[] _lutData;  	_lutData = new byte[256]; @@ -130,15 +95,27 @@ void Graphics::loadPalette(const Common::String &paletteName) {  }  void Graphics::loadPri(const char *priFile) { -	SharedPtr<Common::SeekableReadStream> priStream = _vm->openFile(priFile); - -	delete[] _priData; -	_priData = new byte[SCREEN_WIDTH*SCREEN_HEIGHT / 2]; +	SharedPtr<Common::SeekableReadStream> priStream = _vm->loadFile(priFile);  	priStream->read(_priData, SCREEN_WIDTH*SCREEN_HEIGHT / 2);  } +void Graphics::clearPri() { +	memset(_priData, 0, sizeof(_priData)); +} + +byte Graphics::getPriValue(int x, int y) { +	assert(_screenRect.contains(x, y)); + +	int priOffset = y * SCREEN_WIDTH + x; +	byte b = _priData[priOffset / 2]; +	if ((priOffset % 2) == 1) +		return b & 0xf; +	else +		return b >> 4; +} +  SharedPtr<Bitmap> Graphics::loadBitmap(Common::String basename) { -	return SharedPtr<Bitmap>(new Bitmap(_vm->openFile(basename + ".BMP"))); +	return SharedPtr<Bitmap>(new Bitmap(_vm->loadFile(basename + ".BMP")));  }  Common::Point Graphics::getMousePos() { @@ -150,11 +127,6 @@ void Graphics::setMouseCursor(SharedPtr<Bitmap> bitmap) {  	_vm->_system->setMouseCursor(bitmap->pixels, bitmap->width, bitmap->height, bitmap->xoffset, bitmap->yoffset, 0);  } -void Graphics::redrawScreen() { -	_vm->_system->copyRectToScreen(_backgroundImage->pixels, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); -	drawAllSprites(); -} -  void Graphics::drawSprite(const Sprite &sprite) {  	int left = sprite.drawX;  	int top = sprite.drawY; @@ -448,17 +420,50 @@ void Graphics::delSprite(Sprite *sprite) {  } -void Graphics::drawBitmapToScreen(Bitmap *bitmap) { +void Graphics::drawDirectToScreen(SharedPtr<Bitmap> bitmap) {  	int xoffset = bitmap->xoffset;  	int yoffset = bitmap->yoffset; -	if (xoffset >= SCREEN_WIDTH) -		xoffset = 0; -	if (yoffset >= SCREEN_HEIGHT) -		yoffset = 0;  	_vm->_system->copyRectToScreen(bitmap->pixels, bitmap->width, xoffset, yoffset, bitmap->width, bitmap->height); -	_vm->_system->updateScreen();  } +void Graphics::loadEGAData(const char *filename) { +	// Load EGA palette data +	if (!_egaMode) +		return; + +	if (!_egaData) +		_egaData = new byte[256]; + +	SharedPtr<Common::SeekableReadStream> egaStream = _vm->loadFile(filename); +	egaStream->read(_egaData, 256); +} + +void Graphics::drawBackgroundImage(const char *filename) { +	// Draw an stjr BGD image (palette built-in) + +	SharedPtr<Common::SeekableReadStream> imageStream = _vm->loadFile(filename); +	byte *palette = new byte[256 * 3]; +	imageStream->read(palette, 256 * 3); + +	// Expand color components +	for (uint16 i = 0; i < 256 * 3; i++) +		palette[i] <<= 2; + +	uint16 xoffset = imageStream->readUint16LE(); +	uint16 yoffset = imageStream->readUint16LE(); +	uint16 width = imageStream->readUint16LE(); +	uint16 height = imageStream->readUint16LE(); + +	byte *pixels = new byte[width * height]; +	imageStream->read(pixels, width * height); + +	_vm->_system->getPaletteManager()->setPalette(palette, 0, 256); +	_vm->_system->copyRectToScreen(pixels, width, xoffset, yoffset, width, height); +	_vm->_system->updateScreen(); + +	delete[] palette; +} +  } diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h index 277c63615c..758f327d6b 100644 --- a/engines/startrek/graphics.h +++ b/engines/startrek/graphics.h @@ -70,18 +70,17 @@ public:  	Graphics(StarTrekEngine *vm);  	~Graphics(); -	void loadEGAData(const char *egaFile); -	void drawBackgroundImage(const char *filename); - +	void setBackgroundImage(SharedPtr<Bitmap> bitmap);  	void loadPalette(const String &paletteFile);  	void loadPri(const char *priFile); +	void clearPri(); +	byte getPriValue(int x, int y);  	SharedPtr<Bitmap> loadBitmap(String basename);  	Common::Point getMousePos();  	void setMouseCursor(SharedPtr<Bitmap> bitmap); -	void redrawScreen();  	void drawSprite(const Sprite &sprite);  	void drawSprite(const Sprite &sprite, const Common::Rect &rect);  	void drawAllSprites(); @@ -89,18 +88,19 @@ public:  	void addSprite(Sprite *sprite);  	void delSprite(Sprite *sprite); + +	void drawDirectToScreen(SharedPtr<Bitmap> bitmap); +	void loadEGAData(const char *egaFile); +	void drawBackgroundImage(const char *filename);  private: -	void drawBitmapToScreen(Bitmap *bitmap); - -  	StarTrekEngine *_vm;  	Font *_font;  	bool _egaMode;  	byte *_egaData; -	byte *_priData;  	byte *_lutData; +	byte _priData[SCREEN_WIDTH*SCREEN_HEIGHT / 2];  	Common::Rect _screenRect;  	SharedPtr<Bitmap> _backgroundImage; @@ -156,11 +156,13 @@ public:  private:  	int16 _textDisplayMode; + +public:  	uint32 _textboxVar2; -	uint32 _textboxVar3;  	uint16 _textboxVar6;  	bool _textboxHasMultipleChoices; +private:  	SharedPtr<Menu> _activeMenu;  	// Saved value of StarTrekEngine::_keyboardControlsMouse when menus are up diff --git a/engines/startrek/module.mk b/engines/startrek/module.mk index 9114de4632..3b93fbc439 100644 --- a/engines/startrek/module.mk +++ b/engines/startrek/module.mk @@ -9,6 +9,7 @@ MODULE_OBJS = \  	font.o \  	lzss.o \  	graphics.o \ +	object.o \  	room.o \  	sound.o \  	sprite.o \ diff --git a/engines/startrek/object.cpp b/engines/startrek/object.cpp new file mode 100644 index 0000000000..aafa138ffe --- /dev/null +++ b/engines/startrek/object.cpp @@ -0,0 +1,27 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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. + * + */ + +#include "object.h" + +namespace StarTrek { + +} diff --git a/engines/startrek/object.h b/engines/startrek/object.h new file mode 100644 index 0000000000..41bf1f96c2 --- /dev/null +++ b/engines/startrek/object.h @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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. + * + */ + +#ifndef STARTREK_OBJECT_H +#define STARTREK_OBJECT_H + +#include "startrek/sprite.h" + +#include "common/scummsys.h" + +namespace StarTrek { + +class StarTrekEngine; +class FileStream; + + +struct Object { +	uint16 spriteDrawn; +	char animationString3[16]; +	uint16 animType; +	Sprite sprite; +	char animationString4[10]; +	uint16 scale; +	SharedPtr<FileStream> animFile; +	uint16 numAnimFrames; +	uint16 animFrame; +	uint32 frameToStartNextAnim; +	uint16 field5e; +	uint16 field60; +	uint16 field62; +	uint16 field64; +	uint16 field66; +	char animationString2[8]; +	uint16 field70; +	uint16 field72; +	uint16 field74; +	uint16 field76; +	uint16 iwSrcPosition; +	uint16 iwDestPosition; +	uint16 field7c; +	uint16 field7e; +	uint16 field80; +	uint16 field82; +	uint16 field84; +	uint16 field86; +	uint16 field88; +	uint16 field8a; +	uint16 field8c; +	uint16 field8e; +	uint16 field90; +	uint16 field92; +	uint16 field94; +	uint16 field96; +	char animationString[9]; +	uint8  fielda1; +	uint16 fielda2; +	uint16 fielda4; +	uint16 fielda6; +}; + +} + +#endif + diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp index 3516aaa437..a68737454f 100644 --- a/engines/startrek/room.cpp +++ b/engines/startrek/room.cpp @@ -31,7 +31,7 @@  namespace StarTrek {  Room::Room(StarTrekEngine *vm, Common::String name) : _vm(vm) { -	SharedPtr<FileStream> rdfFile = _vm->openFile(name + ".RDF"); +	SharedPtr<FileStream> rdfFile = _vm->loadFile(name + ".RDF");  	int size = rdfFile->size();  	_rdfData = new byte[size]; diff --git a/engines/startrek/sound.cpp b/engines/startrek/sound.cpp index 2871a88613..105b3a0b7a 100644 --- a/engines/startrek/sound.cpp +++ b/engines/startrek/sound.cpp @@ -149,6 +149,9 @@ void Sound::playMidiMusicTracks(int startTrack, int loopTrack) {  		playMidiTrackInSlot(0, startTrack);  } +/** + * TODO: original game had some caching of loaded voc files. + */  void Sound::playVoc(const Common::String &baseSoundName) {  	/*  	if (_vm->getPlatform() == Common::kPlatformAmiga) @@ -169,7 +172,7 @@ void Sound::playVoc(const Common::String &baseSoundName) {  		sub_2aaa3();  	*/ -	for (int i=0; i<MAX_SFX_PLAYING; i++) { +	for (int i = 0; i < MAX_SFX_PLAYING; i++) {  		if (_vm->_system->getMixer()->isSoundHandleActive(_sfxHandles[i]))  			continue; @@ -304,7 +307,7 @@ void Sound::loadPCMusicFile(const Common::String &baseSoundName) {  	}  	debugC(5, kDebugSound, "Loading midi \'%s\'\n", soundName.c_str()); -	SharedPtr<Common::SeekableReadStream> soundStream = _vm->openFile(soundName.c_str()); +	SharedPtr<Common::SeekableReadStream> soundStream = _vm->loadFile(soundName.c_str());  	if (loadedSoundData != nullptr)  		delete[] loadedSoundData; diff --git a/engines/startrek/sound.h b/engines/startrek/sound.h index 2caa1d0010..6ce4e94a7c 100644 --- a/engines/startrek/sound.h +++ b/engines/startrek/sound.h @@ -82,11 +82,14 @@ private:  	uint32 _midiDevice;	  	// VOC-related variables -	Common::String _loopingAudioName;  	Audio::SoundHandle _sfxHandles[MAX_SFX_PLAYING];  	Audio::SoundHandle _speechHandle;  	bool _playingSpeech; +public: +	Common::String _loopingAudioName; + +private:  	// Driver callback  	static void midiDriverCallback(void *data);  }; diff --git a/engines/startrek/sprite.h b/engines/startrek/sprite.h index 1e75cc416e..844fb80c35 100644 --- a/engines/startrek/sprite.h +++ b/engines/startrek/sprite.h @@ -63,18 +63,6 @@ struct Sprite {  	Common::Rect getRect();  }; - -class SpriteList { -public: -	SpriteList(int n) { sprites = new Sprite[n]; } -	~SpriteList() { delete[] sprites; } - -	Sprite &operator[](int i) const { return sprites[i]; } - -private: -	Sprite *sprites; -}; -  }  #endif diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp index 40fa8d76da..8b05a5a3d2 100644 --- a/engines/startrek/startrek.cpp +++ b/engines/startrek/startrek.cpp @@ -39,14 +39,24 @@  namespace StarTrek { -StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc) : Engine(syst), _gameDescription(gamedesc) { +StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc) : +	Engine(syst), +	_gameDescription(gamedesc), +	_kirkObject(&_objectList[0]), +	_spockObject(&_objectList[1]), +	_mccoyObject(&_objectList[2]), +	_redshirtObject(&_objectList[3]) { +  	DebugMan.addDebugChannel(kDebugSound, "sound", "Sound"); +	DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics");  	_gfx = nullptr;  	_sound = nullptr;  	_macResFork = nullptr;  	_room = nullptr; +	_redshirtDead = false; +  	_clockTicks = 0;  	_musicEnabled = true; @@ -82,86 +92,190 @@ Common::Error StarTrekEngine::run() {  	}  	initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT); -  	initializeEventsAndMouse(); -	 -// Test graphics/music: - -// Music Status: -// DOS Full: Adlib and MT-32 Sounds supported -// DOS Demo: Adlib and MT-32 Sounds supported -// Amiga: Sound effects supported -// Macintosh: MIDI and sound effects playable, format not handled. - -// Graphics Status: -// DOS/Amiga/Macintosh/Demo Graphics: 100% -// Judgment Rites Backgrounds supported too -// EGA not supported + +	_frameIndex = 0; + +	_gameMode = -1; +	_lastGameMode = -1; + +	runGameMode(GAMEMODE_BEAMDOWN); +	return Common::kNoError; + +  #if 1  	_room = new Room(this, "DEMON0"); -	if (getGameType() == GType_ST25) { -		_gfx->loadPalette("PALETTE"); -		_gfx->loadPri("DEMON0.PRI"); -		_gfx->redrawScreen(); -		 -		_sound->loadMusicFile("GROUND"); -	} else { -		_gfx->drawBackgroundImage("BRIDGE.BGD"); -	} +	_gfx->loadPalette("PALETTE"); +	_gfx->loadPri("DEMON0.PRI"); -	// Sprite tests - -	// Draw mode 0 -	Sprite *spr = new Sprite; -	_gfx->addSprite(spr); -	spr->bitmap = _gfx->loadBitmap("MWALKE00"); -	spr->drawPriority = 1; -	spr->pos.x = 150; -	spr->pos.y = 100; -	spr->drawMode = 0; - -	// Draw mode 2 (translucent background) -	spr = new Sprite; -	_gfx->addSprite(spr); -	spr->bitmap = _gfx->loadBitmap("KWALKS00"); -	spr->drawPriority = 1; -	spr->pos.x = 230; -	spr->pos.y = 100; -	spr->drawMode = 2; - -	/* -	// Draw mode 3 (text) -	spr = new Sprite; -	_gfx->addSprite(spr); -	spr->bitmap = SharedPtr<Bitmap>(new TextBitmap(8*8,8*8)); -	for (int i=0;i<8*8;i++) -		spr->bitmap->pixels[i] = 0x40+i; -	spr->pos.x = 8*10; -	spr->pos.y = 50; -	spr->textColor = 0xb3; -	spr->drawMode = 3; - -	// initTextSprite function -	spr = new Sprite; -	int x=0,y=0; -	_gfx->initTextSprite(&x, &y, 0xb3, 3, false, spr); -	spr->pos.y = 150; -	*/ +	_sound->loadMusicFile("GROUND");  	while (true) {  		_gfx->showOptionsMenu(0, 0);  	} -	_gfx->showText(&Graphics::readTextFromRdf, 0x2220, 150, 160, 0xb3, 0, 10, 0);  	while (!shouldQuit()) {  		pollSystemEvents();  	} + +	return Common::kNoError;  #endif +} + +Common::Error StarTrekEngine::runGameMode(int mode) { +	_gameMode = mode; + +	_sound->stopAllVocSounds(); +	if (!_sound->_loopingAudioName.empty()) +		_sound->playVoc(_sound->_loopingAudioName); + +	if (_gameMode == GAMEMODE_START) +		_gameMode = GAMEMODE_BRIDGE; + +	while (true) { +		if (_gameMode != _lastGameMode) { +			// Cleanup previous game mode +			switch (_lastGameMode) { +			case GAMEMODE_BRIDGE: +				//cleanupBridgeMode(); +				break; + +			case GAMEMODE_AWAYMISSION: +				//cleanupAwayMissionMode(); +				break; + +			case GAMEMODE_BEAMDOWN: +			case GAMEMODE_BEAMUP: +				break; +			} + +			_lastGameMode = _gameMode; + +			// Load next game mode +			switch (_gameMode) { +			case GAMEMODE_BRIDGE: +				_sound->loadMusicFile("bridge"); +				//initBridge(); +				break; + +			case GAMEMODE_AWAYMISSION: +				//initAwayMission(); +				break; + +			case GAMEMODE_BEAMDOWN: +				_redshirtDead = false; +				_sound->loadMusicFile("ground"); +				runTransportSequence("teled"); +				_gameMode = GAMEMODE_AWAYMISSION; +				continue; // Back to start of loop + +			case GAMEMODE_BEAMUP: +				runTransportSequence("teleb"); +				_gameMode = GAMEMODE_BRIDGE; +				//sub_15c61(); +				_sound->stopAllVocSounds(); +				_sound->playVoc("bridloop"); +				continue; // Back to start of loop +			} +		} + +		// Run current game mode +		switch (_gameMode) { +		case GAMEMODE_BRIDGE: +			//runBridge(); +			break; + +		case GAMEMODE_AWAYMISSION: +			//runAwayMission(); +			break; + +		case GAMEMODE_BEAMDOWN: +		case GAMEMODE_BEAMUP: +			error("Can't be here."); +			break; +		} +	}  	return Common::kNoError;  } +void StarTrekEngine::runTransportSequence(const Common::String &name) { +	const uint16 crewmanTransportPositions[][2] = { +		{ 0x8e, 0x7c }, +		{ 0xbe, 0x7c }, +		{ 0x7e, 0x72 }, +		{ 0xaa, 0x72 } +	}; + +	_sound->stopAllVocSounds(); +	// sub_1e70d(); +	objectFunc1(); +	initObjects(); + +	SharedPtr<Bitmap> bgImage = _gfx->loadBitmap("transprt"); +	_gfx->setBackgroundImage(bgImage); +	_gfx->clearPri(); +	_gfx->loadPalette("palette"); +	_gfx->drawDirectToScreen(bgImage); +	_system->updateScreen(); + +	for (int i = 0; i < (_redshirtDead ? 3 : 4); i++) { +		Common::String filename = getCrewmanAnimFilename(i, name); +		int x = crewmanTransportPositions[i][0]; +		int y = crewmanTransportPositions[i][1]; +		loadAnimationForObject(i, filename, x, y, 256); +		_objectList[i].animationString[0] = '\0'; +	} + +	if (_missionToLoad.equalsIgnoreCase("feather") && name[4] == 'b') { +		loadAnimationForObject(9, "qteleb", 0x61, 0x79, 0x100); +	} +	else if (_missionToLoad.equalsIgnoreCase("trial")) { +		if (name[4] == 'd') { +			loadAnimationForObject(9, "qteled", 0x61, 0x79, 0x100); +		} +		/* TODO +		else if (word_51156 >= 3) { +			loadAnimationForObject(9, "qteleb", 0x61, 0x79, 0x100); +		} +		*/ +	} + +	loadAnimationForObject(8, "transc", 0, 0, 0x100); + +	// TODO: redraw mouse and sprite_52c4e? + +	_gfx->drawAllSprites(); +	// sub_1e6ab(); + +	playSoundEffectIndex(0x0a); + +	if (name.equalsIgnoreCase("teled")) +		playSoundEffectIndex(0x08); +	else +		playSoundEffectIndex(0x09); + +	while (_objectList[0].field62 == 0) { +		TrekEvent event; +		if (popNextEvent(&event)) { +			if (event.type == TREKEVENT_TICK) { +				// TODO: redraw sprite_52c4e? +				_frameIndex++; +				updateObjectAnimations(); +				_gfx->drawAllSprites(); +			} +		} +	} + +	// TODO: redraw sprite_52c4e? + +	_gfx->drawAllSprites(); +	// sub_1e70d(); +	objectFunc1(); +	initObjects(); +} +  Room *StarTrekEngine::getRoom() {  	return _room;  } @@ -191,13 +305,19 @@ void StarTrekEngine::pollSystemEvents() {  			break;  		}  	} -	_gfx->drawAllSprites(); + +	// FIXME: get the actual duration of a tick right +	_clockTicks++; +	TrekEvent tickEvent; +	tickEvent.type = TREKEVENT_TICK; +	tickEvent.tick = _clockTicks; +	addEventToQueue(tickEvent);  	_system->delayMillis(1000/60);  }  void StarTrekEngine::playSoundEffectIndex(int index) { -	switch(index) { +	switch (index) {  	case 0x04:  		_sound->playVoc("tricorde");  		break; @@ -256,14 +376,262 @@ void StarTrekEngine::stopPlayingSpeech() {  	_sound->stopPlayingSpeech();  } +void StarTrekEngine::initObjects() { +	for (int i = 0; i < MAX_OBJECTS; i++) { +		_objectList[i] = Object(); +	} +	for (int i = 0; i < MAX_OBJECTS / 2; i++) +		_objectBanFiles[i].reset(); + +	strcpy(_kirkObject->animationString, "kstnd"); +	strcpy(_spockObject->animationString, "sstnd"); +	strcpy(_mccoyObject->animationString, "mstnd"); +	strcpy(_redshirtObject->animationString, "rstnd"); +} + +int StarTrekEngine::loadAnimationForObject(int objectIndex, const Common::String &animName, uint16 x, uint16 y, uint16 arg8) { +	debugC(6, kDebugGraphics, "Load animation '%s' on object %d", animName.c_str(), objectIndex); + +	Object *object; + +	if (objectIndex == -1) { +		// TODO +	} +	else +		object = &_objectList[objectIndex]; + +	if (object->spriteDrawn) { +		releaseAnim(object); +		drawObjectToScreen(object, animName, x, y, arg8, false); +	} +	else { +		drawObjectToScreen(object, animName, x, y, arg8, true); +	} + +	object->field64 = 0; +	object->field66 = 0; + +	return objectIndex; +} + +void StarTrekEngine::updateObjectAnimations() { +	for (int i = 0; i < MAX_OBJECTS; i++) { +		Object *object = &_objectList[i]; +		if (!object->spriteDrawn) +			continue; + +		switch (object->animType) { +		case 0: +		case 2: +			if (object->frameToStartNextAnim >= _frameIndex) { +				int nextAnimIndex = 0; // TODO: "chooseNextAnimFrame" function +				object->animFile->seek(18 + nextAnimIndex + object->animFrame * 22, SEEK_SET); +				byte nextAnimFrame = object->animFile->readByte(); + +				debugC(7, kDebugGraphics, "Object %d animation frame %d", i, nextAnimFrame); + +				if (object->animFrame != nextAnimFrame) { +					if (nextAnimFrame == object->numAnimFrames - 1) { +						object->field62++; +						if (object->field64 != 0) { +							// sub_20099(10, object->field66, 0, 0); +						} +					} +				} + +				object->animFrame = nextAnimFrame; +				if (object->animFrame >= object->numAnimFrames) { +					if (object->animationString[0] == '\0') +						removeObjectFromScreen(i); +					/* +					else // TODO +						initStandAnim(i); +						*/ +				} +				else { +					Sprite *sprite = &object->sprite; + +					object->animFile->seek(object->animFrame * 22, SEEK_SET); +					char animFrameFilename[16]; +					object->animFile->read(animFrameFilename, 16); +					sprite->setBitmap(loadAnimationFrame(animFrameFilename, object->scale)); + +					memset(object->animationString4, 0, 16); +					strncpy(object->animationString4, animFrameFilename, 15); + +					object->animFile->seek(10, SEEK_SET); +					uint16 xOffset = object->animFile->readUint16(); +					uint16 yOffset = object->animFile->readUint16(); +					uint16 basePriority = object->animFile->readUint16(); + +					sprite->pos.x = xOffset + object->field5e; +					sprite->pos.y = yOffset + object->field60; +					sprite->drawPriority = _gfx->getPriValue(0, yOffset + object->field60) + basePriority; +					sprite->bitmapChanged = true; + +					object->frameToStartNextAnim = object->animFile->readUint16() + _frameIndex; +				} +			} +			break; +		case 1: // TODO +			warning("Unimplemented anim type %d", object->animType); +			break; +		default: +			error("Invalid anim type."); +			break; +		} +	} +} + +void StarTrekEngine::removeObjectFromScreen(int objectIndex) { +	Object *object = &_objectList[objectIndex]; + +	if (object->spriteDrawn != 1) +		return; + +	debugC(6, kDebugGraphics, "Stop drawing object %d", objectIndex); + +	Sprite *sprite = &object->sprite; +	sprite->field16 = true; +	sprite->bitmapChanged = true; +	_gfx->drawAllSprites(); +	_gfx->delSprite(sprite); +	releaseAnim(object); +} + +void StarTrekEngine::objectFunc1() { +	for (int i = 0; i < MAX_OBJECTS; i++) { +		if (_objectList[i].spriteDrawn == 1) { +			removeObjectFromScreen(i); +		} +	} + +	for (int i = 0; i < MAX_OBJECTS / 2; i++) { +		_objectBanFiles[i].reset(); +	} +} + +void StarTrekEngine::drawObjectToScreen(Object *object, const Common::String &_animName, uint16 x, uint16 y, uint16 arg8, bool addSprite) { +	Common::String animFilename = _animName; +	if (_animName.hasPrefixIgnoreCase("stnd") /* && word_45d20 == -1 */) // TODO +		animFilename += 'j'; +	memcpy(object->animationString3, _animName.c_str(), sizeof(object->animationString3)); + +	object->animType = 2; +	object->animFile = loadFile(animFilename + ".anm"); +	object->numAnimFrames = object->animFile->size() / 22; +	object->animFrame = 0; +	object->field5e = x; +	object->field60 = y; +	object->field62 = 0; +	object->scale = arg8; + +	object->animFile->seek(16, SEEK_SET); +	object->frameToStartNextAnim = object->animFile->readUint16() + _frameIndex; + +	char firstFrameFilename[10]; +	object->animFile->seek(0, SEEK_SET); +	object->animFile->read(firstFrameFilename, 10); + +	Sprite *sprite = &object->sprite; +	if (addSprite) +		_gfx->addSprite(sprite); + +	sprite->setBitmap(loadAnimationFrame(firstFrameFilename, arg8)); +	memset(object->animationString4, 0, sizeof(char) * 10); +	strncpy(object->animationString4, firstFrameFilename, sizeof(char) * 9); + +	object->scale = arg8; + +	object->animFile->seek(10, SEEK_SET); +	uint16 xOffset = object->animFile->readUint16(); +	uint16 yOffset = object->animFile->readUint16(); +	uint16 basePriority = object->animFile->readUint16(); + +	sprite->pos.x = xOffset + object->field5e; +	sprite->pos.y = yOffset + object->field60; +	sprite->drawPriority = _gfx->getPriValue(0, yOffset + object->field60) + basePriority; +	sprite->bitmapChanged = true; + +	object->spriteDrawn = 1; +} + +void StarTrekEngine::releaseAnim(Object *object) { +	switch (object->animType) { +	case 0: +	case 2: +		object->sprite.bitmap.reset(); +		object->animFile.reset(); +		break; +	case 1: // TODO +		warning("Unimplemented anim type %d", object->animType); +		break; +	default: +		error("Invalid anim type."); +		break; +	} + +	object->spriteDrawn = 0; +} + +SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filename, uint16 arg2) { +	SharedPtr<Bitmap> bitmapToReturn; + +	char basename[5]; +	strncpy(basename, filename.c_str()+1, 4); +	basename[4] = '\0'; + +	char c = filename[0]; +	if ((strcmp(basename, "stnd") == 0 || strcmp(basename, "tele") == 0) +			&& (c == 'm' || c == 's' || c == 'k' || c == 'r')) { +		if (c == 'm') { +			bitmapToReturn = _gfx->loadBitmap(filename); +		} +		else { +			// bitmapToReturn = _gfx->loadBitmap(filename + ".$bm"); // FIXME: should be this? +			if (bitmapToReturn == nullptr) { +				Common::String newFilename = filename; +				newFilename.setChar('m', 0); // FIXME: original writes directly to argument; does that affect anything? +				bitmapToReturn = _gfx->loadBitmap(newFilename); +			} +		} +	} +	else { +		// TODO: when loading a bitmap, it passes a different argument than is standard to +		// the "file loading with cache" function... +		bitmapToReturn = _gfx->loadBitmap(filename); +	} + +	if (arg2 != 256) { +		// TODO +		// bitmapToReturn = scaleBitmap(bitmapToReturn, arg2); +	} + +	return bitmapToReturn; +} + +Common::String StarTrekEngine::getCrewmanAnimFilename(int objectIndex, const Common::String &basename) { +	const char *crewmanChars = "ksmr"; +	assert(objectIndex >= 0 && objectIndex < 4); +	return crewmanChars[objectIndex] + basename; +} +  void StarTrekEngine::updateClockTicks() {  	// TODO (based on DOS interrupt 1A, AH=0; read system clock counter)  	_clockTicks = 0;  } -SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int fileIndex) { +/** + * TODO: + *   - Should return nullptr on failure to open a file? + *   - This is supposed to cache results, return same FileStream on multiple accesses. + *   - This is supposed to read from a "patches" folder which overrides files in the + *     packed blob. + */ +SharedPtr<FileStream> StarTrekEngine::loadFile(Common::String filename, int fileIndex) {  	filename.toUppercase(); +  	Common::String basename, extension;  	bool bigEndian = getPlatform() == Common::kPlatformAmiga; @@ -278,11 +646,18 @@ SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int file  		}  	} +	// FIXME: don't know if this is right, or if it goes here +	while (!basename.empty() && basename.lastChar() == ' ') { +		basename.erase(basename.size() - 1, 1); +	} + +	filename = basename + '.' + extension; +  	// The Judgment Rites demo has its files not in the standard archive  	if (getGameType() == GType_STJR && (getFeatures() & GF_DEMO)) {  		Common::File *file = new Common::File();  		if (!file->open(filename.c_str())) -			error ("Could not find file \'%s\'", filename.c_str()); +			error("Could not find file \'%s\'", filename.c_str());  		return SharedPtr<FileStream>(new FileStream(file, bigEndian));  	} @@ -291,7 +666,7 @@ SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int file  	if (getPlatform() == Common::kPlatformAmiga) {  		indexFile = SearchMan.createReadStreamForMember("data000.dir");  		if (!indexFile) -			error ("Could not open data000.dir"); +			error("Could not open data000.dir");  	} else if (getPlatform() == Common::kPlatformMacintosh) {  		indexFile = _macResFork->getResource("Directory");  		if (!indexFile) @@ -299,7 +674,7 @@ SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int file  	} else {  		indexFile = SearchMan.createReadStreamForMember("data.dir");  		if (!indexFile) -			error ("Could not open data.dir"); +			error("Could not open data.dir");  	}  	uint32 indexOffset = 0; @@ -353,9 +728,9 @@ SharedPtr<FileStream> StarTrekEngine::openFile(Common::String filename, int file  		if ((basename.lastChar() >= '1' && basename.lastChar() <= '9') ||  				(basename.lastChar() >= 'B' && basename.lastChar() <= 'Z')) {  			basename.setChar(basename.lastChar()-1, basename.size()-1); -			return openFile(basename + "." + extension, fileIndex+1); +			return loadFile(basename + "." + extension, fileIndex+1);  		} else -			error ("Could not find file \'%s\'", filename.c_str()); +			error("Could not find file \'%s\'", filename.c_str());  	}  	if (fileIndex >= fileCount) diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h index 5e81f77a26..6cb175c689 100644 --- a/engines/startrek/startrek.h +++ b/engines/startrek/startrek.h @@ -36,6 +36,7 @@  #include "startrek/filestream.h"  #include "startrek/graphics.h" +#include "startrek/object.h"  #include "startrek/room.h"  #include "startrek/sound.h" @@ -58,10 +59,25 @@ enum StarTrekGameFeatures {  };  enum kDebugLevels { -	kDebugSound =  1 << 0 +	kDebugSound =     1 << 0, +	kDebugGraphics =  1 << 1  }; +enum GameMode { +	GAMEMODE_START = 0, +	GAMEMODE_BRIDGE, +	GAMEMODE_AWAYMISSION, +	GAMEMODE_BEAMDOWN, +	GAMEMODE_BEAMUP +}; + +enum TextDisplayMode { +	TEXTDISPLAY_WAIT = 0,  // Wait for input before closing text +	TEXTDISPLAY_SUBTITLES, // Automatically continue when speech is done +	TEXTDISPLAY_NONE       // No text displayed +}; +  enum TrekEventType {  	TREKEVENT_TICK = 0, // DOS clock changes (see updateClockTicks)  	TREKEVENT_LBUTTONDOWN = 1, @@ -72,12 +88,6 @@ enum TrekEventType {  	TREKEVENT_KEYDOWN = 6  }; -enum TextDisplayMode { -	TEXTDISPLAY_WAIT = 0,  // Wait for input before closing text -	TEXTDISPLAY_SUBTITLES, // Automatically continue when speech is done -	TEXTDISPLAY_NONE       // No text displayed -}; -  struct TrekEvent {  	TrekEventType type;  	Common::KeyState kbd; @@ -85,6 +95,8 @@ struct TrekEvent {  	uint32 tick;  }; +const int MAX_OBJECTS = 0x20; +  struct StarTrekGameDescription;  class Graphics;  class Sound; @@ -93,6 +105,11 @@ class StarTrekEngine : public ::Engine {  protected:  	Common::Error run(); +private: +	// Game modes +	Common::Error runGameMode(int mode); +	void runTransportSequence(const Common::String &name); +  public:  	StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc);  	virtual ~StarTrekEngine(); @@ -105,6 +122,18 @@ public:  	void playSpeech(const Common::String &filename);  	void stopPlayingSpeech(); +	// Objects +	void initObjects(); +	int loadAnimationForObject(int objectIndex, const Common::String &animName, uint16 x, uint16 y, uint16 arg8); +	void updateObjectAnimations(); +	void removeObjectFromScreen(int objectIndex); +	void objectFunc1(); +	void drawObjectToScreen(Object *object, const Common::String &animName, uint16 field5e, uint16 field60, uint16 arg8, bool addSprite); +	void releaseAnim(Object *object); + +	SharedPtr<Bitmap> loadAnimationFrame(const Common::String &filename, uint16 arg2); +	Common::String getCrewmanAnimFilename(int objectIndex, const Common::String &basename); +  	// Events  public:  	void initializeEventsAndMouse(); @@ -138,14 +167,30 @@ public:  	Common::Language getLanguage();  	// Resource related functions -	SharedPtr<FileStream> openFile(Common::String filename, int fileIndex=0); +	SharedPtr<FileStream> loadFile(Common::String filename, int fileIndex=0);  	// Movie related functions  	void playMovie(Common::String filename);  	void playMovieMac(Common::String filename); +public: +	int _gameMode; +	int _lastGameMode; +	bool _redshirtDead; +	Common::String _missionToLoad; + +	Object _objectList[MAX_OBJECTS]; +	Object * const _kirkObject; +	Object * const _spockObject; +	Object * const _mccoyObject; +	Object * const _redshirtObject; + +	SharedPtr<FileStream> _objectBanFiles[MAX_OBJECTS / 2]; +	uint16 _objectBanVar2[MAX_OBJECTS / 2]; // TODO: initialize? +  	uint32 _clockTicks; +	uint32 _frameIndex;  	bool _musicEnabled;  	bool _sfxEnabled; diff --git a/engines/startrek/text.cpp b/engines/startrek/text.cpp index 923ebc6c8b..ef5a746756 100644 --- a/engines/startrek/text.cpp +++ b/engines/startrek/text.cpp @@ -68,7 +68,7 @@ int Graphics::showText(TextGetterFunc textGetter, uintptr var, int xoffset, int  	int16 tmpTextDisplayMode = _textDisplayMode;  	uint32 var7c = 8; -	if (_textboxVar3 > _textboxVar2+1) { +	if (_vm->_frameIndex > _textboxVar2+1) {  		var7c = 0x10;  	} @@ -291,7 +291,7 @@ reloadText:  		// sub_272B4  	} -	_textboxVar2 = _textboxVar3; +	_textboxVar2 = _vm->_frameIndex;  	_vm->stopPlayingSpeech();  	return choiceIndex;  } @@ -347,7 +347,7 @@ int Graphics::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool arg4) {  					}  				}  				// sub_1E88C(); -				_textboxVar3++; +				_vm->_frameIndex++;  				if (ticksUntilClickingEnabled != 0 && _vm->_clockTicks >= tickWhenClickingEnabled)  					return MENUEVENT_ENABLEINPUT; @@ -818,7 +818,7 @@ void Graphics::loadMenuButtons(String mnuFilename, int xpos, int ypos) {  	_activeMenu = SharedPtr<Menu>(new Menu());  	_activeMenu->nextMenu = oldMenu; -	SharedPtr<FileStream> stream = _vm->openFile(mnuFilename + ".MNU"); +	SharedPtr<FileStream> stream = _vm->loadFile(mnuFilename + ".MNU");  	_activeMenu->menuFile = stream;  	_activeMenu->numButtons = _activeMenu->menuFile->size() / 16; | 
