Opened 7 days ago

Last modified 3 days ago

#15379 new defect

ADL: HIRES5: Game unsolvable after loading savegame. Save state not properly restored?

Reported by: eriktorbjorn Owned by:
Priority: normal Component: Engine: ADL
Version: Keywords:
Cc: Game: Hi-Res Adventure #5: Time Zone

Description

English version of Time Zone, from the Roberta Williams Anthology.
Current development version of ScummVM.

After completing the first task for Robin Hood, I was told to retrieve a bag of money from the Sheriff's office. At this point I saved. When I went to the office, the bag wasn't there.

I replayed that time zone again, without saving. This time the bag was there.

I think what happens is this. When you complete the first task, it sets the picture for the room where the money is supposed to be:

IF
	ROOM == 28
	&& SAID(*, *)
	&& VARS[6] == 2
THEN
	PRINT(75/YOU HAVE PROVEN YOUR BRAVERY AND SKILL!YOU ARE OFFICIALLY ONE OF ROBIN HOOD'S MERRY MEN. ROBIN HOOD NOW HAS A TASK FOR YOU TO DO. THERE IS A BAG OF MONEY IN THE BACK ROOM OF THE SHERIFF'S OFFICE. GET IT, AND BRING IT BACK TO ROBIN HOOD.)
	VARS[6] = 3
	SET_ROOM_PIC(32, 41)
END

The savegame contains the picture of each room in every region. See AdlEngine_v4::saveState().

However, in AdlEngine_v4::loadState(), once the savegame has been loaded it calls loadRegion(), and I have a hunch that this overwrites the custom pictures with the default ones. Afterwards, it calls restoreRoomState() but that only seems to restore the room picture for the current room.

I'm not sure how to fix this properly. I'm going to attach a savegame. From this, use the following commands:

  1. E. TALK ROBIN. YES. S. S. E. USE BOW. W. W.

You have completed the first task. This is where I saved when I triggered the bug. From here.

  1. N. N. N. N. N. W. N. N. W. LOOK WINDOW.

If you do it without saving/loading, the bag of money will be seen on the table. If you saved and restored, it will not.

Attachments (1)

hires5-apple2.s08 (9.9 KB ) - added by eriktorbjorn 7 days ago.

Download all attachments as: .zip

Change History (6)

by eriktorbjorn, 7 days ago

Attachment: hires5-apple2.s08 added

comment:1 by eriktorbjorn, 6 days ago

The AdlEngine_v4 implementation of saveState() and loadState() are used by the following games, as far as I can tell:

  • Time Zone
  • The Dark Crystal

The latter defines its own version, but it's just a minor extension. So at least it's all games that I own copies of.

The way I understand loadState():

It loads the header of the save file. This tells it which room and region the player is in and, for whatever reason, the previous region as well. Then it loads all the saved data, which consists of:

  • Each room's picture and isFirstTime values.
  • Each region's variables.
  • The room, region and state of every object.
  • Another list of variables, possibly global ones?

Then it calls loadRegion() for the current region. This is presumably to load the constant data for the region (vocabulary, map connections, etc.). That includes the picture, but it probably won't overwrite what was read from the savefile. The current rooms are loaded into _state.rooms while the ones loaded from the savegame are in _state.regions.rooms.

Finally it calls restoreRoomState(_state.room) which will set the picture and curPicture (haven't checked what the difference between the two are) to what was read from the savegame, though only if the room's isFirstTime flag is false. I'm not sure what that's about either.

It seems to me that when loading a saved game, it should fix the picture of every room in the current region?

comment:2 by eriktorbjorn, 6 days ago

This appears to be the code that determines if you can use the bow at the back office:

IF
    ROOM == 32
    && SAID(55/USE     , 17/BOW     )
    && VARS[4] == 1
    && GET_CURPIC() == 41
THEN
    SET_PIC(42)
    PRINT(10/YOU SHOOT THE ARROW AND IT PIERCES THE BAG OF MONEY.)
END

In which case it really does depend on the room picture to determine if the money is there. (Maybe because it's not an object in the sense that you can pick it up?)

comment:3 by eriktorbjorn, 6 days ago

It may be interesting to see if the bug also happens when running it in an Apple II emulator. Unfortunately I had some issues preventing me from doing so when I tried before. I might give it another try later. In the meantime, here is a fairly minimal walkthrough to get you to the same point as the savegame:

  1. N. GO MACHINE. GO MACHINE. SIT. SET BLUE. EUROPE. SET ORANGE. 1000AD. PUSH LEVER. LEAVE MACHINE. E. N. N. N. N. N. W. W. W. W. OPEN DOOR. N. GET MIRROR. S. E. E. E. E. S. S. S. S. S. W. GO MACHINE. SIT. NA. 1400AD. PUSH LEVER. LEAVE MACHINE. W. W. S. D. N. N. N. N. E. N. N. N. GIVE MIRROR. S. S. S. S. S. S. E. GO MACHINE. SIT. EUROPE. 1000AD. PUSH LEVER. LEAVE MACHINE.

comment:4 by eriktorbjorn, 5 days ago

@waltervn pointed out to me that restoreRoomState() is actually called every time you enter a new room, so the changes read from the savegame should be applied. Except that only happens if the isFirstTime flag is false. And since I had never looked through the window before the dryad quest, isFirstTime was true. (Looking through the window a second time does not seem to help here.)

If I look through the window before going on the dryad quest, it does work even after loading a savegame.

Apparently this bug happens with the original interpreter as well. So maybe it makes sense to add some sort of workaround? Question is, does this happen in other places as well?

Note: See TracTickets for help on using tickets.