Post subject: RAM logger for continuous movie comparison lua script (help)
Editor, Skilled player (1536)
Joined: 7/9/2010
Posts: 1319
I did some testing for the NES game called Kage (Shadow of the Ninja) and saved 6 frames on level 1-1. I continued with 1-2, but I lost 5 frames there. The game is very though to optimize, the speed is not constant and lag frames. Which means you could be faster at first, then you're slower, but in the end you end up faster, exactly what happened to me in 1-1. Taking all this into account it gets very annoying comparing a old movie with a second emulator open. So I had an idea to make comparing your work to an old movie easier. I wrote a lua script that saves all the RAM addresses I want to compare for a level/segment into a txt-file. Here is the lua script:
Language: lua

Name = "1-1 started"; -- Marker note in TAS Editor of the segment you want to compare RAMlog = io.open("RAMlog.txt", "a"); RAMlog:write(Name, "\n"); RAMlog:close(); RAMlog_values=function() XPos1 = memory.readbyte(0x0610); XPos2nd1 = memory.readbyte(0x0620); YPos1 = memory.readbyte(0x0630); YPos2nd1 = memory.readbyte(0x0640); XPosition1 = XPos2nd1*256 + XPos1; YPosition1 = YPos2nd1*256 + YPos1; RAMlog = io.open("RAMlog.txt", "a"); RAMlog:write("XP=", XPosition1, " ", "YP=", YPosition1, "\n"); -- message which is written to the txt-file and displayed later using another script RAMlog:close(); end; FCEU.registerafter(RAMlog_values);
You can change the logged RAM addresses and the message to what ever you want. This script creates a txt-file, which looks like this:
1-1 started
XP=5632 YP=8704
XP=5656 YP=8704
XP=5679 YP=8618
XP=5704 YP=8538
XP=5752 YP=8464
XP=5798 YP=8396
.
.
.
1-2 started
XP=5632 YP=8704
.
.
.
Another lua script should read a specific line from the txt-file depending on the framecounter. Note: This only works with TAS Editor due to the usage of Marker which is important. Here's the script for it so far, I need a bit of help to finish it.
Language: lua

Disp=function() if taseditor.engaged() == true then Marker = taseditor.getmarker(movie.framecount()); M_Str = taseditor.getnote(Marker); -- todo: function that finds the frame number of the Marked frame Diff = movie.framecount() - M_frame; -- Diff points at the line in the RAMlog.txt file used for the current frame RAMlog = io.open("RAMlog.txt", "r"); -- todo: -- Search for String in the RAMlog.txt file which is the same as the marker note -- From there use the Diff to pick the right line in the RAMlog.txt file RAMlog:close(); end; end; FCEU.registerafter(Disp);
How should this work: The script reads the frame number and the note of the marker where the playback cursor currently is. Then it calculates a difference between the frame where playback cursor is and the frame number of the marker. Then it searches for a string in the txt-file which is the same string as in the marker note. After something is found it uses the difference between framecounter and marker to pick up the right line. Let's say your marked frame with the note "1-1 started" is frame 300 and the playback cursor is at 305. Five lines after the string "1-1 started" in the txt-file is the right line ("XP=5752 YP=8464"), which should be read out. The marked frame would be the second line in the txt-file. On a new level another marker will point to other areas in the txt-file and read out the corresponding data. As already mentioned this one is not finished, and I would be glad if someone finishes it. I need some help with the io-functions and I couldn't find a function that returns the frame number of a marker. I hope everything is well written and understandable, if not feel free to ask.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Site Admin, Skilled player (1254)
Joined: 4/17/2010
Posts: 11475
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Editor, Skilled player (1536)
Joined: 7/9/2010
Posts: 1319
feos wrote:
http://tasvideos.org/forum/viewtopic.php?p=270971#270971
This script is only for playing back movies, not working on them. Loading a savestate or rewinding doesn't affect the display in the right way, as far as I can tell. I want my script to be able to handle rewinds.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Site Admin, Skilled player (1254)
Joined: 4/17/2010
Posts: 11475
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
Rewinds in TASEditor?
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Editor, Skilled player (1536)
Joined: 7/9/2010
Posts: 1319
Yeah, whenever you go to any previous frame.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Site Admin, Skilled player (1254)
Joined: 4/17/2010
Posts: 11475
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
Um, there's a GUI button and a hotkey for that. EDIT: I actually didn't read your first post carefully, you may want to wait until I do, then maybe I could make more sense.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Editor, Skilled player (1536)
Joined: 7/9/2010
Posts: 1319
I know this, of course. >.< I was trying to say that DarkKobold script can't handle rewinds, but I want mine to be able to do it.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Site Admin, Skilled player (1254)
Joined: 4/17/2010
Posts: 11475
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
I'm guessing you have all stuff displayed, but it doesn't jump to the corresponding frame as you loadstate and rewind, right? If so, you must add framecount to your text file, and then track the framecount delta as you advance/rewind, that way know the line you need to read. Because sometimes mouse wheel advancing jumps over several frames, so you can't plain increment/decrement them. Using delta is very stable. I don't even see why markers are so needed.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Editor, Skilled player (1536)
Joined: 7/9/2010
Posts: 1319
I need the markers for a reference point when a new level starts. After I improved 1-1 by a six frames and then proceed to the next level, the framecounter would be the same, but relative to the beginning of 1-2 it the displayed stuff would be behind by six frame, which I want to avoid. I want to compare the 1st frame of 1-2 of my run with the 1st frame of 1-2 of the old one, the 2nd one with the 2nd one, and so on. I use a delta in my script: Diff = movie.framecount() - M_frame; I just called it Diff for difference. 1. Calculate Diff. 2. Search for string of the marker note in the log file. 3. If something is found go "Diff" amounts of lines to the right line.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Joined: 12/31/2009
Posts: 174
If you need to easily store persistent data with save states, you can find a small area of RAM that is never touched. You just need 2 bytes to store the chapter and 4 bytes to store the frame count when the chapter started. All you would need to do is write a script to increment the chapter and store the current frame counter. You will also need a script to monitor access to that small area of RAM to make sure the game doesn't try to use it. Your script just has to read the current chapter and calculate your Diff with the frame count stored in RAM. When the chapter changes (either by save state or it increments), it'll switch to the "new" current chapter.
Editor, Skilled player (1536)
Joined: 7/9/2010
Posts: 1319
Zanoab, you probably didn't read everything in the thread properly. I don't need to store anything in savestates. The framecount of a chapter isn't a fixed number, I use the marker notes to have a reference point when a chapter starts.
Zanoab wrote:
Your script just has to read the current chapter and calculate your Diff with the frame count stored in RAM. When the chapter changes (either by save state or it increments), it'll switch to the "new" current chapter.
That is literally the same as I mentioned, except I don't use any savestates. I use markers for that. You may not know what markers are. They are just marked frames where something imprortant happens, such as "level end", "item collected" and so on. If you had read this:
Language: lua

-- todo: -- Search for String in the RAMlog.txt file which is the same as the marker note -- From there use the Diff to pick the right line in the RAMlog.txt file
you would know what I need. Some function that searches a string in a txt-file and one that goes to the right line. I'm not really familiar with the io-functions, so I don't know if such thing exits.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Player (137)
Joined: 9/18/2007
Posts: 389
I created something similar for creating my Plok movie, which was also used for the 100% Super Mario World 2 movie, but instead of only displaying RAM differences it also supports delta-copy-and-paste for the input. It's for Snes9x but it shouldn't be too difficult to adjust it for other emulators. I used a small file which can read and write Lua tables from files, then you could avoid the hassle of parsing your custom text files by hand.
Editor, Skilled player (1536)
Joined: 7/9/2010
Posts: 1319
A copy-pasting script is not needed for FCEUX, TAS Editor can copy-paste. I actually wanted to only one text file for the whole game, but it didn't work, because there isn't a io function that can search a string in a text file. So I need a text file for each level. I could also fix the issue with finding the frame number of a marker. There's no function like "taseditor.markedframe(index)" yet which returns the frame number of a marker. I used:
Language: lua

if taseditor.markedframe(movie.framecount())==true then M_frame = movie.framecount(); end;
The problem is the playback courser needs to be on the frame with the marker to find the frame number.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Player (98)
Joined: 12/12/2013
Posts: 378
Location: Russia
you making me sad :( you need to search string in file, and there isn't such function then make it yourself pseudocode:
f = io.open(file,'r');
all = f:read('*a');
s,e = string.find(all,'X1 Y2',1,true); // find from start plain text
(s,e - start, end, indices)
f:close(); // don't forget!
(didn't read whole thread) if you need to know line number then you must go through lines:
local l = 1;
for line in io.lines(filename) do
s,e = string.find(line,pattern,1,true);
if (s ~= nil ) then // I don't remember correct condition)
   return l,s,e; // returns line number, start, end;
end
r = r + 1;
end
something like that..... think please.