Now that we have all of the rearranging and proper structure sizes in
place, it's fairly trivial to implement svcGetThreadContext(). In the
64-bit case we can more or less just write out the context as is, minus
some minor value sanitizing. In the 32-bit case we'll need to clear out
the registers that wouldn't normally be accessible from a 32-bit
AArch32 exectuable (or process).
This will be necessary for the implementation of svcGetThreadContext(),
as the kernel checks whether or not the process that owns the thread
that has it context being retrieved is a 64-bit or 32-bit process.
If the process is 32-bit, then the upper 15 general-purpose registers
and upper 16 vector registers are cleared to zero (as AArch32 only has
15 GPRs and 16 128-bit vector registers. not 31 general-purpose
registers and 32 128-bit vector registers like AArch64).
Makes the public interface consistent in terms of how accesses are done
on a process object. It also makes it slightly nicer to reason about the
logic of the process class, as we don't want to expose everything to
external code.
Internally within the kernel, it also includes a member variable for the
floating-point status register, and TPIDR, so we should do the same here to match
it.
While we're at it, also fix up the size of the struct and add a static
assertion to ensure it always stays the correct size.
A process should never require being reference counted in this
situation. If the handle to a process is freed before this function is
called, it's definitely a bug with our lifetime management, so we can
put the requirement in place for the API that the process must be a
valid instance.
boost::static_pointer_cast for boost::intrusive_ptr (what SharedPtr is),
takes its parameter by const reference. Given that, it means that this
std::move doesn't actually do anything other than obscure what the
function's actual behavior is, so we can remove this. To clarify, this
would only do something if the parameter was either taking its argument
by value, by non-const ref, or by rvalue-reference.
Add asserts for compute shader dispatching, transform feedback being
enabled and alpha testing. These have in common that they'll probably break
rendering without logging.
The std::vector instances are already initially allocated with all
entries having these values, there's no need to loop through and fill
them with it again when they aren't modified.
auto x = 0;
auto-deduces x to be an int. This is undesirable when working with
unsigned values. It also causes sign conversion warnings. Instead, we
can make it a proper unsigned value with the correct width that the
following expressions operate on.
Ternary operators have a lower precedence than arithmetic operators, so
what was actually occurring here is "return (out + full) ? x : y" which most
definitely isn't intended, given we calculate out recursively above. We
were essentially doing a lot of work for nothing.
This can cause warnings about static constructors, and is also not ideal
performance-wise due to the indirection through std::function. This also
keeps the behavior itself separate from the surrounding code, which can
make it nicer to read, due to the size of the code.
Given these are only added to the class to allow those functions to
access the private constructor, it's a better approach to just make them
static functions in the interface, to make the dependency explicit.
This converts it into a regular constructor parameter. There's no need
to make this a template parameter on the class when it functions
perfectly well as a constructor argument.
This also reduces the amount of code bloat produced by the compiler, as
it doesn't need to generate the same code for multiple different
instantiations of the same class type, but with a different fill value.
The locations of these can actually vary depending on the address space
layout, so we shouldn't be using these when determining where to map
memory or be using them as offsets for calculations. This keeps all the
memory ranges flexible and malleable based off of the virtual memory
manager instance state.
Previously, these were reporting hardcoded values, but given the regions
can change depending on the requested address spaces, these need to
report the values that the memory manager contains.
Rather than hard-code the address range to be 36-bit, we can derive the
parameters from supplied NPDM metadata if the supplied exectuable
supports it. This is the bare minimum necessary for this to be possible.
The following commits will rework the memory code further to adjust to
this.
* Implemented fatal:u properly
fatal:u now is properly implemented with all the ipc cmds. Error reports/Crash reports are also now implemented for fatal:u. Crash reports save to yuzu/logs/crash_reports/
The register dump is currently known as sysmodules send all zeros. If there are any non zero values for the "registers" or the unknown values, let me know!
* Fatal:U fixups
* Made fatal:u execution break more clear
* Fatal fixups
* Stubbed IRS
Currently we have no ideal way of implementing IRS. For the time being we should have the functions stubbed until we come up with a way to emulate IRS properly.
* Added IRS to logging backend
* Forward declared shared memory for irs
Preserves the meaning/type-safetiness of the stream state instead of
making it an opaque u32. This makes it usable for other things outside
of the service HLE context.
* Added glObjectLabels for renderdoc for textures and shader programs
* Changed hardcoded "Texture" name to reflect the texture type instead
* Removed string initialize
This isn't used anywhere within the header, so we can remove it, along
with the include that was previously necessary. This also uncovers an
indirect include in the cpp file for the assertion macros.
This was very likely intended to be a logical OR based off the
conditioning and testing of inversion in one case.
Even if this was intentional, this is the kind of non-obvious thing one
should be clarifying with a comment.
Even though setting this value to 3 is more correct. We break more games than we fix due to missing implementations. We should keep this as 0 for the time being
The owning process of a thread is required to exist before the thread,
so we can enforce this API-wise by using a reference. We can also avoid
the reliance on the system instance by using that parameter to access
the page table that needs to be set.
Qt provides an overload of tr() that operates on quantities in relation
to pluralization. This also allows the translation to adapt based on the
target language rules better.
For example, the previous code would result in an incorrect translation
for the French language (which doesn't use the pluralized version of
"result" in the case of a total of zero. While in English it's
correct to use the pluralized version of "result", that is, "results"
---
For example:
English: "0 results"
French: "0 résultat" (uses the singular form)
In French, the noun being counted is singular if the quantity is 0 or 1.
In English, on the other hand, if the noun being counted has a quantity
of 0 or N > 1, then the noun is pluralized.
---
For another example in a language that has different counting methods
than the above, consider English and Irish. Irish has a special form of
of a grammatical number called a dual. Which alters how a word is
written when N of something is 2. This won't appear in this case with a
direct number "2", but it would change if we ever used "Two" to refer to
two of something. For example:
English: "Zero results"
Irish: "Toradh ar bith"
English: "One result"
Irish: "Toradh amháin"
English: "Two results"
Irish: "Dhá thorthaí" <- Dual case
Which is an important distinction to make between singular and plural,
because in other situations, "two" on its own would be written as "dó"
in Irish. There's also a few other cases where the order the words are
placed *and* whether or not the plural or singular variant of the word
is used *and* whether or not the word is placed after or between a set
of numbers can vary. Counting in Irish also differs depending on whether or not
you're counting things (like above) or counting people, in which case an
entirely different set of numbers are used.
It's not important for this case, but it's provided as an example as to why one
should never assume the placement of values in text will be like that of
English or other languages. Some languages have very different ways to
represent counting, and breaking up the translated string like this
isn't advisable because it makes it extremely difficult to get right
depending on what language a translator is translating text into due to
the ambiguity of the strings being presented for translation.
In this case a translator would see three fragmented strings on
Transifex (and not necessarily grouped beside one another, but even
then, it would still be annoying to decipher):
- "of"
- "result"
- "results"
There is no way a translator is going to know what those sets of words
are actually used for unless they look at the code to see what is being
done with them (which they shouldn't have to do).
Several classes have a lot of non-trivial members within them, or don't
but likely should have the destructor defaulted in the cpp file for
future-proofing/being more friendly to forward declarations.
Leaving the destructor unspecified allows the compiler to inline the
destruction code all over the place, which is generally undesirable from
a code bloat perspective.
This was used in two different translation units
(deconstructed_rom_directory and patch_manager). This means we'd be
pointlessly duplicating the whole array twice due to it being defined
within the header.
These variables aren't used, which still has an impact, as std::vector
cannot be optimized away by the compiler (it's constructor and
destructor are both non-trivial), so this was just wasting memory.
std::shared_ptr isn't strictly necessary here and is only ever used in
contexts where the object doesn't depend on being shared. This also
makes the interface more flexible, as it's possible to create a
std::shared_ptr from a std::unique_ptr (std::shared_ptr has a
constructor that accepts a std::unique_ptr), but not the other way
around.
An instance of the NAX apploader already has an existing NAX instance in
memory. Calling directly into IdentifyType() directly would re-parse the
whole file again into yet another NAX instance, only to toss it away
again.
This gets rid of unnecessary/redundant file parsing and allocations.
AsNCA() allocates an NCA instance every time it's called. In the current
manner it's used, it's quite inefficient as it's making a redundant
allocation.
We can just amend the order of the conditionals to make it easier to
just call it once.