Previously, the Lingo state would be frozen by persisting the frames on
the bottom of the callstack with a special flag. This required extra
logic to determine whether or not the callstack was intended to be empty
after execution finished, with some complex edge cases.
The new approach is to swap out the LingoState object on the window,
meaning that an empty callstack always signifies execution has completed.
It remains to be seen if we'll need to track more than one frozen
context; for now it seems to be okay.
Fixes driving to locations in DEVO Presents: Adventures of the Smart Patrol.
The previous arrangement was to copy the bits of Lingo state back and forth from
the Window object to the Lingo instance, and query the window for the
callstack. This refactor consolidates the current Lingo state into a single
struct, owned by the Window object and accessible via a pointer on the
Lingo object.
The loading of the next movie and corresponding shared cast
is now handled in seperate functions.
There checks when to load a new shared cast and when to delete
the previous one could be simplified by returning early when the
previous and new shared casts are the same.
At the same time it fixes a Dereference after null check from Coverity.
sharedCast->getArchive() could return a null pointer and wasn't checked
in all places.
Fixes COVERITY: 1498090
When an error happens during go, for example with a nonexisting movie
the lingo callstack isn't cleaned up properly.
Now the callstack is cleaned up via `popContext(aborting=true)`.
This improves on commit:
DIRECTOR: fix memleak when lingo context is frozen
27b314cb25
The Lingo tests were failing because of memory leaks.
- `move` overwrote an existing cast without deleting it
- `puppetTransition` was set but not removed on class destruction
- the *.lingo test files were opened but never removed
Cleanup the lingo callstack when closing.
When a movie calls `go frameId` a big pause button is hit
and everything is put into order to not go to the frame +1
but to the requested frameId. That big pause button is called
`_freezeContext`.
However when quitting in the middle of a frozen context
there are lingo frames left on the callstack.
This can be reliably reproduced with a plethora of D2 and D3 movies
with the debugflags fewframesonly,fast.
Lingo function `closeResFile` is only responsible for closing resource
file opened by `openResFile`. Register in `openResFile` which files
where opened and close only those files in `closeResFile`.
- Rename `_openResFiles` to `_allOpenResFiles` and
- Add new `_openResFiles` hashmap to track which files were opened in
`openResFile`.
A pointer to sharedCast was stored in the HashMap_openResFiles.
sharedCasts were deleted when a switch to a new movie was made
while _openResFiles is cleared when quitting Director.
This fix removes the reference to the shared cast when the shared cast
is deleted.
The engine treats film loops as N full channels getting rendered to the
screen in the space of one. As such, it's impossible to pre-blit together
the content, as any blitter mode can be used for each of the items.
This fixes https://trello.com/c/bucHPI2F/429-majestic-regression
hasFrozenContext is now a function which checks the call stack for
frozen contexts. Not updating this variable manually leaves less room
for error.
The game Majestic dynamically sets the castNum to video casts and expects them to play directly.
Videos were also stopped erroneously. Video stoppage is assumed when
movieRate is 0. The comment als indicated that it was probably broken
for D4.
The corresponding lingo code is, where anim is a cast label.
set the castNum of sprite 48 to cast(anim)
updateStage()
set the movieRate of sprite 48 to 1
repeat while the movieRate of sprite 48
updateStage()
end repeat