Joined: 2/29/2008
Posts: 1
Perhaps we could use the Lua thing to basically do what the Mac version does, but in windows? That'd really be awesome.
Chamale
He/Him
Player (182)
Joined: 10/20/2006
Posts: 1353
Location: Canada
Here's an idea: Maybe someone more motivated than me could do this for the .smv files for the SMW fastest-possible TASes. The Mario who stays in the camera would be the one from the current TAS. The Bowser fight would be interesting, as Mario keeps reappearing at the spawn point.
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
I have made a ghost script of the same kind as the one Dromiceius wrote, but for Super Metroid. It consists of two parts, a recorder and a player. One runs the recorder one time for each movie one wants to compare with. It writed files with position, room transition and hitbox data. One then runs the player script, which reads these files, and superimposes hitboxes on the run you want to compare the others to. The recorder has only one option: The smv file to record for. Each time you run the recorder, you must edit the line at the top of the file specifying this. The player has several options. You must first specify which smv will be the main movie, i.e. the one that snes9x will run now, and that the others will be compared to. Next, you can specify a list of smvs to compare it with. The recorder must have been run for all of these. The colors option specifies which colors should be used for the hitboxes of the other smvs. The most interesting options are the ingame and room options. With ingame = 0, you will see all frames. With ingame = 1, frames where the ingame time does not change are not displayed, but realtime is still used for synchronization. Finally, ingame = 2 uses ingame time both for deciding which frames to display, and for synchronization. Since we have runs that focus on both realtime and ingame time, this option is quite handy. The room option specifies whether room comparison mode should be used. If room = 0, things will be synchronized by using the absolute frame number, while with room = 1, it will find the closest matching room transition, and sync from the start of that, so in this mode, all the movies will enter each room at the same time, and you can compare how they traverse each room. If moviefile is undefined, a main smv file is not loaded, and you can play while comparing to others (this is usually a depressing experience :P). Savestates should work, and not mess up sync, and fast forwarding and frame advance, too. I made this script on a slightly modified snes9x, but I don't think I use any non-standard lua calls here. It would be nice if somebody could test, though. The files are at http://folk.uio.no/sigurdkn/recorder.lua and http://folk.uio.no/sigurdkn/player.lua. Ps. The initialization during player.lua takes a bit of time (about 2-3 s per comparison movie, on my computer). All of these scripts load the smv files themselves, so do not load them manually. Pps. I have also made a modified version of snes9x which plays several movies concurrently, and superimposes graphics from all but one of them on the last one. It basically works like this script, but with all sprites instead of just hit boxes. It, does not support savestates or frame skipping, though, and will be much work to port to windows, so I probably won't finish it.
S@G
Joined: 9/7/2006
Posts: 81
Location: Luxemburg
Too bad that a windows version of this Projekt was never released.
I don't need a Signature
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
I think this can be done easily with Lua if there were a couple of more extensions to it. If there were a mode to "load" a movie file into a table (not actually play it), have the number of frames since the last reset (you can probably track that in lua though), and most importantly; have a way in lua to turn off the background and everything, you can do this:
load movie file as input array
create player state
create movie state
save both here
now for every frame do
  save player state
  load movie state
  do next movie input
  get image string
  save movie state
  load player state
  do player input
  draw the movie input over the player input with some transparancy (or something to make sure who's who)
repeat
And this would be a ghost, emulator independent (FCEUX can disable background etc as well) and game independant! You can do the same principle for multiple movies too :)
qfox.nl
Banned User
Joined: 12/23/2004
Posts: 1850
Sure, until you realize that turning off the background can make some screenshots entirely meaningless (SMB1).
Perma-banned
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Well, more like, you need positioning. But if you have a static MEM_X_COORD MEM_Y_COORD then all you have to do for the ghost to work for a game is to find the x/y coords for the character. Well, basically anyways.
qfox.nl
Banned User
Joined: 12/23/2004
Posts: 1850
You still have to take into account a game's camera positioning and "area", among other things... not to mention removing pause screens or other undesirable sprites. At that point it isn't really very game-independant.
Perma-banned
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Well I'm not saying it's an ideal script. And multi angle camera games would not work, period. But I'm just saying that in most 2d games, it will suffice.
qfox.nl
Banned User
Joined: 12/23/2004
Posts: 1850
I never brought up the issue of 3D. All of my remarks are meant only to be applied to 2D games. Doing a 3D ghost in Lua would be borderline impossible.
Perma-banned
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
XKeeper: actually, this is how I first tried implementing this. It ran horribly slowly, and I also seem to remember some problems from a one frame delay occuring every time you load. Saving and loading state is an expensive operation. To make it less expensive, I tried implementing memory-only savestates, but it did not help much, and I didn't manage to implement them well enough, since they led to desyncs. Which is why I went with the multiprocess approach instead. Ofcourse, if running time is not an issue, it is probably feasable to fix the other problems and implement a script like the one you suggest, but it would still be a lot of work.
Banned User
Joined: 12/23/2004
Posts: 1850
amaurea wrote:
XKeeper: actually, this is how I first tried implementing this. It ran horribly slowly, and I also seem to remember some problems from a one frame delay occuring every time you load. Saving and loading state is an expensive operation. To make it less expensive, I tried implementing memory-only savestates, but it did not help much, and I didn't manage to implement them well enough, since they led to desyncs. Which is why I went with the multiprocess approach instead. Ofcourse, if running time is not an issue, it is probably feasable to fix the other problems and implement a script like the one you suggest, but it would still be a lot of work.
You can use gui.register to do the drawing-to-screen operations, and keep information in the main emu.frameadvance() loop. Of course, it really requires that there is an easy way to tell what position you're in in a movie; from what I've seen, there's no way to get something like emu.framecounter, and even then frame counters aren't stored for normal (non-movie) gameplay, except inthe case of VBA.
Perma-banned
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
Telling where you are in a movie is not that hard: you just count how many frames have been executed so far. Another problem with this approach is that every other frame will display something from the other movie: Your loop has two frames, one per movie, per iteration, and this will lead to flickering. You can't fast forward past one of these, since there will be no graphics to capture in that case. I guess this could be worked around by not only adding the secondary movie's graphics to the primary one's, but also the other way around, but this would require two screenshot buffers, and would still lead to flickering in the form of things alternately being in front of and behind each other. Still, it would be very nice if you could get this to work! Just because I gave up doesn't mean it's impossible.
Banned User
Joined: 12/23/2004
Posts: 1850
amaurea wrote:
Telling where you are in a movie is not that hard: you just count how many frames have been executed so far.
Savestates can easily break that idea; if you rewind 10 frames, how will the script know that? This is why I think there should be an easy-to-use "emu.frames" or "emu.playpos". Preferrably like VBA's, that stores both game and movie frames (i.e., starting recording mid-game = game 100, movie 1), that is savestate-persistant.
Another problem with this approach is that every other frame will display something from the other movie: Your loop has two frames, one per movie, per iteration, and this will lead to flickering. You can't fast forward past one of these, since there will be no graphics to capture in that case. I guess this could be worked around by not only adding the secondary movie's graphics to the primary one's, but also the other way around, but this would require two screenshot buffers, and would still lead to flickering in the form of things alternately being in front of and behind each other.
No, what you would do is store an external "replay" file that simply has frame# and a few relevant variables (camerapos, area, player location, animation frame). It would use the replay data instead of switching between two movies.
Still, it would be very nice if you could get this to work! Just because I gave up doesn't mean it's impossible.
If somebody could tell me how to get GD + Lua working in these emulators, I would consider it.
Perma-banned
Banned User
Joined: 12/23/2004
Posts: 1850
http://www.youtube.com/watch?v=biaZSfjy_Vg 6 hours of mindless drooling later, this. Lua can shove its table system UP. ITS. ASS. Yeah, I said it. Fuck you and your tables, Lua. Maybe I can get alden (or was it qFox) to help me with a basic interface, and maybe get a way to get frame counts. As it is, the only way to sync it is to ... well, there isn't! Mostly just "pause, reset, record movie, load Lua, start playing" (due to how Lua hijacks the emulator's speed settings...) Some screenshots without the debug output, showcasing klmz's first version (v1 marker) and his next one:
Perma-banned
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
Xkeeper wrote:
amaurea wrote:
Telling where you are in a movie is not that hard: you just count how many frames have been executed so far.
Savestates can easily break that idea; if you rewind 10 frames, how will the script know that?
I would use registersave and registerload to make that variable be stored with the savestate.
Xkeeper wrote:
This is why I think there should be an easy-to-use "emu.frames" or "emu.playpos". Preferrably like VBA's, that stores both game and movie frames (i.e., starting recording mid-game = game 100, movie 1), that is savestate-persistant.
I still think that this is a good idea, though.
Xkeeper wrote:
Another problem with this approach is that every other frame will display something from the other movie: Your loop has two frames, one per movie, per iteration, and this will lead to flickering. You can't fast forward past one of these, since there will be no graphics to capture in that case. I guess this could be worked around by not only adding the secondary movie's graphics to the primary one's, but also the other way around, but this would require two screenshot buffers, and would still lead to flickering in the form of things alternately being in front of and behind each other.
No, what you would do is store an external "replay" file that simply has frame# and a few relevant variables (camerapos, area, player location, animation frame). It would use the replay data instead of switching between two movies.
How will you display the correct sprite for the ghost, then? If you just display a hit box, then it sounds just like what I did for super metroid. I guess it would be possible to store the actual sprite in the file too. This could be done in several ways: 1. Store the sprite for every frame. This gives you a very big file. 2. Store every different sprite once, and then the index in that list for every frame. This is probably the best way of doing it. It requires knowledge of the memory address which holds which sprite is being used. 3. Store only the sprite number, and then decode the sprite from the rom during playback. This is probably a bit over the top. Number 2 is probably the best option here. I am tempted to give it a try.[/list]
Banned User
Joined: 12/23/2004
Posts: 1850
My method would have an index of sprite animations (e.g., "1 = x1,y1-x2,y2") and store only the frame number, relying on an external PNG or similar.
I would use registersave and registerload to make that variable be stored with the savestate.
Hm. Something to look into, perhaps.
Perma-banned
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
An external png sounds like a nice solution. It removes the most difficult part of what I thought of, and also opens for interesting possibilities like making Mario's ghost be Luigi, for example.
Banned User
Joined: 12/23/2004
Posts: 1850
Or for having multiple players each have their own graphic :)
Perma-banned
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
The current interim of fceux will always return a framecount for movie.framecount(), even when no movie is playing. Like on screen, it will then return the number of frames since last reset. Needs a little testing, but I think it's ok. That should solve your problem as well.
qfox.nl
Banned User
Joined: 12/23/2004
Posts: 1850
qFox wrote:
The current interim of fceux will always return a framecount for movie.framecount(), even when no movie is playing. Like on screen, it will then return the number of frames since last reset. Needs a little testing, but I think it's ok. That should solve your problem as well.
Last reset? Eh... since last ROM load would be better, or at least last poweron, but thanks for the tip (much superior to nothing). I don't recall seeing that in the manual, though. By the way, would you be interested in helping me out with this a bit? I could use somebody who has experience with iup to do an interface, and your help would be greatly appreciated.
Perma-banned
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Nope, it's in the interim (the current unreleased build) because I've changed it to work that way last friday :) I've also added a setrenderplanes() function to fceux, explained here: http://cbc.qfox.nl/emulua#emu.setrenderplanes But! Don't get used to the syntax yet. This is unreleased and the syntax will probably be changed to something more flexible. The principle will stay though :)
qfox.nl
Joined: 12/30/2008
Posts: 2
Layer would be required. Take the NES Zelda for example: You will have 2 sets of octoroks, one for player A, one for player B. each player can only attack their own ocktorocks. This would get confusing and would require the ghost to have a different pallette of enemies or some sort of transarencies (of course, transparencies in games is just 1 frame of the sprite, one off, in a tas race, this wouldn't be adivsable...
Joined: 3/11/2008
Posts: 583
Location: USA
Xkeeper wrote:
Doing a 3D ghost in Lua would be borderline impossible.
Not really. Just go Sonic spirit style- flying glowy dot/circle/sphere. You just need the camera info(position, rotation) and track of where the ghost should be, and from there it's just translate/rotate, clip, draw. (if you so desire, draw one on the player as well.) There's the level/scene break problem, but that'll be there in any game really.
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
An improved version of my super metroid ghost script, based on my discussion with Xkeeper above, is described here, along with a demonstration video: http://tasvideos.org/forum/viewtopic.php?t=6539&start=168