Jump to content

Home

Is there a tool to read/edit Scumm-Script ?


Damien.fa

Recommended Posts

Hello,

 

I'm looking for a tool which permits to read Scumm-Scripts in an understandable language (I mean "not in Hex").

Is there a tool to edit a script ? (change a var, add instructions...)

 

I knew "Descumm" (a ScummVM tool") and it's quite interesting but I just want to know if an editor still exists before I start to build my own ?

 

Thks !

 

Damien

Link to comment
Share on other sites

I tried Scummbler, but it doesn't seem to work for me. Scummpacker does, though.

I tried it with the example code from the manual, and this is what I got:

Traceback (most recent call last):
 File "F:\monkey_test\scummbler.py", line 409, in <module>
   main_selector()
 File "F:\monkey_test\scummbler.py", line 399, in main_selector
   main()
 File "F:\monkey_test\scummbler.py", line 377, in main
   compile_script(infile, SCUMM_version)
 File "F:\monkey_test\scummbler.py", line 286, in compile_script
   results = comp.compileFile(infile)
 File "F:\monkey_test\scummbler_compiler.py", line 86, in compileFile
   results = self.rootExpression.parseFile(filename)
 File "E:\Python26\lib\site-packages\pyparsing.py", line 1405, in parseFile
   return self.parseString(file_contents, parseAll)
 File "E:\Python26\lib\site-packages\pyparsing.py", line 1070, in parseString
   loc, tokens = self._parse( instring, 0 )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 945, in _parseNoCache
   loc,tokens = self.parseImpl( instring, preloc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 2352, in parseImpl
   loc, exprtokens = e._parse( instring, loc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 945, in _parseNoCache
   loc,tokens = self.parseImpl( instring, preloc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 2717, in parseImpl
   loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 945, in _parseNoCache
   loc,tokens = self.parseImpl( instring, preloc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 2604, in parseImpl
   return self.expr._parse( instring, loc, doActions, callPreParse=False )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 945, in _parseNoCache
   loc,tokens = self.parseImpl( instring, preloc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 2418, in parseImpl
   return maxMatchExp._parse( instring, loc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 945, in _parseNoCache
   loc,tokens = self.parseImpl( instring, preloc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 2352, in parseImpl
   loc, exprtokens = e._parse( instring, loc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 945, in _parseNoCache
   loc,tokens = self.parseImpl( instring, preloc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 2461, in parseImpl
   ret = e._parse( instring, loc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 945, in _parseNoCache
   loc,tokens = self.parseImpl( instring, preloc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 2336, in parseImpl
   loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 945, in _parseNoCache
   loc,tokens = self.parseImpl( instring, preloc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 2461, in parseImpl
   ret = e._parse( instring, loc, doActions )
 File "E:\Python26\lib\site-packages\pyparsing.py", line 971, in _parseNoCache
   tokens = fn( instring, tokensStart, retTokens )
 File "F:\monkey_test\scummbler_compiler.py", line 711, in do_grFunc_cutscene
   op = self.opFunctionTable[toks.function]
KeyError: 'cutscene'

Results from anything taken directly from descrumm produces similar results.

Any idea what I did wrong? I'm new to Python.

Link to comment
Share on other sites

I tried Scummbler, but it doesn't seem to work for me. Scummpacker does, though.

I tried it with the example code from the manual, and this is what I got:

Traceback (most recent call last):
*snip*

Results from anything taken directly from descrumm produces similar results.

Any idea what I did wrong? I'm new to Python.

 

I MAY have uploaded the latest version of Scummbler without actually testing that it worked, and I MAY not have finished writing the code before I uploaded it. Then again, the moon landing MAY have been faked; we just can't be sure about these things, can we?

 

Anyway, you may find this more useful.

 

(outdated link removed, see below for new links)

Link to comment
Share on other sites

Still doesn't work. Now, with the example code, I get:

Traceback (most recent call last):
 File "F:\monkey_test\scummbler.py", line 409, in <module>
   main_selector()
 File "F:\monkey_test\scummbler.py", line 399, in main_selector
   main()
 File "F:\monkey_test\scummbler.py", line 377, in main
   compile_script(infile, SCUMM_version)
 File "F:\monkey_test\scummbler.py", line 288, in compile_script
   header = comp.generateHeader(len(results))
 File "F:\monkey_test\scummbler_compiler.py", line 2497, in generateHeader
   objdata += to_byte(self.scriptNum)
 File "F:\monkey_test\scummbler_misc.py", line 143, in to_byte
   inval = int(inval)
ValueError: invalid literal for int() with base 10: '\xca'

I tried another script from descumm, unchanged, and scummbler says "Parsing "script.txt"..." and then just hangs.

Link to comment
Share on other sites

Still doesn't work. Now, with the example code, I get:
Traceback (most recent call last):
 File "F:\monkey_test\scummbler.py", line 409, in <module>
   main_selector()
 File "F:\monkey_test\scummbler.py", line 399, in main_selector
   main()
 File "F:\monkey_test\scummbler.py", line 377, in main
   compile_script(infile, SCUMM_version)
 File "F:\monkey_test\scummbler.py", line 288, in compile_script
   header = comp.generateHeader(len(results))
 File "F:\monkey_test\scummbler_compiler.py", line 2497, in generateHeader
   objdata += to_byte(self.scriptNum)
 File "F:\monkey_test\scummbler_misc.py", line 143, in to_byte
   inval = int(inval)
ValueError: invalid literal for int() with base 10: '\xca'

I tried another script from descumm, unchanged, and scummbler says "Parsing "script.txt"..." and then just hangs.

 

Fixed the first problem, download again from the same location and let me know how it goes.

 

As for the hanging up, just let it go for a bit longer and it should finish. I have not implemented blocks very well, so it gets stupidly slow on nested "if" statements.

Link to comment
Share on other sites

So far, I've noticed two oddities using this tool on MI1:

 

000_LECF\083_LFLF_cu-dock\000_ROOM\032_LSCR.dmp

Error parsing input file: Local script number must be greater than 200.

 

000_LECF\030_LFLF_store\000_ROOM\050_LSCR.dmp

decompiled with descumm and then compiled again with scummbler results in a different file. Using descumm on that gives an error:

ERROR: opcode 0xAB: Unhandled subop 0!

 

 

EDIT: I did some further testing:

I tried to recompile every script with ^255^3-text in it. To be sure that it is no issue with my splitline-tool, I recompiled them unchanged to see if it works.

 

Apparently, there are some compiler bugs as scummtr gives the following errors:

ERROR: Script error at 0x18FFDA in MONKEY.001 (Bad jump(s)) [030:LSCR#0204]

ERROR: Script error at 0x2104BA in MONKEY.001 (Bad jump(s)) [037:LSCR#0205]

ERROR: Script error at 0x210672 in MONKEY.001 (Bad jump(s)) [037:LSCR#0207]

ERROR: Script error at 0x212075 in MONKEY.001 (Bad jump(s)) [037:SCRP#0060]

ERROR: Script error at 0x223214 in MONKEY.001 (Bad jump(s)) [038:SCRP#0120]

ERROR: Script error at 0x2F0DDE in MONKEY.001 (Bad jump(s)) [053:LSCR#0217]

ERROR: Script error at 0x346456 in MONKEY.001 (Bad jump(s)) [059:SCRP#0056]

 

And for another minor problem:

000_LECF\030_LFLF_store\000_ROOM\049_LSCR.dmp won't compile. It gives this error: Exception: Invalid escape code: ^375

I can see the problem here. Luckily, this is not a problem with my tools, since it is solved as a side effect of this line split.

 

I'm using the talkie-hack without sample references.

Link to comment
Share on other sites

Those bad jumps occur because jumps are based on hex addresses. When you split the lines to multiple prints and waits, this corrupts some of the jumps.

 

Here's an example:

1. jump to this plus 1 (line 2)

2. jump to this plus 2 (line 4)

3. print

4. local[0]+=1

5. jump to this plus 2 (line 7)

6. jump to this minus 5 (line 1)

6. end

 

After line split (O is correct, X is incorrect):

1. jump to this plus 1 (line 2) O

2. jump to this plus 2 (line 4) X

3. print

4. wait

5. print

6. wait

7. local[0]+=1

8. jump to this plus 2(line 10) O

9. jump to this minus 5 (line 4) X

10. end

 

That's just a simple example. The actual change is even more since a jump might go to the wrong hex value than the start of an opcode. So to fix this you need to change all jump values based on the additional bytes added between the jumps.

Link to comment
Share on other sites

Those bad jumps occur because jumps are based on hex addresses. When you split the lines to multiple prints and waits, this corrupts some of the jumps.

 

*snip*

 

That's just a simple example. The actual change is even more since a jump might go to the wrong hex value than the start of an opcode. So to fix this you need to change all jump values based on the additional bytes added between the jumps.

 

This is not necessary when using version v2+ of Scummbler, it uses labels for jumps. The actual text in the label is irrelevant. This means you can insert as many instruction as you want between a jump and the jump target, and it will still behave as normal. The actual cause for these "bad jump" errors is mentioned below.

 

So far, I've noticed two oddities using this tool on MI1:

I'll use the original, non-speech-hacked Monkey Island 1 CD files as reference here (not the files in MI:SE).

 

000_LECF\083_LFLF_cu-dock\000_ROOM\032_LSCR.dmp

Error parsing input file: Local script number must be greater than 200.

Compiles/decompiles fine for me, the script number should be 204. Slightly different files due to descumm automatically commenting out a goto instruction. Could you upload your descummed script to http://pastebin.com/ ?

 

000_LECF\030_LFLF_store\000_ROOM\050_LSCR.dmp

decompiled with descumm and then compiled again with scummbler results in a different file. Using descumm on that gives an error:

ERROR: opcode 0xAB: Unhandled subop 0!

My fault; the delayVariable opcode was being incorrectly modified to indicate that the following parameter was a variable (not a constant), which is unnecessary (delayVariable, funnily enough, only ever takes a variable).

 

Apparently, there are some compiler bugs as scummtr gives the following errors:

ERROR: Script error at 0x18FFDA in MONKEY.001 (Bad jump(s)) [030:LSCR#0204]

... etc...

I had somehow entered the wrong opcode for loadRoomWithEgo. Instead, it was the opcode for "jump if class of object is" instruction, which is what causes the "bad jump" errors.

 

I looked at the first three scripts you listed here and they all have the "loadRoomWithEgo", so I'm assuming that's the only problem with those scripts.

 

And for another minor problem:

000_LECF\030_LFLF_store\000_ROOM\049_LSCR.dmp won't compile. It gives this error: Exception: Invalid escape code: ^375

I can see the problem here. Luckily, this is not a problem with my tools, since it is solved as a side effect of this line split.

Yes, this is a problem with descumm's escape character handling. It would be nice if I implemented an alternative way of writing escape characters in Scummbler. I know you've gotten around this problem now, but a simple fix is to just put a space between the escape character digits and the dialogue text digits.

 

Here's the latest fixed version of Scummbler:

(link removed)

 

Hope it works this time :thmbup1:

Link to comment
Share on other sites

Hello,

 

I'm looking for a tool which permits to read Scumm-Scripts in an understandable language (I mean "not in Hex").

Is there a tool to edit a script ? (change a var, add instructions...)

 

I knew "Descumm" (a ScummVM tool") and it's quite interesting but I just want to know if an editor still exists before I start to build my own ?

 

Thks !

 

Damien

 

Ok a couple of questions from me because I am not good with script and can baraley get the whole concept of it.

 

What is Descumm for? and what is a Scumm Script and why would you want to edit it/make your own? Please answer. Thanks.

Link to comment
Share on other sites

Ok a couple of questions from me because I am not good with script and can baraley get the whole concept of it.

 

What is Descumm for? and what is a Scumm Script and why would you want to edit it/make your own? Please answer. Thanks.

 

SCUMM is the scripting language used in LucasArts adventure games. In the game files, SCUMM scripts are stored in a format known as "bytecode", which is easily read by machines. descumm is a tool by the ScummVM developers to translate that bytecode into a human-readable format. Scummbler is a tool I wrote to translate that human-readable format back into bytecode.

 

All of the game's logic is stored in SCUMM scripts. This includes cutscenes, conversations, interactions with objects, and more technical matters like loading game resources. As for why you want to edit it or make your own? Some people just like to hack around in old games, really.

Link to comment
Share on other sites

Compiles/decompiles fine for me, the script number should be 204.
It is with the original game data. Must be a bug with cocomonk22's patch. There it is Script# 155.

 

Scummbler compiles all fine with lines split with the original game data. Now I'm trying the new version with cocomonk22's patch applied.

Link to comment
Share on other sites

It is with the original game data. Must be a bug with cocomonk22's patch. There it is Script# 155.

 

Scummbler compiles all fine with lines split with the original game data. Now I'm trying the new version with cocomonk22's patch applied.

 

Well, I don't want to change the check in Scummbler, since the numbering convention for SCUMM scripts is that all global scripts are from 1 to 199, all local scripts are 200-255 (I think, anyway). I'm not sure if there are conflicts when you have a local script with the same number as a global script.

 

If you really want, you can disable the check by commenting out lines 181 and 182 in scummbler_compiler.py, like so:

 

#        if int(toks.scriptnum) < 200: # will throw exception if scriptnum can't be cast to int.
#            raise ScummblerParseException("Local script number must be greater than 200.")

 

cocomonk22, would it be possible to change the script number & any calls to it?

Link to comment
Share on other sites

Yet another bug:

000_LECF\036_LFLF_mansion-e\000_ROOM\021_LSCR.dmp

gives:

Error parsing input file: Expected end of text (at char 92), (line:4, col:1)

[0009] (48) if (Local[0] == 566) {

 

Perhaps, but not with Scummbler! This sort of error indicates either a syntax error in the script, or an otherwise unknown instruction. I can compile this script fine. Have you made any changes to the script, and if so, what are they?

 

(As an aside, this error will always point to the start of the block containing the error, rather than the offending line. This is partially because of my implementation of "if" blocks, and partially the parsing library I'm using which does not seem to have a fail-fast behaviour)

Link to comment
Share on other sites

Well, I don't want to change the check in Scummbler, since the numbering convention for SCUMM scripts is that all global scripts are from 1 to 199, all local scripts are 200-255 (I think, anyway). I'm not sure if there are conflicts when you have a local script with the same number as a global script.

 

If you really want, you can disable the check by commenting out lines 181 and 182 in scummbler_compiler.py, like so:

 

#        if int(toks.scriptnum) < 200: # will throw exception if scriptnum can't be cast to int.
#            raise ScummblerParseException("Local script number must be greater than 200.")

 

cocomonk22, would it be possible to change the script number & any calls to it?

Yes, I already corrected that, it was an error on my part:

http://www.lucasforums.com/showthread.php?p=2654773#post2654773

Link to comment
Share on other sites

  • 11 months later...

I've found a bug with 000_LECF_original\061_LFLF_sword-mas\001_SCRP_058.dmp

 

Here is the problematic excerpt of the original:

[027D] (48) } else if (Var[284] == 2) {
[0287] (80)   breakHere()
[0288] (94)   print(VAR_EGO,[Text("OK, I think I got it this time.")]);
[02AC] (AE)   WaitForMessage()
[02AE] (18)   goto 0693;
[02B1] (48) } else if (Var[284] == 3) {
[02BB] (80)   breakHere()
[02BC] (94)   print(VAR_EGO,[Text("I return, fresh from a kill!")]);
[02DD] (AE)   WaitForMessage()
[02DF] (18)   goto 0693;
[02E2] (18) } else {
[02E5] (80)   breakHere()

And this is the same section decompiled from what scummbler produces:

[027D] (48) } else if (Var[284] == 2) {
[0287] (80)   breakHere()
[0288] (94)   print(VAR_EGO,[Text("OK, I think I got it this time.")]);
[02AC] (AE)   WaitForMessage()
[02AE] (18)   goto 0693;
[02B1] (18) } else {
[02B4] (48)   if (Var[284] == 3) {
[02BB] (80)     breakHere()
[02BC] (94)     print(VAR_EGO,[Text("I return, fresh from a kill!")]);
[02DD] (AE)     WaitForMessage()
[02DF] (18)     goto 0693;
[02E2] (18)   } else {
[02E5] (80)     breakHere()

The result is, that the dialog options appear on screen, and then it goes right to "Let's get this over with.", and the fight starts. With the additional { in there, an entire block between those is erroneously skipped.

Link to comment
Share on other sites

I see the problem now. It is actually descumm which got confused here.

There are two "} else {" blocks in a row when the latter really just should be a "goto"-instruction prior to a "}". I can manually change this, and scummbler compiles it fine, and the game plays as ususal. When I use descumm on the recompiled script, I'll get those "} else {" blocks again.

I'll report it on the ScummVM site as well.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...