[Scummvm-cvs-logs] SF.net SVN: scummvm: [28800] scummvm/trunk/engines/agi

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Sat Sep 1 20:46:55 CEST 2007


Revision: 28800
          http://scummvm.svn.sourceforge.net/scummvm/?rev=28800&view=rev
Author:   thebluegr
Date:     2007-09-01 11:46:55 -0700 (Sat, 01 Sep 2007)

Log Message:
-----------
Added WIP logic code for Mickey's Space Adventure

Modified Paths:
--------------
    scummvm/trunk/engines/agi/agi.h
    scummvm/trunk/engines/agi/preagi_mickey.cpp

Modified: scummvm/trunk/engines/agi/agi.h
===================================================================
--- scummvm/trunk/engines/agi/agi.h	2007-09-01 17:54:41 UTC (rev 28799)
+++ scummvm/trunk/engines/agi/agi.h	2007-09-01 18:46:55 UTC (rev 28800)
@@ -995,23 +995,11 @@
 		int16 p4, int16 p5, int16 p6, int16 p7) {}
 	void releaseImageStack() {}
 
-/*
-	int agiInit();
-	int agiDeinit();
-	int agiVersion();
-	int agiGetRelease();
-	void agiSetRelease(int);
-	int agiDetectGame();
-	int agiLoadResource(int, int);
-	int agiUnloadResource(int, int);
-	void agiUnloadResources();
-*/
-
 	// Keyboard, preagi
 	void waitAnyKeyAnim();
 	int getSelection(int type);
 	bool waitAnyKeyChoice();
-	void waitAnyKey(bool anim);
+	void waitAnyKey(bool anim = false);
 
 };
 

Modified: scummvm/trunk/engines/agi/preagi_mickey.cpp
===================================================================
--- scummvm/trunk/engines/agi/preagi_mickey.cpp	2007-09-01 17:54:41 UTC (rev 28799)
+++ scummvm/trunk/engines/agi/preagi_mickey.cpp	2007-09-01 18:46:55 UTC (rev 28800)
@@ -23,73 +23,781 @@
  *
  */
 
+#include "common/stdafx.h"
+#include "common/events.h"
+
 #include "agi/preagi_mickey.h"
 #include "agi/graphics.h"
 
+// default attributes
+#define IDA_DEFAULT		0x0F
+#define IDA_DEFAULT_REV	0xF0
+
 namespace Agi {
 
-Mickey::Mickey(PreAgiEngine *vm) : _vm(vm) {
+int Mickey::getDat(int iRoom) {
+	if (((iRoom > 0) && (iRoom < 24)) || iRoom == 154 || iRoom == 155) return IDI_MSA_PLANET_EARTH;
+	if ((iRoom >= 30) && (iRoom <= 39)) return IDI_MSA_PLANET_VENUS;
+	if ((iRoom >= 40) && (iRoom <= 69)) return IDI_MSA_PLANET_NEPTUNE;
+	if ((iRoom >= 70) && (iRoom <= 82)) return IDI_MSA_PLANET_MERCURY;
+	if ((iRoom >= 83) && (iRoom <= 92)) return IDI_MSA_PLANET_SATURN;
+	if ((iRoom >= 93) && (iRoom <= 103)) return IDI_MSA_PLANET_PLUTO;
+	if ((iRoom >= 106) && (iRoom <= 120)) return IDI_MSA_PLANET_JUPITER;
+	if ((iRoom >= 121) && (iRoom <= 132)) return IDI_MSA_PLANET_MARS;
+	if ((iRoom >= 133) && (iRoom <= 145)) return IDI_MSA_PLANET_URANUS;
+	return IDI_MSA_PLANET_SPACESHIP;
 }
 
-Mickey::~Mickey() {
+void Mickey::readExe(int ofs, uint8 *buffer, long buflen) {
+	Common::File infile;
+	if (!infile.open(IDS_MSA_PATH_EXE))
+		return;
+	infile.seek(ofs, SEEK_SET);
+	infile.read(buffer, buflen);
+	infile.close();
 }
 
-void Mickey::init() {
+void Mickey::getDatFileName(int iRoom, char *szFile) {
+	sprintf(szFile, IDS_MSA_PATH_DAT, IDS_MSA_NAME_DAT[getDat(iRoom)]);
 }
 
-void Mickey::run() {
-	intro();
-	while(true) {
-		_vm->getSelection(0);
-		_vm->_system->delayMillis(10);
+void Mickey::readDatHdr(char *szFile, MSA_DAT_HEADER *hdr) {
+	Common::File infile;
+
+	if (!infile.open(szFile))
+		return;
+
+	hdr->filelen = infile.readByte();
+	hdr->filelen += infile.readByte() * 0x100;
+	for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
+		hdr->ofsRoom[i] = infile.readByte();
+		hdr->ofsRoom[i] += infile.readByte() * 0x100;
 	}
-	//gameLoop();
-	//gameOver();
+	for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
+		hdr->ofsDesc[i] = infile.readByte();
+		hdr->ofsDesc[i] += infile.readByte() * 0x100;
+	}
+	for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
+		hdr->ofsStr[i] = infile.readByte();
+		hdr->ofsStr[i] += infile.readByte() * 0x100;
+	}
+
+	infile.close();
 }
 
-void Mickey::intro() {
-	// draw sierra logo
-	drawLogo();
+void Mickey::readDesc(int iRoom, char *buffer, long buflen) {
+	MSA_DAT_HEADER hdr;
+	char szFile[256] = {0};
 	
-	// draw title picture
-	game.iRoom = IDI_MSA_PIC_TITLE;
-	drawRoom();
+	getDatFileName(iRoom, szFile);
+	readDatHdr(szFile, &hdr);
+	
+	Common::File infile;
 
-#if 0
-	// show copyright and play theme
-	PrintExeMsg(IDO_MSA_COPYRIGHT);
-	PlaySound(IDI_MSA_SND_THEME);
-		
-	// load game
-	game.fIntro = true;
-	if (ChooseY_N(IDO_MSA_LOAD_GAME[0], true)) {
-		if (LoadGame()) {
-			game.iPlanet = IDI_MSA_PLANET_EARTH;
-			game.fIntro = false;
-			game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
+	if (!infile.open(szFile))
+		return;
+
+	memset(buffer, 0, buflen);
+
+	infile.seek(hdr.ofsDesc[iRoom - 1] + IDI_MSA_OFS_DAT, SEEK_SET);
+	infile.read(buffer, buflen);
+	infile.close();
+}
+
+void Mickey::readMenu(int iRoom, char *buffer) {
+	MSA_DAT_HEADER hdr;
+	char szFile[256] = {0};
+
+	getDatFileName(iRoom, szFile);
+	readDatHdr(szFile, &hdr);
+	
+	Common::File infile;
+
+	if (!infile.open(szFile))
+		return;
+
+	infile.seek(hdr.ofsRoom[iRoom - 1] + IDI_MSA_OFS_DAT, SEEK_SET);
+	infile.read((uint8 *)buffer, sizeof(MSA_MENU));
+	infile.close();
+}
+
+void Mickey::readDatStr(int iDat, int iStr, char *buffer, long buflen) {
+	MSA_DAT_HEADER hdr;
+	char szFile[256] = {0};
+	
+	sprintf(szFile, IDS_MSA_PATH_DAT, IDS_MSA_NAME_DAT[iDat]);
+	readDatHdr(szFile, &hdr);
+
+	Common::File infile;
+
+	if (!infile.open(szFile))
+		return;
+
+	infile.seek(hdr.ofsStr[iStr] + IDI_MSA_OFS_DAT, SEEK_SET);
+	infile.read((uint8 *)buffer, buflen);
+	infile.close();
+}
+
+void Mickey::readOfsData(int offset, int iItem, uint8 *buffer, long buflen) {
+	uint16 ofs[256];
+
+	readExe(offset, buffer, buflen);
+//	memcpy(ofs, buffer, sizeof(ofs));
+	for (int i = 0; i < 256; i++)
+		ofs[i] = buffer[i*2] + 256 * buffer[i*2+1];
+	readExe(ofs[iItem] + IDI_MSA_OFS_EXE, buffer, buflen);
+}
+
+// User Interface
+
+bool Mickey::chooseY_N(int ofsPrompt, bool fErrorMsg) {
+	printExeStr(ofsPrompt);
+
+	int a = _vm->getSelection(0);
+	for (;;) {
+		switch (a) {
+			case 0: return false;
+			case 1: return true;
+			default: if (fErrorMsg) {
+						printExeStr(IDO_MSA_PRESS_YES_OR_NO);
+						_vm->waitAnyKey();
+						printExeStr(ofsPrompt);
+					}
+					break;
+		}
+		a = _vm->getSelection(0);
+	}
+}
+
+int Mickey::choose1to9(int ofsPrompt) {
+	printExeStr(ofsPrompt);
+
+	int a = _vm->getSelection(1);
+	for (;;) {
+		if (a == 10) {
+			printExeStr(IDO_MSA_PRESS_1_TO_9);
+			if (!_vm->waitAnyKeyChoice())
+				return 0;
+			printExeStr(ofsPrompt);
+		} else return a;
+		a = _vm->getSelection(1);
+	}
+
+}
+
+void Mickey::printStr(char *buffer) {
+	int pc = 1;
+	int nRows, iCol, iRow;
+	
+	nRows = *buffer + IDI_MSA_ROW_MENU_0;
+
+	//clearTextArea();	// TODO
+
+	for (iRow = IDI_MSA_ROW_MENU_0; iRow < nRows; iRow++) {
+		iCol = *(buffer + pc++);
+		// drawStr(iRow, iCol, buffer + pc);	// TODO
+		pc += strlen(buffer + pc) + 1;
+	}
+}
+
+void Mickey::printExeStr(int ofs) {
+	uint8 buffer[256] = {0};
+
+	if (!ofs)
+		return;
+
+	readExe(ofs, buffer, sizeof(buffer));
+	printStr((char *)buffer);
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+
+}
+
+void Mickey::printExeMsg(int ofs) {
+	if (!ofs)
+		return;
+	printExeStr(ofs);
+	_vm->waitAnyKeyAnim();
+}
+
+void Mickey::printDatStr(int iDat, int iStr) {
+	char *buffer = (char *)malloc(256);
+	readDatStr(iDat, iStr, buffer, 256);
+	printStr(buffer);
+	free(buffer);
+}
+
+void Mickey::printDesc(int iRoom) {
+	char *buffer = (char *)malloc(256);
+	readDesc(iRoom, buffer, 256);
+	printStr(buffer);
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+	free(buffer);
+}
+
+void Mickey::drawMenu(MSA_MENU menu, int sel0, int sel1) {
+	int iWord;
+	int iRow;
+	int sel;
+	uint8 attr;
+
+	// draw menu
+
+	// clearTextArea();	// TODO
+
+	for (iRow = 0; iRow < 2; iRow++) {
+		for (iWord = 0; iWord < menu.row[iRow].count; iWord++) {
+			if (iRow)
+				sel = sel1; 
+			else 
+				sel = sel0;
+
+			if (iWord == sel) 
+				attr = IDA_DEFAULT_REV; 
+			else 
+				attr = IDA_DEFAULT;
+
+			// TODO
+			//drawStrAttr(IDI_MSA_ROW_MENU_0 + iRow, menu.row[iRow].entry[iWord].x0, 
+			//	attr, (char *)menu.row[iRow].entry[iWord].szText);
+		}
+	}
+
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+}
+
+void Mickey::getMouseMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow, int x, int y) {
+	int iWord;
+	int *sel = 0;
+
+	switch(iRow) {
+	case 0:
+		if (y != IDI_MSA_ROW_MENU_0) return;
+		sel = sel0;
+		break;
+	case 1:
+		if (y != IDI_MSA_ROW_MENU_1) return;
+		sel = sel1;
+		break;
+	}
+
+	for (iWord = 0; iWord < menu.row[iRow].count; iWord++) {
+		if ((x >= menu.row[iRow].entry[iWord].x0) && 
+			(x < (int)(menu.row[iRow].entry[iWord].x0 + 
+			strlen((char *)menu.row[iRow].entry[iWord].szText)))) {
+				*sel = iWord;
+				break;
+		}
+	}
+}
+
+bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
+	Common::Event event;
+	int *sel = 0;
+	int nWords;
+	int x, y;
+
+	switch(iRow) {
+	case 0:
+		sel = sel0;
+		break;
+	case 1:
+		sel = sel1;
+		break;
+	}
+	nWords = menu.row[iRow].count;
+
+	drawMenu(menu, *sel0, *sel1);
+
+	for (;;) {
+		while (_vm->_system->getEventManager()->pollEvent(event)) {
+			switch(event.type) {
+			case Common::EVENT_QUIT:
+				exit(0);
+			case Common::EVENT_MOUSEMOVE:
+				if (iRow < 2) {
+					// TODO
+					x = y = 0;	// TODO: remove this
+					//x = event.mouse.x / getFontWidth();
+					//y = event.mouse.y / getFontHeight();
+					getMouseMenuSelRow(menu, sel0, sel1, iRow, x, y);
+					drawMenu(menu, *sel0, *sel1);
+				}
+				break;
+			case Common::EVENT_LBUTTONUP:
+				return true;
+			//FIXME: ScummVM does not support middle button
+			/*case Common::EVENT_MBUTTONUP:
+				inventory();
+				drawRoom();
+				*sel0 = 0; *sel1 = -1;
+				return false;*/
+			case Common::EVENT_RBUTTONUP:
+				*sel0 = 0; *sel1 = -1; 
+				return false;
+			case Common::EVENT_WHEELUP:
+				if (iRow < 2) {
+					*sel -= 1;
+					if (*sel < 0) *sel = nWords - 1;
+					drawMenu(menu, *sel0, *sel1);
+				}
+				break;
+			case Common::EVENT_WHEELDOWN:
+				if (iRow < 2) {
+					*sel += 1;
+					if (*sel == nWords) *sel = 0;
+					drawMenu(menu, *sel0, *sel1);
+				}
+				break;
+			case Common::EVENT_KEYDOWN:
+				switch (event.kbd.keycode) {
+				case Common::KEYCODE_F11:
+					//flipCGA();	// TODO
+					drawRoom();
+					drawMenu(menu, *sel0, *sel1);
+					break;
+				case Common::KEYCODE_F12:
+					//flipDblSize();	// TODO
+					drawRoom();
+					drawMenu(menu, *sel0, *sel1);
+					break;
+				case Common::KEYCODE_2:
+					hidden();
+					break;
+				case Common::KEYCODE_8:
+					if (event.kbd.flags & Common::KBD_CTRL) {
+						*sel0 = 0; *sel1 = -1; return false;
+					}
+					break;
+				case Common::KEYCODE_ESCAPE:
+					*sel0 = 0; *sel1 = -1; return false;
+				case Common::KEYCODE_s:
+					//flipSound();	// TODO
+					break;
+				case Common::KEYCODE_c:
+					inventory();
+					drawRoom();
+					*sel0 = 0; *sel1 = -1; return false;
+				case Common::KEYCODE_b:
+					printRoomDesc();
+					drawMenu(menu, *sel0, *sel1);
+					*sel0 = 0; *sel1 = -1; return false;
+				case Common::KEYCODE_LEFT:
+				case Common::KEYCODE_KP4:
+				case Common::KEYCODE_4:
+					if (iRow < 2) {
+						*sel -= 1;
+						if (*sel < 0) *sel = nWords - 1;
+						drawMenu(menu, *sel0, *sel1);
+					}
+					break;
+				case Common::KEYCODE_RIGHT:
+				case Common::KEYCODE_SPACE:
+				case Common::KEYCODE_KP6:
+				case Common::KEYCODE_6:
+					if (iRow < 2) {
+						*sel += 1;
+						if (*sel == nWords) *sel = 0;
+						drawMenu(menu, *sel0, *sel1);
+					}
+					break;
+				case Common::KEYCODE_RETURN:
+				//FIXME:
+				//case SDLK_KP_ENTER:
+					return true;
+				default:
+					break;
+				}
+				break;
+			}
+			animate();
+			drawMenu(menu, *sel0, *sel1);
+		}
+		animate();
+		drawMenu(menu, *sel0, *sel1);
+	}
+}
+
+void Mickey::getMenuSel(char *buffer, int *sel0, int *sel1) {
+	MSA_MENU menu;
+
+	memcpy(&menu, buffer, sizeof(MSA_MENU));
+
+	*sel0 = 0;
+	*sel1 = -1;
+
+	for (;;) {
+		for (;;) {
+			if (getMenuSelRow(menu, sel0, sel1, 0)) {
+				*sel1 = 0;
+				if (getMenuSelRow(menu, sel0, sel1, 1)) {
+					break;
+				}
+			}
+		}
+		if (getMenuSelRow(menu, sel0, sel1, 2)) {
+			break;
+		}
+	}
+}
+
+void Mickey::centerMenu(MSA_MENU *menu) {
+	int iWord;
+	int iRow;
+	int w, x;
+
+	for (iRow = 0; iRow < 2; iRow++) {
+		w = 0;
+		for (iWord = 0; iWord < menu->row[iRow].count; iWord++) {
+			w += strlen((char *)menu->row[iRow].entry[iWord].szText);
+		}
+		w += menu->row[iRow].count - 1;
+		x = (40 - w) / 2;	// FIX
+		for (iWord = 0; iWord < menu->row[iRow].count; iWord++) {
+			menu->row[iRow].entry[iWord].x0 = x;
+			x += strlen((char *)menu->row[iRow].entry[iWord].szText) + 1;
+		}
+	}
+}
+
+void Mickey::patchMenu(MSA_MENU *menu) {
+	uint8 buffer[512];
+	uint8 menubuf[sizeof(MSA_MENU)];
+	int nPatches;
+	int pBuf = 0;
+
+	// change planet name in ship airlock menu
+	if (game.iRoom == IDI_MSA_PIC_SHIP_AIRLOCK) {
+		strcpy((char *)menu->row[1].entry[2].szText, IDS_MSA_NAME_PLANET[game.iPlanet]);
+	}
+
+	// exit if fix unnecessary
+	if (!game.iRmMenu[game.iRoom]) {
+		centerMenu(menu);
+		return;
+	}
+
+	// copy menu to menubuf
+	memcpy(menubuf, menu, sizeof(menubuf));
+
+	// read patches
+	readOfsData(
+		IDOFS_MSA_MENU_PATCHES, 
+		game.nRmMenu[game.iRoom] + game.iRmMenu[game.iRoom] - 1,
+		buffer, sizeof(buffer)
+	);
+
+	// get number of patches
+	nPatches = buffer[pBuf++];
+
+	// patch menubuf
+	for (int iPatch = 0; iPatch < nPatches; iPatch++) {
+		if (buffer[pBuf] > sizeof(menubuf)) {
+			// patch address out of bounds
+		}
+		menubuf[buffer[pBuf]] = buffer[pBuf + 1];
+		pBuf += 2;
+	}
+
+	// copy menubuf back to menu
+	memcpy(menu, menubuf, sizeof(MSA_MENU));
+
+	// center menu
+	centerMenu(menu);
+}
+
+void Mickey::printDatString(int iStr) {
+	printDatStr(getDat(game.iRoom), iStr);
+}
+
+void Mickey::printDatMessage(int iStr) {
+	printDatString(iStr);
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+	_vm->waitAnyKeyAnim();
+}
+
+// Sound
+
+// TODO
+/*
+void Mickey::_PlayNote(MSA_SND_NOTE note) {
+	if (!note.counter)
+		playNote(1, 0, note.length / IDI_SND_TIMER_RESOLUTION);
+	else
+		playNote(1, IDI_SND_OSCILLATOR_FREQUENCY / note.counter, 
+			note.length / IDI_SND_TIMER_RESOLUTION / IDI_SND_PITCH);
+}
+
+void Mickey::PlaySound(ENUM_MSA_SOUND iSound) {
+	if (!GetSound())
+		return;
+
+	SDL_Event event;
+	MSA_SND_NOTE note;
+	uint8 *buffer = new uint8[1024];
+	int pBuf = 1;
+
+	switch(iSound) {
+	case IDI_MSA_SND_XL30:
+		for (int iNote = 0; iNote < 6; iNote++) {
+			note.counter = _vm->Rnd(59600) + 59;
+			note.length = 4;
+			_PlayNote(note);
+		}
+		break;
+	default:
+		readOfsData(IDOFS_MSA_SOUND_DATA, iSound, buffer, 1024);
+
+		for (;;) {
+			memcpy(&note, buffer + pBuf, sizeof(note));
+			if (!note.counter && !note.length)
+				break;
+			_PlayNote(note);
+			pBuf += 3;
+
+			if (iSound == IDI_MSA_SND_THEME) {
+				while (SDL_PollEvent(&event)) {
+					switch(event.type) {
+					case SDL_QUIT:
+						exit(0);
+					case SDL_MOUSEBUTTONUP:
+					case SDL_KEYDOWN:
+						delete [] buffer;
+						return;
+					}
+				}
+			}
+		}
+
+		break;
+	}
+
+	delete [] buffer;
+}
+*/
+
+void Mickey::debug() {
+	char szLine[41] = {0};
+
+	//ClearScreen(IDA_DEFAULT);	// TODO
+
+	sprintf(szLine, IDS_MSA_DEBUG_ROOM, game.iRoom);
+	//drawStr(5, 10, szLine);	// TODO
+
+	if (game.iRoom < IDI_MSA_MAX_PIC_ROOM) {
+		if (game.iRmObj[game.iRoom] != IDI_MSA_OBJECT_NONE) {
+			sprintf(szLine, IDS_MSA_DEBUG_OBJ, game.iRmObj[game.iRoom]);
+			//drawStr(7, 10, szLine); // TODO
+		}
+	} else {
+		sprintf(szLine, IDS_MSA_DEBUG_OBJ, 32);
+		//drawStr(7, 10, szLine); // TODO
+	}
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+}
+
+// Graphics
+
+void Mickey::drawObj(ENUM_MSA_OBJECT iObj, int x0, int y0) {
+	uint8 *buffer = new uint8[4096];
+	char szFile[255] = {0};
+
+	sprintf(szFile, IDS_MSA_PATH_OBJ, IDS_MSA_NAME_OBJ[iObj]);
+
+	Common::File infile;
+
+	if(!infile.open(szFile))
+		return;
+	
+	
+	infile.read(buffer, infile.size());
+
+	// TODO
+	/*
+	if (iObj == IDI_MSA_OBJECT_CRYSTAL) {
+		AGI_DrawPic(IDI_MSA_PIC_X0 + x0, IDI_MSA_PIC_Y0 + y0, IDF_AGI_PIC_V2 | IDF_AGI_STEP, buffer);
+	} else {
+		AGI_DrawPic(IDI_MSA_PIC_X0 + x0, IDI_MSA_PIC_Y0 + y0, IDF_AGI_PIC_V2, buffer);
+	}
+	*/
+
+	infile.close();
+	delete [] buffer;
+}
+
+void Mickey::drawPic(int iPic) {
+	_vm->preAgiLoadResource(rPICTURE, iPic);
+	_vm->_picture->decodePicture(iPic, true);
+	_vm->_picture->showPic();
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+/*
+	int w = IDI_MSA_PIC_WIDTH, h = IDI_MSA_PIC_HEIGHT;
+	int flags = IDF_AGI_PIC_V2;
+
+	if (iPic == IDI_MSA_PIC_STAR_MAP) {
+		w++; 
+		h++;
+		flags |= IDF_AGI_CIRCLE;
+	}
+
+	ClearScreenAGI(w, h, IDI_MSA_PIC_X0, IDI_MSA_PIC_Y0, flags);
+
+	if (iPic) {
+		uint8 *buffer = new uint8[4096];
+		char szFile[255] = {0};
+
+		sprintf(szFile, IDS_MSA_PATH_PIC, iPic);
+		Common::File infile;
+		if (!infile.open(szFile))
 			return;
+		infile.read(buffer, infile.size());
+		infile.close();
+		AGI_DrawPic(IDI_MSA_PIC_X0, IDI_MSA_PIC_Y0, flags, buffer);
+		delete [] buffer;
+	}
+*/
+}
+
+void Mickey::drawRoomPicture() {
+	if (false) {	// (getDebug()) {	// TODO
+		drawPic(0);
+		debug();
+	} else {
+		if (game.iRoom == IDI_MSA_PIC_TITLE) {
+			drawPic(IDI_MSA_PIC_TITLE);
+		} else {
+			drawPic(game.iRmPic[game.iRoom]);
 		}
 	}
+}
 
-	// play spaceship landing scene
-	game.iPlanet = IDI_MSA_PLANET_EARTH;
-	game.iRoom = IDI_MSA_PIC_EARTH_ROAD_4;
+void Mickey::drawRoomObjects() {
+	if (game.iRoom >= IDI_MSA_MAX_PIC_ROOM)
+		return;
 
-	DrawRoom();
-	PrintRoomDesc();
+	uint8 buffer[256];
+	int pBuf = 0;
+	int nObjs;
 
-	#ifndef _DEBUG
-	PlaySound(IDI_MSA_SND_SHIP_LAND);
-	#endif
+	// draw ship control room window
 
-	FlashScreen();
-	FlashScreen();
-	FlashScreen();
+	if (game.iRoom == IDI_MSA_PIC_SHIP_CONTROLS) {
+		if (game.fFlying) {
+			drawObj(IDI_MSA_OBJECT_W_SPACE, 0, 0);
+		} else {
+			drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_W_EARTH + game.iPlanet), 0, 1);
+		}
+	}
 
-	PrintExeMsg(IDO_MSA_INTRO);
-#endif
+	// draw objects
+
+	if (game.iRmObj[game.iRoom] != IDI_MSA_OBJECT_NONE) {
+		readOfsData(IDO_MSA_ROOM_OBJECT_XY_OFFSETS, 
+			game.iRmObj[game.iRoom], buffer, sizeof(buffer));
+
+		nObjs = buffer[pBuf++];
+
+		for (int iObj = 0; iObj < nObjs; iObj++) {
+			drawObj((ENUM_MSA_OBJECT)buffer[pBuf], buffer[pBuf + 1], buffer[pBuf + 2]);
+			pBuf += 3;
+		}
+	}
 }
 
+void Mickey::drawRoomAnimation() {
+	uint8 objLight[] = {
+		0xF0, 1, 0xF9, 2, 53, 45, 0xFF
+	};
+
+	switch(game.iRoom) {
+	case IDI_MSA_PIC_EARTH_SHIP:
+	case IDI_MSA_PIC_VENUS_SHIP:
+	case IDI_MSA_PIC_NEPTUNE_SHIP:
+	case IDI_MSA_PIC_MERCURY_SHIP:
+	case IDI_MSA_PIC_SATURN_SHIP:
+	case IDI_MSA_PIC_PLUTO_SHIP:
+	case IDI_MSA_PIC_JUPITER_SHIP:
+	case IDI_MSA_PIC_MARS_SHIP:
+	case IDI_MSA_PIC_URANUS_SHIP:
+	case IDI_MSA_PIC_SHIP_VENUS:
+	case IDI_MSA_PIC_SHIP_NEPTUNE:
+	case IDI_MSA_PIC_SHIP_MERCURY:
+	case IDI_MSA_PIC_SHIP_SATURN:
+	case IDI_MSA_PIC_SHIP_PLUTO:
+	case IDI_MSA_PIC_SHIP_JUPITER:
+	case IDI_MSA_PIC_SHIP_MARS:
+	case IDI_MSA_PIC_SHIP_URANUS:
+
+		// draw blinking ship lights
+
+		int iColor;
+
+		for (int i = 0; i < 12; i++) {
+			iColor = game.nFrame + i;
+			if (iColor > 15) iColor -= 15;
+
+			objLight[1] = iColor;
+			objLight[4] += 7;
+			
+			// TODO
+			//AGI_DrawPic(0, 0, IDF_AGI_PIC_V2 | IDF_AGI_CIRCLE, (uint8 *)objLight);
+		}
+
+		game.nFrame--;
+		if (game.nFrame < 0) game.nFrame = 15;
+
+		// TODO
+		//PlaySound(IDI_MSA_SND_PRESS_BLUE);
+
+		break;
+
+	case IDI_MSA_PIC_SHIP_CONTROLS:
+
+		// draw XL30 screen
+
+		if (game.fAnimXL30) {
+			if (game.nFrame > 5) game.nFrame = 0;
+			drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_XL31 + game.nFrame), 0, 4);
+			game.nFrame++;
+		};
+
+		break;
+
+	default:
+
+		// draw crystal
+
+		if (game.iRoom == IDI_MSA_XTAL_ROOM_XY[game.iPlanet][0]) {
+			if (!game.fHasXtal) {
+				switch(game.iPlanet) {
+				case IDI_MSA_PLANET_VENUS:
+					if (game.iRmMenu[game.iRoom] != 2) break;
+				default:
+					drawObj(
+						IDI_MSA_OBJECT_CRYSTAL, 
+						IDI_MSA_XTAL_ROOM_XY[game.iPlanet][1], 
+						IDI_MSA_XTAL_ROOM_XY[game.iPlanet][2]
+					);
+					break;
+				}
+			}
+		}
+
+		break;
+	}
+}
+
+void Mickey::drawRoom() {
+	drawRoomPicture();
+	drawRoomObjects();
+	drawRoomAnimation();
+}
+
 void Mickey::drawLogo() {
 	char szFile[256] = {0};
 	uint8 *buffer = new uint8[16384];
@@ -101,40 +809,1265 @@
 		return;
 	infile.read(buffer, infile.size());
 	infile.close();
-		
+	
 	// draw logo bitmap
-	// TODO
-	//drawPictureBCG(buffer);
-	//updateScreen();
+	//drawPictureBCG(buffer);	// TODO
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
 
 	delete [] buffer;
 }
 
-void Mickey::drawRoomPicture() {
-	if (false) { //(getDebug()) {
-		drawPic(0);
-		//debug();	// TODO
+void Mickey::animate() {
+	// TODO
+/*	if ((int)SDL_GetTicks() > (game.nTicks + IDI_MSA_ANIM_DELAY)) {
+		game.nTicks = SDL_GetTicks();
+		drawRoomAnimation();
+	}
+*/
+}
+
+void Mickey::printRoomDesc() {
+	// print room description
+
+	printDesc(game.iRoom);
+	_vm->waitAnyKeyAnim();
+
+	// print extended room description
+
+	if (game.fRmTxt[game.iRoom]) {
+		printExeMsg(game.oRmTxt[game.iRoom] + IDI_MSA_OFS_EXE);
+	}
+}
+
+bool Mickey::loadGame() {
+	Common::File infile;
+	char szFile[256] = {0};
+	bool diskerror = true;
+	int sel;
+
+	while (diskerror) {
+		sel = choose1to9(IDO_MSA_LOAD_GAME[1]);
+		if (!sel)
+			return false;
+
+		// load game
+		//sprintf(szFile, "%s.s%2d", target, sel);	// TODO
+		if (!infile.open(szFile)) {
+			printExeStr(IDO_MSA_CHECK_DISK_DRIVE);
+			if (!_vm->waitAnyKeyChoice())
+				return false;
+		} else {
+			//infile->read(game, sizeof(MSA_GAME));
+			diskerror = false;
+			infile.close();			
+		}
+	}
+
+	printExeMsg(IDO_MSA_LOAD_GAME[2]);
+	return true;
+}
+
+void Mickey::saveGame() {
+	Common::File outfile;
+	char szFile[256] = {0};
+	bool diskerror = true;
+	int sel;
+
+	bool fOldDisk = chooseY_N(IDO_MSA_SAVE_GAME[0], false);
+
+	if (fOldDisk)
+		printExeStr(IDO_MSA_SAVE_GAME[1]);
+	else
+		printExeStr(IDO_MSA_SAVE_GAME[2]);
+
+	if (!_vm->waitAnyKeyChoice())
+		return;
+	
+	while (diskerror) {
+		sel = choose1to9(IDO_MSA_SAVE_GAME[3]);
+		if (!sel)
+			return;
+
+		if (fOldDisk)
+			printExeStr(IDO_MSA_SAVE_GAME[5]);
+		else
+			printExeStr(IDO_MSA_SAVE_GAME[4]);
+
+		if (!_vm->waitAnyKeyChoice())
+			return;
+
+		// save game
+		// TODO
+		/*
+		sprintf(szFile, "%s.s%2d", target, sel);
+		if (!outfile.open(szFile)) {
+			printExeStr(IDO_MSA_CHECK_DISK_DRIVE);
+			if (!_vm->waitAnyKeyChoice())
+				return;
+		} else {
+			//outfile->write(game, sizeof(MSA_GAME))
+			diskerror = false;
+			outfile.close();						
+		}
+		*/
+	}
+
+	printExeMsg(IDO_MSA_SAVE_GAME[6]);
+}
+
+void Mickey::showPlanetInfo() {
+	for (int i = 0; i < IDI_MSA_MAX_PLANET_INFO; i++) {
+		printExeStr(IDO_MSA_PLANET_INFO[game.iPlanet][i]);
+		_vm->waitAnyKey();
+	}
+}
+
+void Mickey::printStory() {
+	char buffer[IDI_MSA_LEN_STORY] = {0};
+	char szLine[41] = {0};
+	int iRow;
+	int pBuf = 0;
+	
+	readExe(IDO_MSA_GAME_STORY, (uint8 *)buffer, sizeof(buffer));
+	
+	//ClearScreen(IDA_DEFAULT);	// TODO
+	for (iRow = 0; iRow < 25; iRow++) {
+		strcpy(szLine, buffer + pBuf);
+		//drawStr(iRow, 0, szLine); // TODO
+		pBuf += strlen(szLine) + 1;
+	}
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+	_vm->waitAnyKey();
+
+	//ClearScreen(IDA_DEFAULT); // TODO
+	for (iRow = 0; iRow < 21; iRow++) {
+		strcpy(szLine, buffer + pBuf);
+		//drawStr(iRow, 0, szLine);	// TODO
+		pBuf += strlen(szLine) + 1;
+	}
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+	_vm->waitAnyKey();
+
+	drawRoom();
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+
+	game.fStoryShown = true;
+}
+
+void Mickey::hidden() {
+	if (game.iRoom == IDI_MSA_PIC_MERCURY_CAVE_0) {
+		for (int i = 0; i < 5; i++) {
+			//printExeMsg(IDO_MSA_HIDDEN_MSG[i]);	// TODO
+		}
+		// clearTextArea();	// TODO
+		_vm->_gfx->doUpdate();
+		_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+		_vm->waitAnyKey();
+	}
+}
+
+int Mickey::getPlanet() {
+	if (!game.nButtons)
+		return -1;
+
+	for (int iPlanet = 0; iPlanet < IDI_MSA_MAX_DAT; iPlanet++) {
+		if (!strcmp(IDS_MSA_ADDR_PLANET[iPlanet], game.szAddr)) {
+			return iPlanet;
+		}
+	}
+
+	return -1;
+}
+
+void Mickey::pressOB(int iButton) {
+	char szButtons[12] = {0};
+
+	// check if too many buttons pressed
+	if (game.nButtons == IDI_MSA_MAX_BUTTON) {
+		game.nButtons = 0;
+		memset(game.szAddr, 0, sizeof(game.szAddr));
+		printExeMsg(IDO_MSA_TOO_MANY_BUTTONS_PRESSED);
+		return;
+	}
+	
+	// add button press to address
+	game.nButtons++;
+	game.szAddr[game.nButtons - 1] = (char)iButton;
+
+	// format buttons string
+	for (int i = 0; i < IDI_MSA_MAX_BUTTON; i++) {
+		szButtons[i * 2] = game.szAddr[i];
+		if (game.szAddr[i + 1]) szButtons[(i * 2) + 1] = ',';
+	}
+
+	// print pressed buttons
+	printExeStr(IDO_MSA_MICKEY_HAS_PRESSED);
+	//drawStr(IDI_MSA_ROW_BUTTONS, IDI_MSA_COL_BUTTONS, szButtons);	// TODO
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+	_vm->waitAnyKey();
+}
+
+void Mickey::checkAirSupply(bool fSuit, int *iSupply) {
+	if (fSuit) {
+		*iSupply -= 1;
+		for (int i = 0; i < 4; i++) {
+			if (*iSupply == IDI_MSA_AIR_SUPPLY[i]) {
+				//playSound(IDI_MSA_SND_XL30);	// TODO
+				printExeMsg(IDO_MSA_XL30_SPEAKING);
+				printExeMsg(IDO_MSA_AIR_SUPPLY[i]);
+				if (i == 3) {
+					exit(0);
+				}
+			}
+		}
 	} else {
-		if (game.iRoom == IDI_MSA_PIC_TITLE) {
-			drawPic(IDI_MSA_PIC_TITLE);
+		*iSupply = IDI_MSA_MAX_AIR_SUPPLY;
+	}
+}
+
+void Mickey::insertDisk(int iDisk) {
+	//clearTextArea(); // TODO
+	// TODO
+	//drawStr(IDI_MSA_ROW_INSERT_DISK, IDI_MSA_COL_INSERT_DISK, (char *)IDS_MSA_INSERT_DISK[iDisk]);
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+	_vm->waitAnyKey();
+}
+
+void Mickey::gameOver() {
+	drawPic(IDI_MSA_PIC_EARTH_SHIP_LEAVING);
+	printExeMsg(IDO_MSA_GAME_OVER[3]);
+	//playSound(IDI_MSA_SND_GAME_OVER);	// TODO
+
+	if (game.fItemUsed[IDI_MSA_ITEM_LETTER]) {
+		drawPic(IDI_MSA_PIC_EARTH_MINNIE);
+		printExeMsg(IDO_MSA_GAME_OVER[4]);
+		printExeMsg(IDO_MSA_GAME_OVER[5]);
+	} else {
+		printExeMsg(IDO_MSA_GAME_OVER[6]);
+		printExeMsg(IDO_MSA_GAME_OVER[7]);
+	}
+
+	_vm->waitAnyKey();
+	exit(0);
+}
+
+void Mickey::flipSwitch() {
+	if (game.fHasXtal || game.nXtals) {
+		if (!game.fStoryShown) {
+			printStory();
+			randomize();
+		}
+
+		// activate screen animation
+		game.fAnimXL30 = true;
+
+		// clearTextArea();	// TODO
+		_vm->_gfx->doUpdate();
+		_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+		//playSound(IDI_MSA_SND_XL30);	// TODO
+		printExeMsg(IDO_MSA_XL30_SPEAKING);
+
+		if (game.fHasXtal) {
+			game.fHasXtal = false;
+			printExeMsg(IDO_MSA_CRYSTAL_PIECE_FOUND);
+		}
+		
+		if (game.nXtals == IDI_MSA_MAX_PLANET) {
+			printExeMsg(IDO_MSA_GAME_OVER[0]);
+			printExeMsg(IDO_MSA_GAME_OVER[1]);
+			printExeMsg(IDO_MSA_GAME_OVER[2]);
+
+#ifdef _DEBUG
+			strcpy(game.szAddr, (char *)IDS_MSA_ADDR_PLANET[IDI_MSA_PLANET_EARTH]);
+			game.nButtons = strlen(game.szAddr);
+#endif
+
 		} else {
-			drawPic(game.iRmPic[game.iRoom]);
+			printExeStr(game.iClue[game.nXtals]);
+
+#ifdef _DEBUG
+			// TODO
+			//drawStr(24, 12, (char *)IDS_MSA_NAME_PLANET_2[game.iPlanetXtal[game.nXtals]]);
+			//drawStr(24, 22, (char *)IDS_MSA_ADDR_PLANET[game.iPlanetXtal[game.nXtals]]);
+			strcpy(game.szAddr, (char *)IDS_MSA_ADDR_PLANET[game.iPlanetXtal[game.nXtals]]);
+			game.nButtons = strlen(game.szAddr);
+			_vm->_gfx->doUpdate();
+			_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+#endif
+
+			_vm->waitAnyKeyAnim();
 		}
+	} else {
+		printStory();
 	}
 }
 
-void Mickey::drawPic(int iPic) {
-	_vm->preAgiLoadResource(rPICTURE, iPic);
-	_vm->_picture->decodePicture(iPic, true);
-	_vm->_picture->showPic();
+void Mickey::inventory() {
+	int iRow = IDI_MSA_ROW_INV_ITEMS;
+	char szCrystals[12] = {0};
+
+	sprintf(szCrystals, IDS_MSA_CRYSTALS, IDS_MSA_CRYSTAL_NO[game.nXtals]);
+
+	// TODO
+	/*
+	ClearScreen(IDA_DEFAULT);
+	drawStr(IDI_MSA_ROW_INV_TITLE, IDI_MSA_COL_INV_TITLE, IDS_MSA_INVENTORY);
+	drawStr(IDI_MSA_ROW_INV_CRYSTALS, IDI_MSA_COL_INV_ITEMS, szCrystals);
+	*/
+
+	for (int iItem = 0; iItem < IDI_MSA_MAX_ITEM; iItem++) {
+		if (game.fItem[game.iItem[iItem]] && (game.iItem[iItem] != IDI_MSA_OBJECT_NONE)) {
+			//drawStr(iRow++, IDI_MSA_COL_INV_ITEMS, (char *)IDS_MSA_NAME_ITEM[game.iItem[iItem]]); // TODO
+		}
+	}
+
 	_vm->_gfx->doUpdate();
 	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+	_vm->waitAnyKey();
+
+	//ClearScreen(IDA_DEFAULT);		// TODO
 }
 
-void Mickey::drawRoom() {
-	drawRoomPicture();
-	//drawRoomObjects();
-	//drawRoomAnimation();
+void Mickey::randomize() {
+	int iPlanet = 0;
+	int iHint = 0;
+	bool done;
+
+	// TODO
+	memset(game.iPlanetXtal, 0, sizeof(game.iPlanetXtal));
+	memset(game.iClue, 0, sizeof(game.iClue));
+
+	game.iPlanetXtal[0] = IDI_MSA_PLANET_EARTH;
+	game.iPlanetXtal[8] = IDI_MSA_PLANET_URANUS;
+
+	for (int i = 1; i < 9; i++) {
+		if (i == 8) {
+			iPlanet = IDI_MSA_PLANET_URANUS;
+		} else {
+			done = false;
+			while (!done) {
+				//iPlanet = _vm->rnd(IDI_MSA_MAX_PLANET);	// TODO
+				done = true;
+				for (int j = 0; j < IDI_MSA_MAX_PLANET; j++) {
+					if (game.iPlanetXtal[j] == iPlanet) {
+						done = false;
+						break;
+					}
+				}
+			}
+		}
+
+		game.iPlanetXtal[i] = iPlanet;
+		
+		done = false;
+		while (!done) {
+			//iHint = _vm->rnd(5);	// TODO
+			done = true;
+		}
+
+		game.iClue[i] = IDO_MSA_NEXT_PIECE[iPlanet][iHint];
+	}
 }
 
+void Mickey::flashScreen() {
+	//playSound(IDI_MSA_SND_PRESS_BLUE);	// TODO
+
+	//clearGfxScreen(15);	// TODO
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+
+	drawRoom();
+	printDesc(game.iRoom);
+	_vm->_gfx->doUpdate();
+	_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
 }
+
+void Mickey::intro() {
+	// draw sierra logo
+	drawLogo();
+
+	// draw title picture
+	game.iRoom = IDI_MSA_PIC_TITLE;
+	drawRoom();
+	
+	// show copyright and play theme
+	printExeMsg(IDO_MSA_COPYRIGHT);
+	//playSound(IDI_MSA_SND_THEME);	// TODO
+	
+	// load game
+	game.fIntro = true;
+	if (chooseY_N(IDO_MSA_LOAD_GAME[0], true)) {
+		if (loadGame()) {
+			game.iPlanet = IDI_MSA_PLANET_EARTH;
+			game.fIntro = false;
+			game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
+			return;
+		}
+	}
+
+	// play spaceship landing scene
+	game.iPlanet = IDI_MSA_PLANET_EARTH;
+	game.iRoom = IDI_MSA_PIC_EARTH_ROAD_4;
+
+	drawRoom();
+	printRoomDesc();
+
+#ifndef _DEBUG
+	PlaySound(IDI_MSA_SND_SHIP_LAND);
+#endif
+
+	flashScreen();
+	flashScreen();
+	flashScreen();
+
+	printExeMsg(IDO_MSA_INTRO);
+}
+
+void Mickey::getItem(ENUM_MSA_ITEM iItem) {
+	game.fItem[iItem] = true;
+	game.iItem[game.nItems++] = iItem;
+	game.fRmTxt[game.iRoom] = 0;
+	//playSound(IDI_MSA_SND_TAKE);	// TODO
+	drawRoom();
+}
+
+void Mickey::getXtal(int iStr) {
+	game.fRmTxt[game.iRoom] = 0;
+	game.fHasXtal = true;
+	game.nXtals++;
+	//playSound(IDI_MSA_SND_CRYSTAL);	// TODO
+	drawRoom();
+	printDatMessage(iStr);
+}
+
+bool Mickey::parse(int cmd, int arg) {
+	switch(cmd) {
+
+	// BASIC
+
+	case IDI_MSA_ACTION_GOTO_ROOM:
+		game.iRoom = arg;
+		return true;
+	case IDI_MSA_ACTION_SHOW_INT_STR:
+		printExeMsg(IDO_MSA_ERROR[arg]);
+		break;
+	case IDI_MSA_ACTION_SHOW_DAT_STR:
+		printDatMessage(arg);
+		break;
+
+	// GENERAL
+
+	case IDI_MSA_ACTION_PLANET_INFO:
+		showPlanetInfo();
+		break;
+	case IDI_MSA_ACTION_SAVE_GAME:
+		saveGame();
+		break;
+	case IDI_MSA_ACTION_LOOK_MICKEY:
+		printExeMsg(IDO_MSA_YOU_CAN_SEE_MICKEY_ALREADY);
+		break;
+
+	// EARTH
+
+	case IDI_MSA_ACTION_GET_ROPE:
+		if (game.iRmMenu[game.iRoom] == 2) {
+			game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+			game.iRmMenu[game.iRoom] = 3;
+			getItem(IDI_MSA_ITEM_ROPE);
+			printExeMsg(IDO_MSA_ERROR[7]);
+		} else {
+			game.iRmMenu[game.iRoom] = 1;
+			printDatMessage(11);
+		}
+		break;
+	case IDI_MSA_ACTION_UNTIE_ROPE:
+		game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_TIRE_SWING_1;
+		game.iRmObj[game.iRoom] = 0;
+		game.iRmMenu[game.iRoom] = 2;
+		drawRoom();
+		printDatMessage(12);
+		break;
+	case IDI_MSA_ACTION_GET_BONE:
+		game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+		game.iRmMenu[game.iRoom] = 1;
+		getItem(IDI_MSA_ITEM_BONE);
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_GET_XTAL_EARTH:
+		game.iRmMenu[game.iRoom] = 1;
+		getXtal(arg);
+		break;
+	case IDI_MSA_ACTION_LOOK_DESK:
+		game.iRmMenu[game.iRoom] = 1;
+		game.iRmObj[game.iRoom] = 2;
+		drawRoom();
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_WRITE_LETTER:
+		game.iRmMenu[game.iRoom] = 3;
+		game.iRmMenu[IDI_MSA_PIC_EARTH_MAILBOX] = 1;
+		game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+		getItem(IDI_MSA_ITEM_LETTER);
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_MAIL_LETTER:
+		game.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
+		game.fItem[IDI_MSA_ITEM_LETTER] = false;
+		game.iRmMenu[game.iRoom] = 0;
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_OPEN_MAILBOX:
+		if (game.fItemUsed[IDI_MSA_ITEM_LETTER]) {
+			printDatMessage(110);
+		} else {
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_OPEN_CUPBOARD:
+		if (game.iRmMenu[game.iRoom]) {
+			if (game.iRmObj[game.iRoom] == IDI_MSA_OBJECT_NONE) {
+				printDatMessage(78);
+			} else {
+				printDatMessage(arg);
+			}
+		} else {
+			game.iRmMenu[game.iRoom] = 1;
+			game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_KITCHEN_1;
+			game.iRmObj[game.iRoom] = 3;
+			drawRoom();
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_FLASHLIGHT:
+		if (game.fItem[IDI_MSA_ITEM_FLASHLIGHT]) {
+			printDatMessage(90);
+		} else {
+			game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+			getItem(IDI_MSA_ITEM_FLASHLIGHT);
+			drawRoom();
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_OPEN_CABINET:
+		if (game.iRmMenu[game.iRoom]) {
+			printDatMessage(109);
+		} else {
+			game.iRmMenu[game.iRoom] = 1;
+			game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_GARAGE_1;
+			game.iRmObj[game.iRoom] = 15;
+			drawRoom();
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_CROWBAR:
+		if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
+			printDatMessage(90);
+		} else {
+			game.iRmObj[game.iRoom]--;
+			getItem(IDI_MSA_ITEM_CROWBAR);
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_WRENCH:
+		if (game.fItem[IDI_MSA_ITEM_WRENCH]) {
+			printDatMessage(90);
+		} else {
+			game.iRmObj[game.iRoom] -= 2;
+			getItem(IDI_MSA_ITEM_WRENCH);
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_OPEN_CLOSET:
+		if (game.iRmMenu[game.iRoom]) {
+			printDatMessage(99);
+		} else {
+			game.iRmMenu[game.iRoom] = 1;
+			game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_BEDROOM_1;
+			game.iRmObj[game.iRoom] = 7;
+			drawRoom();
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_MATTRESS:
+		if (game.fItem[IDI_MSA_ITEM_MATTRESS]) {
+			printDatMessage(90);
+		} else {
+			game.iRmObj[game.iRoom]--;
+			getItem(IDI_MSA_ITEM_MATTRESS);
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_SCARF:
+		if (game.fItem[IDI_MSA_ITEM_SCARF]) {
+			printDatMessage(90);
+		} else {
+			game.iRmObj[game.iRoom] -= 2;
+			getItem(IDI_MSA_ITEM_SCARF);
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_SUNGLASSES:
+		if (game.fItem[IDI_MSA_ITEM_SUNGLASSES]) {
+			printDatMessage(90);
+		} else {
+			game.iRmObj[game.iRoom]--;
+			getItem(IDI_MSA_ITEM_SUNGLASSES);
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_SCALE:
+		if (game.fItem[IDI_MSA_ITEM_SCALE]) {
+			printDatMessage(90);
+		} else {
+			game.iRmMenu[IDI_MSA_PIC_VENUS_WEIGH] = 1;
+			game.iRmMenu[IDI_MSA_PIC_NEPTUNE_WEIGH] = 1;
+			game.iRmMenu[IDI_MSA_PIC_MERCURY_WEIGH] = 1;
+			game.iRmMenu[IDI_MSA_PIC_SATURN_WEIGH] = 1;
+			game.iRmMenu[IDI_MSA_PIC_PLUTO_WEIGH] = 1;
+			game.iRmMenu[IDI_MSA_PIC_JUPITER_WEIGH] = 1;
+			game.iRmMenu[IDI_MSA_PIC_MARS_WEIGH] = 1;
+			game.iRmMenu[IDI_MSA_PIC_URANUS_WEIGH] = 1;
+			game.iRmObj[game.iRoom] -= 2;
+			getItem(IDI_MSA_ITEM_SCALE);
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GOTO_SPACESHIP:
+		game.iRoom = IDI_MSA_PIC_SHIP_AIRLOCK;
+		if (game.iPlanet != IDI_MSA_PLANET_EARTH)
+			insertDisk(0);
+		return true;
+
+	// VENUS
+
+	case IDI_MSA_ACTION_DOWN_CHASM:
+		if (game.fItem[IDI_MSA_ITEM_ROPE]) {
+			game.iRmMenu[game.iRoom] = 1;
+		}
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_DOWN_ROPE:
+		if (game.fItemUsed[IDI_MSA_ITEM_ROPE]) {
+			game.iRoom = IDI_MSA_PIC_VENUS_PROBE;
+			return true;
+		} else {
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_USE_ROPE:
+		if (game.fItemUsed[IDI_MSA_ITEM_ROPE]) {
+			printDatMessage(22);
+		} else {
+			game.fItemUsed[IDI_MSA_ITEM_ROPE] = true;
+			game.fItem[IDI_MSA_ITEM_ROPE] = false;
+			game.iRmPic[game.iRoom] = IDI_MSA_PIC_VENUS_CHASM_1;
+			drawRoom();
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_OPEN_HATCH:
+		if (game.fItemUsed[IDI_MSA_ITEM_WRENCH]) {
+			if ((game.iRmMenu[game.iRoom] == 3) || (game.iRmPic[game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1))
+				printDatMessage(39);
+			else {
+				game.iRmMenu[game.iRoom] = 2;
+				game.iRmPic[game.iRoom] = IDI_MSA_PIC_VENUS_PROBE_1;
+				drawRoom();
+				printDatMessage(24);
+			}
+		} else {
+			if (game.fItem[IDI_MSA_ITEM_WRENCH]) {
+				game.iRmMenu[game.iRoom] = 1;
+			}
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_USE_WRENCH:
+		game.fItemUsed[IDI_MSA_ITEM_WRENCH] = true;
+		printDatString(arg);
+		if (game.iRmPic[game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1) {
+			//ClearRow(22);	// TODO
+		}
+		_vm->_gfx->doUpdate();
+		_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+		_vm->waitAnyKey();
+		break;
+	case IDI_MSA_ACTION_GET_XTAL_VENUS:
+		game.iRmMenu[game.iRoom] = 3;
+		getXtal(arg);
+		break;
+
+	// TRITON (NEPTUNE)
+
+	case IDI_MSA_ACTION_LOOK_CASTLE:
+		if (!game.iRmMenu[game.iRoom]) {
+			game.iRmMenu[game.iRoom] = 1;
+		}
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_ENTER_OPENING:
+		if (game.fItemUsed[IDI_MSA_ITEM_CROWBAR]) {
+			game.iRoom = IDI_MSA_PIC_NEPTUNE_CASTLE_4;
+			return true;
+		} else {
+			if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
+				game.iRmMenu[game.iRoom] = 2;
+			}
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_USE_CROWBAR:
+		game.fItemUsed[IDI_MSA_ITEM_CROWBAR] = true;
+		game.iRmMenu[game.iRoom] = 1;
+		game.iRmPic[game.iRoom] = IDI_MSA_PIC_NEPTUNE_ENTRANCE_1;
+		drawRoom();
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_GET_XTAL_NEPTUNE:
+		if (game.fHasXtal) {
+			printDatMessage(71);
+		} else {
+			if (game.fItem[IDI_MSA_ITEM_SCARF]) {
+				game.iRmMenu[game.iRoom] = 1;
+			}
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_TALK_LEADER:
+		game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
+		printDatMessage(arg);
+		return true;
+	case IDI_MSA_ACTION_GIVE_SCARF:
+		game.iRmObj[game.iRoom] = 18;
+		getXtal(arg);
+		game.fItem[IDI_MSA_ITEM_SCARF] = false;
+		game.iRmMenu[game.iRoom] = 0;
+		game.iRmMenu[IDI_MSA_PIC_EARTH_BEDROOM] = 2;
+		game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
+		return true;
+
+	// MERCURY
+
+	case IDI_MSA_ACTION_GET_XTAL_MERCURY:
+		if (game.fHasXtal) {
+			game.iRmMenu[game.iRoom] = 2;
+			printDatMessage(32);
+		} else {
+			if (game.fItem[IDI_MSA_ITEM_SUNGLASSES]) {
+				game.iRmMenu[game.iRoom] = 1;
+			}
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GIVE_SUNGLASSES:
+		game.iRmObj[game.iRoom] = 17;
+		game.iRmMenu[game.iRoom] = 2;
+		game.fItem[IDI_MSA_ITEM_SUNGLASSES] = false;
+		getXtal(arg);
+		break;
+
+	// TITAN (SATURN)
+
+	case IDI_MSA_ACTION_CROSS_LAKE:
+		if (game.fItem[IDI_MSA_ITEM_MATTRESS]) {
+			game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_0] = 1;
+			game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_1] = 1;
+			game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_2] = 1;
+		}
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_USE_MATTRESS:
+		game.iRoom = IDI_MSA_PIC_SATURN_ISLAND;
+		printDatMessage(arg);
+		return true;
+	case IDI_MSA_ACTION_GET_XTAL_SATURN:
+		if (game.fHasXtal) {
+			printDatMessage(29);
+		} else {
+			getXtal(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_LEAVE_ISLAND:
+		game.iRoom = IDI_MSA_PIC_SATURN_LAKE_1;
+		printDatMessage(arg);
+		return true;
+
+	// PLUTO
+
+	case IDI_MSA_ACTION_GET_XTAL_PLUTO:
+		if (game.fHasXtal) {
+			printDatMessage(19);
+		} else {
+			if (game.fItem[IDI_MSA_ITEM_BONE]) {
+				game.iRmMenu[game.iRoom] = 1;
+			}
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GIVE_BONE:
+		game.fItem[IDI_MSA_ITEM_BONE] = false;
+		game.iRmMenu[game.iRoom] = 0;
+		game.iRmObj[game.iRoom] = 16;
+		getXtal(arg);
+		break;
+
+	// IO (JUPITER)
+
+	case IDI_MSA_ACTION_GET_ROCK_0:
+		if (game.fItem[IDI_MSA_ITEM_ROCK]) {
+			printDatMessage(38);
+		} else {
+			game.iRmMenu[game.iRoom] = 1;
+			game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+			getItem(IDI_MSA_ITEM_ROCK);
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_ROCK_1:
+		if (game.fItem[IDI_MSA_ITEM_ROCK]) {
+			printDatMessage(38);
+		} else {
+			game.iRmMenu[game.iRoom] = 1;
+			game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+			getItem(IDI_MSA_ITEM_ROCK);
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_XTAL_JUPITER:
+		if (game.fHasXtal) {
+			printDatMessage(15);
+		} else {
+			switch (game.nRocks) {
+			case 0:
+				if (game.fItem[IDI_MSA_ITEM_ROCK]) {
+					game.iRmMenu[game.iRoom] = 1;
+				}
+				printDatMessage(arg);
+				break;
+			case 1:
+				if (game.fItem[IDI_MSA_ITEM_ROCK]) {
+					game.iRmMenu[game.iRoom] = 1;
+				}
+				printDatMessage(34);
+				break;
+			case 2:
+				getXtal(35);
+				break;
+			}
+		}
+		break;
+	case IDI_MSA_ACTION_THROW_ROCK:
+		game.fItem[IDI_MSA_ITEM_ROCK] = false;
+		game.nItems--;
+		game.iRmObj[game.iRoom]++;
+		game.iRmMenu[game.iRoom] = 0;
+		drawRoom();
+		if (game.nRocks) {
+			printDatMessage(37);
+		} else {
+			printDatMessage(arg);
+		}
+		game.nRocks++;
+		break;
+
+	// MARS
+
+	case IDI_MSA_ACTION_GO_TUBE:
+		if (game.fItem[IDI_MSA_ITEM_FLASHLIGHT]) {
+			game.iRmMenu[game.iRoom] = 1;
+		}
+		printDatMessage(arg);
+		break;
+	case IDI_MSA_ACTION_USE_FLASHLIGHT:
+		game.iRoom = IDI_MSA_PIC_MARS_TUBE_1;
+		printDatMessage(15);
+		return true;
+	case IDI_MSA_ACTION_PLUTO_DIG:
+		if (game.fHasXtal) {
+			printDatMessage(21);
+		} else {
+			getXtal(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_XTAL_MARS:
+		if (game.fHasXtal) {
+			printDatMessage(23);
+		} else {
+			printDatMessage(arg);
+		}
+		break;
+
+	// OBERON (URANUS)
+
+	case IDI_MSA_ACTION_ENTER_TEMPLE:
+		game.iRoom = IDI_MSA_PIC_URANUS_TEMPLE;
+		return true;
+	case IDI_MSA_ACTION_USE_CRYSTAL:
+		if (game.iRmMenu[game.iRoom]) {
+			printDatMessage(25);
+		} else {
+			game.iRmMenu[game.iRoom] = 1;
+			game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_1;
+			drawRoom();
+			game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE;
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_OPEN_DOOR:
+		if (game.fTempleDoorOpen) {
+			printDatMessage(36);
+		} else {
+			game.fTempleDoorOpen = 1;
+			game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_2;
+			drawRoom();
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_ENTER_DOOR:
+		if (game.fTempleDoorOpen) {
+			game.iRoom = IDI_MSA_PIC_URANUS_STEPS;
+			return true;
+		} else {
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GET_XTAL_URANUS:
+		if (game.fHasXtal) {
+			printDatMessage(34);
+		} else {
+			if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
+				game.iRmMenu[game.iRoom] = 1;
+			}
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_USE_CROWBAR_1:
+		game.iRmMenu[game.iRoom] = 0;
+		getXtal(arg);
+		break;
+
+	// SPACESHIP
+
+	case IDI_MSA_ACTION_GO_NORTH:
+		if (game.fShipDoorOpen) {
+			if (game.fSuit) {
+				printDatMessage(45);
+			} else {
+				game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
+				return true;
+			}
+		} else {
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_GO_PLANET:
+		if (!game.fShipDoorOpen) {
+			if ((game.nXtals == IDI_MSA_MAX_PLANET) && (game.iPlanet == IDI_MSA_PLANET_EARTH))
+				gameOver();
+			if ((game.iPlanet == game.iPlanetXtal[game.nXtals]) || (game.iPlanet == IDI_MSA_PLANET_EARTH)) {
+				game.fHasXtal = false;
+				game.iRoom = IDI_MSA_HOME_PLANET[game.iPlanet];
+				if (game.iPlanet != IDI_MSA_PLANET_EARTH)
+					insertDisk(1);
+				return true;
+			} else {
+				game.iRoom = IDI_MSA_SHIP_PLANET[game.iPlanet];
+				return true;
+			}
+		} else {
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_PRESS_BUTTON:
+		if (game.fShipDoorOpen) {		// inner door open
+			if (game.iPlanet && !game.fSuit) {
+				printDatMessage(arg);
+			} else {
+				game.fShipDoorOpen = false;
+				game.iRmPic[game.iRoom]--;
+				drawRoom();
+				printDatMessage(2);
+			}
+		} else {
+			game.fShipDoorOpen = true;
+			game.iRmPic[game.iRoom]++;
+			drawRoom();
+			printDatMessage(14);
+		}
+		break;
+	case IDI_MSA_ACTION_WEAR_SPACESUIT:
+		if (game.fSuit) {
+			if (game.fShipDoorOpen) {
+				game.fSuit = false;
+				game.iRmMenu[game.iRoom] = 0;
+				game.iRmPic[game.iRoom] -= 2;
+				drawRoom();
+				printDatMessage(13);
+			} else {
+				printDatMessage(3);
+			}
+		} else {
+			if (game.iPlanet) {
+				game.fSuit = true;
+				game.iRmMenu[game.iRoom] = 1;
+				game.iRmPic[game.iRoom] += 2;
+				drawRoom();
+				printDatMessage(arg);
+			} else {
+				printDatMessage(12);
+			}
+		}
+		break;
+	case IDI_MSA_ACTION_READ_GAUGE:
+		printDatString(arg);
+		/*
+		drawStr(IDI_MSA_ROW_TEMPERATURE, IDI_MSA_COL_TEMPERATURE_C, 
+			(char *)IDS_MSA_TEMP_C[game.iPlanet]);
+		drawStr(IDI_MSA_ROW_TEMPERATURE, IDI_MSA_COL_TEMPERATURE_F, 
+			(char *)IDS_MSA_TEMP_F[game.iPlanet]);
+		*/
+		_vm->_gfx->doUpdate();
+		_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+		_vm->waitAnyKey();
+		break;
+	case IDI_MSA_ACTION_PRESS_ORANGE:
+		if (game.fFlying) {
+			printDatMessage(4);
+		} else {
+			//playSound(IDI_MSA_SND_PRESS_ORANGE);	// TODO
+			printDatMessage(arg);
+			pressOB(IDI_MSA_BUTTON_ORANGE);
+		}
+		break;
+	case IDI_MSA_ACTION_PRESS_BLUE:
+		if (game.fFlying) {
+			printDatMessage(4);
+		} else {
+			//playSound(IDI_MSA_SND_PRESS_BLUE);	// TODO
+			printDatMessage(arg);
+			pressOB(IDI_MSA_BUTTON_BLUE);
+		}
+		break;
+	case IDI_MSA_ACTION_FLIP_SWITCH:
+		flipSwitch();
+		break;
+	case IDI_MSA_ACTION_PUSH_THROTTLE:
+		if (game.fFlying) {
+			game.fFlying = false;
+			game.nButtons = 0;
+			memset(game.szAddr, 0, sizeof(game.szAddr));
+			drawRoom();
+			printDatString(22);
+			// TODO
+			//drawStr(IDI_MSA_ROW_PLANET, IDI_MSA_COL_PLANET, 
+			//	(char *)IDS_MSA_PLANETS[game.iPlanet]);
+			_vm->_gfx->doUpdate();
+			_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+			_vm->waitAnyKeyAnim();
+			showPlanetInfo();
+		} else {
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_PULL_THROTTLE:
+		if (game.fFlying) {
+			printDatMessage(18);
+		} else {
+			if (getPlanet() != -1) {
+				game.fFlying = true;
+				game.iPlanet = getPlanet();
+				drawRoom();
+				printDatMessage(16);
+			} else {
+				game.nButtons = 0;
+				memset(game.szAddr, 0, sizeof(game.szAddr));
+				printDatMessage(17);
+			}
+		}
+		break;
+	case IDI_MSA_ACTION_LEAVE_ROOM:
+		if (game.fFlying) {
+			printDatMessage(24);
+		} else {
+			game.iRoom = arg;
+			return true;
+		}
+		break;
+	case IDI_MSA_ACTION_OPEN_CABINET_1:
+		if (game.iRmMenu[game.iRoom]) {
+			printExeMsg(IDO_MSA_THE_CABINET_IS_ALREADY_OPEN);
+		} else {
+			game.iRmMenu[game.iRoom] = 1;
+			game.iRmPic[game.iRoom] = IDI_MSA_PIC_SHIP_KITCHEN_1;
+			drawRoom();
+			printDatMessage(arg);
+		}
+		break;
+	case IDI_MSA_ACTION_READ_MAP:
+		game.iRmPic[game.iRoom] = IDI_MSA_PIC_STAR_MAP;
+		drawRoom();
+		printDatMessage(46);
+		printDatMessage(47);
+		printDatMessage(48);
+		game.iRmPic[game.iRoom] = IDI_MSA_PIC_SHIP_BEDROOM;
+		drawRoom();
+		break;
+	case IDI_MSA_ACTION_GO_WEST:
+		game.nButtons = 0;
+		memset(game.szAddr, 0, sizeof(game.szAddr));
+		game.iRoom = arg;
+		return true;
+	}
+
+	return false;
+}
+
+void Mickey::gameLoop() {
+	char *buffer = new char[sizeof(MSA_MENU)];
+	MSA_MENU menu;
+	int iSel0, iSel1;
+	bool done;
+
+	for (;;) {
+		drawRoom();
+
+		if (game.fIntro) {
+			game.fIntro = false;
+		} else {
+			printRoomDesc();
+		}
+		
+		if (game.iRoom == IDI_MSA_PIC_NEPTUNE_GUARD) {
+			game.iRoom = IDI_MSA_PIC_NEPTUNE_LEADER;
+			done = true;
+		} else {
+			done = false;
+		}
+
+		while (!done) {
+			checkAirSupply(game.fSuit, &game.nAir);
+			readMenu(game.iRoom, buffer);
+			memcpy(&menu, buffer, sizeof(MSA_MENU));
+			patchMenu(&menu);
+			memcpy(buffer, &menu, sizeof(MSA_MENU));
+			getMenuSel(buffer, &iSel0, &iSel1);
+			done = parse(menu.cmd[iSel0].data[iSel1], menu.arg[iSel0].data[iSel1]);
+		}
+
+		game.nFrame = 0;
+	}
+
+	delete [] buffer;
+}
+
+// Debug
+
+void Mickey::debug_DrawObjs() {
+	char szTitle[14] = {0};
+
+	for (int iObj = 0; iObj < IDI_MSA_MAX_OBJ; iObj++) {
+		drawPic(0);
+		drawObj((ENUM_MSA_OBJECT)iObj, 0, 0);
+
+		///clearTextArea();	// TODO
+		sprintf(szTitle, "Object %d", iObj);
+		// TODO
+		//drawStrAttrMiddle(22, IDA_DEFAULT, szTitle);
+		//drawStrAttrMiddle(23, IDA_DEFAULT, (char *)IDS_MSA_NAME_OBJ[iObj]);
+		_vm->_gfx->doUpdate();
+		_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+		_vm->waitAnyKey();
+	}
+}
+
+void Mickey::debug_DrawPics(){
+	char szTitle[14] = {0};
+
+	for (int iPic = 1; iPic <= IDI_MSA_MAX_PIC; iPic++) {
+		drawPic(iPic);
+
+		//clearTextArea();	// TODO
+		sprintf(szTitle, "Picture %d", iPic);
+		//drawStrAttrMiddle(22, IDA_DEFAULT, szTitle);	// TODO
+		_vm->_gfx->doUpdate();
+		_vm->_system->updateScreen();	// TODO: this should go in the game's main loop
+		_vm->waitAnyKey();
+	}
+}
+
+// Init
+
+void Mickey::initVars() {
+	uint8 buffer[512];
+
+	// clear game struct
+	memset(&game, 0, sizeof(game));
+	memset(&game.iItem, IDI_MSA_OBJECT_NONE, sizeof(game.iItem));
+	// read room extended desc flags
+	readExe(IDO_MSA_ROOM_TEXT, buffer, sizeof(buffer));
+	memcpy(game.fRmTxt, buffer, sizeof(game.fRmTxt));
+
+	// read room extended desc offsets
+	readExe(IDO_MSA_ROOM_TEXT_OFFSETS, buffer, sizeof(buffer));
+//	memcpy(game.oRmTxt, buffer, sizeof(game.oRmTxt));
+	for (int i = 0; i < IDI_MSA_MAX_ROOM; i++)
+		game.oRmTxt[i] = buffer[i*2] + 256 * buffer[i*2+1];
+
+	// read room object indices
+	readExe(IDO_MSA_ROOM_OBJECT, buffer, sizeof(buffer));
+	memcpy(game.iRmObj, buffer, sizeof(game.iRmObj));
+	
+	// read room picture indices
+	//Mickey_readExe(IDO_MSA_ROOM_PICTURE, buffer, sizeof(buffer));
+	//memcpy(game.iRmPic, buffer, sizeof(game.iRmPic));
+
+	// read room menu patch indices
+	readExe(IDO_MSA_ROOM_MENU_FIX, buffer, sizeof(buffer));
+	memcpy(game.nRmMenu, buffer, sizeof(game.nRmMenu));
+
+	// set room picture indices
+	for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
+		game.iRmPic[i] = i;
+	}
+	game.iRmPic[IDI_MSA_PIC_SHIP_AIRLOCK] = IDI_MSA_PIC_SHIP_AIRLOCK_0;
+
+#ifdef _DEBUG
+
+	game.iPlanet = IDI_MSA_PLANET_EARTH;
+	game.iRoom = IDI_MSA_PIC_SHIP_CONTROLS;
+	game.fHasXtal = true;
+	game.nXtals = 9;
+	game.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
+
+#endif
+
+}
+
+void Mickey::initEngine() {
+	// PreAGI sets the screen params here, but we've already done that in the preagi class
+}
+
+Mickey::Mickey(PreAgiEngine *vm) : _vm(vm) {
+}
+
+Mickey::~Mickey() {
+}
+
+void Mickey::init() {
+	initEngine();
+	initVars();
+}
+
+void Mickey::run() {
+	intro();
+	gameLoop();
+	gameOver();
+}
+
+}


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list