Damien.fa Posted July 20, 2009 Share Posted July 20, 2009 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 More sharing options...
s-island Posted July 20, 2009 Share Posted July 20, 2009 One of the last Scummrev betas/alphas can decompile SCUMM scripts. You should be able to find it over at LucasHacks. Link to comment Share on other sites More sharing options...
Benny Posted July 20, 2009 Share Posted July 20, 2009 http://hibernatus34.free.fr/scumm/ Link to comment Share on other sites More sharing options...
cocomonk22 Posted July 20, 2009 Share Posted July 20, 2009 Use scummtr on that page. EDIT: Sorry, thought you mean just the text. Use jestar jokin's tools. Link to comment Share on other sites More sharing options...
jestar_jokin Posted July 22, 2009 Share Posted July 22, 2009 I have written a tool called Scummbler that can compile scripts output from Descumm. It supports scripts from SCUMM V3, 4, and 5. http://www.jestarjokin.net/ Manual: http://www.jestarjokin.net/sw/scummbler_manual.html There is also ScummC for creating new scripts for SCUMM V6. http://alban.dotsec.net/7.html Link to comment Share on other sites More sharing options...
Benny Posted July 22, 2009 Share Posted July 22, 2009 Bloody hell, well done jestar. I've been wanting a tool to do that for years. Link to comment Share on other sites More sharing options...
LogicDeLuxe Posted July 23, 2009 Share Posted July 23, 2009 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 More sharing options...
jestar_jokin Posted July 23, 2009 Share Posted July 23, 2009 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 More sharing options...
LogicDeLuxe Posted July 23, 2009 Share Posted July 23, 2009 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 More sharing options...
jestar_jokin Posted July 23, 2009 Share Posted July 23, 2009 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 More sharing options...
LogicDeLuxe Posted July 23, 2009 Share Posted July 23, 2009 Thanks. It works now. I can put the stump joke back. Link to comment Share on other sites More sharing options...
LogicDeLuxe Posted July 24, 2009 Share Posted July 24, 2009 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 More sharing options...
cocomonk22 Posted July 24, 2009 Share Posted July 24, 2009 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 More sharing options...
jestar_jokin Posted July 25, 2009 Share Posted July 25, 2009 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 Link to comment Share on other sites More sharing options...
cocomonk22 Posted July 25, 2009 Share Posted July 25, 2009 That certainly did it! Scummtr extracts without error now. Link to comment Share on other sites More sharing options...
purple_tentacle_ Posted July 25, 2009 Share Posted July 25, 2009 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 More sharing options...
jestar_jokin Posted July 25, 2009 Share Posted July 25, 2009 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 More sharing options...
LogicDeLuxe Posted July 25, 2009 Share Posted July 25, 2009 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 More sharing options...
jestar_jokin Posted July 25, 2009 Share Posted July 25, 2009 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 More sharing options...
LogicDeLuxe Posted July 26, 2009 Share Posted July 26, 2009 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) { Link to comment Share on other sites More sharing options...
jestar_jokin Posted July 27, 2009 Share Posted July 27, 2009 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 More sharing options...
LogicDeLuxe Posted July 27, 2009 Share Posted July 27, 2009 Have you made any changes to the script, and if so, what are they?Yes, the file was accidentally altered. I tried again, and it works indeed. Link to comment Share on other sites More sharing options...
cocomonk22 Posted July 27, 2009 Share Posted July 27, 2009 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 More sharing options...
LogicDeLuxe Posted July 16, 2010 Share Posted July 16, 2010 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 More sharing options...
LogicDeLuxe Posted July 17, 2010 Share Posted July 17, 2010 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 More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.