logfilereader: Fix RAM parser issues (#82)
* Create size helper * Replace fixed RAM units with size helper * Rename CommonErrors to CommonError Enum names should be singular * Apply black formatting
This commit is contained in:
parent
9669556a39
commit
72fd725a94
2 changed files with 83 additions and 24 deletions
|
@ -3,9 +3,10 @@ from enum import IntEnum, auto
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
|
|
||||||
from robocop_ng.helpers.disabled_ids import is_build_id_valid
|
from robocop_ng.helpers.disabled_ids import is_build_id_valid
|
||||||
|
from robocop_ng.helpers.size import Size
|
||||||
|
|
||||||
|
|
||||||
class CommonErrors(IntEnum):
|
class CommonError(IntEnum):
|
||||||
SHADER_CACHE_COLLISION = auto()
|
SHADER_CACHE_COLLISION = auto()
|
||||||
DUMP_HASH = auto()
|
DUMP_HASH = auto()
|
||||||
SHADER_CACHE_CORRUPTION = auto()
|
SHADER_CACHE_CORRUPTION = auto()
|
||||||
|
@ -209,24 +210,29 @@ class LogAnalyser:
|
||||||
self._hardware_info[setting] = cpu_match.group(1).rstrip()
|
self._hardware_info[setting] = cpu_match.group(1).rstrip()
|
||||||
|
|
||||||
case "ram":
|
case "ram":
|
||||||
|
sizes = "|".join(Size.names())
|
||||||
ram_match = re.search(
|
ram_match = re.search(
|
||||||
r"RAM: Total ([\d.]+) (MiB|GB) ; Available ([\d.]+) (MiB|GB)",
|
rf"RAM: Total ([\d.]+) ({sizes}) ; Available ([\d.]+) ({sizes})",
|
||||||
self._log_text,
|
self._log_text,
|
||||||
re.MULTILINE,
|
re.MULTILINE,
|
||||||
)
|
)
|
||||||
if ram_match is not None:
|
if ram_match is not None:
|
||||||
try:
|
try:
|
||||||
|
dest_unit = Size.MiB
|
||||||
|
|
||||||
ram_available = float(ram_match.group(3))
|
ram_available = float(ram_match.group(3))
|
||||||
if ram_match.group(4) == "GB":
|
ram_available = Size.from_name(ram_match.group(4)).convert(
|
||||||
ram_available *= 1024
|
ram_available, dest_unit
|
||||||
|
)
|
||||||
|
|
||||||
ram_total = float(ram_match.group(1))
|
ram_total = float(ram_match.group(1))
|
||||||
if ram_match.group(2) == "GB":
|
ram_total = Size.from_name(ram_match.group(2)).convert(
|
||||||
ram_total *= 1024
|
ram_total, dest_unit
|
||||||
|
)
|
||||||
|
|
||||||
self._hardware_info[
|
self._hardware_info[
|
||||||
setting
|
setting
|
||||||
] = f"{ram_available}/{ram_total} MiB"
|
] = f"{ram_available:.0f}/{ram_total:.0f} {dest_unit.name}"
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# ram_match.group(1) or ram_match.group(3) couldn't be parsed as a float.
|
# ram_match.group(1) or ram_match.group(3) couldn't be parsed as a float.
|
||||||
self._hardware_info[setting] = "Error"
|
self._hardware_info[setting] = "Error"
|
||||||
|
@ -500,36 +506,36 @@ class LogAnalyser:
|
||||||
def __get_notes(self):
|
def __get_notes(self):
|
||||||
for common_error in self.get_common_errors():
|
for common_error in self.get_common_errors():
|
||||||
match common_error:
|
match common_error:
|
||||||
case CommonErrors.SHADER_CACHE_COLLISION:
|
case CommonError.SHADER_CACHE_COLLISION:
|
||||||
self._notes.append(
|
self._notes.append(
|
||||||
"⚠️ Cache collision detected. Investigate possible shader cache issues"
|
"⚠️ Cache collision detected. Investigate possible shader cache issues"
|
||||||
)
|
)
|
||||||
case CommonErrors.SHADER_CACHE_CORRUPTION:
|
case CommonError.SHADER_CACHE_CORRUPTION:
|
||||||
self._notes.append(
|
self._notes.append(
|
||||||
"⚠️ Cache corruption detected. Investigate possible shader cache issues"
|
"⚠️ Cache corruption detected. Investigate possible shader cache issues"
|
||||||
)
|
)
|
||||||
case CommonErrors.DUMP_HASH:
|
case CommonError.DUMP_HASH:
|
||||||
self._notes.append(
|
self._notes.append(
|
||||||
"⚠️ Dump error detected. Investigate possible bad game/firmware dump issues"
|
"⚠️ Dump error detected. Investigate possible bad game/firmware dump issues"
|
||||||
)
|
)
|
||||||
case CommonErrors.UPDATE_KEYS:
|
case CommonError.UPDATE_KEYS:
|
||||||
self._notes.append(
|
self._notes.append(
|
||||||
"⚠️ Keys or firmware out of date, consider updating them"
|
"⚠️ Keys or firmware out of date, consider updating them"
|
||||||
)
|
)
|
||||||
case CommonErrors.FILE_PERMISSIONS:
|
case CommonError.FILE_PERMISSIONS:
|
||||||
self._notes.append(
|
self._notes.append(
|
||||||
"⚠️ File permission error. Consider deleting save directory and allowing Ryujinx to make a new one"
|
"⚠️ File permission error. Consider deleting save directory and allowing Ryujinx to make a new one"
|
||||||
)
|
)
|
||||||
case CommonErrors.FILE_NOT_FOUND:
|
case CommonError.FILE_NOT_FOUND:
|
||||||
self._notes.append(
|
self._notes.append(
|
||||||
"⚠️ Save not found error. Consider starting game without a save file or using a new save file⚠️ Save not found error. Consider starting game without a save file or using a new save file"
|
"⚠️ Save not found error. Consider starting game without a save file or using a new save file⚠️ Save not found error. Consider starting game without a save file or using a new save file"
|
||||||
)
|
)
|
||||||
case CommonErrors.MISSING_SERVICES:
|
case CommonError.MISSING_SERVICES:
|
||||||
if self._settings["ignore_missing_services"] == "False":
|
if self._settings["ignore_missing_services"] == "False":
|
||||||
self._notes.append(
|
self._notes.append(
|
||||||
"⚠️ Consider enabling `Ignore Missing Services` in Ryujinx settings"
|
"⚠️ Consider enabling `Ignore Missing Services` in Ryujinx settings"
|
||||||
)
|
)
|
||||||
case CommonErrors.VULKAN_OUT_OF_MEMORY:
|
case CommonError.VULKAN_OUT_OF_MEMORY:
|
||||||
if self._settings["texture_recompression"] == "Disabled":
|
if self._settings["texture_recompression"] == "Disabled":
|
||||||
self._notes.append(
|
self._notes.append(
|
||||||
"⚠️ Consider enabling `Texture Recompression` in Ryujinx settings"
|
"⚠️ Consider enabling `Texture Recompression` in Ryujinx settings"
|
||||||
|
@ -591,11 +597,11 @@ class LogAnalyser:
|
||||||
def get_last_error(self) -> Optional[list[str]]:
|
def get_last_error(self) -> Optional[list[str]]:
|
||||||
return self._log_errors[-1] if len(self._log_errors) > 0 else None
|
return self._log_errors[-1] if len(self._log_errors) > 0 else None
|
||||||
|
|
||||||
def get_common_errors(self) -> list[CommonErrors]:
|
def get_common_errors(self) -> list[CommonError]:
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
if self.contains_errors(["Cache collision found"], self._log_errors):
|
if self.contains_errors(["Cache collision found"], self._log_errors):
|
||||||
errors.append(CommonErrors.SHADER_CACHE_COLLISION)
|
errors.append(CommonError.SHADER_CACHE_COLLISION)
|
||||||
if self.contains_errors(
|
if self.contains_errors(
|
||||||
[
|
[
|
||||||
"ResultFsInvalidIvfcHash",
|
"ResultFsInvalidIvfcHash",
|
||||||
|
@ -603,7 +609,7 @@ class LogAnalyser:
|
||||||
],
|
],
|
||||||
self._log_errors,
|
self._log_errors,
|
||||||
):
|
):
|
||||||
errors.append(CommonErrors.DUMP_HASH)
|
errors.append(CommonError.DUMP_HASH)
|
||||||
if self.contains_errors(
|
if self.contains_errors(
|
||||||
[
|
[
|
||||||
"Ryujinx.Graphics.Gpu.Shader.ShaderCache.Initialize()",
|
"Ryujinx.Graphics.Gpu.Shader.ShaderCache.Initialize()",
|
||||||
|
@ -612,17 +618,17 @@ class LogAnalyser:
|
||||||
],
|
],
|
||||||
self._log_errors,
|
self._log_errors,
|
||||||
):
|
):
|
||||||
errors.append(CommonErrors.SHADER_CACHE_CORRUPTION)
|
errors.append(CommonError.SHADER_CACHE_CORRUPTION)
|
||||||
if self.contains_errors(["MissingKeyException"], self._log_errors):
|
if self.contains_errors(["MissingKeyException"], self._log_errors):
|
||||||
errors.append(CommonErrors.UPDATE_KEYS)
|
errors.append(CommonError.UPDATE_KEYS)
|
||||||
if self.contains_errors(["ResultFsPermissionDenied"], self._log_errors):
|
if self.contains_errors(["ResultFsPermissionDenied"], self._log_errors):
|
||||||
errors.append(CommonErrors.FILE_PERMISSIONS)
|
errors.append(CommonError.FILE_PERMISSIONS)
|
||||||
if self.contains_errors(["ResultFsTargetNotFound"], self._log_errors):
|
if self.contains_errors(["ResultFsTargetNotFound"], self._log_errors):
|
||||||
errors.append(CommonErrors.FILE_NOT_FOUND)
|
errors.append(CommonError.FILE_NOT_FOUND)
|
||||||
if self.contains_errors(["ServiceNotImplementedException"], self._log_errors):
|
if self.contains_errors(["ServiceNotImplementedException"], self._log_errors):
|
||||||
errors.append(CommonErrors.MISSING_SERVICES)
|
errors.append(CommonError.MISSING_SERVICES)
|
||||||
if self.contains_errors(["ErrorOutOfDeviceMemory"], self._log_errors):
|
if self.contains_errors(["ErrorOutOfDeviceMemory"], self._log_errors):
|
||||||
errors.append(CommonErrors.VULKAN_OUT_OF_MEMORY)
|
errors.append(CommonError.VULKAN_OUT_OF_MEMORY)
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
53
robocop_ng/helpers/size.py
Normal file
53
robocop_ng/helpers/size.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
from enum import IntEnum, auto
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
|
|
||||||
|
class Size(IntEnum):
|
||||||
|
KB = auto()
|
||||||
|
KiB = auto()
|
||||||
|
MB = auto()
|
||||||
|
MiB = auto()
|
||||||
|
GB = auto()
|
||||||
|
GiB = auto()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def names(cls) -> list[str]:
|
||||||
|
return [size.name for size in cls]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_name(cls, name: str) -> Self:
|
||||||
|
for size in cls:
|
||||||
|
if size.name.lower() == name.lower():
|
||||||
|
return size
|
||||||
|
raise ValueError(f"No matching member found for: {name}")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _is_si_unit(self) -> bool:
|
||||||
|
return self.value % 2 != 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _unit_value(self) -> int:
|
||||||
|
return self.value // 2 + (1 if self._is_si_unit else 0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _base_factor(self) -> int:
|
||||||
|
return 10**3 if self._is_si_unit else 2**10
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _byte_factor(self) -> int:
|
||||||
|
return (
|
||||||
|
10 ** (3 * self._unit_value)
|
||||||
|
if self._is_si_unit
|
||||||
|
else 2 ** (10 * self._unit_value)
|
||||||
|
)
|
||||||
|
|
||||||
|
def convert(self, value: float, fmt: Self) -> float:
|
||||||
|
if self == fmt:
|
||||||
|
return value
|
||||||
|
if self._is_si_unit == fmt._is_si_unit:
|
||||||
|
if self < fmt:
|
||||||
|
return value / self._base_factor ** (fmt._unit_value - self._unit_value)
|
||||||
|
else:
|
||||||
|
return value * self._base_factor ** (self._unit_value - fmt._unit_value)
|
||||||
|
else:
|
||||||
|
return value * (self._byte_factor / fmt._byte_factor)
|
Loading…
Reference in a new issue