diff --git a/src/mudlib/zmachine/quetzal.py b/src/mudlib/zmachine/quetzal.py index 90ecda8..6d402fb 100644 --- a/src/mudlib/zmachine/quetzal.py +++ b/src/mudlib/zmachine/quetzal.py @@ -12,14 +12,30 @@ # root directory of this distribution. # -# Woohoo! Python has a module to parse IFF files, which is a generic -# interchange format. A Quetzal file is in fact a type of IFF file. -import chunk import os +import struct from . import bitfield, zstackmanager from .zlogging import log + +def _read_iff_chunk(f): + """Read one IFF chunk from a file-like object. Returns (name, data). + + Raises EOFError when there are no more chunks to read. + """ + header = f.read(8) + if len(header) < 8: + raise EOFError + name = header[:4] + (size,) = struct.unpack(">I", header[4:8]) + data = f.read(size) + # IFF chunks are padded to even byte boundaries + if size % 2 == 1: + f.read(1) + return name, data + + # The general format of Queztal is that of a "FORM" IFF file, which is # a container class for 'chunks'. # @@ -339,10 +355,8 @@ class QuetzalParser: log("Parsing chunks from byte data") try: while 1: - c = chunk.Chunk(self._file) - chunkname = c.getname() - chunksize = c.getsize() - chunk_data = c.read(chunksize) + chunkname, chunk_data = _read_iff_chunk(self._file) + chunksize = len(chunk_data) log(f"** Found chunk ID {chunkname}: length {chunksize}") self._last_loaded_metadata[chunkname] = chunksize @@ -406,10 +420,8 @@ class QuetzalParser: try: while 1: - c = chunk.Chunk(self._file) - chunkname = c.getname() - chunksize = c.getsize() - data = c.read(chunksize) + chunkname, data = _read_iff_chunk(self._file) + chunksize = len(data) log(f"** Found chunk ID {chunkname}: length {chunksize}") self._last_loaded_metadata[chunkname] = chunksize