[Scummvm-cvs-logs] CVS: scummvm/scumm cursor.cpp,2.26,2.27 intern.h,2.327,2.328 resource_v7he.cpp,1.13,1.14 resource_v7he.h,1.11,1.12 scumm.cpp,1.309,1.310

Eugene Sandulenko sev at users.sourceforge.net
Sun Jan 30 19:55:34 CET 2005


Update of /cvsroot/scummvm/scummvm/scumm
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15563

Modified Files:
	cursor.cpp intern.h resource_v7he.cpp resource_v7he.h 
	scumm.cpp 
Log Message:
Support for Mac cursors.

  TODO:
    o Allow reading from non-processed game executable. Now you need to get
      .bin file out of it
    o Use color versions of cursors
    o Combine MacResExtractor with Win32ResExtractor. Now I just stupidly
      create 2 objects and do not use new cursor caching code.


Index: cursor.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/cursor.cpp,v
retrieving revision 2.26
retrieving revision 2.27
diff -u -d -r2.26 -r2.27
--- cursor.cpp	30 Jan 2005 02:00:24 -0000	2.26
+++ cursor.cpp	31 Jan 2005 03:53:35 -0000	2.27
@@ -144,11 +144,10 @@
 }
 
 void ScummEngine_v70he::setCursorFromImg(uint img, uint room, uint imgindex) {
-	// HACK Macintosh cursors aren't supported yet.
 	if (_features & GF_MACINTOSH && _heversion == 72) 
-		return;
-
-	_win32ResExtractor->setCursor(img);
+		_macResExtractor->setCursor(img);
+	else
+		_win32ResExtractor->setCursor(img);
 }
 
 void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) {

Index: intern.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/intern.h,v
retrieving revision 2.327
retrieving revision 2.328
diff -u -d -r2.327 -r2.328
--- intern.h	30 Jan 2005 11:03:47 -0000	2.327
+++ intern.h	31 Jan 2005 03:53:35 -0000	2.328
@@ -633,6 +633,7 @@
 
 class ScummEngine_v70he : public ScummEngine_v60he {
 	friend class Win32ResExtractor;
+	friend class MacResExtractor;
 
 protected:
 	typedef void (ScummEngine_v70he::*OpcodeProcv70he)();
@@ -644,6 +645,7 @@
 	const OpcodeEntryv70he *_opcodesv70he;
 
 	Win32ResExtractor *_win32ResExtractor;
+	MacResExtractor *_macResExtractor;
 
 	int _heSndSoundFreq, _heSndOffset, _heSndChannel, _heSndSoundId, _heSndFlags;
 

Index: resource_v7he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/resource_v7he.cpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- resource_v7he.cpp	30 Jan 2005 20:38:54 -0000	1.13
+++ resource_v7he.cpp	31 Jan 2005 03:53:35 -0000	1.14
@@ -51,7 +51,7 @@
 Win32ResExtractor::Win32ResExtractor(ScummEngine_v70he *scumm) {
 	_vm = scumm;
 
-	snprintf(_fileName, 256, "%s.he3", _vm->getGameName());
+	_fileName[0] = 0;
 	memset(_cursorCache, 0, sizeof(_cursorCache));
 }
 
@@ -146,6 +146,9 @@
 	fi.memory = NULL;
 	fi.file = new File;
 
+	if (!_fileName[0]) // We are running for the first time
+		snprintf(_fileName, 256, "%s.he3", _vm->getGameName());
+
 	/* get file size */
 	fi.file->open(_fileName);
 	if (!fi.file->isOpen()) {
@@ -1257,4 +1260,257 @@
 }
 
 
+MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) {
+	_vm = scumm;
+
+	_fileName[0] = 0;
+	_resOffset = -1;
+}
+
+void MacResExtractor::setCursor(int id) {
+	byte *cursorRes = 0, *cursor = 0;
+	int cursorsize;
+	int w = 0, h = 0, hotspot_x = 0, hotspot_y = 0;
+	int keycolor;
+
+	if (!_fileName[0]) // We are running for the first time
+		if (_vm->_heMacFileNameIndex > 0) {
+			char buf1[128];
+
+			snprintf(buf1, 128, "%s.he3", _vm->getGameName());
+			_vm->generateMacFileName(buf1, _fileName, 128, 0, _vm->_heMacFileNameIndex);
+		}
+
+	cursorsize = extractResource(id, &cursorRes);
+	convertIcons(cursorRes, cursorsize, &cursor, &w, &h, &hotspot_x, &hotspot_y, &keycolor);
+
+	_vm->setCursorHotspot(hotspot_x, hotspot_y);
+	_vm->setCursorFromBuffer(cursor, w, h, w);
+	free(cursorRes);
+	free(cursor);
+}
+
+int MacResExtractor::extractResource(int id, byte **buf) {
+	File in;
+	int size;
+
+	in.open(_fileName);
+	if (!in.isOpen()) {
+		error("Cannot open file %s", _fileName);
+	}
+
+	// we haven't calculated it
+	if (_resOffset == -1) {
+		if (!init(in))
+			error("Invalid file format (%s)", _fileName);
+		debug(0, "ResOffset: %d", _resOffset);
+	}
+
+	*buf = getResource(in, "crsr", 1000 + id, &size);
+
+	if (*buf == NULL)
+		error("Cannot read cursor ID: %d", id);
+
+	return size;
+}
+
+#define MBI_INFOHDR 128
+#define MBI_ZERO1 0
+#define MBI_NAMELEN 1
+#define MBI_ZERO2 74
+#define MBI_ZERO3 82
+#define MBI_DFLEN 83
+#define MBI_RFLEN 87
+#define MAXNAMELEN 63
+
+bool MacResExtractor::init(File in) {
+	byte infoHeader[MBI_INFOHDR];
+	int32 data_size, rsrc_size;
+	int32 data_size_pad, rsrc_size_pad;
+	int filelen;
+
+	filelen = in.size();
+	in.read(infoHeader, MBI_INFOHDR);
+
+	// Following should be 0 bytes
+	if(infoHeader[MBI_ZERO1] != 0) return false;
+
+	if(infoHeader[MBI_ZERO2] != 0) return false;
+
+	if(infoHeader[MBI_ZERO3] != 0) return false;
+
+	// Filename has a length range
+	if(infoHeader[MBI_NAMELEN] > MAXNAMELEN) return false;
+
+	// Pull out fork lengths
+	data_size = READ_BE_UINT32(infoHeader + MBI_DFLEN);
+	rsrc_size = READ_BE_UINT32(infoHeader + MBI_RFLEN);
+
+	data_size_pad = (((data_size + 127) >> 7) << 7);
+	rsrc_size_pad = (((rsrc_size + 127) >> 7) << 7);
+
+	// Length check
+	int sumlen =  MBI_INFOHDR + data_size_pad + rsrc_size_pad;
+	if(sumlen != filelen) return false;
+
+	_resOffset = MBI_INFOHDR + data_size_pad;
+
+	in.seek(_resOffset);
+
+	_dataOffset = in.readUint32BE() + _resOffset;
+	_mapOffset = in.readUint32BE() + _resOffset;
+	_dataLength = in.readUint32BE();
+	_mapLength = in.readUint32BE();
+
+	debug(0, "got header: data %d [%d] map %d [%d]", 
+		_dataOffset, _dataLength, _mapOffset, _mapLength);
+
+	readMap(in);
+
+	return true;
+}
+
+byte *MacResExtractor::getResource(File in, const char *typeID, int16 resID, int *size) {
+	int	i;
+	int typeNum = -1;
+	int resNum = -1;
+	byte *buf;
+	int len;
+	
+	for (i = 0; i < _resMap.numTypes; i++)
+		if (strcmp(_resTypes[i].id, typeID) == 0) {
+			typeNum = i;
+			break;
+		}
+
+	if (typeNum == -1)
+		return NULL;
+
+	for (i = 0; i < _resTypes[typeNum].items; i++)
+		if (_resLists[typeNum][i].id == resID) {
+			resNum = i;
+			break;
+		}
+
+	if (resNum == -1)
+		return NULL;
+
+	in.seek(_dataOffset + _resLists[typeNum][resNum].dataOffset);
+
+	len = in.readUint32BE();
+	buf = (byte *)malloc(len);
+
+	in.read(buf, len);
+
+	*size = len;
+
+	return buf;
+}
+
+void MacResExtractor::readMap(File in) {
+	int	i, j, len;
+	
+	in.seek(_mapOffset + 22);
+
+	_resMap.resAttr = in.readUint16BE();
+	_resMap.typeOffset = in.readUint16BE();
+	_resMap.nameOffset = in.readUint16BE();
+	_resMap.numTypes = in.readUint16BE();
+	_resMap.numTypes++;
+
+	debug(0, "Read %d types, type offset %d, name offset %d", _resMap.numTypes,
+		_resMap.typeOffset, _resMap.nameOffset);
+
+	in.seek(_mapOffset + _resMap.typeOffset + 2);
+	_resTypes = new ResType[_resMap.numTypes];
+
+	for (i = 0; i < _resMap.numTypes; i++) {
+		in.read(_resTypes[i].id, 4);
+		_resTypes[i].items = in.readUint16BE();
+		_resTypes[i].offset = in.readUint16BE();
+		_resTypes[i].items++;
+	}
+	
+	for (i = 0; i < _resMap.numTypes; i++) {
+		debug(0, "resource '%c%c%c%c': items %d, offset %d", 
+			_resTypes[i].id[0], _resTypes[i].id[1], 
+			_resTypes[i].id[2], _resTypes[i].id[3],
+			_resTypes[i].items, _resTypes[i].offset);
+	}	
+
+	_resLists = new ResPtr[_resMap.numTypes];
+	
+	for (i = 0; i < _resMap.numTypes; i++) {
+		_resLists[i] = new Resource[_resTypes[i].items];
+		in.seek(_resTypes[i].offset + _mapOffset + _resMap.typeOffset);
+
+		for (j = 0; j < _resTypes[i].items; j++) {
+			ResPtr resPtr = _resLists[i] + j;
+			
+			resPtr->id = in.readUint16BE();
+			resPtr->nameOffset = in.readUint16BE();
+			resPtr->dataOffset = in.readUint32BE();
+			in.readUint32BE();
+			resPtr->name = 0;
+			
+			resPtr->attr = resPtr->dataOffset >> 24;
+			resPtr->dataOffset &= 0xFFFFFF;
+
+			debug(0, "resource '%c%c%c%c' %d: name %d, data %d, attr %d", 
+				_resTypes[i].id[0], _resTypes[i].id[1], 
+				_resTypes[i].id[2], _resTypes[i].id[3],
+				resPtr->id, resPtr->nameOffset, resPtr->dataOffset, resPtr->attr);
+		}
+
+		for (j = 0; j < _resTypes[i].items; j++) {
+			if (_resLists[i][j].nameOffset != -1) {
+				in.seek(_resLists[i][j].nameOffset + _mapOffset + _resMap.nameOffset);
+				
+				len = in.readByte();
+				_resLists[i][j].name = new byte[len + 1];
+				_resLists[i][j].name[len] = 0;
+				in.read(_resLists[i][j].name, len);
+				debug(0, "name of %d: %s", _resLists[i][j].id, _resLists[i][j].name);
+			}
+		}
+	}
+}
+
+void MacResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
+							int *hotspot_x, int *hotspot_y, int *keycolor) {
+	Common::MemoryReadStream dis(data, datasize);
+	int i, b;
+	byte imageByte;
+	int ignored;
+
+	ignored = dis.readUint16BE(); // type
+	ignored = dis.readUint32BE(); // offset to pixle map
+	ignored = dis.readUint32BE(); // offset to pixel data
+	ignored = dis.readUint32BE(); // expanded cursor data
+	ignored = dis.readUint16BE(); // expanded data depth
+	ignored = dis.readUint32BE(); // reserved
+	  
+	// Grab icon data
+	*cursor = (byte *)malloc(256);
+	for (i = 0; i < 32; i++) {
+		imageByte = dis.readByte();
+		for (b = 0; b < 8; b++)
+			cursor[0][i*8+b] = (byte)((imageByte &
+									  (0x80 >> b)) > 0? 0x0F: 0x00);
+	}
+
+	// Grab mask data
+	for (i = 0; i < 32; i++) {
+		imageByte = dis.readByte();
+		for (b = 0; b < 8; b++)
+			if ((imageByte & (0x80 >> b)) == 0)
+				cursor[0][i*8+b] = 0xff;
+	}
+
+	// Could use DataInputStream - but just 2 bytes
+	*hotspot_y = dis.readUint16BE();
+	*hotspot_x = dis.readUint16BE();
+	*w = *h = 16;
+}
+
 } // End of namespace Scumm

Index: resource_v7he.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/resource_v7he.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- resource_v7he.h	30 Jan 2005 20:38:54 -0000	1.11
+++ resource_v7he.h	31 Jan 2005 03:53:35 -0000	1.12
@@ -481,6 +481,57 @@
 	void fix_win32_image_data_directory(Win32ImageDataDirectory *obj);
 };
 
+class MacResExtractor {
+
+public:
+	MacResExtractor(ScummEngine_v70he *scumm);
+	~MacResExtractor() { }
+	void setCursor(int id) ;
+
+private:
+	int extractResource(int id, byte **buf);
+	bool init(File in);
+	void readMap(File in);
+	byte *getResource(File in, const char *typeID, int16 resID, int *size);
+	void convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
+					 int *hotspot_x, int *hotspot_y, int *keycolor);
+
+	struct ResMap {
+		int16 resAttr;
+		int16 typeOffset;
+		int16 nameOffset;
+		int16 numTypes;
+	};
+
+	struct ResType {
+		char  id[5];
+		int16 items;
+		int16 offset;
+	};
+
+	struct Resource {
+		int16 id;
+		int16 nameOffset;
+		byte  attr;
+		int32 dataOffset;
+		byte  *name;
+	};
+
+	typedef Resource *ResPtr;
+
+private:
+	ScummEngine_v70he *_vm;
+	char _fileName[256];
+	int _resOffset;
+	int32 _dataOffset;
+	int32 _dataLength;
+	int32 _mapOffset;
+	int32 _mapLength;
+	ResMap _resMap;
+	ResType *_resTypes;
+	ResPtr  *_resLists;
+}; 
+
 } // End of namespace Scumm
 
 #endif

Index: scumm.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.cpp,v
retrieving revision 1.309
retrieving revision 1.310
diff -u -d -r1.309 -r1.310
--- scumm.cpp	30 Jan 2005 05:11:04 -0000	1.309
+++ scumm.cpp	31 Jan 2005 03:53:35 -0000	1.310
@@ -1046,6 +1046,7 @@
 ScummEngine_v70he::ScummEngine_v70he(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs, uint8 md5sum[16])
  : ScummEngine_v60he(detector, syst, gs, md5sum) {
 	 _win32ResExtractor = new Win32ResExtractor(this);
+	 _macResExtractor = new MacResExtractor(this);
 
 	_heSndSoundId = 0;
 	_heSndOffset = 0;
@@ -2763,10 +2764,15 @@
 
 	for (int i = cont; i < ARRAYSIZE(heMacFileNameTable); i++) {
 		if (!scumm_strnicmp(filename, heMacFileNameTable[i].winName, len)) {
-			if (heMacFileNameTable[i].hasParens)
-				snprintf(buf, bufsize, "%s (%c)", heMacFileNameTable[i].macName, num);
-			else 
-				snprintf(buf, bufsize, "%s %c", heMacFileNameTable[i].macName, num);
+			if (num == '3') { // special case for cursors
+				// For mac they're stored in game binary
+				strncpy(buf, heMacFileNameTable[i].macName, bufsize);
+			} else {
+				if (heMacFileNameTable[i].hasParens)
+					snprintf(buf, bufsize, "%s (%c)", heMacFileNameTable[i].macName, num);
+				else 
+					snprintf(buf, bufsize, "%s %c", heMacFileNameTable[i].macName, num);
+			}
 
 			return i;
 		}





More information about the Scummvm-git-logs mailing list