Skip to content

Commit

Permalink
Add a custom Python script "add2tar.py" to create the vram0 tar file
Browse files Browse the repository at this point in the history
  • Loading branch information
ihaveamac authored and d0k3 committed Dec 25, 2017
1 parent 4ea35ef commit e94adae
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ export RELDIR := release
# Definitions for initial RAM disk
VRAM_OUT := $(OUTDIR)/vram0.tar
VRAM_DATA := data
VRAM_FLAGS := --format=v7 --blocking-factor=1 --xform='s/^$(VRAM_DATA)\/\|^resources\///'
VRAM_FLAGS := --make-new --path-limit 99 --size-limit 3145728

ifeq ($(OS),Windows_NT)
PY3 := py -3
else
PY3 := python3
endif

# Definitions for ARM binaries
export INCLUDE := -I"$(shell pwd)/common"
Expand Down Expand Up @@ -62,7 +68,7 @@ release: clean
vram0:
@mkdir -p "$(OUTDIR)"
@echo "Creating $(VRAM_OUT)"
@tar cf $(VRAM_OUT) $(VRAM_FLAGS) $(shell ls -d $(README) $(SPLASH) $(VRAM_DATA)/*)
@$(PY3) utils/add2tar.py $(VRAM_FLAGS) $(VRAM_OUT) $(shell ls -d $(README) $(SPLASH) $(VRAM_DATA)/*)

elf:
@set -e; for elf in $(ELF); do \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ You may now run GodMode9 via holding the X Button (or any other button you chose


## How to build this / developer info
Build `GodMode9.firm` via `make firm` (requires [firmtool](https://github.com/TuxSH/firmtool) installed). On macOS, you may have to install [gnu-tar](https://www.gnu.org/software/tar/) first - do so in terminal via `brew install gnu-tar --with-default-names`.
Build `GodMode9.firm` via `make firm`. This requires [firmtool](https://github.com/TuxSH/firmtool), [Python 3.5+](https://www.python.org/downloads/) and [devkitARM](https://sourceforge.net/projects/devkitpro/) installed).

You may run `make release` to get a nice, release-ready package of all required files. To build __SafeMode9__ (a bricksafe variant of GodMode9, with limited write permissions) instead of GodMode9, compile with `make FLAVOR=SafeMode9`. To switch screens, compile with `make SWITCH_SCREENS=1`. For additional customization, you may choose the internal font via `make FONT=6X10`, `make FONT=ACORN`, `make FONT=GB` or `make FONT=ORIG`. You may also hardcode the brightness via `make FIXED_BRIGHTNESS=x`, whereas `x` is a value between 0...15.

Expand Down
75 changes: 75 additions & 0 deletions utils/add2tar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python3

import argparse
import tarfile
import glob
import os.path
import posixpath
from os import unlink

# don't add useless files
prefix_to_ignore = ('thumbs.db', 'desktop.ini', '$recycle.bin', '.')


class PathTooLongException(Exception):
"""Filename is too long to be added to the TAR file."""


class TarTooLargeException(Exception):
"""Resulting tar is larger than the given size."""


def tarpack(*, items, out, size_limit=0, path_limit=0, make_new=False):
with tarfile.open(out, 'w' if make_new else 'a', format=tarfile.USTAR_FORMAT, bufsize=tarfile.BLOCKSIZE) as tar:
def addtotar(realpath, tarpath):
if path_limit and len(tarpath) > path_limit:
raise PathTooLongException("path is longer than {} chars ({}): {}".format(path_limit, len(tarpath), tarpath))
print('add:', tarpath)
info = tarfile.TarInfo(tarpath)
info.size = os.path.getsize(realpath)
with open(realpath, 'rb') as f:
tar.addfile(tarinfo=info, fileobj=f)

def iterdir(realpath, tarpath):
items = os.listdir(realpath)
if path_limit and len(tarpath) > path_limit:
raise PathTooLongException("path is longer than {} chars ({}): {}".format(path_limit, len(tarpath), tarpath))
info = tarfile.TarInfo(tarpath)
info.type = tarfile.DIRTYPE
tar.addfile(info)
for path in items:
new_realpath = os.path.join(realpath, path)
if os.path.isdir(new_realpath) and not os.path.basename(path).lower().startswith(prefix_to_ignore):
iterdir(new_realpath, posixpath.join(tarpath, path))
elif os.path.isfile(new_realpath) and not os.path.basename(path).lower().startswith(prefix_to_ignore):
addtotar(os.path.join(realpath, path), posixpath.join(tarpath, path))

for i in items:
if os.path.isdir(i):
iterdir(i, os.path.basename(i))
elif os.path.isfile(i):
addtotar(i, os.path.basename(i))
else:
raise FileNotFoundError("couldn't find " + i)

# tarfile is adding more end blocks when it only needs two
tar.fileobj.seek(0, 2)
tar.fileobj.write(tarfile.NUL * (tarfile.BLOCKSIZE * 2))
tar.fileobj.close()
tar.closed = True

tarsize = os.path.getsize(out)
if size_limit and tarsize > size_limit:
raise TarTooLargeException("TAR size is {} bytes is larger than the limit of {} bytes".format(tarsize, size_limit))


if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Pack files into a TAR file, leaving out extra information.")
parser.add_argument('--make-new', '-n', help="Always create a new TAR file.", action='store_true')
parser.add_argument('--size-limit', '-l', type=int, help="Throw an error when the file size reaches the specified limit.")
parser.add_argument('--path-limit', '-p', type=int, help="Throw an error when a file path is longer than the specified limit.")
parser.add_argument('out', help="Output filename.")
parser.add_argument('items', nargs='+', help="Files and directories to add.")

a = parser.parse_args()
tarpack(items=a.items, out=a.out, size_limit=a.size_limit, path_limit=a.path_limit, make_new=a.make_new)

0 comments on commit e94adae

Please sign in to comment.