Skip to content

Commit

Permalink
remove unpack roms
Browse files Browse the repository at this point in the history
  • Loading branch information
jjshoots committed Apr 10, 2024
1 parent 1e8ceb1 commit b9fcdd1
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 62 deletions.
78 changes: 16 additions & 62 deletions src/python/roms/__init__.py
Original file line number Diff line number Diff line change
@@ -1,95 +1,49 @@
from __future__ import annotations

import base64
import functools
import hashlib
import json
import tarfile
import warnings
from pathlib import Path


@functools.lru_cache(maxsize=1)
def _get_all_rom_hashes() -> dict[str, str]:
def _get_expected_bin_hashes() -> dict[str, str]:
# this is a map of {rom.bin : md5 checksum}
with open(Path(__file__).parent / "md5.json") as f:
return json.load(f)


def _unpack_roms() -> None:
"""Unpacks all roms from the tar.gz file, then matches it to the expected md5 checksum."""
all_roms = _get_all_rom_hashes()

# load the b64 file, this assumes that the b64 already exists
# if you are a dev seeing this, please run `./curl_tar_gz_b64.sh` in the root of this project.
with open(Path(__file__).parent / "Roms.tar.gz.b64") as f:
tar_gz_b64 = f.read()

# decode the b64 into the tar.gz and save it
tar_gz = base64.b64decode(tar_gz_b64)
save_path = Path(__file__).parent / "Roms.tar.gz"
with open(save_path, "wb") as f:
f.write(tar_gz)

# iterate through each file in the tar
with tarfile.open(name=save_path) as tar_fp:
for member in tar_fp.getmembers():
# ignore if this is not a valid bin file
if not (member.isfile() and member.name.endswith(".bin")):
continue

# grab the rom name from the member name, ie: `pong.bin`
# member.name is ROM/rom_name/rom_name.bin, so we just want the last thing
rom_name = member.name.split("/")[-1]

# assert that this member.name should be supported
assert (
rom_name in all_roms
), f"File {rom_name} not supported. Please report this to a dev."

# extract the rom file from the archive
rom_bytes = tar_fp.extractfile(
member
).read() # pyright: ignore[reportOptionalMemberAccess]

# get hash
md5 = hashlib.md5()
md5.update(rom_bytes)
md5_hash = md5.hexdigest()

# assert that the hash matches
assert md5_hash == all_roms[rom_name], (
f"Rom {rom_name}'s hash ({md5_hash}) does not match what was expected ({all_roms[rom_name]}). "
"Please report this to a dev."
)

# save this rom
rom_path = Path(__file__).parent / rom_name
with open(rom_path, "wb") as rom_fp:
rom_fp.write(rom_bytes)


def get_rom_path(name: str) -> Path | None:
"""Expects name as a snake_case name, returns the full path of the .bin file if it's valid, otherwise returns None."""
# the theoretical location of the binary rom file
bin_file = f"{name}.bin"
bin_path = Path(__file__).parent / bin_file

# check if it exists within the the hash dictionary
all_roms = _get_all_rom_hashes()
if bin_file not in all_roms:
bin_hashes = _get_expected_bin_hashes()
if bin_file not in bin_hashes.keys():
warnings.warn(f"Rom {name} not supported.")
return None

# if the bin_path doesn't exist, TELL SOMEONE PANIC THE WORLD IS ENDING
if not bin_path.exists():
_unpack_roms()
# check the rom hash
with open(bin_path, "rb") as bin_fp:
md5 = hashlib.md5()
md5.update(bin_fp.read())
md5_hash = md5.hexdigest()

if md5_hash != bin_hashes[bin_file]:
raise IOError(
f"The hash of {bin_file} does not match what was expected!\n"
f"Expected ({bin_hashes[bin_file]}),\n"
f"Obtained ({md5_hash})."
)

# return the path
return bin_path


def get_all_rom_ids() -> list[str]:
"""Returns a list of all available rom_ids, ie: ['tetris', 'pong', 'zaxxon', ...]."""
all_roms = _get_all_rom_hashes()
all_roms = _get_expected_bin_hashes()
return [key.split(".")[0] for key in all_roms.keys()]
Empty file modified src/python/roms/tetris.bin
100644 → 100755
Empty file.

0 comments on commit b9fcdd1

Please sign in to comment.