upthorn / gens-rerecording

Automatically exported from code.google.com/p/gens-rerecording
0 stars 0 forks source link

Lua Savestate.load should not automatically redraw the screen, or should provide "nodraw" option #61

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
The current behavior of Lua's savestate.load makes it awkward to write
camhacks and such in Lua, as it requires some extra work to dance around
the fact that savestate.load will immediately redraw the screen from the
contents of the savestate.

I'm tagging this a defect because it seems counter to developer intent in
implementing the feature.

Original issue reported on code.google.com by Upth...@gmail.com on 19 Mar 2009 at 12:37

GoogleCodeExporter commented 8 years ago
I think I've misinterpreted what was happening, closing the issue as invalid.

Original comment by Upth...@gmail.com on 19 Mar 2009 at 12:50

GoogleCodeExporter commented 8 years ago
... I should really test these things more exhaustively before I make snap 
decisions
like that. (Both in submitting this issue and in invalidating it)

Original comment by Upth...@gmail.com on 19 Mar 2009 at 1:00

GoogleCodeExporter commented 8 years ago
savestate.load does not immediately redraw the frame when loading anonymous
savestates. You can verify this by noting that the following script doesn't draw
anything:

local temp = savestate.create()
while true do
  gens.emulateframeinvisible()
  gens.wait()
  savestate.save(temp)
  savestate.load(temp)
end

I'm not sure why you'd ever want to use non-anonymous savestates for something 
like a
camhack, but if you want to do it anyway, you can disable immediate redraw by 
setting
speedmode("maximum") before loading the numbered savestate (and presumably 
you'd want
to set it back afterward with speedmode("normal")).

Original comment by nitsuja-@hotmail.com on 19 Mar 2009 at 4:48

GoogleCodeExporter commented 8 years ago
Then, can you explain why the following code:

                            local ost_totallength = addr_ostend-addr_ost
                            local objlist =
memory.readbyterange(addr_ost,ost_totallength)
                            local state = savestate.create()
                            local curycam = ycamera-240
                            savestate.save(state)
                            while curycam <= ycamera do
                                 memory.writeword(addr_ycamera,curycam)
                                 local i = 1
                                 gens.emulateframeinvisible()
                                 while i <= ost_totallength do
                                      memory.writebyte(addr_ost+i-1,objlist[i])
                                      i = i + 1
                                 end
                                 curycam = curycam + 16
                            end
                            gui.redraw()
                            savestate.load(state)

required "local screen = gui.gdscreenshot()" and "gui.image(screen)" to 
surround the
"savestate.load(state)" in order to display the result on screen?

Original comment by Upth...@gmail.com on 19 Mar 2009 at 4:55

GoogleCodeExporter commented 8 years ago
As far as I can tell, it doesn't require that. I see what appears to be the 
correct
result onscreen (the scene drawing with the camera in a different place, 
whatever I
set ycamera to), and when I surround the call to savestate.load with that 
screenshot
code, the image I see doesn't change. Maybe a more complete example would help 
show
the issue?

Original comment by nitsuja-@hotmail.com on 19 Mar 2009 at 5:28

GoogleCodeExporter commented 8 years ago
Here's the full script. Modified from DeltaPHC's sonic level editing Lua script
(http://pastebin.ca/1364116) 
(http://tasvideos.org/forum/viewtopic.php?p=194375#194375)

Open Sonic 1 or S3K
start a level and run that script
slow down the emulator to the point where you can see individual frames (as the
resulting tile will only display for one frame before the game overwrites it 
due to
the savestate being loaded)
click "tiles" then click + or - on any individual tile.
When I do this, I do not see the selected tile change, even for one frame.

However, if I uncomment the "local screen = gui.gdscreenshot()" and
"gui.image(screen)" lines (185, 187, 212, and 214), and repeat that process, 
the tile
graphic does change as expected (only for one frame, though, because there's not
currently any way to read or write to the VRAM nametables from Lua).

Original comment by Upth...@gmail.com on 19 Mar 2009 at 5:45

Attachments:

GoogleCodeExporter commented 8 years ago
Upon further testing, it seems to be a bug in the script somewhere, not
savestate.load() doing it.

Original comment by Upth...@gmail.com on 19 Mar 2009 at 6:43

GoogleCodeExporter commented 8 years ago

Original comment by Upth...@gmail.com on 19 Mar 2009 at 6:45

GoogleCodeExporter commented 8 years ago
I guess you figured this out already but I'll post it anyway to clarify for 
others,
and for one sort-of-question I had.

The screen is not refreshing when the savestate is loaded. It's refreshing well 
after
that, at the end of the current frame, like normal.

Sequence of events:
sleep
beginframe
-> script calls redraw to try to show the selected tile
-> script loads a prior savestate but doesn't draw it yet
endframe
updategui
-> emulator renders the current state, and the current state doesn't have the 
altered
tile so you'll barely see that since it was drawn less than a frame ago
sleep
etc.

The quick fix for this is to call a function that tells the next frame not to 
render,
which doesn't quite exist (not as a built-in function at least) but that is
essentially what the screenshot trick is doing and why that works.

I'm still not sure what he should do instead so I'm curious as to what bug you 
found
in the script that would fix the problem if resolved. I haven't run into this 
problem
when making camhack-like scripts, though.

Original comment by nitsuja-@hotmail.com on 19 Mar 2009 at 7:16

GoogleCodeExporter commented 8 years ago
If the gens.registerbefore is changed to gens.registerafter, everything works, 
and it
doesn't get immediately refreshed. Similarly if body of the anonymous
gens.registerbefore function is moved into the body of the anonymous 
gui.register
function, so that is the solution.

Though making the updated screen last more than one frame is still going to be 
a bit
of a trick.

Original comment by Upth...@gmail.com on 19 Mar 2009 at 7:42