Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
Well, I guess the tolerable desync concept is somewhat debatable, so far all my script had 15 as value, so I could bypass some other annoyance like extended sound glitch. I'll probably just add a setting for the tolerable desync, where minvalue would be 1 so we can get a checkpoint as soon as there a desync. This way, we can see what kind of "audio output" we shall get from one game to an another. So it should be fine.
Publisher
Joined: 4/23/2009
Posts: 1283
BadPotato wrote:
Well, I guess the tolerable desync concept is somewhat debatable, so far all my script had 15 as value, so I could bypass some other annoyance like extended sound glitch. I'll probably just add a setting for the tolerable desync, where minvalue would be 1 so we can get a checkpoint as soon as there a desync. This way, we can see what kind of "audio output" we shall get from one game to an another. So it should be fine.
What extended sound glitch do you mean? Do you have an example that I can take a look at? I don't see how tolerable desync would fix this problem any more than going backwards at most 15 frames. Maybe this is what I have been missing but seemly all the proposed workflows does not go backwards. Is going backwards hard? Even at setting of 1 for tolerable desync, the script should be going backwards at most 15 frames to cover the sound delay.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
Aktan wrote:
Even at setting of 1 for tolerable desync, the script should be going backwards at most 15 frames to cover the sound delay.
From some some of my old experiments, there's 2 way to fix the "sound delay" issue. Either we proceed with that "scalable" tolerable desync(the "good enough" concept). Or: Make a TAS-checkpoint a bit *before* the desync, then load it with the sync script, so eternal can rearrange the sound output from the last TAS-checkpoint savestate and when it reach the desync point... make an another checkpoint, so the sound is perfectly fluent. Way before, I tried to attempt this second solution, but I had several crash from pcsxrr, since the emulator couldn't support all the multiple savestate/loadstate going on. Right now, I just want our current workflow to work so we can test how good our current workflow is with several game. As for example, I think I encounter of these sound issue in the Breath Of Fire 3 run, but I don't remember where exactly this happen. I guess, once the workflow is fully setup, I could try to reproduce this.
Publisher
Joined: 4/23/2009
Posts: 1283
The second solution sounds like you made two savestates when one is only needed. But from what I think I gather, you're saying it isn't possible to go backwards. The 15 frame number I keep talking about is for frames going backwards. If the workflow never goes backwards, the 15 frame number is useless then. I still think there is a miscommunication between us since seemly you keep insisting a savestate at the exact desync frame, while I keep insisting a savestate before the desync frame. I should really draw a diagram.
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
In fact, even with lua/sockets my concept of keeping one instance a bit behind must work. Aktan's need this way can be done perfectly. I was saying about 15 frames back not due to tolerable desync already, but for this: Once check app gets to a desync point, backup app, that is 15 frames behind, already makes a state there and pauses. Or it can make 10 slot states in a row, as I described earlier. Only then check app starts loading these states. And if one of them resyncs, it is saved to disc with a name. But his point in 15 frames back is to allow seamless splicing with no sound glitches. Which includes additional manipulations and resplicing later. For initial test we can go for 10 or even 5 frames back for now, create and load just a single state for each mismatch. Even without dumping the frame numbers to xml I'd say. Just to see how it would work. No need in several hundred backup states this way.
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.
Publisher
Joined: 4/23/2009
Posts: 1283
Here is my diagram. I got lazy near the end on explaining pass 3, and some more information needs to be saved in pass 2 (like how many frames before the desync frame was the savestate that finally worked), but I think the general idea is there.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
I should point out that using a second savestate(from the eternal plugin) at the desync point is just a little technical detail to me, since it doesn't enhance to much the workflow, so we can do it your way as well. If I get my tool right, I should be able to make different kind of setting, so we can experiment several way of when taking savestate, etc. That said, I 100% approve the great capacity of this diagram since it should work, but sadly there's still an important flaw that we should consider with the "backward checkpoint": Note1: All green bar are also desync Note2: Some major desync will only be fixed by a savestate at desync, in such case... we might just have wasted all the previous savestate trying to bypass the desync himself. So yeah, the best matchup at some point would probably to anticipate if there a specific "strategy" pattern to favorise. Some strategy would be -Use the backward tas-savestate for minor desync, -Use eternal-savestate(that is actually processing frame from a backward tas-savestate) for minor desync point -Use tas-savestate directly for major desync point Note: the difference between major and minor desync would be, that the game is likely to desync in the next "few" frame(let's say max 15 frames) Also, keep in mind that our goal is trying to make plan for getting an efficient "list of savestate" to load while replaying the at last pass of the run in an automated way. For testing purpose I'll just make the workflow as simple as possible using savestate at desync point, but step by step and while testing with several game, we should be able to enhance the workflow to make it better, while using the best strategy avalaible, avoid possible issue, etc.. --- That said, I'm pretty sure I just spotted why we kept getting memory leak issue before. Since I have no idea how to copy/paste a Call Stack from VS2008, here's the screenshot. The relevant info is: >pcsx.exe!savestate_create(lua_State * L=0x010a3740) Line 1256 + 0x9 bytes C++ which is actually this line from LuaEngine.cpp(around line 1256):
	// The filename was allocated using malloc. Do something about that.
	free(filename);
For some reason my debugger don't want to run this line. It alway seem be to be ignored/skipped and it seem that the guy to blame is malloc. What's up with that?
edit: might not be relevant actually
Publisher
Joined: 4/23/2009
Posts: 1283
I've not encounter where the next desync 1 frame ahead of the previous desync, but I have encountered desyncs (rarely) where it is a few frames from the last one. When you say all the previous of "minor" desyncs are wasted from a major one, I say it isn't because there are frame differences (aka inaccurate) that were fixed. Basically, to me, a desync is a desync, there is no major or minor desync. If it desyncs, it should be fixed. Also I'm confused why you use pass 3 as your basis as that is the capture phase and all desyncs have been fixed already. Maybe I should clarify that... (which I did just now, lol) Just to make sure, the savestates made are always from TAS SPU, and not Eternal SPU, right? Might be another misunderstanding, but using savestates from Eternal SPU will probably cause more desyncs, hence why I am making sure...
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
Aktan wrote:
Just to make sure, the savestates made are always from TAS SPU, and not Eternal SPU, right? Might be another misunderstanding, but using savestates from Eternal SPU will probably cause more desyncs, hence why I am making sure...
Well, clarification is good. And nope, for now I dont plan to use Eternal SPU savestate. If I use them, that would be of course few frame after loading a TAS SPU savestate, but this still an another experimental idea. Right now, I just found out the beatiful GUI used by TheAxeMan in his Crystalis run and I'm amazed how fluent this run well in realtime. So I tried to get the Iup with some auxlibs to work on pcsx-rr(just like fceux) and it run fine until you want to stop the script, but I guess that could be manageable. But still, I'll prefer to look foward for these IPC function. That said current build has some ridiculous bug and it doesn't seem to be caused by feos's recent change. Here's what to do in order to reproduce: Replay a movie from BB2 or any game. Wait until the movie get a bit advanced into the game. Make a normale savestate using the hotkey. Example: use Shift+F1(Default) Close pcsxrr completly. Start pcsxrr again Replay the movie Load the movie right away. You will see at this point that the screen is filled with garbage and some random texture.
Publisher
Joined: 4/23/2009
Posts: 1283
This random garbage, does it go away after a while? I believe I've seen this before and it was due to loading the state while the game is not rendering from the initial game load, so loading a bit later fixed it.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
Aktan wrote:
I believe I've seen this before and it was due to loading the state while the game is not rendering from the initial game load, so loading a bit later fixed it.
Erf, I really don't get it what did just happened, but somehow I got it fixed by replacing my plugin folder by a backup. I'm completly clueless how come I even got this issue, since I've been testing it with different gpu plugin, but oh well. Now, these issue out of the way, one of the only feature missing would be the ability to relay only on savestate from RAM instead of getting pcsxrr alway using on slot from the sstate folder, so we get a bit less of IO bandwidth trafic. But I gotta admit that I'm unsure how we should proceed for this, yet. Should we just duplicate the savestate 0,1,2,3,4,5,6,8,9 into memory or making indepedant slot like "100","101","102"... etc ? How to get these "savestate/data object" shared thought IPC or any kind of API and from pcsxrr instance to an another? Despite Nach you woke on about some idea for this, I really can't tell if such a thing is possible. So I'm thinking about to rewrote my Lua script and aiming for single instance, so we can at least test how switchspu on fly is efficient while minalizing the risk of memory leak. Also, since I got more tool to work with, the process should be easier to make. My only last concern was to get pcsx.redrawscreen() to work, so I can reload a savestate without having to manage more framedelay(you can test by yourself, you alway has to frameadvance at least once for a normal loadstate to work) or doing weird experiment on the lua side... but yeah, framedelay management is fine. Expect more progress soon. Oh and one last thing, someone still have a backup from the old dammit script from there? luapastey seem to be down :/
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 guess you need to store the state contents to clipboard and get it from there then. Since just storing something in memory doesn't account application instance interaction. However, preparing the entire state for storing is another question. It consists of various data segments of various types. They all can be packed in a struct, but I'm not skilled enough to implement the whole thing (tried yesterday). Also, single instance would still cause the entropy accumulation for eternalSPU, if you roll back while playing it back with eternalSPU you most likely won't have the memory state necessary for successful resync. While tasSPU is stable at any point when played back with from the beginning (no entropy gets in).
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.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
Ok, I played around with the switchspu function and yeah... I got some weird result. I believe that function could be improved, but for now, double instance workflow seem the way to go. This time, I'll use socket and I started to read how ZMQ work, as I mentionned on the first page of this thread. This is what I should have done right in beggining, anyway. One more thing, anyone know how to disable ASSERT from external lib, when your are in "debbuging mode" with VisualStudio 2008? I keep getting this issue where the debbuger keep poping up some message that some code is not 100% safe(relevant from loading savestate, etc..) and it simply it refuse to ignore them. Thought, I don't have this problem at all in "Release mode". edit1: Well, it's seem that I got these assert issue, only when a bad pointer might not be null at the startup of the application... I might need some tip to know if there any clean way to get around this problem. edit2: I succesfully managed to get 2 instance communicate thought tcp socket with lua-zmq, but I just found out an another fantastic API, called winapi... it even seem to work well with the IPC protocol, so I'll probably use it instead. edit3: Sigh... Using both socket or Pipe asynchronously require at some point to relay manually on thread. It certainly can be done, but I believe we should avoid to do this as much as possible for such a simple task. Lua is basically a language designed without multithreading feature anyway and I think it might create some problem sooner or later. So I'll just use the clipboard to handle communcation(for desync point) instead of xml/socket/pipe. Thought, if I find a better idea later, clipboard should be replaced. edit4: Well, actually... I managed to setup somekind of file token and it seem to work. So, no clipboard, socket or anything complicated will be used.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
So, I rewrited a big part of the code. Now I just need clean up some stuff and you guys should be able to enjoy the new workflow. Meanwhile, here's a somewhat crappy encode of Bushido Blade 2. And here's the list of the 161 checkpoints for this 4minutes movie(with 15 "tolerable" frame desync):
{500, 1000, 1500, 1921, 2000, 2500, 2685, 2804, 2828, 2947, 3000, 3072, 3197, 3326, 3356, 3453, 3500, 3578, 3705, 3831, 3961, 4000, 4090, 4217, 4344, 4469, 4500, 4596, 4725, 4852, 4880, 4977, 5000, 5105, 5235, 5360, 5500, 5612, 5741, 5868, 6000, 6122, 6247, 6279, 6377, 6431, 6500, 6543, 6662, 6787, 6916, 7000, 7043, 7170, 7295, 7422, 7500, 7549, 7695, 7735, 7823, 7950, 8000, 8075, 8202, 8329, 8456, 8500, 8583, 8710, 8835, 8891, 9000, 9147, 9266, 9401, 9500, 9520, 9649, 9774, 9899, 10000, 10024, 10151, 10279, 10407, 10500, 10532, 10659, 10786, 10911, 11000, 11038, 11165, 11290, 11417, 11500, 11543, 11669, 11794, 11919, 12000, 12044, 12169, 12294, 12419, 12500, 12544, 12669, 12721, 12795, 12819, 12887, 12941, 12981, 13000, 13045, 13100, 13243, 13303, 13386, 13410, 13500, 13529, 13553, 13593, 13672, 13698, 13748, 13815, 13839, 13958, 13982, 14000, 14036, 14101, 14125, 14245, 14373, 14397, 14500, 14572, 14659, 14683, 14735, 14749, 14802, 14826, 15000, 15019, 15073, 15112, 15174, 15311, 15375, 15500, 15530, 15554, 15614, 15628, 16000}
Checkpoint at every 500 frame are obselete and should be removed soon(this way, we should be able to shorten the list by around 33 checkpoints). But, since we got a case here to study here, I would like that you check the movie and listen and see if you can spot some weird sound glitch. Maybe I never took the time to explain why all this weird sound happen, so let me explain. A minimal number of desync improve sound quality over visual frame, because when we "savestate" a frame from the TAS SPU plugin, the sound for that particuliar frame is kept in the memory. Then Eternal SPU has to handle sound and sometime SPU Eternal can't do much, since he can't get real info sound data from the past. I should have kept a log of all the desync that has been "tolerated", but I can say that there is still a bunch. That's why I believe that getting more "TAS-desyncproof-savestate" by lowering the value of "tolerable desync" at 1 is a bad idea if you don't want to lower the sound quality. All these cut in the sound memory make the audio sometime even less natural and annoying, even if it's still probably better than using TAS SPU all the way. Right now, as long as we use TAS SPU savestate, we want to get the savestate list as short as possible, while still matching the movie to avoid these "sound cut" issue. Thought, as I mentionned earlier as a future experimentation. It would be possible to fix *must* of these issue by using "Eternal savestate" at desync point, if they playback from a TAS savestate around ~30frame(1 second) or more(the longer affect the savestate "desyncless" lifetime), so they can have a chance to buffer the last music/SFX, etc.. Now the reason, why I said *must* is because sometime there won't be any effect, or worse it... I also fear that this might cause crash for some game... so that's why I would like that we try to encode some game with what we currently have. Breath of Fire, Symphony of Night, some 3D platformer, CD switch feature etc... all these kind of fame should be tested, first. As I said, I'll try to get the code a bit more solid before release. If my shedule isn't to heavy, you can expect an update by the end of the week.
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
There is a workaround to prevent sound glitching. It requires dumping the frame numbers in a specific manner. Each checkpoint is fixed by loading a state some frames back, as usual, but that state is loaded NOT at the frame it is saved at (NOT when the movie gets to that frame), but only after the capture already reaches the last sync frame. Then eternalSPU gets some extra frames to figure out how all the new data must be processed, and the frames where the sound is still glitched are cut away from the captured video. Desync is at frame 415. We save the tasSPU sate at frame 400. We capture the movie up to frame 415 with eternalSPU. Then we LOAD the tasSPU state from frame 400. In the encode, the frame 430 will be equal to our movie frame 415, but right after the tasSPU state (from frame 400) was loaded (at frame 415), there is the sound glitch. So we give eternalSPU these extra frames. But while doing this, we must dump another list - a list of avisynth trim commands with the corresponding frames. There's no command to cut out a bunch of frames in avisynth, only to pick and process some segment, so we need to append all the segments we pick with Trim. But what frames to trim at? As I said, we already have the properly sounding frames 0-415 from eternalSPU. So the first Trim command would use this segment. Then we shift the frame number forward by the diff between 400 and 415 (extra frames offset) and have the second segment starting at frame 430. Let's assume it needs to end at frame 810 then. At frame 810 we load the state from frame 800 (this means we have the new offset of 10 frames) and the next segment will start at the video frame 820, etc. So here is the code that must be dumped to a different text file, it then will be directly copypasted to our usual avisynth script and used for encoding.
Language: avisynth

Trim(0, 415) + \ Trim(430, 810) + \ Trim(820, 1000)
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.
creaothceann
He/Him
Editor
Joined: 4/7/2005
Posts: 1874
Location: Germany
If you know the index of the glitch and the number of frames it affects, you can do this:
Language: avisynth

AVISource(...) Remove(415, 15) Remove(811, ...) ... function Remove(clip c, int i, int Count) { c Trim(0, -i) + Trim(i + Count, 0) }
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
BadPotato, post the latest workflow you have,I want to test one thing.
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.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
Yup, I'll put it this weekend. I just got more busy than expected. edit: Arg, Sorry guys I got terribly sick lately and I didn't even check the code since. But here's a preview. The gui is almost over, but right now it doesn't do anything useful. In order to get it work just edit the "movieName = [[path]]" variable in pcsxrrWorkflowConfig. That should do it.
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
Uh, please describe how must it work. I run detect script to the end. Sync script launches another instance by itself. But it can't find any savestates, just runs forward, while sync instance waits for a fix...
detect script wrote:
frame 0000000000000000000015611 frame 0000000000000000000015612 frame 0000000000000000000015613 frame 0000000000000000000015614 Now awaiting for any incoming desync. Now trying fix the desync at frame 142 ... No savestate/checkpoint found near the desync, the emulator will reset.
and it never resets... Also, only one savestate gets created - at frame 15614
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.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
For the record here's the fix: https://dl.dropboxusercontent.com/u/1682902/PcsxrrEncodeWofkflowV6.01.7z I just tested this and it seem you'll need to do some temporary additionnal step to get it work: -First, once collecting is done by phase1(by using the TAS sound plugin), make a backup of your encode folder(should be "BB2 slash mode 6443 dammit.pxm") -When you're ready to start the the sync script make sure to use the Eternal plugin -The sync script will launch an another instance of pcsxrr using the detect script with a switch plugin feature. The last time I tried(some month ago) it used to work, but now for some reason, now I encounter a desync fest around the first few kill. To fix that: *Restore your backup folder(or restart from the very beggining if you didn't used a backup) *Start the sync script using the Eternal plugin. *Close the second instance using the detect script. *Manualy launch a new pcsxrr instance using the detection script and the TAS sound plugin. And that's it, no more desync fest. As I said, these additionnal step might be required as long as I/we didn't figure what's up with the switch plugin feature that may or not work sometime. Just make sure to at least test without these step for your first time. That said, thanks for reporting anything that might help me.
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
Now it looks like the detect application launched by sync script doesn't use TASspu, since there is a desync at EVERY frame, and it is not fixed by loading checkpoints..
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.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
feos wrote:
Now it looks like the detect application launched by sync script doesn't use TASspu, since there is a desync at EVERY frame, and it is not fixed by loading checkpoints..
It's kind of weird as the detect instance still fixe the first desync, but then it just give up. Anyway, in that case you'll need to follow these extra step:
BadPotato wrote:
-The sync script will launch an another instance of pcsxrr using the detect script with a switch plugin feature. The last time I tried(some month ago) it used to work, but now for some reason, now I encounter a desync fest around the first few kill. To fix that: *Restore your backup folder(or restart from the very beggining if you didn't used a backup) *Start the sync script using the Eternal plugin. *Close the second instance using the detect script. *Manualy launch a new pcsxrr instance using the detection script and the TAS sound plugin. And that's it, no more desync fest. As I said, these additionnal step might be required as long as I/we didn't figure what's up with the switch plugin feature that may or not work sometime. Just make sure to at least test without these step for your first time.
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
http://tasvideos.org/2415M.html Okay the movie is published. But the way kkapture dumps still leaves black frames when loading a state. But listen to the sound! It is amazing. Still in 2 places the voice sample was cut in teh middle, but there are no glitches or noises or something. It is because tas spu state is NOT LOADED along with savestates. But still, if we add a feature to dump extra frames and then cut them out with avisynth, it would make my spu savestates hack unnecessary and video frame not dying. Since we can use a custom avisynth function, dumping to a text file these: Remove(frame#, offset) But that would require an extra conversation - how to do extra frames in the first place.
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.
Spikestuff
They/Them
Editor, Publisher, Expert player (2642)
Joined: 10/12/2011
Posts: 6438
Location: The land down under.
Since I don't know how to package them can I request one please, I want to test this out too.
WebNations/Sabih wrote:
+fsvgm777 never censoring anything.
Disables Comments and Ratings for the YouTube account. Something better for yourself and also others.
Joined: 1/26/2009
Posts: 558
Location: Canada - Québec
Spikestuff wrote:
Since I don't know how to package them can I request one please, I want to test this out too.
Here's the svn r624 revision. According to the feos commit message that should do the job for encoding, but we should definitly add a checkbox setting somewhere so people can keep TASing in sync/efficiently when loading a savestate. As for the fullpackage, I'll try to work on it soon. There's an almost finished UI(kind of optionnal though) and some code clean left to do.