One of the biggest pains working with JPC-rr is the fact that the movie files are so hard to refactor. To patch in a change into a finished movie is nearly impossible, as the movie files are stored with very specific relative time values. Changing any one of these values has a ripple effect that impacts all the others, and can often lead to invalid values and desyncs everywhere.
After thinking about the problem for a while, I decided to try and create a set of lua scripts to make this process easier. Once finished, I tested it out on my
Hero's Quest TAS, and was happy to find out that it was a great success. The scripts I created convert the complicated movie file format into something readable and easily editable. And although it's not perfect and does cause some desyncs, fixing them is a lot simpler now. To give some perspective, it took me about eight hours to refactor the Hero's Quest TAS and remove the resyncs. It would have taken me 3 - 4 times that long redoing it from scratch. When I found another possible improvement at the end of refactoring, it took me just two hours to refactor it from the start again and remove the resyncs a second time.
I think it's at a state where I can share it with the rest of the community now, so without further ado, here is what I've named "TAS Scripts".
Step 1: Record a TAS script
The first step in refactoring the code is to convert a movie file to a TAS Script.
1) Download the
recordtasscript.lua and
fileio.lua files and put it in your lua directory.
2) Put the movie file you want to convert into the lua directory
3) Edit the recordtasscript.lua file in a text editor and update the moveFile variable with the name of the movie file you want to refactor, and the TASScriptFile variable with the name of the TAS Script file you want to create. Save.
4) Open JPC-rr and load the movie file
5) In the Lua window, run recordtasscript.lua. Wait until it has parsed the movie file and says you can start your movie running.
6) Run your movie to the end. The script will convert the movie to a TAS Script as it plays.
7) Terminate the script once the movie has fully played.
If successful, your movie file which looks something like this:
+0 SAVESTATE 48ee390aca349821084b61652763eca08be308bf526e0b77 0
+87008950 SAVESTATE ca11a6f0219e1c4e48461de8b5641fca6ee5bfc0dc42ae0c 3
+14268150 SAVESTATE 1ac0e82719240fc23c8222406999edb018d8463475ef46b4 4
+55220 org.jpc.emulator.peripheral.Keyboard KEYEDGE 28
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 28
+614031020 SAVESTATE b6200e347c52b8ceeecc66dd64b47ab13b3dc878f66eece4 4
+13044500 SAVESTATE 78314316d124332100e7d03ea6705f0b90cbe47b229e2c54 4
+0 SAVESTATE d3d78c36ed464e355691fbe346b3d2057de3277fb28833a8 11
+0 SAVESTATE 83a31f8ee5f07ef4a95ba118cb39feff85f7ae11b0afe868 15
+51542 org.jpc.emulator.peripheral.Keyboard KEYEDGE 66
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 66
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 21
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 21
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 28
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 28
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 21
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 21
+666660 org.jpc.emulator.peripheral.Keyboard KEYEDGE 28
will have been turned into a TAS Script file that looks something like this:
Save:798
FAdv:3
Type:<lctrl>cc<lctrl>ooppeenn<enter><enter>
FAdv:42
Save:801
FAdv:6
Save:816
Type:<esc><esc>ggeett rroocckk<enter><enter>
FAdv:8
Save:817
MXMove:-54
MYMove:29
FAdv:1
MClick:0
FAdv:1
MClick:0
FAdv:1
MXMove:64
MYMove:-40
The TAS Script
The TAS Script has the following commands (case-sensitive):
FAdv:#
This command tells the script runner to frame advance # number of frames. You'll most likely be editing these values whenever you run into a desync.
MXMove:#
This translates to an XMOUSEMOTION command that moves the mouse along the X-axis by #
MYMove:#
This translates to an YMOUSEMOTION command that moves the mouse along the Y-axis by #
MClick:#
This translates into an MOUSEBUTTON command that clicks the # button on the mouse (0 for left button, 1 for right)
Type:abcde
This creates KEYEDGE commands for all the letters after the colon. Note that special keys are bracketed in '<' and '>' brackets (see fileio.lua for list of keys) and normal keys are represented by their un-shifted values. In other words, to type an exclamation mark, you need to put "<lshift>11<lshift>". Also note that usually you will type every key twice, once for the key press and once again for the key release.
Save:#
This represents a save that was made in the movie, along with the save number as #. When running the TAS file, it can't save, so it does a XMOUSEMOTION 0 instead. The save number can be useful to quickly find how far you are into your TAS file when you're running it.
Pause:
This is a very useful command that pauses playback when you're running your TAS script. Good for when you want to hone in on a particular section, or want to set up a savestate.
You can also add your own comments to your TAS file, either by starting a line with a colon:
: This is a comment
or by adding a colon to the end of an existing line:
FAdv:4:This is a comment
Step 2: Running and Editing your TAS Script
To run your TAS Script, first you need to download
runtasscript.lua and save it in your lua directory. You also need the aforementioned
fileio.lua file.
Open runtasscript.lua in a text editor and change the scriptFile variable to be the name of your TAS Script file. Now assemble your game from scratch, then in your Lua window run runtasscript.lua. Wait until it has parsed your TAS Script file, then start JPC-rr running. You'll see it playing the commands listed in your script file.
At some point in time it will desync. To better look at what is causing the desync, throw a Pause: command in somewhere before the desync, then step your movie frame-by-frame. Once you've identified where it's desyncing, you can update your TAS Script file to try and get around the desync. To test your changes, terminate the Lua VM, reassemble your game, and run runtasscript.lua again. Note that it is important that you do it in that order. If you're correct, you will have fixed the desync. If you are wrong, then you'll have to try something else to fix it.
Soon you will get far enough that you don't want to start from the beginning every time. Throw a Pause: command in just before you desync. It will run one frame advance after the Pause: command and then stop. Create a save state, then delete everything from your script file from the start to the next FAdv after the Pause: command you entered (subtract one from that FAdv). Save it as a new TAS Script file (as you'll probably want to keep your old one around). Edit runtasscript.lua to point to your new TAS Script file and save. Then terminate the Lua VM, load your save state, and then re-run runtasscript.lua (again in that order). You should now be able to start running from your save state.
Inserting new commands into a TAS Script file works the same as fixing desyncs, except instead you're now inserting new commands. Type what you want to type, move the mouse how you want to move it, and put frame advances where you want them. Then rerun and see what impacts your changes have.
That's basically it. Let me know if you have any questions, and I'll leave you with two TAS Scripts that run the boot sequence for you. This one skips Config.sys and Autoexec.bat:
Save:0
FAdv:5
Save:2
Type:<enter><enter>
FAdv:40
Save:3
Type:<f5><f5>
FAdv:6
Save:12
and this one runs Config.sys (for extra memory) but skips Autoexec.bat which you shouldn't need:
Save:0
FAdv:4
Save:3
FAdv:1
Save:4
Type:<enter><enter>
FAdv:44
Save:4
FAdv:1
Save:4
Save:11
Save:15
Type:<f8><f8>yy<enter><enter>yy<enter><enter>yy<enter><enter><esc><esc>
If you need the mouse, just add
Type:ccttmmouousese //rr3322
at the end
Finally, it only seems to work if TAS files are saved in UNIX format. It doesn't like the line endings in PC format. I'll look into that sometime when I have more time.