We don't really have to keep track of device opens/closes manually,
since we can already check that by calling IsOpened() on the device.
This also replaces some loops with for range loops.
Certain parts of the standard library try to determine whether or not a
transfer operation should either be a copy or a move. The prevalent notion
of move constructors/assignment operators is that they should not throw,
they simply move an already existing resource somewhere else.
This is typically done with 'std::move_if_noexcept'. Like the name says,
if a type's move constructor is noexcept, then the functions retrieves an
r-value reference (for move semantics), or an l-value (for copy semantics)
if it is not noexcept.
As IOFile deletes the copy constructor and copy assignment operators,
using IOFile with certain parts of the standard library can fail in
unexcepted ways (especially when used with various container
implementations). This prevents that.
'operator void*' is basically a pre-C++11-ism that was used, as C++03
only had the notion of implicit type-conversion operators, but not explicit type
conversion operators (allowing implicit conversion of a file handle to
bool can go downhill pretty quickly).
ExecuteCommand was becoming pretty confusing with unused variables
for some commands, confusing names (device ID != IOS file descriptor),
duplicated checks, not keeping the indentation level low, and having
tons of things into a single function.
This commit gives more correct names to variables, deduplicates the
device checking code, and splits ExecuteCommand so that it's
easier to read.
It's worth noting that some device checks have been forgotten in the
past, which has caused a bug (which was recently fixed in 288e75f6).
From what I can tell, the emulated GPU places (0,0) at the lower left of
the image, and we were generating texture coordinates so that (0,0) was
at the upper-left in the expansion geometry shader, causing textures
used by point sprites to be flipped vertically.
Fixes the upside-down A button in Mario Golf.
Since in this case we're setting it based on the state at record start
time, not when a register is loaded, UseMemory would not be called, so
this could potentially wipe out texture memory that was valid.
This should ensure that when playing with loop enabled, the first frame is
in the same state each time. There is potentially still issues when the
start frame is set to something other than zero, but I'm not sure how we
could work around this without capturing the entire state on each frame.
Doing it from the add dialogs instead would prevent the call to these dialogs outside of a breakpointWindow which would be necessary for hotkeys binding.
This also makes it a strongly-typed enum.
Considering that the flushing mode is a trait/behavior for the register
cache, it doesn't really make sense to have the enum separate from it.
This also has the benefit of removing constants from global scope.