mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-02 23:01:42 +00:00
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. svn-id: r44388
This commit is contained in:
parent
5d2d8c580a
commit
d3c1916384
@ -216,9 +216,9 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvoc
|
||||
* @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 ********************/
|
||||
/**
|
||||
|
@ -197,11 +197,11 @@ void file_open(EngineState *s, const char *filename, int mode) {
|
||||
}
|
||||
|
||||
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 @@ void fwrite_wrapper(EngineState *s, int handle, const char *data, int length) {
|
||||
|
||||
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 @@ static void fseek_wrapper(EngineState *s, int handle, int offset, int whence) {
|
||||
}
|
||||
|
||||
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 @@ reg_t kFGets(EngineState *s, int, int argc, reg_t *argv) {
|
||||
* 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 @@ enum {
|
||||
|
||||
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 kGetSaveDir(EngineState *s, int, int argc, reg_t *argv) {
|
||||
}
|
||||
|
||||
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 @@ void listSavegames(Common::Array<SavegameDesc> &saves) {
|
||||
}
|
||||
|
||||
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 kCheckSaveGame(EngineState *s, int, int argc, reg_t *argv) {
|
||||
}
|
||||
|
||||
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 @@ reg_t kGetSaveFiles(EngineState *s, int, int argc, reg_t *argv) {
|
||||
++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 @@ reg_t kSaveGame(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 kSaveGame(EngineState *s, int, int argc, reg_t *argv) {
|
||||
}
|
||||
|
||||
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 @@ reg_t kRestoreGame(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 kRestoreGame(EngineState *s, int, int argc, reg_t *argv) {
|
||||
}
|
||||
|
||||
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 @@ void DirSeeker::nextFile() {
|
||||
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 @@ reg_t kFileIO(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
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 @@ reg_t kFileIO(EngineState *s, int, int argc, reg_t *argv) {
|
||||
}
|
||||
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 @@ reg_t kFileIO(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kFileIO(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kFileIO(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kFileIO(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 :
|
||||
|
@ -445,7 +445,7 @@ void _k_graph_rebuild_port_with_color(EngineState *s, gfx_color_t newbgcolor) {
|
||||
|
||||
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 kGraph(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
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 _k_draw_control(EngineState *s, reg_t obj, int inverse);
|
||||
|
||||
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 @@ static void disableCertainButtons(SegManager *segMan, Common::String gameName, r
|
||||
* 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 @@ void update_cursor_limits(int *display_offset, int *cursor, int max_displayed) {
|
||||
|
||||
#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 kEditControl(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kEditControl(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kEditControl(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
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 @@ reg_t kEditControl(EngineState *s, int, int argc, reg_t *argv) {
|
||||
}
|
||||
|
||||
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 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
|
||||
|
||||
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 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
|
||||
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 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
|
||||
|
||||
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 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
|
||||
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 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
|
||||
|
||||
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 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
|
||||
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 @@ reg_t kNewWindow(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
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 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
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 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
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 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kDisplay(EngineState *s, int, int argc, reg_t *argv) {
|
||||
}
|
||||
|
||||
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_Windows(EngineState *s, int argc, reg_t *argv) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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 @@ reg_t kDrawStatus(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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);
|
||||
|
@ -180,53 +180,39 @@ reg_t kMemory(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -257,27 +257,18 @@ struct PathfindingState {
|
||||
|
||||
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 @@ static bool polygons_equal(SegManager *segMan, reg_t p1, reg_t p2) {
|
||||
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 @@ static void draw_polygon(EngineState *s, reg_t polygon) {
|
||||
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 @@ static void print_polygon(SegManager *segMan, reg_t polygon) {
|
||||
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 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) {
|
||||
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 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -39,12 +39,12 @@ namespace Sci {
|
||||
}
|
||||
|
||||
/* 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 kSetSynonyms(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kParse(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
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 @@ reg_t kParse(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 kParse(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
reg_t kStrEnd(EngineState *s, int, int argc, reg_t *argv) {
|
||||
reg_t address = argv[0];
|
||||
char *seeker = s->segMan->derefString(address);
|
||||
|
||||
while (*seeker++)
|
||||
++address.offset;
|
||||
address.offset += s->segMan->strlen(address);
|
||||
|
||||
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 kStrAt(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
|
||||
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 kReadNumber(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kFormat(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kFormat(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kFormat(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
}
|
||||
|
||||
strcpy(target, tempsource);
|
||||
strcpy(target, tempsource.c_str());
|
||||
target += slen;
|
||||
|
||||
switch (align) {
|
||||
@ -627,19 +565,15 @@ reg_t kFormat(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 @@ reg_t kGetFarText(EngineState *s, int, int argc, reg_t *argv) {
|
||||
** 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 @@ reg_t kMessage(EngineState *s, int, int argc, reg_t *argv) {
|
||||
case K_MESSAGE_GET:
|
||||
case K_MESSAGE_NEXT: {
|
||||
reg_t bufferReg;
|
||||
char *buffer = NULL;
|
||||
Common::String str;
|
||||
reg_t retval;
|
||||
|
||||
@ -739,18 +672,15 @@ reg_t kMessage(EngineState *s, int, int argc, reg_t *argv) {
|
||||
|
||||
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 @@ reg_t kMessage(EngineState *s, int, int argc, reg_t *argv) {
|
||||
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 kMessage(EngineState *s, int, int argc, reg_t *argv) {
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -175,7 +175,7 @@ GfxPort *sciw_new_window(EngineState *s,
|
||||
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;
|
||||
|
@ -382,7 +382,7 @@ struct GfxPort : public GfxContainer {
|
||||
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:
|
||||
|
@ -1581,7 +1581,6 @@ GfxPort::GfxPort(GfxVisual *visual_, rect_t area, gfx_color_t fgcolor, gfx_color
|
||||
port_bg = NULL;
|
||||
_parent = NULL;
|
||||
_decorations = NULL;
|
||||
title_text = NULL;
|
||||
draw_pos = Common::Point(0, 0);
|
||||
gray_text = 0;
|
||||
_color = fgcolor;
|
||||
|
@ -122,7 +122,7 @@ int Menu::addMenuItem(GfxState *state, MenuType type, const char *left, const ch
|
||||
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 @@ void Menubar::addMenu(GfxState *state, const char *title, const char *entries, i
|
||||
|
||||
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 @@ void Menubar::addMenu(GfxState *state, const char *title, const char *entries, i
|
||||
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 @@ void Menubar::addMenu(GfxState *state, const char *title, const char *entries, i
|
||||
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 @@ void Menubar::addMenu(GfxState *state, const char *title, const char *entries, i
|
||||
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 @@ int Menubar::setAttribute(EngineState *s, int menu_nr, int item_nr, int attribut
|
||||
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 @@ int Menubar::setAttribute(EngineState *s, int menu_nr, int item_nr, int attribut
|
||||
|
||||
case MENU_ATTRIBUTE_TEXT:
|
||||
assert(value.segment);
|
||||
item->_text = s->segMan->derefString(value);
|
||||
item->_text = s->segMan->getString(value);
|
||||
item->_textPos = value;
|
||||
break;
|
||||
|
||||
|
@ -171,7 +171,7 @@ public:
|
||||
* @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);
|
||||
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user