Maniac Mansion script questions (setOwnerOf, paint remover!)

General chat related to ScummVM, adventure gaming, and so on.

Moderator: ScummVM Team

Post Reply
rasteve
Posts: 9
Joined: Mon Aug 18, 2014 12:20 am

Maniac Mansion script questions (setOwnerOf, paint remover!)

Post by rasteve »

Non-technical:

There are several dead-ends in the original game and I was wondering if there was anything that could be done to fix the scripts. Take the example of the paint remover. You need it to get access to the door behind the plant. However, you can use it on pretty much anything causing it to disappear from your inventory.

Technical:

Through a mix of ScummVM debug and descumm I have narrowed the paint remover down to the following roomobj-14-200 script:

Code: Select all

Events:
   3 - 004E
   B - 0027
   E - 0024
[0024] (D0) pickupObject(VAR_ACTIVE_OBJECT1);
[0026] (00) stopObjectCode();
[0027] (A9) setOwnerOf(VAR_ACTIVE_OBJECT1,14);
[002A] (48) if (VAR_ACTIVE_OBJECT2 == 101) {
[0030] (07)   setState08(101);
[0033] (57)   setState02(101);
[0036] (18) } else {
[0039] (D8)   printEgo("That sure was a waste.");
[004D] (**) }
[004D] (00) stopObjectCode();
[004E] (48) if (VAR_ACTIVE_OBJECT2 == 14) {
[0054] (D8)   printEgo("Yech! No thanks.");
&#91;0064&#93; &#40;78&#41; &#125; else if &#40;VAR_ACTIVE_OBJECT2 < 8&#41; &#123;
&#91;006D&#93; &#40;E9&#41;   setOwnerOf&#40;VAR_ACTIVE_OBJECT1,VAR_ACTIVE_OBJECT2&#41;;
&#91;0070&#93; &#40;**&#41; &#125;
&#91;0070&#93; &#40;00&#41; stopObjectCode&#40;&#41;;
END
The section from [0027] to [004D] appears to be the part of the script that runs when you use the object. However, by this point the object is already used (i.e. gone) and this is merely the outcome. The VAR_ACTIVE_OBJECT2 == 101 condition checks if the object you are using it against is the wet paint. If true, there is a change in state (i.e. door appears!) else you get the standard text.

I am not sure on the usage of opcodes, but isn't the problem with this line:

setOwnerOf(VAR_ACTIVE_OBJECT1,14)

Shouldn't this be in the if clause rather than before it?

In other words, am I right in saying that setOwnerOf(x,14) causes you to lose an item from your inventory?

Update

Okay, I have managed to create a patch (after finding out the entire 14.LFL is XOR'd with 0xFF).

I have got to the point where the paint remover ONLY works on the paint blotch. For everything else, nothing happens. I am trying to get it so that you are given a decent message.

Here is the original section of code I am changing:

Code: Select all

&#91;0027&#93; &#40;A9&#41; setOwnerOf&#40;VAR_ACTIVE_OBJECT1,14&#41;;			// a9 09 0e
&#91;002A&#93; &#40;48&#41; if &#40;VAR_ACTIVE_OBJECT2 == 101&#41; &#123;			// 48  00 0a 65 00 09 00
&#91;0030&#93; &#40;07&#41;   setState08&#40;101&#41;;						//  07 65 00
&#91;0033&#93; &#40;57&#41;   setState02&#40;101&#41;;						//  57 65 00
&#91;0036&#93; &#40;18&#41; &#125; else &#123;							// 18 14 00
&#91;0039&#93; &#40;D8&#41;   printEgo&#40;"That sure was a waste."&#41;;			
				//  d8 54 68 61 f4 73 75 72 e5 77 61 f3 e1 77 61 73 74 65 2e 00
&#91;004D&#93; &#40;**&#41; &#125;
&#91;004D&#93; &#40;00&#41; stopObjectCode&#40;&#41;;					// 00
Here are my changes:

Code: Select all

&#91;0027&#93; &#40;48&#41; if &#40;VAR_ACTIVE_OBJECT2 == 101&#41; &#123;			// 48 0a 65 00 09 00 
&#91;002D&#93; &#40;A9&#41; setOwnerOf&#40;VAR_ACTIVE_OBJECT1,14&#41;;		// a9 09 0e
&#91;0030&#93; &#40;07&#41;   setState08&#40;101&#41;;						// 07 65 00
&#91;0033&#93; &#40;57&#41;   setState02&#40;101&#41;;						// 57 65 00
&#91;0036&#93; &#40;18&#41; &#125; else &#123;							// 18 14 00
&#91;0039&#93; &#40;D8&#41;   printEgo&#40;"That would be a waste."&#41;;		
				//  d8 54 68 61 f4 77 6f 75 6c e4 62 e5 e1 77 61 73 74 65 2e 00
&#91;004D&#93; &#40;**&#41; &#125;							
&#91;004D&#93; &#40;00&#41; stopObjectCode&#40;&#41;;					// 00
I have run the patched file under ScummVM (which actually works), and using the debug tools I can see that I have screwed up the if clause perhaps. There is a jump that bypasses my custom text:

Code: Select all

Events&#58;
   3 - 004E
   B - 0027
   E - 0024
&#91;0024&#93; &#40;D0&#41; pickupObject&#40;VAR_ACTIVE_OBJECT1&#41;;
&#91;0026&#93; &#40;00&#41; stopObjectCode&#40;&#41;;
&#91;0027&#93; &#40;48&#41; if &#40;VAR_ACTIVE_OBJECT2 == 101&#41; &#123;
&#91;002D&#93; &#40;A9&#41;   setOwnerOf&#40;VAR_ACTIVE_OBJECT1,14&#41;;
&#91;0030&#93; &#40;07&#41;   setState08&#40;101&#41;;
&#91;0033&#93; &#40;57&#41;   setState02&#40;101&#41;;
&#91;0036&#93; &#40;**&#41; &#125;
&#91;0036&#93; &#40;18&#41; goto 004D;
&#91;0039&#93; &#40;D8&#41; printEgo&#40;"That would be a waste."&#41;;
&#91;004D&#93; &#40;00&#41; stopObjectCode&#40;&#41;;
&#91;004E&#93; &#40;48&#41; if &#40;VAR_ACTIVE_OBJECT2 == 14&#41; &#123;
&#91;0054&#93; &#40;D8&#41;   printEgo&#40;"Yech! No thanks."&#41;;
&#91;0064&#93; &#40;78&#41; &#125; else if &#40;VAR_ACTIVE_OBJECT2 < 8&#41; &#123;
&#91;006D&#93; &#40;E9&#41;   setOwnerOf&#40;VAR_ACTIVE_OBJECT1,VAR_ACTIVE_OBJECT2&#41;;
&#91;0070&#93; &#40;**&#41; &#125;
&#91;0070&#93; &#40;00&#41; stopObjectCode&#40;&#41;;
END

Update 2

Cool, got this working fully now in ScummVM and DosBox. The issue in my last update was due to the if statement needs to specify the relative jump. As my if block was now 3 bytes larger, I just needed to add 3 to the jump (09 to 0c).
rasteve
Posts: 9
Joined: Mon Aug 18, 2014 12:20 am

Post by rasteve »

I have kinda answered my own question here.

It looks like setOwnerOf(VAR_ACTIVE_OBJECT1,14) (in MM-v2 at least) basically means you no longer have the object.

I have patched my copy of MM to now remove the dead-end caused by using the paint remover on anything BUT the paint blotch.

To my surprise, you can also play this patch in ScummVM. I'm going to have a look into making more fixes to the dead-ends. Maybe I could add a completely new ending and/or make Jeff more useful?
User avatar
sev
ScummVM Lead
Posts: 2277
Joined: Wed Sep 21, 2005 1:06 pm
Contact:

Post by sev »

Heh, that was an interesting read.


Eugene
User avatar
md5
ScummVM Developer
Posts: 2250
Joined: Thu Nov 03, 2005 9:31 pm
Location: Athens, Greece

Post by md5 »

Very interesting read!

There are a lot of dead ends in this game, which are documented here:
http://maniacmansionfan.50webs.com/waystolose.html

Perhaps the following can be patched the same way you patched the script that handles the paint remover:

- "If you do catch Ed's package before him but if you give it to him without collecting the unused stamps, the game becomes unwinnable with Razor, Syd and Wendy." - you could disallow giving Ed the package if it has the unused stamps on it
- "If you open the sealed envelope in Edna's safe the regular way (instead of steaming it open in the microwave), you will rip it and will no longer be able to send anything to Mark Eteer, making the game unwinnable with Razor, Syd and Wendy. In the Nes version, this was deemed too hard on the player, and if you try to open the envelope the regular way it will simply refuse to open." - you could disallow opening the envelope
- "If you send irrelevant material to Mark Eteer, you won't get to send anything else and this will make the game unwinnable with Razor, Syd and Wendy." - either disallow sending irrelevant material, or remove the check that disallows sending anything else
- "If you call the Meteor Police three times without unlocking the secret lab's door, they will refuse to come afterwards, making the game unwinnable with Bernard." - same as above, either remove the check where the police refuses to come, or disallow calling them until the secret lab door is unlocked
rasteve
Posts: 9
Joined: Mon Aug 18, 2014 12:20 am

Post by rasteve »

I am part way through patching the problem with the developer/sponge dead end. In the game you can feed it to the plant (which kills the plant). If the plant is dead, you cannot go to the room above, or possibly trap any kid (and their inventory) in the room above.

Whilst working on this fix I found another unknown bug. In the game you should be able to squeeze the sponge into the jar. There is code to handle the transfer of water or developer fluid, and to even use a jar of developer fluid elsewhere.

In the script roomobj-24-123:

Code: Select all

Events&#58;
   3 - 0049
   B - 002F
   E - 002C
&#91;002C&#93; &#40;D0&#41; pickupObject&#40;VAR_ACTIVE_OBJECT1&#41;;
&#91;002E&#93; &#40;00&#41; stopObjectCode&#40;&#41;;
&#91;002F&#93; &#40;48&#41; if &#40;VAR_ACTIVE_OBJECT2 == 132&#41; &#123;
&#91;0035&#93; &#40;9A&#41;   Var&#91;168&#93; = Var&#91;166&#93;;
&#91;0038&#93; &#40;1A&#41;   Var&#91;166&#93; = 0;
&#91;003C&#93; &#40;42&#41;   startScript&#40;80&#41;;
&#91;003E&#93; &#40;42&#41;   startScript&#40;79&#41;;
&#91;0040&#93; &#40;18&#41; &#125; else &#123;
&#91;0043&#93; &#40;79&#41;   doSentence&#40;11,VAR_ACTIVE_OBJECT2,VAR_ACTIVE_OBJECT1,0&#41;;
&#91;0048&#93; &#40;**&#41; &#125;
&#91;0048&#93; &#40;00&#41; stopObjectCode&#40;&#41;;
&#91;0049&#93; &#40;48&#41; if &#40;VAR_ACTIVE_OBJECT2 == 19&#41; &#123;
&#91;004F&#93; &#40;19&#41;   doSentence&#40;11,304,123,0&#41;;
&#91;0056&#93; &#40;**&#41; &#125;
&#91;0056&#93; &#40;78&#41; if &#40;VAR_ACTIVE_OBJECT2 < 8&#41; &#123;
&#91;005C&#93; &#40;E9&#41;   setOwnerOf&#40;VAR_ACTIVE_OBJECT1,VAR_ACTIVE_OBJECT2&#41;;
&#91;005F&#93; &#40;**&#41; &#125;
&#91;005F&#93; &#40;00&#41; stopObjectCode&#40;&#41;;
END
These lines are bugged:

Code: Select all

&#91;0035&#93; &#40;9A&#41;   Var&#91;168&#93; = Var&#91;166&#93;;
&#91;0038&#93; &#40;1A&#41;   Var&#91;166&#93; = 0;
It should read as:

Code: Select all

&#91;0035&#93; &#40;9A&#41;   Var&#91;166&#93; = Var&#91;168&#93;;			// jar now has sponge status
&#91;0038&#93; &#40;1A&#41;   Var&#91;168&#93; = 0;				// sponge now empty
It doesn't look like there is anything to stop you mixing developer fluid with water (which will be a dead end if you use a sponge with water on a jar with developer fluid, and possibly any water source on a jar with developer fluid). That fix will have to come later on...

Some of the fixes (such as the stamps, envelopes etc) and even to add new endings will require the scripts being expanded. I haven't tried changing their size yet (all my text changes are actually the same size so far). The reason being that I was unsure if there are hardcoded offsets.

When reading the sparse documentation on 00.LFL there seemed to be an opinion that some offsets are hardcoded, so people haven't had any luck in making substantial changes.

I guess I will find out soon.

I have some ideas for modding other Scumm games too. An easier version of Indiana Jones & the Last Crusade (higher punch power, more hit points on plane section), an easier "fists" path in the Fate of Atlantis (higher punch power again) and restore some missing scenes from Loom in talkie edition. Of course, bug fixes along the way.
User avatar
md5
ScummVM Developer
Posts: 2250
Joined: Thu Nov 03, 2005 9:31 pm
Location: Athens, Greece

Post by md5 »

rasteve wrote: I have some ideas for modding other Scumm games too. An easier version of Indiana Jones & the Last Crusade (higher punch power, more hit points on plane section), an easier "fists" path in the Fate of Atlantis (higher punch power again)
Higher punch power / more hit points should be doable via the ScummVM console. You can manipulate state variables directly there. Press Control-D to show the console, and type "help" to show the available commands
User avatar
clone2727
Retired
Posts: 1611
Joined: Fri Jun 09, 2006 8:23 pm
Location: NJ, USA

Post by clone2727 »

rasteve wrote:An easier version of Indiana Jones & the Last Crusade (higher punch power, more hit points on plane section), an easier "fists" path in the Fate of Atlantis (higher punch power again)
When you can't beat the game... cheat?
rasteve
Posts: 9
Joined: Mon Aug 18, 2014 12:20 am

Post by rasteve »

The Indy3 patch is aimed at making the game more forgiving. The controls for both fighting and the plane section make things difficult. Adding a little more power to the punch, and adding a few more hit points to your plane would bring the difficulty down.

Beyond that I don't know what else to change. I could add in a couple of scenes/rooms missed from the movie but first I need to get a better handle on the LFL file structures.

Update

Reading the source code in ScummVM it appears that the 00.LFL files will need to be amended if I do anything to change the file sizes of non-index files. This is about to happen as I am cleaning up some scripts in Maniac Mansion!

This is directly related to what I read in the ResourceManager class code (specifically regarding offsets).

The 00.LFL has a relatively simple file structure. I wonder, is the "globals" section the variables list?

Anyway, next task is to make an attempt at understanding the non-index file structure. I am hoping there are no offsets that need cleaning up if I make my intended changes to the scripts.
User avatar
LogicDeLuxe
Posts: 432
Joined: Thu Nov 10, 2005 9:54 pm

Post by LogicDeLuxe »

rasteve wrote:I have some ideas for modding other Scumm games too. An easier version of Indiana Jones & the Last Crusade (higher punch power, more hit points on plane section), an easier "fists" path in the Fate of Atlantis (higher punch power again) and restore some missing scenes from Loom in talkie edition. Of course, bug fixes along the way.
For Fate of Atlantis, why not just hit 0?


I did myself a bunch of bug fixes in the Monkey Island Ultimate Talkie Editions. See those readme files there for a huge list.
rasteve
Posts: 9
Joined: Mon Aug 18, 2014 12:20 am

Post by rasteve »

Hitting zero is fine, but I am thinking more along the lines of softening the difficulty so you don't need to do the sucker punch. Also, with a patch you could pick up all the IQ points in the game.

These are just ideas for the Indy games. At the moment I am working on MM, which has a lot of potential for modding. I am kinda stuck on the none-index file structures at the moment. I have found some sources on line which explain the file headers (and these do appear to tally up to my files). In the headers there are fields that control object offsets, and seeing as I am making changes I am figuring out if I need to change these offsets.

Looking at the source code on ScummVM, I think I could get away with only making changes to the offsets in the 00.LFL file. I can't see the code that splits these non-index files from the start, rather I can only really see that the offsets in the 00.LFL file are used to seek the object directly in the resource file.

However, I don't know if this will break the alternative way of running the game (e.g. DosBox). I am hoping that these headers are redundant to the game engine (possibly only needed for the original script editors).

The best/only articles I see on these file structures are one by Lloyd Rosen (SCUMM &#8208; The Infernal Machine) and some notes on a LFLView utility. The ScummVM wiki and other sources seem to have better notes on later version on Scumm, rather than this early version I am looking into.

Once I get through this I should be able to speed up, get a working patch out that fixes a number of dead-ends, add some new endings and maybe a new playable character or two? Hoagie and Laverne?

Nice work on the MI talkies. I will have to pick up the SE and try out your mods.
rasteve
Posts: 9
Joined: Mon Aug 18, 2014 12:20 am

Post by rasteve »

Progress update - still working on inserting a script of a different size. Along the way I have managed to map large parts of the LFL structure (even been able to dump out bitmaps of the room background images).

Anyway, there are offsets in both the 00.LFL and corresponding room LFL file that need changing. I can get Maniac Mansion to load up but as soon as I select my 2 kids to start a new game it crashes out.

It would be nice getting my hands on the ScummRP / resource packer source code. I cannot find it online. In the meantime I am writing my own crude packer using ScummVM source code as a reference against my own notes. I must be missing an offset somewhere.

Does anyone know if the interface itself is determined by a script? Forward thinking - it would be nice porting any Scumm script into the latest version of Scumm (CMI). However, the interface does change considerably along the way. Look at MM vs. MI2 vs. Loom vs. CMI etc. Technically, this does seem like a major stumbling block if the interface is hard-coded into the engine.
User avatar
clone2727
Retired
Posts: 1611
Joined: Fri Jun 09, 2006 8:23 pm
Location: NJ, USA

Post by clone2727 »

rasteve wrote:the latest version of Scumm (CMI)
I think you're missing a few years of the SCUMM engine :wink:
rasteve
Posts: 9
Joined: Mon Aug 18, 2014 12:20 am

Post by rasteve »

Yes, sorry I was limiting it to LucasArts releases. Has there been any significant changes to Scumm post-CMI? Visually, CMI looks pretty clean so would be happy giving some artist the ability to insert audio and greater image quality.

If porting was possible, I was merely thinking of a utility that converted older game scripts into a later copy of the game. Maniac Mansion to CMI, for example. It would require at least the original MM files (and at most the CMI exe if you want to run it outside of ScummVM).
User avatar
LogicDeLuxe
Posts: 432
Joined: Thu Nov 10, 2005 9:54 pm

Post by LogicDeLuxe »

clone2727 wrote:
rasteve wrote:the latest version of Scumm (CMI)
I think you're missing a few years of the SCUMM engine :wink:
This page ends with CMI, though: http://wiki.scummvm.org/index.php/SCUMM/Versions

rasteve wrote:Does anyone know if the interface itself is determined by a script? Forward thinking - it would be nice porting any Scumm script into the latest version of Scumm (CMI). However, the interface does change considerably along the way. Look at MM vs. MI2 vs. Loom vs. CMI etc. Technically, this does seem like a major stumbling block if the interface is hard-coded into the engine.
I'm not sure about the very early games, but Loom and Sam&Max show extensive examples of scripted interfaces, since both differ completely from other SCUMM games with the same engine version.

Especially Sam&Max's interface is obviously no engine addition, since it runs (somewhat glitchy though) with the DOTT executable.

The savegame menu is a special case. It is scripted in some games. You can tell by pressing shift-f5 in ScummVM, which calls the savegame menu script, if the game has one.
rasteve
Posts: 9
Joined: Mon Aug 18, 2014 12:20 am

Post by rasteve »

Thanks, that is something to go on.
Post Reply