Opened 2 months ago
Last modified 7 weeks 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:
- 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.
- 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)
Change History (7)
by , 2 months ago
Attachment: | hires5-apple2.s08 added |
---|
comment:1 by , 2 months ago
comment:2 by , 2 months 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 , 2 months 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:
- 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 , 2 months 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?
comment:5 by , 2 months ago
I think something like this should do the trick: https://github.com/waltervn/scummvm/commit/d8f3b6f96e6e7329523a184af7a081fc6971e790
comment:6 by , 7 weeks ago
The AdlEngine_v2::takeItem()
function does call isInventoryFull()
function. But only if it makes it past the IDI_ITEM_DOESNT_MOVE
and IDI_ITEM_DROPPED
cases.
Which at least for the oxygen mask at the beginning of the game seems to mean that it's only called the first time you pick it up, not on subsequent attempts?
The
AdlEngine_v4
implementation ofsaveState()
andloadState()
are used by the following games, as far as I can tell: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:
picture
andisFirstTime
values.room
,region
andstate
of every object.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 thepicture
, 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 thepicture
andcurPicture
(haven't checked what the difference between the two are) to what was read from the savegame, though only if the room'sisFirstTime
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?