dolphin icon indicating copy to clipboard operation
dolphin copied to clipboard

Fix SYSCONF movie settings

Open CasualPokePlayer opened this issue 2 years ago • 14 comments

The movie config layer is not active for recording, only playback. Thus, recording ends up stuck with default SYSCONF settings. The fix somewhat hacky, but seems to work.

This fixes https://bugs.dolphin-emu.org/issues/12822

CasualPokePlayer avatar Jul 12 '22 11:07 CasualPokePlayer

I'm not convinced your first change actually does anything? It already returns a nonconst pointer and I see no place that could possibly produce a copy.

AdmiralCurtiss avatar Jul 12 '22 13:07 AdmiralCurtiss

Also you probably need to explain the second one in more detail, how exactly does that fix the issue? e: Is that even safe? The generated loader (and layer) stores a pointer to the passed header, which would go out of scope at the end of BeginRecordingInput().

AdmiralCurtiss avatar Jul 12 '22 13:07 AdmiralCurtiss

I'm not convinced your first change actually does anything? It already returns a nonconst pointer and I see no place that could possibly produce a copy.

Yep, the explanation seems a bit dubious to me. A const iterator (an iterator that is const) and a const_iterator are not the same thing, and the same overload of begin/end is being called regardless of the constness of the iterator variable in which you store the result of find_if.

leoetlino avatar Jul 12 '22 13:07 leoetlino

I'm not convinced your first change actually does anything? It already returns a nonconst pointer and I see no place that could possibly produce a copy.

It's UB. You aren't allowed to modify the object from a const_iterator. I'm just saying the behavior I observed from this (I assume this is some "protection" against modification).

Also you probably need to explain the second one in more detail, how exactly does that fix the issue? e: Is that even safe? The generated loader (and layer) stores a pointer to the passed header, which would go out of scope at the end of BeginRecordingInput().

The header is only read once on construction from what I saw. I could change it to just use tmpHeader (or maybe just make this instance static there).

It fixes the issue as it now stores the relevant sysconf settings to the movie layer, allowing it to pass the later predicate used for setting sysconf: https://github.com/dolphin-emu/dolphin/blob/128fa8aec3738ab76075836780f7724a02d87f42/Source/Core/Core/BootManager.cpp#L162

I'm not convinced your first change actually does anything? It already returns a nonconst pointer and I see no place that could possibly produce a copy.

Yep, the explanation seems a bit dubious to me. A const iterator (an iterator that is const) and a const_iterator are not the same thing, and the same overload of begin/end is being called regardless of the constness of the iterator variable in which you store the result of find_if.

The type is const std::vector<Entry>::const_iterator. This can plainly be seen in a debugger. You are not allowed to modify the object from a const_iterator.

CasualPokePlayer avatar Jul 12 '22 15:07 CasualPokePlayer

The type is const std::vector::const_iterator. This can plainly be seen in a debugger. You are not allowed to modify the object from a const_iterator.

But there's no reason why find_if would be returning a const_iterator. Besides, if it was a const_iterator, evaluating &*iterator would result in a const SysConf::Entry*, which would cause a compilation error since the return type of the function is declared as SysConf::Entry*.

For what it's worth, the inline type display in VS2022 shows it as iterator and not const_iterator for me.

JosJuice avatar Jul 12 '22 16:07 JosJuice

That seems weird, my setup shows it as const iterator when it's const auto, not iterator. image

From what I can see to, it doesn't evaluate as const SysConf::Entry*, rather it evaluates to SysConf::Entry* and of course doesn't cause any errors for compiling.

CasualPokePlayer avatar Jul 12 '22 19:07 CasualPokePlayer

It says ::iterator right there in the second line, what are you talking about??

AdmiralCurtiss avatar Jul 12 '22 19:07 AdmiralCurtiss

It says ::iterator right there in the second line, what are you talking about??

Yes, when it's auto it's iterator, as the above function (that this PR modifies to be just auto rather than const auto) has. The below function is const auto, which has const_iterator.

CasualPokePlayer avatar Jul 12 '22 20:07 CasualPokePlayer

To be extremely clear what is happening here: grafik

AdmiralCurtiss avatar Jul 12 '22 20:07 AdmiralCurtiss

Again, that doesn't make any sense. Whether the member function is const qualified is what determines whether the const overload of begin/end gets called (and whether you get const_iterator or not). Const qualifying the variable does absolutely nothing and definitely does not change an iterator into a const_iterator. Note the underscore; those are different types.

leoetlino avatar Jul 12 '22 20:07 leoetlino

Ok, seems to go to iterator adding back the const auto. Weird, not sure what I was seeing then. Apologies then, I'll just revert that change back.

CasualPokePlayer avatar Jul 12 '22 20:07 CasualPokePlayer

Regarding the now remaining change: Doesn't this make it so that the "placeholder" header you're creating will override the user's settings?

JosJuice avatar Jul 16 '22 12:07 JosJuice

The "placeholder" header only contains settings the DTM would normally have and is filled with current settings at the time of starting the movie (with the ConfigLoaders::SaveToDTM(&header);). It should be similar to playing back a movie, although the settings would just be taken from the current active user settings rather than an actual file.

CasualPokePlayer avatar Jul 17 '22 06:07 CasualPokePlayer

Ah, so SaveToDTM doesn't actually save to a DTM file, it saves to the header you passed in. Yes, that makes sense then.

JosJuice avatar Jul 17 '22 06:07 JosJuice

Is there anything blocking this from being merged?

CasualPokePlayer avatar Nov 15 '22 01:11 CasualPokePlayer

Personally I'm not happy with more global state, and I also don't really understand why this works -- which also means I can't tell if this breaks anything.

AdmiralCurtiss avatar Nov 15 '22 01:11 AdmiralCurtiss

fwiw since I think our TAS setup logic needs a big overhaul anyway (like, in terms of letting the user configure what settings they want to start with) and since you're part of the TASing community (I think so, yeah?) if you're sure this works we can merge for now, probably...

AdmiralCurtiss avatar Nov 15 '22 01:11 AdmiralCurtiss

It works because the SYSCONF settings when recording a movie try to take them from the movie config layer specifically, and uses "default" settings otherwise (not sure how this is decided exactly, but moot anyways). This is intended so SYSCONF is set only with movie settings and other settings not exposed in the DTM go to predictable defaults rather than whatever is set otherwise.

This movie config layer is only set when playing back a movie, not recording one, so this ends up breaking when recording a movie. Language is hit hard since "default" here means "English" even for e.g. Japanese games, which can just cause the game to immediately crash. Other SYSCONF settings are also affected but probably don't have the same impact language has here?

This PR simply actually adds the movie config layer when recording a movie (also proceeds to remove it once the movie is done playing/recording, as it shouldn't be needed anymore).

CasualPokePlayer avatar Nov 15 '22 02:11 CasualPokePlayer

I'm still not 100% happy here but since this is well documented as a hack and very tiny, sure, whatever.

AdmiralCurtiss avatar Jan 30 '23 08:01 AdmiralCurtiss