[Scummvm-cvs-logs] SF.net SVN: scummvm:[44388] scummvm/trunk/engines/sci

wjpalenstijn at users.sourceforge.net wjpalenstijn at users.sourceforge.net
Sun Sep 27 03:50:26 CEST 2009


Revision: 44388
          http://scummvm.svn.sourceforge.net/scummvm/?rev=44388&view=rev
Author:   wjpalenstijn
Date:     2009-09-27 01:50:26 +0000 (Sun, 27 Sep 2009)

Log Message:
-----------
SCI: Major string handling update.

All string access to segments should now work with both raw and non-raw
(reg_t) segments, using the new utility functions in segMan.

There will likely be regressions.

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/kernel.h
    scummvm/trunk/engines/sci/engine/kfile.cpp
    scummvm/trunk/engines/sci/engine/kgraphics.cpp
    scummvm/trunk/engines/sci/engine/kmenu.cpp
    scummvm/trunk/engines/sci/engine/kmisc.cpp
    scummvm/trunk/engines/sci/engine/kpathing.cpp
    scummvm/trunk/engines/sci/engine/kstring.cpp
    scummvm/trunk/engines/sci/gfx/gfx_gui.cpp
    scummvm/trunk/engines/sci/gfx/gfx_state_internal.h
    scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp
    scummvm/trunk/engines/sci/gfx/menubar.cpp
    scummvm/trunk/engines/sci/gfx/menubar.h

Modified: scummvm/trunk/engines/sci/engine/kernel.h
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.h	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/engine/kernel.h	2009-09-27 01:50:26 UTC (rev 44388)
@@ -216,9 +216,9 @@
  * @param s The current state
  * @param address The address to look up
  * @param index The relative index
- * @return The referenced text, or NULL on error.
+ * @return The referenced text, or empty string on error.
  */
-char *kernel_lookup_text(EngineState *s, reg_t address, int index);
+Common::String kernel_lookup_text(EngineState *s, reg_t address, int index);
 
 /******************** Priority macros/functions ********************/
 /**

Modified: scummvm/trunk/engines/sci/engine/kfile.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kfile.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/engine/kfile.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -197,11 +197,11 @@
 }
 
 reg_t kFOpen(EngineState *s, int, int argc, reg_t *argv) {
-	char *name = s->segMan->derefString(argv[0]);
+	Common::String name = s->segMan->getString(argv[0]);
 	int mode = argv[1].toUint16();
 
-	debug(3, "kFOpen(%s,0x%x)", name, mode);
-	file_open(s, name, mode);
+	debug(3, "kFOpen(%s,0x%x)", name.c_str(), mode);
+	file_open(s, name.c_str(), mode);
 	return s->r_acc;
 }
 
@@ -250,9 +250,9 @@
 
 reg_t kFPuts(EngineState *s, int, int argc, reg_t *argv) {
 	int handle = argv[0].toUint16();
-	char *data = s->segMan->derefString(argv[1]);
+	Common::String data = s->segMan->getString(argv[1]);
 
-	fwrite_wrapper(s, handle, data, strlen(data));
+	fwrite_wrapper(s, handle, data.c_str(), data.size());
 	return s->r_acc;
 }
 
@@ -307,12 +307,13 @@
 }
 
 reg_t kFGets(EngineState *s, int, int argc, reg_t *argv) {
-	char *dest = s->segMan->derefString(argv[0]);
 	int maxsize = argv[1].toUint16();
+	char *buf = new char[maxsize];
 	int handle = argv[2].toUint16();
 
 	debug(3, "kFGets(%d,%d)", handle, maxsize);
-	fgets_wrapper(s, dest, maxsize, handle);
+	fgets_wrapper(s, buf, maxsize, handle);
+	s->segMan->memcpy(argv[0], (const byte*)buf, maxsize);
 	return argv[0];
 }
 
@@ -320,14 +321,12 @@
  * Writes the cwd to the supplied address and returns the address in acc.
  */
 reg_t kGetCWD(EngineState *s, int, int argc, reg_t *argv) {
-	char *targetaddr = s->segMan->derefString(argv[0]);
-
 	// We do not let the scripts see the file system, instead pretending
 	// we are always in the same directory.
 	// TODO/FIXME: Is "/" a good value? Maybe "" or "." or "C:\" are better?
-	strcpy(targetaddr, "/");
+	s->segMan->strcpy(argv[0], "/");
 
-	debug(3, "kGetCWD() -> %s", targetaddr);
+	debug(3, "kGetCWD() -> %s", "/");
 
 	return argv[0];
 }
@@ -352,58 +351,50 @@
 
 reg_t kDeviceInfo(EngineState *s, int, int argc, reg_t *argv) {
 	int mode = argv[0].toUint16();
-	char *game_prefix, *input_s, *output_s;
 
 	switch (mode) {
-	case K_DEVICE_INFO_GET_DEVICE:
-		input_s = s->segMan->derefString(argv[1]);
-		output_s = s->segMan->derefString(argv[2]);
-		assert(input_s != output_s);
+	case K_DEVICE_INFO_GET_DEVICE: {
+		Common::String input_str = s->segMan->getString(argv[1]);
 
-		strcpy(output_s, "/");
-		debug(3, "K_DEVICE_INFO_GET_DEVICE(%s) -> %s", input_s, output_s);
+		s->segMan->strcpy(argv[2], "/");
+		debug(3, "K_DEVICE_INFO_GET_DEVICE(%s) -> %s", input_str.c_str(), "/");
 		break;
-
+	}
 	case K_DEVICE_INFO_GET_CURRENT_DEVICE:
-		output_s = s->segMan->derefString(argv[1]);
-
-		strcpy(output_s, "/");
-		debug(3, "K_DEVICE_INFO_GET_CURRENT_DEVICE() -> %s", output_s);
+		s->segMan->strcpy(argv[1], "/");
+		debug(3, "K_DEVICE_INFO_GET_CURRENT_DEVICE() -> %s", "/");
 		break;
 
 	case K_DEVICE_INFO_PATHS_EQUAL: {
-		char *path1_s = s->segMan->derefString(argv[1]);
-		char *path2_s = s->segMan->derefString(argv[2]);
-		debug(3, "K_DEVICE_INFO_PATHS_EQUAL(%s,%s)", path1_s, path2_s);
+		Common::String path1_s = s->segMan->getString(argv[1]);
+		Common::String path2_s = s->segMan->getString(argv[2]);
+		debug(3, "K_DEVICE_INFO_PATHS_EQUAL(%s,%s)", path1_s.c_str(), path2_s.c_str());
 
-		return make_reg(0, Common::matchString(path2_s, path1_s, false, true));
+		return make_reg(0, Common::matchString(path2_s.c_str(), path1_s.c_str(), false, true));
 		}
 		break;
 
-	case K_DEVICE_INFO_IS_FLOPPY:
-		input_s = s->segMan->derefString(argv[1]);
-		debug(3, "K_DEVICE_INFO_IS_FLOPPY(%s)", input_s);
+	case K_DEVICE_INFO_IS_FLOPPY: {
+		Common::String input_str = s->segMan->getString(argv[1]);
+		debug(3, "K_DEVICE_INFO_IS_FLOPPY(%s)", input_str.c_str());
 		return NULL_REG; /* Never */
-
+	}
 	/* SCI uses these in a less-than-portable way to delete savegames.
 	** Read http://www-plan.cs.colorado.edu/creichen/freesci-logs/2005.10/log20051019.html
 	** for more information on our workaround for this.
 	*/
 	case K_DEVICE_INFO_GET_SAVECAT_NAME: {
-		output_s = s->segMan->derefString(argv[1]);
-		game_prefix = s->segMan->derefString(argv[2]);
-
-		sprintf(output_s, "__throwaway");
-		debug(3, "K_DEVICE_INFO_GET_SAVECAT_NAME(%s) -> %s", game_prefix, output_s);
+		Common::String game_prefix = s->segMan->getString(argv[2]);
+		s->segMan->strcpy(argv[1], "__throwaway");
+		debug(3, "K_DEVICE_INFO_GET_SAVECAT_NAME(%s) -> %s", game_prefix.c_str(), "__throwaway");
 		}
 
 	break;
 	case K_DEVICE_INFO_GET_SAVEFILE_NAME: {
-		output_s = s->segMan->derefString(argv[1]);
-		game_prefix = s->segMan->derefString(argv[2]);
+		Common::String game_prefix = s->segMan->getString(argv[2]);
 		int savegame_id = argv[3].toUint16();
-		sprintf(output_s, "__throwaway");
-		debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix, savegame_id, output_s);
+		s->segMan->strcpy(argv[1], "__throwaway");
+		debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix.c_str(), savegame_id, "__throwaway");
 		delete_savegame(s, savegame_id);
 		}
 		break;
@@ -428,9 +419,9 @@
 }
 
 reg_t kCheckFreeSpace(EngineState *s, int, int argc, reg_t *argv) {
-	char *path = s->segMan->derefString(argv[0]);
+	Common::String path = s->segMan->getString(argv[0]);
 
-	debug(3, "kCheckFreeSpace(%s)", path);
+	debug(3, "kCheckFreeSpace(%s)", path.c_str());
 	// We simply always pretend that there is enough space.
 	// The alternative would be to write a big test file, which is not nice
 	// on systems where doing so is very slow.
@@ -486,10 +477,10 @@
 }
 
 reg_t kCheckSaveGame(EngineState *s, int, int argc, reg_t *argv) {
-	char *game_id = s->segMan->derefString(argv[0]);
+	Common::String game_id = s->segMan->getString(argv[0]);
 	int savedir_nr = argv[1].toUint16();
 
-	debug(3, "kCheckSaveGame(%s, %d)", game_id, savedir_nr);
+	debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), savedir_nr);
 
 	Common::Array<SavegameDesc> saves;
 	listSavegames(saves);
@@ -522,12 +513,11 @@
 }
 
 reg_t kGetSaveFiles(EngineState *s, int, int argc, reg_t *argv) {
-	char *game_id = s->segMan->derefString(argv[0]);
-	char *nametarget = s->segMan->derefString(argv[1]);
-	reg_t nametarget_base = argv[1];
+	Common::String game_id = s->segMan->getString(argv[0]);
+	reg_t nametarget = argv[1];
 	reg_t *nameoffsets = s->segMan->derefRegPtr(argv[2], 0);
 
-	debug(3, "kGetSaveFiles(%s,%s)", game_id, nametarget);
+	debug(3, "kGetSaveFiles(%s)", game_id.c_str());
 
 	Common::Array<SavegameDesc> saves;
 	listSavegames(saves);
@@ -556,29 +546,34 @@
 				++s->r_acc.offset; // Increase number of files found
 
 				nameoffsets++; // Make sure the next ID string address is written to the next pointer
-				strncpy(nametarget, meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH); // Copy identifier string
-				*(nametarget + SCI_MAX_SAVENAME_LENGTH - 1) = 0; // Make sure it's terminated
-				nametarget += SCI_MAX_SAVENAME_LENGTH; // Increase name offset pointer accordingly
-				nametarget_base.offset += SCI_MAX_SAVENAME_LENGTH;
+				Common::String name = meta.savegame_name;
+				if (name.size() > SCI_MAX_SAVENAME_LENGTH-1)
+					name = Common::String(meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH-1);
+				s->segMan->strcpy(nametarget, name.c_str());
+
+				// Increase name offset pointer accordingly
+				nametarget.offset += SCI_MAX_SAVENAME_LENGTH;
 			}
 			delete in;
 		}
 	}
 
 	//free(gfname);
-	*nametarget = 0; // Terminate list
+	s->segMan->strcpy(nametarget, ""); // Terminate list
 
 	return s->r_acc;
 }
 
 reg_t kSaveGame(EngineState *s, int, int argc, reg_t *argv) {
-	char *game_id = s->segMan->derefString(argv[0]);
+	Common::String game_id = s->segMan->getString(argv[0]);
 	int savedir_nr = argv[1].toUint16();
 	int savedir_id; // Savegame ID, derived from savedir_nr and the savegame ID list
-	char *game_description = s->segMan->derefString(argv[2]);
-	char *version = argc > 3 ? strdup(s->segMan->derefString(argv[3])) : NULL;
+	Common::String game_description = s->segMan->getString(argv[2]);
+	Common::String version;
+	if (argc > 3)
+		version = s->segMan->getString(argv[3]);
 
-	debug(3, "kSaveGame(%s,%d,%s,%s)", game_id, savedir_nr, game_description, version);
+	debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), savedir_nr, game_description.c_str(), version.c_str());
 
 	Common::Array<SavegameDesc> saves;
 	listSavegames(saves);
@@ -623,7 +618,7 @@
 		return NULL_REG;
 	}
 
-	if (gamestate_save(s, out, game_description, version)) {
+	if (gamestate_save(s, out, game_description.c_str(), version.c_str())) {
 		warning("Saving the game failed.");
 		s->r_acc = NULL_REG;
 	} else {
@@ -642,10 +637,10 @@
 }
 
 reg_t kRestoreGame(EngineState *s, int, int argc, reg_t *argv) {
-	char *game_id = s->segMan->derefString(argv[0]);
+	Common::String game_id = s->segMan->getString(argv[0]);
 	int savedir_nr = argv[1].toUint16();
 
-	debug(3, "kRestoreGame(%s,%d)", game_id, savedir_nr);
+	debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savedir_nr);
 
 	Common::Array<SavegameDesc> saves;
 	listSavegames(saves);
@@ -668,7 +663,7 @@
 				shrink_execution_stack(s, s->execution_stack_base + 1);
 			} else {
 				s->r_acc = make_reg(0, 1);
-				warning("Restoring failed (game_id = '%s')", game_id);
+				warning("Restoring failed (game_id = '%s')", game_id.c_str());
 			}
 			return s->r_acc;
 		}
@@ -681,12 +676,12 @@
 }
 
 reg_t kValidPath(EngineState *s, int, int argc, reg_t *argv) {
-	const char *path = s->segMan->derefString(argv[0]);
+	Common::String path = s->segMan->getString(argv[0]);
 
 	// FIXME: For now, we only accept the (fake) root dir "/" as a valid path.
-	s->r_acc = make_reg(0, 0 == strcmp(path, "/"));
+	s->r_acc = make_reg(0, path == "/");
 
-	debug(3, "kValidPath(%s) -> %d", path, s->r_acc.offset);
+	debug(3, "kValidPath(%s) -> %d", path.c_str(), s->r_acc.offset);
 
 	return s->r_acc;
 }
@@ -732,14 +727,12 @@
 		return;
 	}
 
-	char *mem = _vm->segMan->derefString(_outbuffer);
-	memset(mem, 0, 13);
-
 	// TODO: Transform the string back into a format usable by the SCI scripts.
 	// I.e., strip any TARGET- prefix.
-	const char *string = _iter->c_str();
-	assert(string);
-	strncpy(mem, string, 12);
+	Common::String string = *_iter;
+	if (string.size() > 12)
+		string = Common::String(string.c_str(), 12);
+	_vm->segMan->strcpy(_outbuffer, string.c_str());
 
 	// Return the result and advance the list iterator :)
 	_vm->r_acc = _outbuffer;
@@ -753,11 +746,11 @@
 
 	switch (func_nr) {
 	case K_FILEIO_OPEN : {
-		char *name = s->segMan->derefString(argv[1]);
+		Common::String name = s->segMan->getString(argv[1]);
 		int mode = argv[2].toUint16();
 
-		file_open(s, name, mode);
-		debug(3, "K_FILEIO_OPEN(%s,0x%x)", name, mode);
+		file_open(s, name.c_str(), mode);
+		debug(3, "K_FILEIO_OPEN(%s,0x%x)", name.c_str(), mode);
 		break;
 	}
 	case K_FILEIO_CLOSE : {
@@ -769,25 +762,29 @@
 	}
 	case K_FILEIO_READ_RAW : {
 		int handle = argv[1].toUint16();
-		char *dest = s->segMan->derefString(argv[2]);
 		int size = argv[3].toUint16();
+		char *buf = new char[size];
 		debug(3, "K_FILEIO_READ_RAW(%d,%d)", handle, size);
 
-		fread_wrapper(s, dest, size, handle);
+		fread_wrapper(s, buf, size, handle);
+		s->segMan->memcpy(argv[2], (const byte*)buf, size);
+		delete[] buf;
 		break;
 	}
 	case K_FILEIO_WRITE_RAW : {
 		int handle = argv[1].toUint16();
-		char *buf = s->segMan->derefString(argv[2]);
 		int size = argv[3].toUint16();
+		char *buf = new char[size];
+		s->segMan->memcpy((byte*)buf, argv[2], size);
 		debug(3, "K_FILEIO_WRITE_RAW(%d,%d)", handle, size);
 
 		fwrite_wrapper(s, handle, buf, size);
+		delete[] buf;
 		break;
 	}
 	case K_FILEIO_UNLINK : {
-		char *name = s->segMan->derefString(argv[1]);
-		debug(3, "K_FILEIO_UNLINK(%s)", name);
+		Common::String name = s->segMan->getString(argv[1]);
+		debug(3, "K_FILEIO_UNLINK(%s)", name.c_str());
 
 		Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
 		const Common::String wrappedName = ((Sci::SciEngine*)g_engine)->wrapFilename(name);
@@ -797,25 +794,27 @@
 		break;
 	}
 	case K_FILEIO_READ_STRING : {
-		char *dest = s->segMan->derefString(argv[1]);
 		int size = argv[2].toUint16();
+		char *buf = new char[size];
 		int handle = argv[3].toUint16();
 		debug(3, "K_FILEIO_READ_STRING(%d,%d)", handle, size);
 
-		fgets_wrapper(s, dest, size, handle);
+		fgets_wrapper(s, buf, size, handle);
+		s->segMan->memcpy(argv[1], (const byte*)buf, size);
+		delete[] buf;
 		return argv[1];
 	}
 	case K_FILEIO_WRITE_STRING : {
 		int handle = argv[1].toUint16();
 		int size = argv[3].toUint16();
-		char *buf = s->segMan->derefString(argv[2]);
+		Common::String str = s->segMan->getString(argv[2]);
 		debug(3, "K_FILEIO_WRITE_STRING(%d,%d)", handle, size);
 
 		// CHECKME: Is the size parameter used at all?
 		// In the LSL5 password protection it is zero, and we should
 		// then write a full string. (Not sure if it should write the
 		// terminating zero.)
-		fwrite_wrapper(s, handle, buf, strlen(buf));
+		fwrite_wrapper(s, handle, str.c_str(), str.size());
 		break;
 	}
 	case K_FILEIO_SEEK : {
@@ -828,16 +827,16 @@
 		break;
 	}
 	case K_FILEIO_FIND_FIRST : {
-		char *mask = s->segMan->derefString(argv[1]);
+		Common::String mask = s->segMan->getString(argv[1]);
 		reg_t buf = argv[2];
 		int attr = argv[3].toUint16(); // We won't use this, Win32 might, though...
-		debug(3, "K_FILEIO_FIND_FIRST(%s,0x%x)", mask, attr);
+		debug(3, "K_FILEIO_FIND_FIRST(%s,0x%x)", mask.c_str(), attr);
 
 #ifndef WIN32
-		if (strcmp(mask, "*.*") == 0)
-			strcpy(mask, "*"); // For UNIX
+		if (mask == "*.*")
+			mask = "*"; // For UNIX
 #endif
-		s->_dirseeker.firstFile(mask, buf);
+		s->_dirseeker.firstFile(mask.c_str(), buf);
 
 		break;
 	}
@@ -847,7 +846,7 @@
 		break;
 	}
 	case K_FILEIO_FILE_EXISTS : {
-		char *name = s->segMan->derefString(argv[1]);
+		Common::String name = s->segMan->getString(argv[1]);
 
 		// Check for regular file
 		bool exists = Common::File::exists(name);
@@ -859,7 +858,7 @@
 			exists = !saveFileMan->listSavefiles(name).empty();
 		}
 
-		debug(3, "K_FILEIO_FILE_EXISTS(%s) -> %d", name, exists);
+		debug(3, "K_FILEIO_FILE_EXISTS(%s) -> %d", name.c_str(), exists);
 		return make_reg(0, exists);
 	}
 	default :

Modified: scummvm/trunk/engines/sci/engine/kgraphics.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kgraphics.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/engine/kgraphics.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -445,7 +445,7 @@
 
 	newport = sciw_new_window(s, port->zone, port->_font, port->_color, newbgcolor,
 	                          s->titlebar_port->_font, s->ega_colors[15], s->ega_colors[8],
-	                          port->title_text, port->port_flags & ~kWindowTransparent);
+	                          port->_title_text.c_str(), port->port_flags & ~kWindowTransparent);
 
 	if (s->dyn_views) {
 		int found = 0;
@@ -602,29 +602,32 @@
 
 reg_t kTextSize(EngineState *s, int, int argc, reg_t *argv) {
 	int width, height;
-	char *text = argv[1].segment ? s->segMan->derefString(argv[1]) : NULL;
-	const char *sep = NULL; 
+	Common::String text = s->segMan->getString(argv[1]);
 	reg_t *dest = s->segMan->derefRegPtr(argv[0], 4);
 	int maxwidth = (argc > 3) ? argv[3].toUint16() : 0;
 	int font_nr = argv[2].toUint16();
 
-	if ((argc > 4) && (argv[4].segment))
-		sep = s->segMan->derefString(argv[4]);
+	Common::String sep_str;
+	const char *sep = NULL; 
+	if ((argc > 4) && (argv[4].segment)) {
+		sep_str = s->segMan->getString(argv[4]);
+		sep = sep_str.c_str();
+	}
 
 	if (maxwidth < 0)
 		maxwidth = 0;
 
 	dest[0] = dest[1] = NULL_REG;
 
-	if (!text || !*text || !dest) { // Empty text
+	if (text.empty() || !dest) { // Empty text
 		dest[2] = dest[3] = make_reg(0, 0);
 		debugC(2, kDebugLevelStrings, "GetTextSize: Empty string\n");
 		return s->r_acc;
 	}
 
-	gfxop_get_text_params(s->gfx_state, font_nr, s->strSplit(text, sep).c_str(), maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
+	gfxop_get_text_params(s->gfx_state, font_nr, s->strSplit(text.c_str(), sep).c_str(), maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
 	                                 &width, &height, 0, NULL, NULL, NULL);
-	debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text, width, height);
+	debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text.c_str(), width, height);
 
 	dest[2] = make_reg(0, height);
 //	dest[3] = make_reg(0, maxwidth? maxwidth : width);
@@ -1303,7 +1306,9 @@
 
 static void disableCertainButtons(SegManager *segMan, Common::String gameName, reg_t obj) {
 	reg_t text_pos = GET_SEL32(obj, text);
-	char *text = text_pos.isNull() ? NULL : segMan->derefString(text_pos);
+	Common::String text;
+	if (!text_pos.isNull())
+		text = segMan->getString(text_pos);
 	int type = GET_SEL32V(obj, type);
 	int state = GET_SEL32V(obj, state);
 
@@ -1327,15 +1332,15 @@
 	 * that game - bringing the save/load dialog on a par with SCI0.
 	 */
 	// NOTE: This _only_ works with the English version
-	if (type == K_CONTROL_BUTTON && text && (gameName == "sq4") &&
-			getSciVersion() < SCI_VERSION_1_1 && !strcmp(text, " Delete ")) {
+	if (type == K_CONTROL_BUTTON && (gameName == "sq4") &&
+			getSciVersion() < SCI_VERSION_1_1 && text == " Delete ") {
 		PUT_SEL32V(obj, state, (state | kControlStateDisabled) & ~kControlStateEnabled);
 	}
 
 	// Disable the "Change Directory" button, as we don't allow the game engine to
 	// change the directory where saved games are placed
 	// NOTE: This _only_ works with the English version
-	if (type == K_CONTROL_BUTTON && text && !strcmp(text, "Change\r\nDirectory")) {
+	if (type == K_CONTROL_BUTTON && text == "Change\r\nDirectory") {
 		PUT_SEL32V(obj, state, (state | kControlStateDisabled) & ~kControlStateEnabled);
 	}
 }
@@ -1369,13 +1374,13 @@
 
 #define _K_EDIT_DELETE \
 	if (cursor < textlen) { \
-		memmove(text + cursor, text + cursor + 1, textlen - cursor +1); \
+		text.deleteChar(cursor); \
 	}
 
 #define _K_EDIT_BACKSPACE \
 	if (cursor) { \
 		--cursor;    \
-		memmove(text + cursor, text + cursor + 1, textlen - cursor +1); \
+		text.deleteChar(cursor); \
 		--textlen; \
 	}
 
@@ -1401,15 +1406,17 @@
 				reg_t text_pos = GET_SEL32(obj, text);
 				int display_offset = 0;
 
-				char *text = s->segMan->derefString(text_pos);
+				Common::String text = s->segMan->getString(text_pos);
 				int textlen;
 
+#if 0
 				if (!text) {
 					warning("Could not draw control: %04x:%04x does not reference text", PRINT_REG(text_pos));
 					return s->r_acc;
 				}
+#endif
 
-				textlen = strlen(text);
+				textlen = text.size();
 
 				cursor += display_offset;
 
@@ -1432,7 +1439,7 @@
 						if (cursor > 0) --cursor;
 						break;
 					case 'k':
-						text[cursor] = 0;
+						text = Common::String(text.c_str(), cursor);
 						break; // Terminate string
 					case 'h':
 						_K_EDIT_BACKSPACE;
@@ -1503,20 +1510,20 @@
 
 					if (cursor == textlen) {
 						if (textlen < max) {
-							text[cursor++] = key;
-							text[cursor] = 0; // Terminate string
+							text += key;
+							cursor++;
 						}
 					} else if (inserting) {
 						if (textlen < max) {
 							int i;
 
 							for (i = textlen + 2; i >= cursor; i--)
-								text[i] = text[i - 1];
-							text[cursor++] = key;
+								text.setChar(text[i - 1], i);
+							text.setChar(key, cursor++);
 
 						}
 					} else { // Overwriting
-						text[cursor++] = key;
+						text.setChar(key, cursor++);
 					}
 
 					if (max_displayed < max)
@@ -1528,6 +1535,7 @@
 				}
 
 				PUT_SEL32V(obj, cursor, cursor); // Write back cursor position
+				s->segMan->strcpy(text_pos, text.c_str()); // Write back string
 			}
 
 		case K_CONTROL_ICON:
@@ -1564,7 +1572,9 @@
 
 	int font_nr = GET_SEL32V(obj, font);
 	reg_t text_pos = GET_SEL32(obj, text);
-	const char *text = text_pos.isNull() ? NULL : s->segMan->derefString(text_pos);
+	Common::String text;
+	if (!text_pos.isNull())
+		text = s->segMan->getString(text_pos);
 	int view = GET_SEL32V(obj, view);
 	int cel = sign_extend_byte(GET_SEL32V(obj, cel));
 	int loop = sign_extend_byte(GET_SEL32V(obj, loop));
@@ -1578,7 +1588,7 @@
 	switch (type) {
 	case K_CONTROL_BUTTON:
 		debugC(2, kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y);
-		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, s->strSplit(text, NULL).c_str(), font_nr,
+		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, s->strSplit(text.c_str(), NULL).c_str(), font_nr,
 		                          (int8)(state & kControlStateFramed), (int8)inverse, (int8)(state & kControlStateDisabled)));
 		break;
 
@@ -1587,7 +1597,7 @@
 
 		debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x to %d,%d, mode=%d\n", PRINT_REG(obj), x, y, mode);
 
-		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, s->strSplit(text).c_str(), font_nr, mode,
+		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, s->strSplit(text.c_str()).c_str(), font_nr, mode,
 									(int8)(!!(state & kControlStateDitherFramed)), (int8)inverse));
 		break;
 
@@ -1597,11 +1607,11 @@
 		max = GET_SEL32V(obj, max);
 		cursor = GET_SEL32V(obj, cursor);
 
-		if (cursor > (signed)strlen(text))
-			cursor = strlen(text);
+		if (cursor > (signed)text.size())
+			cursor = text.size();
 
 //		update_cursor_limits(&s->save_dir_edit_offset, &cursor, max);	FIXME: get rid of this?
-		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_edit_control(s->port, obj, area, text, font_nr, (unsigned)cursor, (int8)inverse));
+		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_edit_control(s->port, obj, area, text.c_str(), font_nr, (unsigned)cursor, (int8)inverse));
 		break;
 
 	case K_CONTROL_ICON:
@@ -1614,8 +1624,6 @@
 
 	case K_CONTROL_CONTROL:
 	case K_CONTROL_CONTROL_ALIAS: {
-		const char **entries_list = NULL;
-		const char *seeker;
 		int entries_nr;
 		int lsTop = GET_SEL32V(obj, lsTop) - text_pos.offset;
 		int list_top = 0;
@@ -1627,29 +1635,41 @@
 		cursor = GET_SEL32V(obj, cursor) - text_pos.offset;
 
 		entries_nr = 0;
-		seeker = text;
-		while (seeker[0]) { // Count string entries in NULL terminated string list
+
+		// NOTE: most types of pointer dereferencing don't like odd offsets
+		assert((entry_size & 1) == 0);
+
+		reg_t seeker = text_pos;
+		// Count string entries in NULL terminated string list
+		while (s->segMan->strlen(seeker) > 0) {
 			++entries_nr;
-			seeker += entry_size;
+			seeker.offset += entry_size;
 		}
 
+		// TODO: This is rather convoluted... It would be a lot cleaner
+		// if sciw_new_list_control would take a list of Common::String
+		Common::String *strings = 0;
+		const char **entries_list = NULL;
+
 		if (entries_nr) { // determine list_top, selection, and the entries_list
-			seeker = text;
+			seeker = text_pos;
 			entries_list = (const char**)malloc(sizeof(char *) * entries_nr);
+			strings = new Common::String[entries_nr];
 			for (i = 0; i < entries_nr; i++) {
-				entries_list[i] = seeker;
-				seeker += entry_size	;
-				if ((seeker - text) == lsTop)
+				strings[i] = s->segMan->getString(seeker);
+				entries_list[i] = strings[i].c_str();
+				seeker.offset += entry_size;
+				if ((seeker.offset - text_pos.offset) == lsTop)
 					list_top = i + 1;
-				if ((seeker - text) == cursor)
+				if ((seeker.offset - text_pos.offset) == cursor)
 					selection = i + 1;
 			}
 		}
-
 		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_list_control(s->port, obj, area, font_nr, entries_list, entries_nr,
 		                          list_top, selection, (int8)inverse));
-		if (entries_nr)
-			free(entries_list);
+
+		free(entries_list);
+		delete[] strings;
 	}
 	break;
 
@@ -2511,10 +2531,14 @@
 	lWhite.alpha = 0;
 	lWhite.priority = -1;
 	lWhite.control = -1;
-	const char *title = argv[4 + argextra].segment ? s->segMan->derefString(argv[4 + argextra]) : NULL;
+	Common::String title;
+	if (argv[4 + argextra].segment) {
+		title = s->segMan->getString(argv[4 + argextra]);
+		title = s->strSplit(title.c_str(), NULL);
+	}
 
 	window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->_font, fgcolor, bgcolor,
-							s->titlebar_port->_font, lWhite, black, title ? s->strSplit(title, NULL).c_str() : NULL, flags);
+							s->titlebar_port->_font, lWhite, black, title.c_str(), flags);
 
 	// PQ3 and SCI1.1 games have the interpreter store underBits implicitly
 	if (argextra)
@@ -3113,7 +3137,7 @@
 	int temp;
 	bool save_under = false;
 	gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
-	char *text;
+	Common::String text;
 	GfxPort *port = (s->port) ? s->port : s->picture_port;
 	bool update_immediately = true;
 
@@ -3139,16 +3163,18 @@
 
 	if (textp.segment) {
 		argpt = 1;
-		text = s->segMan->derefString(textp);
+		text = s->segMan->getString(textp);
 	} else {
 		argpt = 2;
 		text = kernel_lookup_text(s, textp, index);
 	}
 
+#if 0
 	if (!text) {
 		error("Display with invalid reference %04x:%04x", PRINT_REG(textp));
 		return NULL_REG;
 	}
+#endif
 
 	while (argpt < argc) {
 		switch (argv[argpt++].toUint16()) {
@@ -3251,7 +3277,7 @@
 
 	if (halign == ALIGN_LEFT) {
 		// If the text does not fit on the screen, move it to the left and upwards until it does
-		gfxop_get_text_params(s->gfx_state, font_nr, text, area.width, &area.width, &area.height, 0, NULL, NULL, NULL);
+		gfxop_get_text_params(s->gfx_state, font_nr, text.c_str(), area.width, &area.width, &area.height, 0, NULL, NULL, NULL);
 
 		// Make the text fit on the screen
 		if (area.x + area.width > 320)
@@ -3275,7 +3301,7 @@
 
 	assert_primary_widget_lists(s);
 
-	text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
+	text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text.c_str()).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
 
 	if (!text_handle) {
 		error("Display: Failed to create text widget");
@@ -3293,7 +3319,7 @@
 		debugC(2, kDebugLevelGraphics, "Saving (%d, %d) size (%d, %d) as %04x:%04x\n", save_area.x, save_area.y, save_area.width, save_area.height, PRINT_REG(s->r_acc));
 	}
 
-	debugC(2, kDebugLevelGraphics, "Display: Commiting text '%s'\n", text);
+	debugC(2, kDebugLevelGraphics, "Display: Commiting text '%s'\n", text.c_str());
 
 	//ADD_TO_CURRENT_PICTURE_PORT(text_handle);
 
@@ -3307,12 +3333,12 @@
 }
 
 static reg_t kShowMovie_Windows(EngineState *s, int argc, reg_t *argv) {
-	const char *filename = s->segMan->derefString(argv[1]);
+	Common::String filename = s->segMan->getString(argv[1]);
 	
 	Graphics::AVIPlayer *player = new Graphics::AVIPlayer(g_system);
 	
 	if (!player->open(filename)) {
-		warning("Failed to open movie file %s", filename);
+		warning("Failed to open movie file %s", filename.c_str());
 		return s->r_acc;
 	}
 	
@@ -3386,13 +3412,13 @@
 }
 
 static reg_t kShowMovie_DOS(EngineState *s, int argc, reg_t *argv) {
-	const char *filename = s->segMan->derefString(argv[0]);
+	Common::String filename = s->segMan->getString(argv[0]);
 	int delay = argv[1].toUint16(); // Time between frames in ticks
 	int frameNr = 0;
 	SeqDecoder seq;
 
 	if (!seq.loadFile(filename) && !seq.loadFile(Common::String("SEQ/") + filename)) {
-		warning("Failed to open movie file %s", filename);
+		warning("Failed to open movie file %s", filename.c_str());
 		return s->r_acc;
 	}
 

Modified: scummvm/trunk/engines/sci/engine/kmenu.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kmenu.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/engine/kmenu.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -34,8 +34,8 @@
 namespace Sci {
 
 reg_t kAddMenu(EngineState *s, int, int argc, reg_t *argv) {
-	char *name = s->segMan->derefString(argv[0]);
-	char *contents = s->segMan->derefString(argv[1]);
+	Common::String name = s->segMan->getString(argv[0]);
+	Common::String contents = s->segMan->getString(argv[1]);
 
 	s->_menubar->addMenu(s->gfx_state, name,
 	                 contents, s->titlebar_port->_font, argv[1]);
@@ -78,8 +78,7 @@
 	s->status_bar_background = bgcolor;
 
 	if (text.segment) {
-		const char *tmp = s->segMan->derefString(text);
-		s->_statusBarText = tmp ? tmp : "";
+		s->_statusBarText = s->segMan->getString(text);
 	}
 
 	sciw_set_status_bar(s, s->titlebar_port, s->_statusBarText, fgcolor, bgcolor);

Modified: scummvm/trunk/engines/sci/engine/kmisc.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kmisc.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/engine/kmisc.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -180,53 +180,39 @@
 		break;
 	case K_MEMORY_MEMCPY : {
 		int size = argv[3].toUint16();
-		byte *dest = s->segMan->derefBulkPtr(argv[1], size);
-		byte *src = s->segMan->derefBulkPtr(argv[2], size);
-
-		if (dest && src)
-			memcpy(dest, src, size);
-		else {
-			warning("Could not execute kMemory:memcpy of %d bytes:", size);
-			if (!dest) {
-				warning("  dest ptr (%04x:%04x) invalid/memory region too small", PRINT_REG(argv[1]));
-			}
-			if (!src) {
-				warning("  src ptr (%04x:%04x) invalid/memory region too small", PRINT_REG(argv[2]));
-			}
-		}
+		s->segMan->memcpy(argv[1], argv[2], size);
 		break;
 	}
 	case K_MEMORY_PEEK : {
-		byte *ref = s->segMan->derefBulkPtr(argv[1], 2);
+		SegmentRef ref = s->segMan->dereference(argv[1]);
 
-		if (!ref) {
+		if (!ref.isValid() || ref.maxSize < 2) {
 			// This occurs in KQ5CD when interacting with certain objects
 			warning("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1]));
 			return s->r_acc;
 		}
-		if (s->segMan->getSegmentType(argv[1].segment) == SEG_TYPE_LOCALS)
-			return *((reg_t *) ref);
+		if (ref.isRaw)
+			return make_reg(0, (int16)READ_LE_UINT16(ref.raw));
 		else
-			return make_reg(0, (int16)READ_LE_UINT16(ref));
+			return *(ref.reg);
 		break;
 	}
 	case K_MEMORY_POKE : {
-		byte *ref = s->segMan->derefBulkPtr(argv[1], 2);
+		SegmentRef ref = s->segMan->dereference(argv[1]);
 
-		if (!ref) {
+		if (!ref.isValid() || ref.maxSize < 2) {
 			warning("Attempt to poke invalid memory at %04x:%04x", PRINT_REG(argv[1]));
 			return s->r_acc;
 		}
 
-		if (s->segMan->getSegmentType(argv[1].segment) == SEG_TYPE_LOCALS)
-			*((reg_t *) ref) = argv[2];
-		else {
+		if (ref.isRaw) {
 			if (argv[2].segment) {
 				error("Attempt to poke memory reference %04x:%04x to %04x:%04x", PRINT_REG(argv[2]), PRINT_REG(argv[1]));
 				return s->r_acc;
-				WRITE_LE_UINT16(ref, argv[2].offset); // ?
 			}
-		}
+			WRITE_LE_UINT16(ref.raw, argv[2].offset);
+		} else
+			*(ref.reg) = argv[2];
 		break;
 	}
 	}

Modified: scummvm/trunk/engines/sci/engine/kpathing.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kpathing.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/engine/kpathing.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -257,27 +257,18 @@
 
 static Vertex *s_vertex_cur;	// FIXME: Avoid non-const global vars
 
-// FIXME: Temporary hack to deal with points in reg_ts
-static bool polygon_is_reg_t(const byte *list, int size) {
-	// Check the first three reg_ts
-	for (int i = 0; i < (size < 3 ? size : 3); i++)
-		if ((((reg_t *) list) + i)->segment)
-			// Non-zero segment, cannot be reg_ts
-			return false;
-
-	// First three segments were zero, assume reg_ts
-	return true;
-}
-
-static Common::Point read_point(const byte *list, int is_reg_t, int offset) {
+static Common::Point read_point(SegManager *segMan, reg_t list, int offset) {
+	SegmentRef list_r = segMan->dereference(list);
+	if (!list_r.isValid()) {
+		warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(list));
+	}
 	Common::Point point;
 
-	if (!is_reg_t) {
-		POLY_GET_POINT(list, offset, point);
+	if (list_r.isRaw) {
+		POLY_GET_POINT(list_r.raw, offset, point);
 	} else {
-		POLY_GET_POINT_REG_T((reg_t *)list, offset, point);
+		POLY_GET_POINT_REG_T(list_r.reg, offset, point);
 	}
-
 	return point;
 }
 
@@ -295,14 +286,12 @@
 	if (size != GET_SEL32(p2, size).toUint16())
 		return false;
 
-	const byte *p1_points = segMan->derefBulkPtr(GET_SEL32(p1, points), size * POLY_POINT_SIZE);
-	const byte *p2_points = segMan->derefBulkPtr(GET_SEL32(p2, points), size * POLY_POINT_SIZE);
-	bool p1_is_reg_t = polygon_is_reg_t(p1_points, size);
-	bool p2_is_reg_t = polygon_is_reg_t(p2_points, size);
+	reg_t p1_points = GET_SEL32(p1, points);
+	reg_t p2_points = GET_SEL32(p2, points);
 
 	// Check for the same points
 	for (int i = 0; i < size; i++) {
-		if (read_point(p1_points, p1_is_reg_t, i) != read_point(p2_points, p2_is_reg_t, i))
+		if (read_point(segMan, p1_points, i) != read_point(segMan, p2_points, i))
 			return false;
 	}
 
@@ -360,14 +349,12 @@
 	int size = GET_SEL32(polygon, size).toUint16();
 	int type = GET_SEL32(polygon, type).toUint16();
 	Common::Point first, prev;
-	const byte *list = s->segMan->derefBulkPtr(points, size * POLY_POINT_SIZE);
-	int is_reg_t = polygon_is_reg_t(list, size);
 	int i;
 
-	prev = first = read_point(list, is_reg_t, 0);
+	prev = first = read_point(segMan, points, 0);
 
 	for (i = 1; i < size; i++) {
-		Common::Point point = read_point(list, is_reg_t, i);
+		Common::Point point = read_point(segMan, points, i);
 		draw_line(s, prev, point, type);
 		prev = point;
 	}
@@ -407,18 +394,16 @@
 	int size = GET_SEL32(polygon, size).toUint16();
 	int type = GET_SEL32(polygon, type).toUint16();
 	int i;
-	const byte *point_array = segMan->derefBulkPtr(points, size * POLY_POINT_SIZE);
-	int is_reg_t = polygon_is_reg_t(point_array, size);
 	Common::Point point;
 
 	printf("%i:", type);
 
 	for (i = 0; i < size; i++) {
-		point = read_point(point_array, is_reg_t, i);
+		point = read_point(segMan, points, i);
 		printf(" (%i, %i)", point.x, point.y);
 	}
 
-	point = read_point(point_array, is_reg_t, 0);
+	point = read_point(segMan, points, 0);
 	printf(" (%i, %i);\n", point.x, point.y);
 }
 
@@ -1231,15 +1216,15 @@
 	int i;
 	reg_t points = GET_SEL32(polygon, points);
 	int size = GET_SEL32(polygon, size).toUint16();
-	const byte *list = s->segMan->derefBulkPtr(points, size * POLY_POINT_SIZE);
 	Polygon *poly = new Polygon(GET_SEL32(polygon, type).toUint16());
-	int is_reg_t = polygon_is_reg_t(list, size);
 
+	int skip = 0;
+
 	// WORKAROUND: broken polygon in lsl1sci, room 350, after opening elevator
 	// Polygon has 17 points but size is set to 19
 	if ((size == 19) && (s->_gameName == "lsl1sci")) {
 		if ((s->currentRoomNumber() == 350)
-		&& (read_point(list, is_reg_t, 18) == Common::Point(108, 137))) {
+		&& (read_point(segMan, points, 18) == Common::Point(108, 137))) {
 			debug(1, "Applying fix for broken polygon in lsl1sci, room 350");
 			size = 17;
 		}
@@ -1248,33 +1233,31 @@
 	// WORKAROUND: self-intersecting polygons in ECO, rooms 221, 280 and 300
 	if ((size == 11) && (s->_gameName == "ecoquest")) {
 		if ((s->currentRoomNumber() == 300)
-		&& (read_point(list, is_reg_t, 10) == Common::Point(221, 0))) {
+		&& (read_point(segMan, points, 10) == Common::Point(221, 0))) {
 			debug(1, "Applying fix for self-intersecting polygon in ECO, room 300");
 			size = 10;
 		}
 	}
 	if ((size == 12) && (s->_gameName == "ecoquest")) {
 		if ((s->currentRoomNumber() == 280)
-		&& (read_point(list, is_reg_t, 11) == Common::Point(238, 189))) {
+		&& (read_point(segMan, points, 11) == Common::Point(238, 189))) {
 			debug(1, "Applying fix for self-intersecting polygon in ECO, room 280");
 			size = 10;
 		}
 	}
 	if ((size == 16) && (s->_gameName == "ecoquest")) {
 		if ((s->currentRoomNumber() == 221)
-		&& (read_point(list, is_reg_t, 1) == Common::Point(419, 175))) {
+		&& (read_point(segMan, points, 1) == Common::Point(419, 175))) {
 			debug(1, "Applying fix for self-intersecting polygon in ECO, room 221");
 			// Swap the first two points
-			poly->vertices.insertHead(new Vertex(read_point(list, is_reg_t, 1)));
-			poly->vertices.insertHead(new Vertex(read_point(list, is_reg_t, 0)));
-			size = 14;
-			assert(!is_reg_t);
-			list += 2 * POLY_POINT_SIZE;
+			poly->vertices.insertHead(new Vertex(read_point(segMan, points, 1)));
+			poly->vertices.insertHead(new Vertex(read_point(segMan, points, 0)));
+			skip = 2;
 		}
 	}
 
-	for (i = 0; i < size; i++) {
-		Vertex *vertex = new Vertex(read_point(list, is_reg_t, i));
+	for (i = skip; i < size; i++) {
+		Vertex *vertex = new Vertex(read_point(segMan, points, i));
 		poly->vertices.insertHead(vertex);
 	}
 

Modified: scummvm/trunk/engines/sci/engine/kstring.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kstring.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/engine/kstring.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -39,12 +39,12 @@
 	}
 
 /* Returns the string the script intended to address */
-char *kernel_lookup_text(EngineState *s, reg_t address, int index) {
+Common::String kernel_lookup_text(EngineState *s, reg_t address, int index) {
 	char *seeker;
 	Resource *textres;
 
 	if (address.segment)
-		return s->segMan->derefString(address);
+		return s->segMan->getString(address);
 	else {
 		int textlen;
 		int _index = index;
@@ -189,7 +189,7 @@
 reg_t kParse(EngineState *s, int, int argc, reg_t *argv) {
 	SegManager *segMan = s->segMan;
 	reg_t stringpos = argv[0];
-	char *string = s->segMan->derefString(stringpos);
+	Common::String string = s->segMan->getString(stringpos);
 	char *error;
 	ResultWordList words;
 	reg_t event = argv[1];
@@ -197,7 +197,7 @@
 
 	s->parser_event = event;
 
-	bool res = voc->tokenizeString(words, string, &error);
+	bool res = voc->tokenizeString(words, string.c_str(), &error);
 	s->parser_valid = 0; /* not valid */
 
 	if (res && !words.empty()) {
@@ -242,8 +242,7 @@
 		s->r_acc = make_reg(0, 0);
 		PUT_SEL32V(event, claimed, 1);
 		if (error) {
-			char *pbase_str = s->segMan->derefString(s->parser_base);
-			strcpy(pbase_str, error);
+			s->segMan->strcpy(s->parser_base, error);
 			debugC(2, kDebugLevelParser, "Word unknown: %s\n", error);
 			/* Issue warning: */
 
@@ -259,129 +258,66 @@
 
 reg_t kStrEnd(EngineState *s, int, int argc, reg_t *argv) {
 	reg_t address = argv[0];
-	char *seeker = s->segMan->derefString(address);
+	address.offset += s->segMan->strlen(address);
 
-	while (*seeker++)
-		++address.offset;
-
 	return address;
 }
 
 reg_t kStrCat(EngineState *s, int, int argc, reg_t *argv) {
-	char *s1 = s->segMan->derefString(argv[0]);
-	char *s2 = s->segMan->derefString(argv[1]);
+	Common::String s1 = s->segMan->getString(argv[0]);
+	Common::String s2 = s->segMan->getString(argv[1]);
 
-	strcat(s1, s2);
+	s1 += s2;
+	s->segMan->strcpy(argv[0], s1.c_str());
 	return argv[0];
 }
 
 reg_t kStrCmp(EngineState *s, int, int argc, reg_t *argv) {
-	char *s1 = s->segMan->derefString(argv[0]);
-	char *s2 = s->segMan->derefString(argv[1]);
+	Common::String s1 = s->segMan->getString(argv[0]);
+	Common::String s2 = s->segMan->getString(argv[1]);
 
 	if (argc > 2)
-		return make_reg(0, strncmp(s1, s2, argv[2].toUint16()));
+		return make_reg(0, strncmp(s1.c_str(), s2.c_str(), argv[2].toUint16()));
 	else
-		return make_reg(0, strcmp(s1, s2));
+		return make_reg(0, strcmp(s1.c_str(), s2.c_str()));
 }
 
 
 reg_t kStrCpy(EngineState *s, int, int argc, reg_t *argv) {
-	char *dest = s->segMan->derefString(argv[0]);
-	char *src = s->segMan->derefString(argv[1]);
-
-	if (!dest) {
-		warning("Attempt to strcpy TO invalid pointer %04x:%04x",
-		          PRINT_REG(argv[0]));
-		return NULL_REG;
-	}
-	if (!src) {
-		warning("Attempt to strcpy FROM invalid pointer %04x:%04x",
-		          PRINT_REG(argv[1]));
-		*dest = 0;
-		return argv[1];
-	}
-
 	if (argc > 2) {
 		int length = argv[2].toSint16();
 
 		if (length >= 0)
-			strncpy(dest, src, length);
-		else {
-			if (s->segMan->_heap[argv[0].segment]->getType() == SEG_TYPE_DYNMEM) {
-				reg_t *srcp = (reg_t *) src;
-
-				int i;
-				warning("Performing reg_t to raw conversion for AvoidPath");
-				for (i = 0; i < -length / 2; i++) {
-					dest[2 * i] = srcp->offset & 0xff;
-					dest[2 * i + 1] = srcp->offset >> 8;
-					srcp++;
-				}
-			} else
-				memcpy(dest, src, -length);
-		}
+			s->segMan->strncpy(argv[0], argv[1], length);
+		else
+			s->segMan->memcpy(argv[0], argv[1], -length);
 	} else
-		strcpy(dest, src);
+		s->segMan->strcpy(argv[0], argv[1]);
 
 	return argv[0];
 }
 
-/* Simple heuristic to work around array handling peculiarity in SQ4:
-It uses StrAt() to read the individual elements, so we must determine
-whether a string is really a string or an array. */
-static int is_print_str(const char *str) {
-	int printable = 0;
-	int len = strlen(str);
 
-	if (len == 0) return 1;
-
-	while (*str) {
-		// The parameter passed to isprint() needs to be in the range
-		// 0 to 0xFF or EOF, according to MSDN, therefore we cast it
-		// to an unsigned char. Values outside this range (in this
-		// case, negative values) yield unpredictable results. Refer to:
-		// http://msdn.microsoft.com/en-us/library/ewx8s4kw.aspx
-		if (isprint((byte)*str))
-			printable++;
-		str++;
-	}
-
-	return ((float)printable / (float)len >= 0.5);
-}
-
-
 reg_t kStrAt(EngineState *s, int, int argc, reg_t *argv) {
-	byte *dest = (byte*)s->segMan->derefString(argv[0]);
-	reg_t *dest2;
-
-	if (!dest) {
+	SegmentRef dest_r = s->segMan->dereference(argv[0]);
+	if (!dest_r.raw) {
 		warning("Attempt to StrAt at invalid pointer %04x:%04x", PRINT_REG(argv[0]));
 		return NULL_REG;
 	}
 
-	bool lsl5PasswordWorkaround = false;
-	// LSL5 stores the password at the beginning in memory.drv, using XOR encryption,
-	// which means that is_print_str() will fail. Therefore, do not use the heuristic to determine
-	// if we're handling a string or an array for LSL5's password screen (room 155)
-	if (s->_gameName.equalsIgnoreCase("lsl5") && s->currentRoomNumber() == 155)
-		lsl5PasswordWorkaround = true;
+	byte* dest;
 
-	if ((argc == 2) &&
-	        /* Our pathfinder already works around the issue we're trying to fix */
-	        (strcmp(s->segMan->getDescription(argv[0]), AVOIDPATH_DYNMEM_STRING) != 0) &&
-	        ((strlen((const char*)dest) < 2) ||
-	         (!lsl5PasswordWorkaround && !is_print_str((const char*)dest)))) {
-		// SQ4 array handling detected
+	if (dest_r.isRaw) {
+		dest = (byte*)dest_r.raw + argv[1].toUint16();
+	} else {
 #ifndef SCUMM_BIG_ENDIAN
 		int odd = argv[1].toUint16() & 1;
 #else
 		int odd = !(argv[1].toUint16() & 1);
 #endif
-		dest2 = ((reg_t *) dest) + (argv[1].toUint16() / 2);
-		dest = ((byte *)(&dest2->offset)) + odd;
-	} else
-		dest += argv[1].toUint16();
+		reg_t *tmp = dest_r.reg + (argv[1].toUint16() / 2);
+		dest = ((byte *)(&tmp->offset)) + odd;
+	}
 
 	s->r_acc = make_reg(0, *dest);
 
@@ -393,7 +329,8 @@
 
 
 reg_t kReadNumber(EngineState *s, int, int argc, reg_t *argv) {
-	char *source = s->segMan->derefString(argv[0]);
+	Common::String source_str = s->segMan->getString(argv[0]);
+	const char *source = source_str.c_str();
 
 	while (isspace(*source))
 		source++; /* Skip whitespace */
@@ -419,10 +356,10 @@
 reg_t kFormat(EngineState *s, int, int argc, reg_t *argv) {
 	int *arguments;
 	reg_t dest = argv[0];
-	char *target = s->segMan->derefString(dest);
+	char targetbuf[512];
+	char *target = targetbuf;
 	reg_t position = argv[1]; /* source */
 	int index = argv[2].toUint16();
-	char *source;
 	char *str_base = target;
 	int mode = 0;
 	int paramindex = 0; /* Next parameter to evaluate */
@@ -439,7 +376,8 @@
 	else
 		startarg = 3; /* First parameter to use for formatting */
 
-	source = kernel_lookup_text(s, position, index);
+	Common::String source_str = kernel_lookup_text(s, position, index);
+	const char* source = source_str.c_str();
 
 	debugC(2, kDebugLevelStrings, "Formatting \"%s\"\n", source);
 
@@ -505,9 +443,9 @@
 			switch (xfer) {
 			case 's': { /* Copy string */
 				reg_t reg = argv[startarg + paramindex];
-				char *tempsource = kernel_lookup_text(s, reg,
-				                                      arguments[paramindex + 1]);
-				int slen = strlen(tempsource);
+				Common::String tempsource = kernel_lookup_text(s, reg,
+				                                  arguments[paramindex + 1]);
+				int slen = strlen(tempsource.c_str());
 				int extralen = str_leng - slen;
 				CHECK_OVERFLOW1(target, extralen, NULL_REG);
 				if (extralen < 0)
@@ -538,7 +476,7 @@
 
 				}
 
-				strcpy(target, tempsource);
+				strcpy(target, tempsource.c_str());
 				target += slen;
 
 				switch (align) {
@@ -627,19 +565,15 @@
 	free(arguments);
 
 	*target = 0; /* Terminate string */
+
+	s->segMan->strcpy(dest, targetbuf);	
+
 	return dest; /* Return target addr */
 }
 
 
 reg_t kStrLen(EngineState *s, int, int argc, reg_t *argv) {
-	char *str = s->segMan->derefString(argv[0]);
-
-	if (!str) {
-		warning("StrLen: invalid pointer %04x:%04x", PRINT_REG(argv[0]));
-		return NULL_REG;
-	}
-
-	return make_reg(0, strlen(str));
+	return make_reg(0, s->segMan->strlen(argv[0]));
 }
 
 
@@ -664,7 +598,7 @@
 	** resource.
 	*/
 
-	strcpy(s->segMan->derefString(argv[2]), seeker); /* Copy the string and get return value */
+	s->segMan->strcpy(argv[2], seeker); /* Copy the string and get return value */
 	return argv[2];
 }
 
@@ -710,7 +644,6 @@
 	case K_MESSAGE_GET:
 	case K_MESSAGE_NEXT: {
 		reg_t bufferReg;
-		char *buffer = NULL;
 		Common::String str;
 		reg_t retval;
 
@@ -739,18 +672,15 @@
 
 		if (!bufferReg.isNull()) {
 			int len = str.size() + 1;
-			buffer = s->segMan->derefString(bufferReg, len);
-
-			if (buffer) {
-				strcpy(buffer, str.c_str());
-			} else {
+			SegmentRef buffer_r = s->segMan->dereference(bufferReg);
+			if (buffer_r.maxSize < len) {
 				warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(bufferReg), len, str.c_str());
 
 				// Set buffer to empty string if possible
-				buffer = s->segMan->derefString(bufferReg, 1);
-				if (buffer)
-					*buffer = 0;
-			}
+				if (buffer_r.maxSize > 0)
+					s->segMan->strcpy(bufferReg, "");
+			} else
+				s->segMan->strcpy(bufferReg, str.c_str());
 
 			s->_msgState.gotoNext();
 		}
@@ -792,6 +722,8 @@
 		if (buffer) {
 			// FIXME: Is this correct? I.e., do we really write into a "raw" segment
 			// here? Or maybe we want to write 4 reg_t instead?
+			assert(s->segMan->dereference(argv[1]).isRaw);
+
 			WRITE_LE_UINT16(buffer, module);
 			WRITE_LE_UINT16(buffer + 2, msg.noun);
 			WRITE_LE_UINT16(buffer + 4, msg.verb);
@@ -811,26 +743,29 @@
 }
 
 reg_t kSetQuitStr(EngineState *s, int, int argc, reg_t *argv) {
-        char *quitStr = s->segMan->derefString(argv[0]);
-        debug("Setting quit string to '%s'", quitStr);
-        return s->r_acc;
+	Common::String quitStr = s->segMan->getString(argv[0]);
+	debug("Setting quit string to '%s'", quitStr.c_str());
+	return s->r_acc;
 }
 
 reg_t kStrSplit(EngineState *s, int, int argc, reg_t *argv) {
-	const char *format = s->segMan->derefString(argv[1]);
-	const char *sep = !argv[2].isNull() ? s->segMan->derefString(argv[2]) : NULL;
-	Common::String str = s->strSplit(format, sep);
+	Common::String format = s->segMan->getString(argv[1]);
+	Common::String sep_str;
+	const char *sep = NULL;
+	if (!argv[2].isNull()) {
+		sep_str = s->segMan->getString(argv[2]);
+		sep = sep_str.c_str();
+	}
+	Common::String str = s->strSplit(format.c_str(), sep);
 
 	// Make sure target buffer is large enough
-	char *buf = s->segMan->derefString(argv[0], str.size() + 1);
-
-	if (buf) {
-		strcpy(buf, str.c_str());
-		return argv[0];
-	} else {
+	SegmentRef buf_r = s->segMan->dereference(argv[0]);
+	if (!buf_r.isValid() || buf_r.maxSize < (int)str.size() + 1) {
 		warning("StrSplit: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(argv[0]), str.size() + 1, str.c_str());
 		return NULL_REG;
 	}
+	s->segMan->strcpy(argv[0], str.c_str());
+	return argv[0];
 }
 
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/gfx/gfx_gui.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_gui.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/gfx/gfx_gui.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -175,7 +175,7 @@
 	win = new GfxPort(visual, area, color, bgcolor);
 
 	win->_font = font;
-	win->title_text = title;
+	win->_title_text = title;
 	win->port_flags = flags;
 
 	win->_flags |= GFXW_FLAG_IMMUNE_TO_SNAPSHOTS;

Modified: scummvm/trunk/engines/sci/gfx/gfx_state_internal.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_state_internal.h	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/gfx/gfx_state_internal.h	2009-09-27 01:50:26 UTC (rev 44388)
@@ -382,7 +382,7 @@
 	gfxw_snapshot_t *restore_snap; /**< Snapshot to be restored automagically,
 					  experimental feature used in the PQ3 interpreter */
 	int port_flags; /**< interpreter-dependant flags */
-	const char *title_text;
+	Common::String _title_text;
 	byte gray_text; /**< Whether text is 'grayed out' (dithered) */
 
 public:

Modified: scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -1581,7 +1581,6 @@
 	port_bg = NULL;
 	_parent = NULL;
 	_decorations = NULL;
-	title_text = NULL;
 	draw_pos = Common::Point(0, 0);
 	gray_text = 0;
 	_color = fgcolor;

Modified: scummvm/trunk/engines/sci/gfx/menubar.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/menubar.cpp	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/gfx/menubar.cpp	2009-09-27 01:50:26 UTC (rev 44388)
@@ -122,7 +122,7 @@
 	return total_left_size + width;
 }
 
-void Menubar::addMenu(GfxState *state, const char *title, const char *entries, int font, reg_t entries_base) {
+void Menubar::addMenu(GfxState *state, const Common::String &title, const Common::String &entries, int font, reg_t entries_base) {
 	char tracker;
 	char *left = NULL;
 	reg_t left_origin = entries_base;
@@ -134,17 +134,19 @@
 
 	menu._title = title;
 
-	gfxop_get_text_params(state, font, title, SIZE_INF, &(menu._titleWidth), &height, 0, NULL, NULL, NULL);
+	gfxop_get_text_params(state, font, title.c_str(), SIZE_INF, &(menu._titleWidth), &height, 0, NULL, NULL, NULL);
 
+	const char *entries_p = entries.c_str();
+
 	do {
-		tracker = *entries++;
+		tracker = *entries_p++;
 		entries_base.offset++;
 
 		if (!left) { // Left string not finished?
 			if (tracker == '=') { // Hit early-SCI tag assignment?
-				left = sci_strndup(entries - string_len - 1, string_len);
-				tag = atoi(entries++);
-				tracker =  *entries++;
+				left = sci_strndup(entries_p - string_len - 1, string_len);
+				tag = atoi(entries_p++);
+				tracker =  *entries_p++;
 			}
 			if ((tracker == 0 && string_len > 0) || (tracker == '=') || (tracker == ':')) { // End of entry
 				MenuType entrytype = MENU_TYPE_NORMAL;
@@ -152,7 +154,7 @@
 				reg_t beginning;
 
 				if (!left)
-					left = sci_strndup(entries - string_len - 1, string_len);
+					left = sci_strndup(entries_p - string_len - 1, string_len);
 
 				inleft = left;
 				while (isspace(*inleft))
@@ -179,7 +181,7 @@
 				if (!left) {
 					left_origin = entries_base;
 					left_origin.offset -= string_len + 1;
-					left = sci_strndup(entries - string_len - 1, string_len);
+					left = sci_strndup(entries_p - string_len - 1, string_len);
 				}
 				string_len = 0; // Continue with the right string
 			} else
@@ -189,7 +191,7 @@
 			if ((tracker == ':') || (tracker == 0)) { // End of entry
 				int key, modifiers = 0;
 
-				char *right = sci_strndup(entries - string_len - 1, string_len);
+				char *right = sci_strndup(entries_p - string_len - 1, string_len);
 
 				if (right[0] == '#') {
 					right[0] = SCI_SPECIAL_CHAR_FUNCTION; // Function key
@@ -294,7 +296,7 @@
 	case MENU_ATTRIBUTE_SAID:
 		if (value.segment) {
 			item->_saidPos = value;
-			memcpy(item->_said, s->segMan->derefBulkPtr(value, 0), MENU_SAID_SPEC_SIZE); // Copy Said spec
+			s->segMan->memcpy(item->_said, value, MENU_SAID_SPEC_SIZE); // Copy Said spec
 			item->_flags |= MENU_ATTRIBUTE_FLAGS_SAID;
 
 		} else
@@ -304,7 +306,7 @@
 
 	case MENU_ATTRIBUTE_TEXT:
 		assert(value.segment);
-		item->_text = s->segMan->derefString(value);
+		item->_text = s->segMan->getString(value);
 		item->_textPos = value;
 		break;
 

Modified: scummvm/trunk/engines/sci/gfx/menubar.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/menubar.h	2009-09-27 01:49:56 UTC (rev 44387)
+++ scummvm/trunk/engines/sci/gfx/menubar.h	2009-09-27 01:50:26 UTC (rev 44388)
@@ -171,7 +171,7 @@
 	 * @param[in] font			The font which is to be used for drawing
 	 * @param[in] entries_base	Segmented VM address of the entries string
 	 */
-	void addMenu(GfxState *state, const char *title, const char *entries, int font, reg_t entries_base);
+	void addMenu(GfxState *state, const Common::String &title, const Common::String &entries, int font, reg_t entries_base);
 
 
 	/**


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