Module botw.hashes
Provides hash tables for unmodified game files using xxHash
Expand source code
""" Provides hash tables for unmodified game files using xxHash """
# pylint: disable=bad-continuation
from json import loads
from functools import lru_cache
from typing import ByteString, Dict, Iterator, List, Union
from xxhash import xxh32_intdigest
from oead.yaz0 import decompress
from . import DATA_DIR
@lru_cache(None)
def get_wiiu_hash_table() -> Dict[str, List[int]]:
"""
Gets a hash table for game files in the unmodified 1.5.0 Wii U version of
BOTW. It comes as a dict with canonical path names as keys and lists of int
values. The list contains multiple possible hashes for files with no
modified content, including dirty versions affected by automatic processing
through libraries and tools.
"""
return loads((DATA_DIR / "wiiu_hashes.json").read_text("utf-8"))
@lru_cache(None)
def get_switch_hash_table() -> Dict[str, List[int]]:
"""
Gets a hash table for game files in the unmodified 1.5.0 Switch version of
BOTW. It comes as a dict with canonical path names as keys and lists of int
values. The list contains multiple possible hashes for files with no
modified content, including dirty versions affected by automatic processing
through libraries and tools.
"""
return loads((DATA_DIR / "switch_hashes.json").read_text("utf-8"))
class StockHashTable:
""" A class wrapping a hash table for stock BOTW files with a few
convenience methods. """
_table: Dict[str, List[int]]
def __init__(self, wiiu: bool):
table = get_wiiu_hash_table() if wiiu else get_switch_hash_table()
self._table = {file: set(xhashes) for file, xhashes in table.items()}
del table
@lru_cache(None)
def is_file_modded(
self, file_name: str, data: Union[ByteString, int], flag_new: bool = True
) -> bool:
"""Checks a file to see if it has been modified. Automatically decompresses yaz0 data.
Args:
file_name (str): The canonical resource path of the file to check
data (Union[ByteString, int]): Either the file data (as a byteslike object) or an xxh32
hash as an int
flag_new (bool, optional): Whether to flag new files (not in vanilla BOTW) as modified.
Defaults to True.
Returns:
bool: Returns whether the file's hash matches a known version of the hash for the
original version.
"""
if file_name not in self._table:
return flag_new
else:
if isinstance(data, int):
return data not in self._table[file_name]
if data[0:4] == b"Yaz0":
data = decompress(data)
return xxh32_intdigest(data) not in self._table[file_name]
@lru_cache(None)
def is_file_new(self, file_name: str) -> bool:
"""Checks if a file is present in the unmodded game.
Args:
file_name (str): The canonical resource path of the file to check
Returns:
bool: Returns True if the file is present in the stock hash table.
"""
return file_name in self._table
def get_stock_files(self) -> Iterator[str]:
"""Iterates the files in the stock hash table by their canonical resource paths.
Yields:
Iterator[str]: Iterator for stock files in hash table
"""
for file in self._table:
yield file
def list_stock_files(self) -> List[str]:
"""Lists all of the files in the stock hash table by their canonical resource paths.
Returns:
List[str]: List of stock files in hash table
"""
return list(self._table.keys())
Functions
def get_switch_hash_table() ‑> Dict[str, List[int]]
-
Gets a hash table for game files in the unmodified 1.5.0 Switch version of BOTW. It comes as a dict with canonical path names as keys and lists of int values. The list contains multiple possible hashes for files with no modified content, including dirty versions affected by automatic processing through libraries and tools.
Expand source code
@lru_cache(None) def get_switch_hash_table() -> Dict[str, List[int]]: """ Gets a hash table for game files in the unmodified 1.5.0 Switch version of BOTW. It comes as a dict with canonical path names as keys and lists of int values. The list contains multiple possible hashes for files with no modified content, including dirty versions affected by automatic processing through libraries and tools. """ return loads((DATA_DIR / "switch_hashes.json").read_text("utf-8"))
def get_wiiu_hash_table() ‑> Dict[str, List[int]]
-
Gets a hash table for game files in the unmodified 1.5.0 Wii U version of BOTW. It comes as a dict with canonical path names as keys and lists of int values. The list contains multiple possible hashes for files with no modified content, including dirty versions affected by automatic processing through libraries and tools.
Expand source code
@lru_cache(None) def get_wiiu_hash_table() -> Dict[str, List[int]]: """ Gets a hash table for game files in the unmodified 1.5.0 Wii U version of BOTW. It comes as a dict with canonical path names as keys and lists of int values. The list contains multiple possible hashes for files with no modified content, including dirty versions affected by automatic processing through libraries and tools. """ return loads((DATA_DIR / "wiiu_hashes.json").read_text("utf-8"))
Classes
class StockHashTable (wiiu: bool)
-
A class wrapping a hash table for stock BOTW files with a few convenience methods.
Expand source code
class StockHashTable: """ A class wrapping a hash table for stock BOTW files with a few convenience methods. """ _table: Dict[str, List[int]] def __init__(self, wiiu: bool): table = get_wiiu_hash_table() if wiiu else get_switch_hash_table() self._table = {file: set(xhashes) for file, xhashes in table.items()} del table @lru_cache(None) def is_file_modded( self, file_name: str, data: Union[ByteString, int], flag_new: bool = True ) -> bool: """Checks a file to see if it has been modified. Automatically decompresses yaz0 data. Args: file_name (str): The canonical resource path of the file to check data (Union[ByteString, int]): Either the file data (as a byteslike object) or an xxh32 hash as an int flag_new (bool, optional): Whether to flag new files (not in vanilla BOTW) as modified. Defaults to True. Returns: bool: Returns whether the file's hash matches a known version of the hash for the original version. """ if file_name not in self._table: return flag_new else: if isinstance(data, int): return data not in self._table[file_name] if data[0:4] == b"Yaz0": data = decompress(data) return xxh32_intdigest(data) not in self._table[file_name] @lru_cache(None) def is_file_new(self, file_name: str) -> bool: """Checks if a file is present in the unmodded game. Args: file_name (str): The canonical resource path of the file to check Returns: bool: Returns True if the file is present in the stock hash table. """ return file_name in self._table def get_stock_files(self) -> Iterator[str]: """Iterates the files in the stock hash table by their canonical resource paths. Yields: Iterator[str]: Iterator for stock files in hash table """ for file in self._table: yield file def list_stock_files(self) -> List[str]: """Lists all of the files in the stock hash table by their canonical resource paths. Returns: List[str]: List of stock files in hash table """ return list(self._table.keys())
Methods
def get_stock_files(self) ‑> Iterator[str]
-
Iterates the files in the stock hash table by their canonical resource paths.
Yields
Iterator[str]
- Iterator for stock files in hash table
Expand source code
def get_stock_files(self) -> Iterator[str]: """Iterates the files in the stock hash table by their canonical resource paths. Yields: Iterator[str]: Iterator for stock files in hash table """ for file in self._table: yield file
def is_file_modded(self, file_name: str, data: Union[ByteString, int], flag_new: bool = True) ‑> bool
-
Checks a file to see if it has been modified. Automatically decompresses yaz0 data.
Args
file_name
:str
- The canonical resource path of the file to check
data
:Union[ByteString, int]
- Either the file data (as a byteslike object) or an xxh32 hash as an int
flag_new
:bool
, optional- Whether to flag new files (not in vanilla BOTW) as modified. Defaults to True.
Returns
bool
- Returns whether the file's hash matches a known version of the hash for the original version.
Expand source code
@lru_cache(None) def is_file_modded( self, file_name: str, data: Union[ByteString, int], flag_new: bool = True ) -> bool: """Checks a file to see if it has been modified. Automatically decompresses yaz0 data. Args: file_name (str): The canonical resource path of the file to check data (Union[ByteString, int]): Either the file data (as a byteslike object) or an xxh32 hash as an int flag_new (bool, optional): Whether to flag new files (not in vanilla BOTW) as modified. Defaults to True. Returns: bool: Returns whether the file's hash matches a known version of the hash for the original version. """ if file_name not in self._table: return flag_new else: if isinstance(data, int): return data not in self._table[file_name] if data[0:4] == b"Yaz0": data = decompress(data) return xxh32_intdigest(data) not in self._table[file_name]
def is_file_new(self, file_name: str) ‑> bool
-
Checks if a file is present in the unmodded game.
Args
file_name
:str
- The canonical resource path of the file to check
Returns
bool
- Returns True if the file is present in the stock hash table.
Expand source code
@lru_cache(None) def is_file_new(self, file_name: str) -> bool: """Checks if a file is present in the unmodded game. Args: file_name (str): The canonical resource path of the file to check Returns: bool: Returns True if the file is present in the stock hash table. """ return file_name in self._table
def list_stock_files(self) ‑> List[str]
-
Lists all of the files in the stock hash table by their canonical resource paths.
Returns
List[str]
- List of stock files in hash table
Expand source code
def list_stock_files(self) -> List[str]: """Lists all of the files in the stock hash table by their canonical resource paths. Returns: List[str]: List of stock files in hash table """ return list(self._table.keys())