Move the Game Data Format header processing to xgstruct into its own class.
authorMichael Petch <mpetch@capp-sysware.com>
Thu, 2 Jan 2014 04:46:03 +0000 (21:46 -0700)
committerMichael Petch <mpetch@capp-sysware.com>
Thu, 2 Jan 2014 04:46:03 +0000 (21:46 -0700)
More cleanup

xgimport.py
xgstruct.py

index d7aa4da..c8dbeea 100644 (file)
@@ -25,6 +25,7 @@ import struct as _struct
 import os as _os
 import xgutils as _xgutils
 import xgzarc as _xgzarc
+import xgstruct as _xgstruct
 
 
 class Import(object):
@@ -89,29 +90,24 @@ class Import(object):
         with open(self.filename, "rb") as xginfile:
             # Extract the uncompressed Game Data Header (GDH)
             # Note: MS Windows Vista feature
-            unpacked_data = _struct.unpack('<4BiiQi', xginfile.read(24))
-            magicStr = bytearray(unpacked_data[0:4][::-1]).decode('ascii')
-            hdrVer = unpacked_data[4]
-            if magicStr != 'HMGR' or hdrVer != 1:
+            gdfheader = \
+                    _xgstruct.GameDataFormatHdrRecord().fromstream(xginfile)
+            if gdfheader is None:
                 raise Error("Not a game data format file", self.filename)
-
-            hdrSize = unpacked_data[5]
-            thumbOffset = unpacked_data[6]
-            thumbSize = unpacked_data[7]
-
+            
             # Extract the Game Format Header
             with Import.Segment(type=Import.Segment.GDF_HDR) as segment:
                 xginfile.seek(0)
-                block = xginfile.read(hdrSize)
+                block = xginfile.read(gdfheader.HeaderSize)
                 segment.file.write(block)
                 segment.file.flush()
                 yield segment
 
             # Extract the uncompressed thumbnail JPEG from the GDH
-            if (thumbSize > 0):
+            if (gdfheader.ThumbnailSize > 0):
                 with Import.Segment(type=Import.Segment.GDF_IMAGE) as segment:
-                    xginfile.seek(thumbOffset, 1)
-                    imgbuf = xginfile.read(thumbSize)
+                    xginfile.seek(gdfheader.ThumbnailOffset, 1)
+                    imgbuf = xginfile.read(gdfheader.ThumbnailSize)
                     segment.file.write(imgbuf)
                     segment.file.flush()
                     yield segment
index 5d357ec..9b52f73 100644 (file)
 import xgutils as _xgutils
 import struct as _struct
 import os as _os
+import uuid as _uuid
+import binascii as _binascii
 
 
+class GameDataFormatHdrRecord(dict):
+    SIZEOFREC = 8232
+
+    def __init__(self, **kw):
+        defaults = {
+            'MagicNumber': 0,             # $484D4752, RM_MAGICNUMBER
+            'HeaderVersion': 0,           # version
+            'HeaderSize': 0,              # size of the header
+            'ThumbnailOffset': 0,         # location of the thumbnail (jpg)
+            'ThumbnailSize': 0,           # size in bye of the thumbnail
+            'GameGUID': [],               # game id (GUID)
+            'GameName': None,             # Unicode game name
+            'SaveName': None,             # Unicode save name
+            'LevelName': None,            # Unicode level name
+            'Comments': None              # Unicode comments
+            }                              
+        super(GameDataFormatHdrRecord, self).__init__(defaults, **kw)
+
+    def __setattr__(self, key, value):
+        self[key] = value
+
+    def __getattr__(self, key):
+        return self[key]
+
+    def fromstream(self, stream):
+        try:
+            unpacked_data = \
+                _struct.unpack('<4BiiQiLHHBB6s1024H1024H1024H1024H', 
+                stream.read(self.SIZEOFREC))
+        except:
+            return None
+
+        self.MagicNumber = bytearray(unpacked_data[0:4][::-1]).decode('ascii')
+        self.HeaderVersion = unpacked_data[4]
+        if self.MagicNumber != 'HMGR' or self.HeaderVersion != 1:
+            return None
+            
+        self.HeaderSize = unpacked_data[5]
+        self.ThumbnailOffset = unpacked_data[6]
+        self.ThumbnailSize = unpacked_data[7]
+        guidp1,guidp2,guidp3,guidp4,guidp5 = unpacked_data[8:13]
+        guidp6 = int(_binascii.b2a_hex(unpacked_data[13]), 16)
+        self.GameGUID = str(_uuid.UUID(fields=(guidp1,guidp2,guidp3,
+                            guidp4,guidp5,guidp6)))
+
+        self.GameName = _xgutils.utf16intarraytostr(unpacked_data[14:1038])
+        self.SaveName = _xgutils.utf16intarraytostr(unpacked_data[1038:2062])
+        self.LevelName = _xgutils.utf16intarraytostr(unpacked_data[2062:3086])
+        self.Comments = _xgutils.utf16intarraytostr(unpacked_data[3086:4110])
+        return self
+        
+
 class TimeSettingRecord(dict):
 
     SIZEOFREC = 32