diff options
| -rw-r--r-- | engines/simon/event.cpp | 290 | ||||
| -rw-r--r-- | engines/simon/items.cpp | 69 | ||||
| -rw-r--r-- | engines/simon/module.mk | 3 | ||||
| -rw-r--r-- | engines/simon/simon.cpp | 755 | ||||
| -rw-r--r-- | engines/simon/string.cpp | 144 | ||||
| -rw-r--r-- | engines/simon/subroutine.cpp | 319 | ||||
| -rw-r--r-- | engines/simon/window.cpp | 165 | 
7 files changed, 921 insertions, 824 deletions
| diff --git a/engines/simon/event.cpp b/engines/simon/event.cpp new file mode 100644 index 0000000000..15105e7f61 --- /dev/null +++ b/engines/simon/event.cpp @@ -0,0 +1,290 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2006 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" + +#include "simon/simon.h" +#include "simon/intern.h" + +namespace Simon { + +void SimonEngine::addTimeEvent(uint timeout, uint subroutine_id) { +	TimeEvent *te = (TimeEvent *)malloc(sizeof(TimeEvent)), *first, *last = NULL; +	time_t cur_time; + +	time(&cur_time); + +	te->time = cur_time + timeout - _gameStoppedClock; +	if (_clockStopped) +		te->time -= ((uint32)time(NULL) - _clockStopped); +	te->subroutine_id = subroutine_id; + +	first = _firstTimeStruct; +	while (first) { +		if (te->time <= first->time) { +			if (last) { +				last->next = te; +				te->next = first; +				return; +			} +			te->next = _firstTimeStruct; +			_firstTimeStruct = te; +			return; +		} + +		last = first; +		first = first->next; +	} + +	if (last) { +		last->next = te; +		te->next = NULL; +	} else { +		_firstTimeStruct = te; +		te->next = NULL; +	} +} + +void SimonEngine::delTimeEvent(TimeEvent *te) { +	TimeEvent *cur; + +	if (te == _pendingDeleteTimeEvent) +		_pendingDeleteTimeEvent = NULL; + +	if (te == _firstTimeStruct) { +		_firstTimeStruct = te->next; +		free(te); +		return; +	} + +	cur = _firstTimeStruct; +	if (cur == NULL) +		error("delTimeEvent: none available"); + +	for (;;) { +		if (cur->next == NULL) +			error("delTimeEvent: no such te"); +		if (te == cur->next) { +			cur->next = te->next; +			free(te); +			return; +		} +		cur = cur->next; +	} +} + +void SimonEngine::invokeTimeEvent(TimeEvent *te) { +	Subroutine *sub; + +	_scriptVerb = 0; + +	if (_runScriptReturn1) +		return; + +	sub = getSubroutineByID(te->subroutine_id); +	if (sub != NULL) +		startSubroutineEx(sub); + +	_runScriptReturn1 = false; +} + +void SimonEngine::killAllTimers() { +	TimeEvent *cur, *next; + +	for (cur = _firstTimeStruct; cur; cur = next) { +		next = cur->next; +		delTimeEvent(cur); +	} +} + +bool SimonEngine::kickoffTimeEvents() { +	time_t cur_time; +	TimeEvent *te; +	bool result = false; + +	if (_clockStopped) +		return result; + +	time(&cur_time); +	cur_time -= _gameStoppedClock; + +	while ((te = _firstTimeStruct) != NULL && te->time <= (uint32)cur_time) { +		result = true; +		_pendingDeleteTimeEvent = te; +		invokeTimeEvent(te); +		if (_pendingDeleteTimeEvent) { +			_pendingDeleteTimeEvent = NULL; +			delTimeEvent(te); +		} +	} + +	return result; +} + +void SimonEngine::addVgaEvent(uint16 num, const byte *code_ptr, uint16 cur_sprite, uint16 curZoneNum, int32 param) { +	VgaTimerEntry *vte; + +	// When Simon talks to the Golum about stew in French version of +	// Simon the Sorcerer 1 the code_ptr is at wrong location for +	// sprite 200. This  was a bug in the original game, which +	// caused several glitches in this scene. +	// We work around the problem by correcting the code_ptr for sprite +	// 200 in this scene, if it is wrong. +	if (getGameType() == GType_SIMON1 && _language == Common::FR_FRA && +		(code_ptr - _vgaBufferPointers[curZoneNum].vgaFile1 == 4) && (cur_sprite == 200) && (curZoneNum == 2)) +		code_ptr += 0x66; + +	_lockWord |= 1; + +	for (vte = _vgaTimerList; vte->delay; vte++) { +	} + +	vte->delay = num; +	vte->script_pointer = code_ptr; +	vte->sprite_id = cur_sprite; +	vte->cur_vga_file = curZoneNum; +	vte->param = param; + +	_lockWord &= ~1; +} + +void SimonEngine::deleteVgaEvent(VgaTimerEntry * vte) { +	_lockWord |= 1; + +	if (vte + 1 <= _nextVgaTimerToProcess) { +		_nextVgaTimerToProcess--; +	} + +	do { +		memcpy(vte, vte + 1, sizeof(VgaTimerEntry)); +		vte++; +	} while (vte->delay); + +	_lockWord &= ~1; +} + +void SimonEngine::processVgaEvents() { +	VgaTimerEntry *vte = _vgaTimerList; +	uint timer = (getGameType() == GType_FF) ? 5 : 1; + +	_vgaTickCounter++; + +	while (vte->delay) { +		vte->delay -= timer; +		if (vte->delay <= 0) { +			uint16 curZoneNum = vte->cur_vga_file; +			uint16 cur_sprite = vte->sprite_id; +			const byte *script_ptr = vte->script_pointer; +			int32 param = vte->param; + +			_nextVgaTimerToProcess = vte + 1; +			deleteVgaEvent(vte); + +			if (getGameType() == GType_FF && script_ptr == NULL) { +				panEvent(curZoneNum, cur_sprite, param); +			} else if (getGameType() == GType_SIMON2 && script_ptr == NULL) { +				scrollEvent(); +			} else { +				animateEvent(script_ptr, curZoneNum, cur_sprite); +			} +			vte = _nextVgaTimerToProcess; +		} else { +			vte++; +		} +	} +} + +void SimonEngine::animateEvent(const byte *code_ptr, uint16 curZoneNum, uint16 cur_sprite) { +	VgaPointersEntry *vpe; + +	_vgaCurSpriteId = cur_sprite; + +	_vgaCurZoneNum = curZoneNum; +	_zoneNumber = curZoneNum; +	vpe = &_vgaBufferPointers[curZoneNum]; + +	_curVgaFile1 = vpe->vgaFile1; +	_curVgaFile2 = vpe->vgaFile2; +	_curSfxFile = vpe->sfxFile; + +	_vcPtr = code_ptr; + +	runVgaScript(); +} + +void SimonEngine::panEvent(uint16 curZoneNum, uint16 cur_sprite, int32 param) { +	_vgaCurSpriteId = cur_sprite; +	_vgaCurZoneNum = curZoneNum; + +	VgaSprite *vsp = findCurSprite(); + +	param &= 0x10; + +	int32 pan = (vsp->x - _scrollX + param) * 8 - 2560; +	if (pan < -10000) +		pan = -10000; +	if (pan > 10000) +		pan = 10000; + +	//setSfxPan(param, pan); + +	if (pan != 0) +		addVgaEvent(10, NULL, _vgaCurSpriteId, _vgaCurZoneNum); /* pan event */ +	debug(0, "panEvent: param %d pan %d", param, pan); +} + +void SimonEngine::scrollEvent() { +	if (_scrollCount == 0) +		return; + +	if (getGameType() == GType_FF) { +		if (_scrollCount < 0) { +			if (_scrollFlag != -8) { +				_scrollFlag = -8; +				_scrollCount += 8; +			} +		} else { +			if (_scrollFlag != 8) { +				_scrollFlag = 8; +				_scrollCount -= 8; +			} +		} +	} else { +		if (_scrollCount < 0) { +			if (_scrollFlag != -1) { +				_scrollFlag = -1; +				if (++_scrollCount == 0) +					return; +			} +		} else { +			if (_scrollFlag != 1) { +				_scrollFlag = 1; +				if (--_scrollCount == 0) +					return; +			} +		} + +		addVgaEvent(6, NULL, 0, 0); /* scroll event */ +	} +} + +} // End of namespace Simon diff --git a/engines/simon/items.cpp b/engines/simon/items.cpp index 1ff4907a6c..f00aef3ee9 100644 --- a/engines/simon/items.cpp +++ b/engines/simon/items.cpp @@ -2203,75 +2203,6 @@ int SimonEngine::runScript() {  	return getScriptReturn();  } -int SimonEngine::startSubroutine(Subroutine *sub) { -	int result = -1; -	SubroutineLine *sl; -	const byte *old_code_ptr; - -	if (_startMainScript) -		dumpSubroutine(sub); - -	old_code_ptr = _codePtr; - -	if (++_recursionDepth > 40) -		error("Recursion error"); - -	sl = (SubroutineLine *)((byte *)sub + sub->first); - -	while ((byte *)sl != (byte *)sub) { -		if (checkIfToRunSubroutineLine(sl, sub)) { -			result = 0; -			_codePtr = (byte *)sl; -			if (sub->id) -				_codePtr += 2; -			else -				_codePtr += 8; - -			if (_continousMainScript) -				fprintf(_dumpFile, "; %d\n", sub->id); -			result = runScript(); -			if (result != 0) { -				/* result -10 means restart subroutine */ -				if (result == -10) { -					delay(0);							/* maybe leave control to the VGA */ -					sl = (SubroutineLine *)((byte *)sub + sub->first); -					continue; -				} -				break; -			} -		} -		sl = (SubroutineLine *)((byte *)sub + sl->next); -	} - -	_codePtr = old_code_ptr; - -	_recursionDepth--; -	return result; -} - -int SimonEngine::startSubroutineEx(Subroutine *sub) { -	return startSubroutine(sub); -} - -bool SimonEngine::checkIfToRunSubroutineLine(SubroutineLine *sl, Subroutine *sub) { -	if (sub->id) -		return true; - -	if (sl->verb != -1 && sl->verb != _scriptVerb && -			(sl->verb != -2 || _scriptVerb != -1)) -		return false; - -	if (sl->noun1 != -1 && sl->noun1 != _scriptNoun1 && -			(sl->noun1 != -2 || _scriptNoun1 != -1)) -		return false; - -	if (sl->noun2 != -1 && sl->noun2 != _scriptNoun2 && -			(sl->noun2 != -2 || _scriptNoun2 != -1)) -		return false; - -	return true; -} -  void SimonEngine::scriptMouseOn() {  	if (getGameType() == GType_FF && _mouseCursor != 5) {  		resetVerbs(); diff --git a/engines/simon/module.mk b/engines/simon/module.mk index b0e88d9257..1e55c0f0d6 100644 --- a/engines/simon/module.mk +++ b/engines/simon/module.mk @@ -6,6 +6,7 @@ MODULE_OBJS := \  	cursor.o \  	debug.o \  	debugger.o \ +	event.o \  	game.o \  	icons.o \  	items.o \ @@ -17,8 +18,10 @@ MODULE_OBJS := \  	simon.o \  	sound.o \  	string.o \ +	subroutine.o \  	verb.o \  	vga.o \ +	window.o \  MODULE_DIRS += \  	engines/simon diff --git a/engines/simon/simon.cpp b/engines/simon/simon.cpp index 46de8a3a5d..a5fe75faf7 100644 --- a/engines/simon/simon.cpp +++ b/engines/simon/simon.cpp @@ -649,27 +649,6 @@ byte *SimonEngine::allocateItem(uint size) {  	return org;  } -void SimonEngine::alignTableMem() { -	if ((unsigned long)_tablesHeapPtr & 3) { -		_tablesHeapPtr += 2; -		_tablesHeapCurPos += 2; -	} -} - -byte *SimonEngine::allocateTable(uint size) { -	byte *org = _tablesHeapPtr; - -	size = (size + 1) & ~1; - -	_tablesHeapPtr += size; -	_tablesHeapCurPos += size; - -	if (_tablesHeapCurPos > _tablesHeapSize) -		error("Tablesheap overflow"); - -	return org; -} -  int SimonEngine::allocGamePcVars(File *in) {  	uint item_array_size, item_array_inited, stringtable_num;  	uint32 version; @@ -730,117 +709,6 @@ void SimonEngine::createPlayer() {  	setUserFlag(_currentPlayer, 0, 0);  } -void SimonEngine::allocateStringTable(int num) { -	_stringTabPtr = (byte **)calloc(num, sizeof(byte *)); -	_stringTabPos = 0; -	_stringtab_numalloc = num; -} - -void SimonEngine::setupStringTable(byte *mem, int num) { -	int i = 0; -	for (;;) { -		_stringTabPtr[i++] = mem; -		if (--num == 0) -			break; -		for (; *mem; mem++); -		mem++; -	} - -	_stringTabPos = i; -} - -void SimonEngine::setupLocalStringTable(byte *mem, int num) { -	int i = 0; -	for (;;) { -		_localStringtable[i++] = mem; -		if (--num == 0) -			break; -		for (; *mem; mem++); -		mem++; -	} -} - -void SimonEngine::readSubroutineLine(File *in, SubroutineLine *sl, Subroutine *sub) { -	byte line_buffer[1024], *q = line_buffer; -	int size; - -	if (sub->id == 0) { -		sl->verb = in->readUint16BE(); -		sl->noun1 = in->readUint16BE(); -		sl->noun2 = in->readUint16BE(); -	} - -	while ((*q = in->readByte()) != 0xFF) { -		if (*q == 87) { -			in->readUint16BE(); -		} else { -			q = readSingleOpcode(in, q); -		} -	} - -	size = q - line_buffer + 1; - -	memcpy(allocateTable(size), line_buffer, size); -} - -SubroutineLine *SimonEngine::createSubroutineLine(Subroutine *sub, int where) { -	SubroutineLine *sl, *cur_sl = NULL, *last_sl = NULL; - -	if (sub->id == 0) -		sl = (SubroutineLine *)allocateTable(SUBROUTINE_LINE_BIG_SIZE); -	else -		sl = (SubroutineLine *)allocateTable(SUBROUTINE_LINE_SMALL_SIZE); - -	// where is what offset to insert the line at, locate the proper beginning line -	if (sub->first != 0) { -		cur_sl = (SubroutineLine *)((byte *)sub + sub->first); -		while (where) { -			last_sl = cur_sl; -			cur_sl = (SubroutineLine *)((byte *)sub + cur_sl->next); -			if ((byte *)cur_sl == (byte *)sub) -				break; -			where--; -		} -	} - -	if (last_sl != NULL) { -		// Insert the subroutine line in the middle of the link -		last_sl->next = (byte *)sl - (byte *)sub; -		sl->next = (byte *)cur_sl - (byte *)sub; -	} else { -		// Insert the subroutine line at the head of the link -		sl->next = sub->first; -		sub->first = (byte *)sl - (byte *)sub; -	} - -	return sl; -} - -void SimonEngine::readSubroutine(File *in, Subroutine *sub) { -	while (in->readUint16BE() == 0) { -		readSubroutineLine(in, createSubroutineLine(sub, 0xFFFF), sub); -	} -} - -Subroutine *SimonEngine::createSubroutine(uint id) { -	Subroutine *sub; - -	alignTableMem(); - -	sub = (Subroutine *)allocateTable(sizeof(Subroutine)); -	sub->id = id; -	sub->first = 0; -	sub->next = _subroutineList; -	_subroutineList = sub; -	return sub; -} - -void SimonEngine::readSubroutineBlock(File *in) { -	while (in->readUint16BE() == 0) { -		readSubroutine(in, createSubroutine(in->readUint16BE())); -	} -} -  Child *SimonEngine::findChildOfType(Item *i, uint type) {  	Child *child = i->children;  	for (; child; child = child->next) @@ -1108,141 +976,6 @@ void SimonEngine::linkItem(Item *item, Item *parent) {  	}  } -const byte *SimonEngine::getStringPtrByID(uint stringId) { -	const byte *string_ptr; -	byte *dst; - -	_freeStringSlot ^= 1; - -	if (stringId < 0x8000) { -		string_ptr = _stringTabPtr[stringId]; -	} else { -		string_ptr = getLocalStringByID(stringId); -	} - -	dst = _stringReturnBuffer[_freeStringSlot]; -	strcpy((char *)dst, (const char *)string_ptr); -	return dst; -} - -const byte *SimonEngine::getLocalStringByID(uint stringId) { -	if (stringId < _stringIdLocalMin || stringId >= _stringIdLocalMax) { -		loadTextIntoMem(stringId); -	} -	return _localStringtable[stringId - _stringIdLocalMin]; -} - -void SimonEngine::loadTextIntoMem(uint stringId) { -	byte *p; -	char filename[30]; -	int i; -	uint base_min = 0x8000, base_max, size; - -	_tablesHeapPtr = _tablesheapPtrNew; -	_tablesHeapCurPos = _tablesHeapCurPosNew; - -	p = _strippedTxtMem; - -	// get filename -	while (*p) { -		for (i = 0; *p; p++, i++) -			filename[i] = *p; -		filename[i] = 0; -		p++; - -		base_max = (p[0] * 256) | p[1]; -		p += 2; - -		if (stringId < base_max) { -			_stringIdLocalMin = base_min; -			_stringIdLocalMax = base_max; - -			_localStringtable = (byte **)_tablesHeapPtr; - -			size = (base_max - base_min + 1) * sizeof(byte *); -			_tablesHeapPtr += size; -			_tablesHeapCurPos += size; - -			size = loadTextFile(filename, _tablesHeapPtr); - -			setupLocalStringTable(_tablesHeapPtr, base_max - base_min + 1); - -			_tablesHeapPtr += size; -			_tablesHeapCurPos += size; - -			if (_tablesHeapCurPos > _tablesHeapSize) { -				error("loadTextIntoMem: Out of table memory"); -			} -			return; -		} - -		base_min = base_max; -	} - -	error("loadTextIntoMem: didn't find %d", stringId); -} - -void SimonEngine::loadTablesIntoMem(uint subr_id) { -	byte *p; -	int i; -	uint min_num, max_num; -	char filename[30]; -	File *in; - -	p = _tblList; -	if (p == NULL) -		return; - -	while (*p) { -		for (i = 0; *p; p++, i++) -			filename[i] = *p; -		filename[i] = 0; -		p++; - -		for (;;) { -			min_num = (p[0] * 256) | p[1]; -			p += 2; - -			if (min_num == 0) -				break; - -			max_num = (p[0] * 256) | p[1]; -			p += 2; - -			if (subr_id >= min_num && subr_id <= max_num) { -				_subroutineList = _subroutineListOrg; -				_tablesHeapPtr = _tablesHeapPtrOrg; -				_tablesHeapCurPos = _tablesHeapCurPosOrg; -				_stringIdLocalMin = 1; -				_stringIdLocalMax = 0; - -				in = openTablesFile(filename); -				readSubroutineBlock(in); -				closeTablesFile(in); -				if (getGameType() == GType_FF) { -					// TODO -				} else if (getGameType() == GType_SIMON2) { -					_sound->loadSfxTable(_gameFile, _gameOffsetsPtr[atoi(filename + 6) - 1 + SOUND_INDEX_BASE]); -				} else if (getPlatform() == Common::kPlatformWindows) { -					memcpy(filename, "SFXXXX", 6); -					_sound->readSfxFile(filename); -				} - -				alignTableMem(); - -				_tablesheapPtrNew = _tablesHeapPtr; -				_tablesHeapCurPosNew = _tablesHeapCurPos; - -				if (_tablesHeapCurPos > _tablesHeapSize) -					error("loadTablesIntoMem: Out of table memory"); -				return; -			} -		} -	} - -	debug(1,"loadTablesIntoMem: didn't find %d", subr_id); -} -  void SimonEngine::playSting(uint a) {  	if (!midi._enable_sfx)  		return; @@ -1269,212 +1002,6 @@ void SimonEngine::playSting(uint a) {  	midi.startTrack(0);  } -Subroutine *SimonEngine::getSubroutineByID(uint subroutine_id) { -	Subroutine *cur; - -	_subroutine = subroutine_id; - -	for (cur = _subroutineList; cur; cur = cur->next) { -		if (cur->id == subroutine_id) -			return cur; -	} - -	loadTablesIntoMem(subroutine_id); - -	for (cur = _subroutineList; cur; cur = cur->next) { -		if (cur->id == subroutine_id) -			return cur; -	} - -	if (subroutine_id != 160) -		debug(0,"getSubroutineByID: subroutine %d not found", subroutine_id); -	return NULL; -} - -uint SimonEngine::loadTextFile_gme(const char *filename, byte *dst) { -	uint res; -	uint32 offs; -	uint32 size; - -	res = atoi(filename + 4) + TEXT_INDEX_BASE - 1; -	offs = _gameOffsetsPtr[res]; -	size = _gameOffsetsPtr[res + 1] - offs; - -	readGameFile(dst, offs, size); - -	return size; -} - -File *SimonEngine::openTablesFile_gme(const char *filename) { -	uint res; -	uint32 offs; - -	res = atoi(filename + 6) + TABLE_INDEX_BASE - 1; -	offs = _gameOffsetsPtr[res]; - -	_gameFile->seek(offs, SEEK_SET); -	return _gameFile; -} - -uint SimonEngine::loadTextFile_simon1(const char *filename, byte *dst) { -	File fo; -	fo.open(filename); -	uint32 size; - -	if (fo.isOpen() == false) -		error("loadTextFile: Can't open '%s'", filename); - -	size = fo.size(); - -	if (fo.read(dst, size) != size) -		error("loadTextFile: fread failed"); -	fo.close(); - -	return size; -} - -File *SimonEngine::openTablesFile_simon1(const char *filename) { -	File *fo = new File(); -	fo->open(filename); -	if (fo->isOpen() == false) -		error("openTablesFile: Can't open '%s'", filename); -	return fo; -} - -uint SimonEngine::loadTextFile(const char *filename, byte *dst) { -	if (getFeatures() & GF_OLD_BUNDLE) -		return loadTextFile_simon1(filename, dst); -	else -		return loadTextFile_gme(filename, dst); -} - -File *SimonEngine::openTablesFile(const char *filename) { -	if (getFeatures() & GF_OLD_BUNDLE) -		return openTablesFile_simon1(filename); -	else -		return openTablesFile_gme(filename); -} - -void SimonEngine::closeTablesFile(File *in) { -	if (getFeatures() & GF_OLD_BUNDLE) { -		in->close(); -		delete in; -	} -} - -void SimonEngine::addTimeEvent(uint timeout, uint subroutine_id) { -	TimeEvent *te = (TimeEvent *)malloc(sizeof(TimeEvent)), *first, *last = NULL; -	time_t cur_time; - -	time(&cur_time); - -	te->time = cur_time + timeout - _gameStoppedClock; -	if (_clockStopped) -		te->time -= ((uint32)time(NULL) - _clockStopped); -	te->subroutine_id = subroutine_id; - -	first = _firstTimeStruct; -	while (first) { -		if (te->time <= first->time) { -			if (last) { -				last->next = te; -				te->next = first; -				return; -			} -			te->next = _firstTimeStruct; -			_firstTimeStruct = te; -			return; -		} - -		last = first; -		first = first->next; -	} - -	if (last) { -		last->next = te; -		te->next = NULL; -	} else { -		_firstTimeStruct = te; -		te->next = NULL; -	} -} - -void SimonEngine::delTimeEvent(TimeEvent *te) { -	TimeEvent *cur; - -	if (te == _pendingDeleteTimeEvent) -		_pendingDeleteTimeEvent = NULL; - -	if (te == _firstTimeStruct) { -		_firstTimeStruct = te->next; -		free(te); -		return; -	} - -	cur = _firstTimeStruct; -	if (cur == NULL) -		error("delTimeEvent: none available"); - -	for (;;) { -		if (cur->next == NULL) -			error("delTimeEvent: no such te"); -		if (te == cur->next) { -			cur->next = te->next; -			free(te); -			return; -		} -		cur = cur->next; -	} -} - -void SimonEngine::killAllTimers() { -	TimeEvent *cur, *next; - -	for (cur = _firstTimeStruct; cur; cur = next) { -		next = cur->next; -		delTimeEvent(cur); -	} -} - -bool SimonEngine::kickoffTimeEvents() { -	time_t cur_time; -	TimeEvent *te; -	bool result = false; - -	if (_clockStopped) -		return result; - -	time(&cur_time); -	cur_time -= _gameStoppedClock; - -	while ((te = _firstTimeStruct) != NULL && te->time <= (uint32)cur_time) { -		result = true; -		_pendingDeleteTimeEvent = te; -		invokeTimeEvent(te); -		if (_pendingDeleteTimeEvent) { -			_pendingDeleteTimeEvent = NULL; -			delTimeEvent(te); -		} -	} - -	return result; -} - -void SimonEngine::invokeTimeEvent(TimeEvent *te) { -	Subroutine *sub; - -	_scriptVerb = 0; - -	if (_runScriptReturn1) -		return; - -	sub = getSubroutineByID(te->subroutine_id); -	if (sub != NULL) -		startSubroutineEx(sub); - -	_runScriptReturn1 = false; -} -  void SimonEngine::setup_cond_c_helper() {  	HitArea *last;  	uint id; @@ -1600,17 +1127,6 @@ void SimonEngine::endCutscene() {  	_runScriptReturn1 = true;  } -uint SimonEngine::getWindowNum(WindowBlock *window) { -	uint i; - -	for (i = 0; i != ARRAYSIZE(_windowArray); i++) -		if (_windowArray[i] == window) -			return i; - -	error("getWindowNum: not found"); -	return 0; -} -  void SimonEngine::mouseOff() {  	_mouseHideCount++;  } @@ -2337,153 +1853,6 @@ void SimonEngine::set_video_mode_internal(uint16 mode, uint16 vga_res_id) {  	}  } -void SimonEngine::addVgaEvent(uint16 num, const byte *code_ptr, uint16 cur_sprite, uint16 curZoneNum, int32 param) { -	VgaTimerEntry *vte; - -	// When Simon talks to the Golum about stew in French version of -	// Simon the Sorcerer 1 the code_ptr is at wrong location for -	// sprite 200. This  was a bug in the original game, which -	// caused several glitches in this scene. -	// We work around the problem by correcting the code_ptr for sprite -	// 200 in this scene, if it is wrong. -	if (getGameType() == GType_SIMON1 && _language == Common::FR_FRA && -		(code_ptr - _vgaBufferPointers[curZoneNum].vgaFile1 == 4) && (cur_sprite == 200) && (curZoneNum == 2)) -		code_ptr += 0x66; - -	_lockWord |= 1; - -	for (vte = _vgaTimerList; vte->delay; vte++) { -	} - -	vte->delay = num; -	vte->script_pointer = code_ptr; -	vte->sprite_id = cur_sprite; -	vte->cur_vga_file = curZoneNum; -	vte->param = param; - -	_lockWord &= ~1; -} - -void SimonEngine::deleteVgaEvent(VgaTimerEntry * vte) { -	_lockWord |= 1; - -	if (vte + 1 <= _nextVgaTimerToProcess) { -		_nextVgaTimerToProcess--; -	} - -	do { -		memcpy(vte, vte + 1, sizeof(VgaTimerEntry)); -		vte++; -	} while (vte->delay); - -	_lockWord &= ~1; -} - -void SimonEngine::processVgaEvents() { -	VgaTimerEntry *vte = _vgaTimerList; -	uint timer = (getGameType() == GType_FF) ? 5 : 1; - -	_vgaTickCounter++; - -	while (vte->delay) { -		vte->delay -= timer; -		if (vte->delay <= 0) { -			uint16 curZoneNum = vte->cur_vga_file; -			uint16 cur_sprite = vte->sprite_id; -			const byte *script_ptr = vte->script_pointer; -			int32 param = vte->param; - -			_nextVgaTimerToProcess = vte + 1; -			deleteVgaEvent(vte); - -			if (getGameType() == GType_FF && script_ptr == NULL) { -				panEvent(curZoneNum, cur_sprite, param); -			} else if (getGameType() == GType_SIMON2 && script_ptr == NULL) { -				scrollEvent(); -			} else { -				animateEvent(script_ptr, curZoneNum, cur_sprite); -			} -			vte = _nextVgaTimerToProcess; -		} else { -			vte++; -		} -	} -} - -void SimonEngine::animateEvent(const byte *code_ptr, uint16 curZoneNum, uint16 cur_sprite) { -	VgaPointersEntry *vpe; - -	_vgaCurSpriteId = cur_sprite; - -	_vgaCurZoneNum = curZoneNum; -	_zoneNumber = curZoneNum; -	vpe = &_vgaBufferPointers[curZoneNum]; - -	_curVgaFile1 = vpe->vgaFile1; -	_curVgaFile2 = vpe->vgaFile2; -	_curSfxFile = vpe->sfxFile; - -	_vcPtr = code_ptr; - -	runVgaScript(); -} - -void SimonEngine::panEvent(uint16 curZoneNum, uint16 cur_sprite, int32 param) { -	_vgaCurSpriteId = cur_sprite; -	_vgaCurZoneNum = curZoneNum; - -	VgaSprite *vsp = findCurSprite(); - -	param &= 0x10; - -	int32 pan = (vsp->x - _scrollX + param) * 8 - 2560; -	if (pan < -10000) -		pan = -10000; -	if (pan > 10000) -		pan = 10000; - -	//setSfxPan(param, pan); - -	if (pan != 0) -		addVgaEvent(10, NULL, _vgaCurSpriteId, _vgaCurZoneNum); /* pan event */ -	debug(0, "panEvent: param %d pan %d", param, pan); -} - -void SimonEngine::scrollEvent() { -	if (_scrollCount == 0) -		return; - -	if (getGameType() == GType_FF) { -		if (_scrollCount < 0) { -			if (_scrollFlag != -8) { -				_scrollFlag = -8; -				_scrollCount += 8; -			} -		} else { -			if (_scrollFlag != 8) { -				_scrollFlag = 8; -				_scrollCount -= 8; -			} -		} -	} else { -		if (_scrollCount < 0) { -			if (_scrollFlag != -1) { -				_scrollFlag = -1; -				if (++_scrollCount == 0) -					return; -			} -		} else { -			if (_scrollFlag != 1) { -				_scrollFlag = 1; -				if (--_scrollCount == 0) -					return; -			} -		} - -		addVgaEvent(6, NULL, 0, 0); /* scroll event */ -	} -} -  void SimonEngine::waitForSync(uint a) {  	const uint maxCount = (getGameType() == GType_SIMON1) ? 500 : 1000; @@ -2842,57 +2211,6 @@ void SimonEngine::timer_callback() {  	}  } -void SimonEngine::closeWindow(uint a) { -	if (_windowArray[a] == NULL) -		return; -	removeIconArray(a); -	resetWindow(_windowArray[a]); -	_windowArray[a] = NULL; -	if (_curWindow == a) { -		_textWindow = NULL; -		changeWindow(0); -	} -} - -void SimonEngine::changeWindow(uint a) { -	a &= 7; - -	if (_windowArray[a] == NULL || _curWindow == a) -		return; - -	_curWindow = a; -	showmessage_print_char(0); -	_textWindow = _windowArray[a]; - -	if (getGameType() == GType_FF) -		showmessage_helper_3(_textWindow->textColumn, _textWindow->width); -	else -		showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength); -} - -WindowBlock *SimonEngine::openWindow(uint x, uint y, uint w, uint h, uint flags, uint fill_color, uint text_color) { -	WindowBlock *window; - -	window = _windowList; -	while (window->mode != 0) -		window++; - -	window->mode = 2; -	window->x = x; -	window->y = y; -	window->width = w; -	window->height = h; -	window->flags = flags; -	window->fill_color = fill_color; -	window->text_color = text_color; -	window->textColumn = 0; -	window->textRow = 0; -	window->textColumnOffset = 0; -	window->textMaxLength = window->width * 8 / 6; // characters are 6 pixels -	window->scrollY = 0; -	return window; -} -  Item *SimonEngine::derefItem(uint item) {  	if (item >= _itemArraySize)  		error("derefItem: invalid item %d", item); @@ -2913,73 +2231,6 @@ void SimonEngine::delete_hitarea_by_index(uint index) {  	_hitAreas[index].flags = 0;  } -void SimonEngine::windowPutChar(uint a) { -	if (_textWindow != _windowArray[0]) -		windowPutChar(_textWindow, a); -} - -void SimonEngine::clearWindow(WindowBlock *window) { -	if (window->flags & 0x10) -		restoreWindow(window); -	else -		colorWindow(window); - -	window->textColumn = 0; -	window->textRow = 0; -	window->textColumnOffset = 0; -	window->textLength = 0; -	window->scrollY = 0; -} - -void SimonEngine::restoreWindow(WindowBlock *window) { -	_lockWord |= 0x8000; - -	if (getGameType() == GType_FF) { -		restoreBlock(window->y + window->height, window->x + window->width, window->y, window->x); -	} else if (getGameType() == GType_SIMON2) { -		if (_restoreWindow6 && _windowArray[2] == window) { -			window = _windowArray[6]; -			_restoreWindow6 = 0; -		} - -		restoreBlock(window->y + window->height * 8, (window->x + window->width) * 8, window->y, window->x * 8); -	} else { -		restoreBlock(window->y + window->height * 8 + ((window == _windowArray[2]) ? 1 : 0), (window->x + window->width) * 8, window->y, window->x * 8); -	} - -	_lockWord &= ~0x8000; -} - -void SimonEngine::colorWindow(WindowBlock *window) { -	byte *dst; -	uint h, w; - -	_lockWord |= 0x8000; - -	if (getGameType() == GType_FF) { -		dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x; - -		for (h = 0; h < window->height; h++) { -			for (w = 0; w < window->width; w++) { -				if (dst[w] == 113  || dst[w] == 116 || dst[w] == 252) -					dst[w] = window->fill_color; -			} -			dst += _screenWidth; -		} -	} else { -		dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x * 8; -		h = window->height * 8; -		w = window->width * 8; - -		do { -			memset(dst, window->fill_color, w); -			dst += _dxSurfacePitch; -		} while (--h); -	} - -	_lockWord &= ~0x8000; -} -  VgaSprite *SimonEngine::findCurSprite() {  	VgaSprite *vsp = _vgaSprites;  	while (vsp->id) { @@ -3167,12 +2418,6 @@ void SimonEngine::video_toggle_colors(HitArea * ha, byte a, byte b, byte c, byte  	_lockWord &= ~0x8000;  } -void SimonEngine::resetWindow(WindowBlock *window) { -	if (window->flags & 8) -		restoreWindow(window); -	window->mode = 0; -} -  void SimonEngine::loadSprite(uint windowNum, uint zoneNum, uint vgaSpriteId, uint x, uint y, uint palette) {  	VgaSprite *vsp;  	VgaPointersEntry *vpe; diff --git a/engines/simon/string.cpp b/engines/simon/string.cpp index ee709e88b2..ffda5629e8 100644 --- a/engines/simon/string.cpp +++ b/engines/simon/string.cpp @@ -25,8 +25,152 @@  #include "simon/simon.h"  #include "simon/intern.h" +using Common::File; +  namespace Simon { +const byte *SimonEngine::getStringPtrByID(uint stringId) { +	const byte *string_ptr; +	byte *dst; + +	_freeStringSlot ^= 1; + +	if (stringId < 0x8000) { +		string_ptr = _stringTabPtr[stringId]; +	} else { +		string_ptr = getLocalStringByID(stringId); +	} + +	dst = _stringReturnBuffer[_freeStringSlot]; +	strcpy((char *)dst, (const char *)string_ptr); +	return dst; +} + +const byte *SimonEngine::getLocalStringByID(uint stringId) { +	if (stringId < _stringIdLocalMin || stringId >= _stringIdLocalMax) { +		loadTextIntoMem(stringId); +	} +	return _localStringtable[stringId - _stringIdLocalMin]; +} + +void SimonEngine::allocateStringTable(int num) { +	_stringTabPtr = (byte **)calloc(num, sizeof(byte *)); +	_stringTabPos = 0; +	_stringtab_numalloc = num; +} + +void SimonEngine::setupStringTable(byte *mem, int num) { +	int i = 0; +	for (;;) { +		_stringTabPtr[i++] = mem; +		if (--num == 0) +			break; +		for (; *mem; mem++); +		mem++; +	} + +	_stringTabPos = i; +} + +void SimonEngine::setupLocalStringTable(byte *mem, int num) { +	int i = 0; +	for (;;) { +		_localStringtable[i++] = mem; +		if (--num == 0) +			break; +		for (; *mem; mem++); +		mem++; +	} +} + +uint SimonEngine::loadTextFile(const char *filename, byte *dst) { +	if (getFeatures() & GF_OLD_BUNDLE) +		return loadTextFile_simon1(filename, dst); +	else +		return loadTextFile_gme(filename, dst); +} + +uint SimonEngine::loadTextFile_simon1(const char *filename, byte *dst) { +	File fo; +	fo.open(filename); +	uint32 size; + +	if (fo.isOpen() == false) +		error("loadTextFile: Can't open '%s'", filename); + +	size = fo.size(); + +	if (fo.read(dst, size) != size) +		error("loadTextFile: fread failed"); +	fo.close(); + +	return size; +} + +uint SimonEngine::loadTextFile_gme(const char *filename, byte *dst) { +	uint res; +	uint32 offs; +	uint32 size; + +	res = atoi(filename + 4) + TEXT_INDEX_BASE - 1; +	offs = _gameOffsetsPtr[res]; +	size = _gameOffsetsPtr[res + 1] - offs; + +	readGameFile(dst, offs, size); + +	return size; +} + +void SimonEngine::loadTextIntoMem(uint stringId) { +	byte *p; +	char filename[30]; +	int i; +	uint base_min = 0x8000, base_max, size; + +	_tablesHeapPtr = _tablesheapPtrNew; +	_tablesHeapCurPos = _tablesHeapCurPosNew; + +	p = _strippedTxtMem; + +	// get filename +	while (*p) { +		for (i = 0; *p; p++, i++) +			filename[i] = *p; +		filename[i] = 0; +		p++; + +		base_max = (p[0] * 256) | p[1]; +		p += 2; + +		if (stringId < base_max) { +			_stringIdLocalMin = base_min; +			_stringIdLocalMax = base_max; + +			_localStringtable = (byte **)_tablesHeapPtr; + +			size = (base_max - base_min + 1) * sizeof(byte *); +			_tablesHeapPtr += size; +			_tablesHeapCurPos += size; + +			size = loadTextFile(filename, _tablesHeapPtr); + +			setupLocalStringTable(_tablesHeapPtr, base_max - base_min + 1); + +			_tablesHeapPtr += size; +			_tablesHeapCurPos += size; + +			if (_tablesHeapCurPos > _tablesHeapSize) { +				error("loadTextIntoMem: Out of table memory"); +			} +			return; +		} + +		base_min = base_max; +	} + +	error("loadTextIntoMem: didn't find %d", stringId); +} +  static const byte charWidth[226] = {  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/engines/simon/subroutine.cpp b/engines/simon/subroutine.cpp new file mode 100644 index 0000000000..e700182899 --- /dev/null +++ b/engines/simon/subroutine.cpp @@ -0,0 +1,319 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2006 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" + +#include "simon/simon.h" +#include "simon/intern.h" + +using Common::File; + +namespace Simon { + +Subroutine *SimonEngine::getSubroutineByID(uint subroutine_id) { +	Subroutine *cur; + +	_subroutine = subroutine_id; + +	for (cur = _subroutineList; cur; cur = cur->next) { +		if (cur->id == subroutine_id) +			return cur; +	} + +	loadTablesIntoMem(subroutine_id); + +	for (cur = _subroutineList; cur; cur = cur->next) { +		if (cur->id == subroutine_id) +			return cur; +	} + +	if (subroutine_id != 160) +		debug(0,"getSubroutineByID: subroutine %d not found", subroutine_id); +	return NULL; +} + +void SimonEngine::alignTableMem() { +	if ((unsigned long)_tablesHeapPtr & 3) { +		_tablesHeapPtr += 2; +		_tablesHeapCurPos += 2; +	} +} + +byte *SimonEngine::allocateTable(uint size) { +	byte *org = _tablesHeapPtr; + +	size = (size + 1) & ~1; + +	_tablesHeapPtr += size; +	_tablesHeapCurPos += size; + +	if (_tablesHeapCurPos > _tablesHeapSize) +		error("Tablesheap overflow"); + +	return org; +} + +File *SimonEngine::openTablesFile(const char *filename) { +	if (getFeatures() & GF_OLD_BUNDLE) +		return openTablesFile_simon1(filename); +	else +		return openTablesFile_gme(filename); +} + +File *SimonEngine::openTablesFile_simon1(const char *filename) { +	File *fo = new File(); +	fo->open(filename); +	if (fo->isOpen() == false) +		error("openTablesFile: Can't open '%s'", filename); +	return fo; +} + +File *SimonEngine::openTablesFile_gme(const char *filename) { +	uint res; +	uint32 offs; + +	res = atoi(filename + 6) + TABLE_INDEX_BASE - 1; +	offs = _gameOffsetsPtr[res]; + +	_gameFile->seek(offs, SEEK_SET); +	return _gameFile; +} + +void SimonEngine::loadTablesIntoMem(uint subr_id) { +	byte *p; +	int i; +	uint min_num, max_num; +	char filename[30]; +	File *in; + +	p = _tblList; +	if (p == NULL) +		return; + +	while (*p) { +		for (i = 0; *p; p++, i++) +			filename[i] = *p; +		filename[i] = 0; +		p++; + +		for (;;) { +			min_num = (p[0] * 256) | p[1]; +			p += 2; + +			if (min_num == 0) +				break; + +			max_num = (p[0] * 256) | p[1]; +			p += 2; + +			if (subr_id >= min_num && subr_id <= max_num) { +				_subroutineList = _subroutineListOrg; +				_tablesHeapPtr = _tablesHeapPtrOrg; +				_tablesHeapCurPos = _tablesHeapCurPosOrg; +				_stringIdLocalMin = 1; +				_stringIdLocalMax = 0; + +				in = openTablesFile(filename); +				readSubroutineBlock(in); +				closeTablesFile(in); +				if (getGameType() == GType_FF) { +					// TODO +				} else if (getGameType() == GType_SIMON2) { +					_sound->loadSfxTable(_gameFile, _gameOffsetsPtr[atoi(filename + 6) - 1 + SOUND_INDEX_BASE]); +				} else if (getPlatform() == Common::kPlatformWindows) { +					memcpy(filename, "SFXXXX", 6); +					_sound->readSfxFile(filename); +				} + +				alignTableMem(); + +				_tablesheapPtrNew = _tablesHeapPtr; +				_tablesHeapCurPosNew = _tablesHeapCurPos; + +				if (_tablesHeapCurPos > _tablesHeapSize) +					error("loadTablesIntoMem: Out of table memory"); +				return; +			} +		} +	} + +	debug(1,"loadTablesIntoMem: didn't find %d", subr_id); +} + +void SimonEngine::closeTablesFile(File *in) { +	if (getFeatures() & GF_OLD_BUNDLE) { +		in->close(); +		delete in; +	} +} + +Subroutine *SimonEngine::createSubroutine(uint id) { +	Subroutine *sub; + +	alignTableMem(); + +	sub = (Subroutine *)allocateTable(sizeof(Subroutine)); +	sub->id = id; +	sub->first = 0; +	sub->next = _subroutineList; +	_subroutineList = sub; +	return sub; +} + +SubroutineLine *SimonEngine::createSubroutineLine(Subroutine *sub, int where) { +	SubroutineLine *sl, *cur_sl = NULL, *last_sl = NULL; + +	if (sub->id == 0) +		sl = (SubroutineLine *)allocateTable(SUBROUTINE_LINE_BIG_SIZE); +	else +		sl = (SubroutineLine *)allocateTable(SUBROUTINE_LINE_SMALL_SIZE); + +	// where is what offset to insert the line at, locate the proper beginning line +	if (sub->first != 0) { +		cur_sl = (SubroutineLine *)((byte *)sub + sub->first); +		while (where) { +			last_sl = cur_sl; +			cur_sl = (SubroutineLine *)((byte *)sub + cur_sl->next); +			if ((byte *)cur_sl == (byte *)sub) +				break; +			where--; +		} +	} + +	if (last_sl != NULL) { +		// Insert the subroutine line in the middle of the link +		last_sl->next = (byte *)sl - (byte *)sub; +		sl->next = (byte *)cur_sl - (byte *)sub; +	} else { +		// Insert the subroutine line at the head of the link +		sl->next = sub->first; +		sub->first = (byte *)sl - (byte *)sub; +	} + +	return sl; +} + +int SimonEngine::startSubroutine(Subroutine *sub) { +	int result = -1; +	SubroutineLine *sl; +	const byte *old_code_ptr; + +	if (_startMainScript) +		dumpSubroutine(sub); + +	old_code_ptr = _codePtr; + +	if (++_recursionDepth > 40) +		error("Recursion error"); + +	sl = (SubroutineLine *)((byte *)sub + sub->first); + +	while ((byte *)sl != (byte *)sub) { +		if (checkIfToRunSubroutineLine(sl, sub)) { +			result = 0; +			_codePtr = (byte *)sl; +			if (sub->id) +				_codePtr += 2; +			else +				_codePtr += 8; + +			if (_continousMainScript) +				fprintf(_dumpFile, "; %d\n", sub->id); +			result = runScript(); +			if (result != 0) { +				/* result -10 means restart subroutine */ +				if (result == -10) { +					delay(0);							/* maybe leave control to the VGA */ +					sl = (SubroutineLine *)((byte *)sub + sub->first); +					continue; +				} +				break; +			} +		} +		sl = (SubroutineLine *)((byte *)sub + sl->next); +	} + +	_codePtr = old_code_ptr; + +	_recursionDepth--; +	return result; +} + +int SimonEngine::startSubroutineEx(Subroutine *sub) { +	return startSubroutine(sub); +} + +bool SimonEngine::checkIfToRunSubroutineLine(SubroutineLine *sl, Subroutine *sub) { +	if (sub->id) +		return true; + +	if (sl->verb != -1 && sl->verb != _scriptVerb && +			(sl->verb != -2 || _scriptVerb != -1)) +		return false; + +	if (sl->noun1 != -1 && sl->noun1 != _scriptNoun1 && +			(sl->noun1 != -2 || _scriptNoun1 != -1)) +		return false; + +	if (sl->noun2 != -1 && sl->noun2 != _scriptNoun2 && +			(sl->noun2 != -2 || _scriptNoun2 != -1)) +		return false; + +	return true; +} + +void SimonEngine::readSubroutine(File *in, Subroutine *sub) { +	while (in->readUint16BE() == 0) { +		readSubroutineLine(in, createSubroutineLine(sub, 0xFFFF), sub); +	} +} + +void SimonEngine::readSubroutineLine(File *in, SubroutineLine *sl, Subroutine *sub) { +	byte line_buffer[1024], *q = line_buffer; +	int size; + +	if (sub->id == 0) { +		sl->verb = in->readUint16BE(); +		sl->noun1 = in->readUint16BE(); +		sl->noun2 = in->readUint16BE(); +	} + +	while ((*q = in->readByte()) != 0xFF) { +		if (*q == 87) { +			in->readUint16BE(); +		} else { +			q = readSingleOpcode(in, q); +		} +	} + +	size = q - line_buffer + 1; + +	memcpy(allocateTable(size), line_buffer, size); +} + +void SimonEngine::readSubroutineBlock(File *in) { +	while (in->readUint16BE() == 0) { +		readSubroutine(in, createSubroutine(in->readUint16BE())); +	} +} + +} // End of namespace Simon diff --git a/engines/simon/window.cpp b/engines/simon/window.cpp new file mode 100644 index 0000000000..ce4f989a6e --- /dev/null +++ b/engines/simon/window.cpp @@ -0,0 +1,165 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2006 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. + * + * $URL: https://svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/simon/string.cpp $ + * $Id: string.cpp 22062 2006-04-21 00:18:23Z kirben $ + * + */ + +#include "common/stdafx.h" + +#include "simon/simon.h" +#include "simon/intern.h" + +namespace Simon { + +uint SimonEngine::getWindowNum(WindowBlock *window) { +	uint i; + +	for (i = 0; i != ARRAYSIZE(_windowArray); i++) +		if (_windowArray[i] == window) +			return i; + +	error("getWindowNum: not found"); +	return 0; +} + +WindowBlock *SimonEngine::openWindow(uint x, uint y, uint w, uint h, uint flags, uint fill_color, uint text_color) { +	WindowBlock *window; + +	window = _windowList; +	while (window->mode != 0) +		window++; + +	window->mode = 2; +	window->x = x; +	window->y = y; +	window->width = w; +	window->height = h; +	window->flags = flags; +	window->fill_color = fill_color; +	window->text_color = text_color; +	window->textColumn = 0; +	window->textRow = 0; +	window->textColumnOffset = 0; +	window->textMaxLength = window->width * 8 / 6; // characters are 6 pixels +	window->scrollY = 0; +	return window; +} + +void SimonEngine::changeWindow(uint a) { +	a &= 7; + +	if (_windowArray[a] == NULL || _curWindow == a) +		return; + +	_curWindow = a; +	showmessage_print_char(0); +	_textWindow = _windowArray[a]; + +	if (getGameType() == GType_FF) +		showmessage_helper_3(_textWindow->textColumn, _textWindow->width); +	else +		showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength); +} + +void SimonEngine::closeWindow(uint a) { +	if (_windowArray[a] == NULL) +		return; +	removeIconArray(a); +	resetWindow(_windowArray[a]); +	_windowArray[a] = NULL; +	if (_curWindow == a) { +		_textWindow = NULL; +		changeWindow(0); +	} +} + +void SimonEngine::clearWindow(WindowBlock *window) { +	if (window->flags & 0x10) +		restoreWindow(window); +	else +		colorWindow(window); + +	window->textColumn = 0; +	window->textRow = 0; +	window->textColumnOffset = 0; +	window->textLength = 0; +	window->scrollY = 0; +} + +void SimonEngine::colorWindow(WindowBlock *window) { +	byte *dst; +	uint h, w; + +	_lockWord |= 0x8000; + +	if (getGameType() == GType_FF) { +		dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x; + +		for (h = 0; h < window->height; h++) { +			for (w = 0; w < window->width; w++) { +				if (dst[w] == 113  || dst[w] == 116 || dst[w] == 252) +					dst[w] = window->fill_color; +			} +			dst += _screenWidth; +		} +	} else { +		dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x * 8; +		h = window->height * 8; +		w = window->width * 8; + +		do { +			memset(dst, window->fill_color, w); +			dst += _dxSurfacePitch; +		} while (--h); +	} + +	_lockWord &= ~0x8000; +} + +void SimonEngine::resetWindow(WindowBlock *window) { +	if (window->flags & 8) +		restoreWindow(window); +	window->mode = 0; +} + +void SimonEngine::restoreWindow(WindowBlock *window) { +	_lockWord |= 0x8000; + +	if (getGameType() == GType_FF) { +		restoreBlock(window->y + window->height, window->x + window->width, window->y, window->x); +	} else if (getGameType() == GType_SIMON2) { +		if (_restoreWindow6 && _windowArray[2] == window) { +			window = _windowArray[6]; +			_restoreWindow6 = 0; +		} + +		restoreBlock(window->y + window->height * 8, (window->x + window->width) * 8, window->y, window->x * 8); +	} else { +		restoreBlock(window->y + window->height * 8 + ((window == _windowArray[2]) ? 1 : 0), (window->x + window->width) * 8, window->y, window->x * 8); +	} + +	_lockWord &= ~0x8000; +} + +void SimonEngine::windowPutChar(uint a) { +	if (_textWindow != _windowArray[0]) +		windowPutChar(_textWindow, a); +} + +} // End of namespace Simon | 
