[Scummvm-cvs-logs] CVS: tools dekyra.cpp,NONE,1.1 Makefile,1.38,1.39 README,1.24,1.25
James Brown
ender at users.sourceforge.net
Fri Oct 15 08:25:14 CEST 2004
Update of /cvsroot/scummvm/tools
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16962
Modified Files:
Makefile README
Added Files:
dekyra.cpp
Log Message:
Add LordHotos dekyra
--- NEW FILE: dekyra.cpp ---
/* DeKyra - Basic Kyrandia script disassembler
* Copyright (C) 2004- Johannes Schickel
* Copyright (C) 2004- The ScummVM Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/tools/dekyra.cpp,v 1.1 2004/10/15 15:22:22 ender Exp $
*
*/
#include "dekyra.h"
int main(int argc, char** argv) {
if (argc < 2) {
printf("Use:\n"
"%s filename\n"
"-t displays text segment\n"
"-n display only function 'n'. n should be a integer\n",
argv[0]);
return false;
}
uint32 file = 0xFFFFFFFE;
bool displayText = false;
bool displayOnlyOneScript = false;
int32 scriptnum = 0;
// search for some parameters
for (int param = 1; param < argc; ++param) {
if (*argv[param] != '-' && file == 0xFFFFFFFE)
file = param;
else {
if(argv[param][1] == 't')
displayText = true;
else {
scriptnum = atoi(&argv[param][1]);
if (scriptnum >= 0 && scriptnum < 256)
displayOnlyOneScript = true;
}
}
}
if (file == 0xFFFFFFFE) {
printf("Use:\n"
"%s filename\n"
"-t displays text segment\n"
"-n display only function 'n'\n",
argv[0]);
return false;
}
Script myscript(argv[file]);
if (myscript.isOpen()) {
if (displayText) {
myscript.decodeTextArea();
printf("\n\n");
}
if (!displayOnlyOneScript) {
myscript.decodeScript();
} else {
if (!myscript.decodeSpecialScript(scriptnum)) {
error("in this script is no script with number %d", scriptnum);
}
}
} else {
error("couldn't find file '%s'", argv[1]);
}
return true;
}
Script::Script(const char* filename) {
_scriptFile = 0;
FILE* script = fopen(filename, "r");
if (!script)
return;
_scriptSize = fileSize(script);
_scriptFile = new uint8[_scriptSize];
assert(_scriptFile);
fread(_scriptFile, sizeof(uint8) * _scriptSize, 1, script);
fseek(script, 0, SEEK_SET);
uint8 chunkName[sizeof("EMC2ORDR") + 1];
// so lets look for our chunks :)
while(true) {
if ((uint32)ftell(script) >= _scriptSize) {
break;
}
// lets read only the first 4 chars
fread(chunkName, sizeof(uint8) * 4, 1, script);
chunkName[4] = '\0';
// check name of chunk
if (!strcmp((char*)chunkName, "FORM")) {
// FreeKyra swaps the size I only read it in BigEndian :)
_chunks[kForm]._size = readUint32BE(script);
} else if (!strcmp((char*)chunkName, "TEXT")) {
uint32 text_size = readUint32BE(script);
text_size += text_size % 2 != 0 ? 1 : 0;
_chunks[kText]._data = _scriptFile + ftell(script);
_chunks[kText]._size = TO_BE_16(*((uint16*)_chunks[kText]._data)) >> 1;
_chunks[kText]._additional = _chunks[kText]._data + (_chunks[kText]._size << 1);
fseek(script, text_size, SEEK_CUR);
} else if (!strcmp((char*)chunkName, "DATA")) {
_chunks[kData]._size = readUint32BE(script);
_chunks[kData]._data = _scriptFile + ftell(script);
// mostly it will be the end of the file because all files should end with a 'DATA' chunk
fseek(script, _chunks[kData]._size, SEEK_CUR);
} else {
// read next 4 chars
fread(&chunkName[4], sizeof(uint8) * 4, 1, script);
chunkName[8] = '\0';
if (!strcmp((char*)chunkName, "EMC2ORDR")) {
_chunks[kEmc2Ordr]._size = readUint32BE(script) >> 1;
_chunks[kEmc2Ordr]._data = _scriptFile + ftell(script);
fseek(script, _chunks[kEmc2Ordr]._size * 2, SEEK_CUR);
} else {
// any unkown chunk or problems with seeking through the file
error("unknown chunk '%s'", chunkName);
}
}
}
fclose(script);
}
void Script::decodeTextArea(void) {
printf("TEXT chunk:\n");
// first is size
for (uint32 pos = 1; pos < (_chunks[kText]._size << 1); ++pos) {
if (TO_BE_16(((uint16*)_chunks[kText]._data)[pos]) >= _scriptSize) {
break;
}
uint32 startoffset = TO_BE_16(((uint16*)_chunks[kText]._data)[pos]);
printf("Index: %d Offset: %d:\n", pos, startoffset);
/*uint32 endoffset = TO_BE_16(((uint16*)_chunks[kText]._data)[pos+1]);
printf("\nstartoffset = %d, endoffset = %d\n\n", startoffset, endoffset);
for (; startoffset < endoffset; ++startoffset) {
printf("%c", *(char*)(_chunks[kText]._additional + startoffset));
}
printf("\n");*/
printf("%d(%d) : %s\n", pos, startoffset, (char*)(_chunks[kText]._data + startoffset));
}
}
void Script::decodeScript(void) {
for (uint32 script = 0; decodeSpecialScript(script); ++script)
;
}
struct CommandDesc {
uint16 command; // normally uint8
const char* description;
bool usesArgument;
};
struct ScriptDesc {
int32 script; // normally uint8
const char* description;
};
struct OpcodeDesc {
uint16 opcode; // normally uint8
const char* description;
const char* parameters;
};
// function wich calls opcode procs
const uint16 OPCODE_CALLER = 0x0E;
bool Script::decodeSpecialScript(int32 script) {
static CommandDesc commandDesc[] = {
{ 0x00, "c1_goToLine", true },
{ 0x01, "c1_setReturn", true },
{ 0x02, "c1_pushRetRec", true },
{ 0x03, "c1_push", true },
{ 0x04, "c1_push", true },
{ 0x05, "c1_pushVar", true },
{ 0x06, "c1_pushFrameNeg", true },
{ 0x07, "c1_pushFramePos", true },
{ 0x08, "c1_popRetRec", true },
{ 0x09, "c1_popVar", true },
{ 0x0A, "c1_popFrameNeg", true },
{ 0x0B, "c1_popFramePos", true },
{ 0x0C, "c1_addToSP", true },
{ 0x0D, "c1_subFromSP", true },
{ 0x0E, "c1_execOpcode", true },
{ 0x0F, "c1_ifNotGoTo", true },
{ 0x10, "c1_negate", true },
{ 0x11, "c1_evaluate", true },
// normaly only untils 0xFF
{ 0xFFFF, 0, 0 }
};
static ScriptDesc scriptDesc[] = {
{ 0, "kSetupScene" },
{ 1, "kClickEvent" },
{ 2, "kActorEvent" },
{ 4, "kEnterEvent" },
{ 5, "kExitEvent" },
{ 7, "kLoadResources" },
{ 0xFFFF, "unknown script" }
};
static OpcodeDesc opcodeDesc[] = {
};
if ((uint32)script >= _chunks[kEmc2Ordr]._size || script < 0) {
return false;
}
bool gotScriptName = false;
printf("Script: ");
for (uint32 pos = 0; pos < ARRAYSIZE(scriptDesc) - 1; ++pos) {
if (scriptDesc[pos].script == script) {
printf("%s:\n", scriptDesc[pos].description);
gotScriptName = true;
break;
}
}
if (!gotScriptName) {
printf("%s:\n", scriptDesc[ARRAYSIZE(scriptDesc) - 1].description);
}
uint8 _currentCommand = 0;
uint8 _argument = 0;
_currentPos = (TO_BE_16(_chunks[kEmc2Ordr]._data[script]) << 1) + 2;
uint8* script_start = _chunks[kData]._data;
bool gotArgument = true;
uint32 nextScriptStartsAt = getNextScriptPos(_currentPos);
while(true) {
if ((uint32)_currentPos > _chunks[kData]._size || (uint32)_currentPos >= nextScriptStartsAt) {
break;
}
gotArgument = true;
_currentCommand = *(script_start + _currentPos++);
// gets out
if (_currentCommand & 0x80) {
_argument = ((_currentCommand & 0x0F) << 8) | *(script_start + _currentPos++);
_currentCommand &= 0xF0;
} else if (_currentCommand & 0x40) {
_argument = *(script_start + _currentPos++);
} else if (_currentCommand & 0x20) {
_currentPos++;
uint16 tmp = *(uint16*)(script_start + _currentPos);
tmp &= 0xFF7F;
_argument = TO_BE_16(tmp);
_currentPos += 2;
} else {
gotArgument = false;
}
_currentCommand &= 0x1f;
// prints the offset
printf("0x%x:\t", _currentPos);
bool gotCommand = false;
// lets get out what the command means
for (uint32 pos = 0; pos < ARRAYSIZE(commandDesc) - 1; ++pos) {
if (commandDesc[pos].command == _currentCommand) {
gotCommand = true;
printf("%s", commandDesc[pos].description);
if (commandDesc[pos].usesArgument && commandDesc[pos].command != OPCODE_CALLER) {
printf("(0x%x)", _argument);
} else if(commandDesc[pos].usesArgument && commandDesc[pos].command == OPCODE_CALLER) {
bool gotOpcode = false;
// lets look for our opcodes
for (uint32 pos2 = 0; pos2 < ARRAYSIZE(opcodeDesc); ++pos2) {
if (opcodeDesc[pos2].opcode == _argument) {
printf("(%s(%s))", opcodeDesc[pos2].description, opcodeDesc[pos2].parameters);
gotOpcode = true;
break;
}
}
if (!gotOpcode) {
printf("(0x%x(unknown))", _argument);
}
}
break;
}
}
// prints our command number + arg
if (!gotCommand) {
printf("0x%x(0x%x)", _currentCommand, _argument);
}
if (!gotArgument) {
printf("\t; couldn't get argument! maybe command is wrong.");
}
printf("\n");
}
printf("\n-------------\n");
return true;
}
uint32 Script::getNextScriptPos(uint32 current_start) {
uint32 pos = 0xFFFFFFFE;
for (uint32 tmp = 0; tmp < _chunks[kEmc2Ordr]._size; ++tmp) {
if ((uint32)((TO_BE_16(_chunks[kEmc2Ordr]._data[tmp]) << 1) + 2) > current_start &&
(uint32)((TO_BE_16(_chunks[kEmc2Ordr]._data[tmp]) << 1) + 2) < pos) {
pos = ((TO_BE_16(_chunks[kEmc2Ordr]._data[tmp]) << 1) + 2);
}
}
if (pos > _scriptSize) {
pos = _scriptSize;
}
return pos;
}
Index: Makefile
===================================================================
RCS file: /cvsroot/scummvm/tools/Makefile,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- Makefile 13 Oct 2004 00:30:21 -0000 1.38
+++ Makefile 15 Oct 2004 15:22:21 -0000 1.39
@@ -20,6 +20,7 @@
convbdf$(EXEEXT) \
descumm$(EXEEXT) \
desword2$(EXEEXT) \
+ dekyra$(EXEEXT) \
extract$(EXEEXT) \
loom_tg16_extract$(EXEEXT) \
md5table$(EXEEXT) \
@@ -46,6 +47,9 @@
desword2$(EXEEXT): desword2.o util.o
$(CXX) $(LDFLAGS) -o $@ $+
+dekyra$(EXEEXT): dekyra.o util.o
+ $(CXX) $(LDFLAGS) -o $@ $+
+
extract$(EXEEXT): extract.o extract-common.o util.o
$(CC) $(LDFLAGS) -o $@ $+
Index: README
===================================================================
RCS file: /cvsroot/scummvm/tools/README,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- README 14 Oct 2004 08:37:46 -0000 1.24
+++ README 15 Oct 2004 15:22:21 -0000 1.25
@@ -1,12 +1,17 @@
This is a collection of various tools that may be useful to use in conjunction
-with ScummVM.
+with ScummVM. Please note that this module is not always in-sync with the latest
+STABLE version of ScummVM.
+
+This means that although a tool may support a feature, certain
+ScummVM versions may not. ScummVM 0.6.x does not support FLAC audio, for
+example.
Extraction Tools:
- rescumm:
- Extracts Macintosh "single file" SCUMM games into their
- component parts, for use with ScummVM.
+ rescumm
+ Extracts Macintosh "single file" SCUMM games into their
+ component parts, for use with ScummVM.
- loom_tg16_extract:
+ loom_tg16_extract
Extracts data files from TG16 version of Loom
There is currently no support for this game in ScummVM!
@@ -58,6 +63,9 @@
desword2
Disassembles Broken Sword II scripts
+ dekyra
+ Basic script disassembler for Legend of Kyrandia games
+
Other tools:
simon1decr
Used to decrunch the graphics and music files in AGA/ECS
More information about the Scummvm-git-logs
mailing list