From: <edh...@us...> - 2009-08-24 23:14:41
|
Revision: 7046 http://gemrb.svn.sourceforge.net/gemrb/?rev=7046&view=rev Author: edheldil Date: 2009-08-24 22:24:22 +0000 (Mon, 24 Aug 2009) Log Message: ----------- Added SAV format Modified Paths: -------------- ie_shell/trunk/TODO ie_shell/trunk/infinity/defaults.py ie_shell/trunk/infinity/format.py ie_shell/trunk/infinity/formats/__init__.py Added Paths: ----------- ie_shell/trunk/infinity/formats/sav.py Modified: ie_shell/trunk/TODO =================================================================== --- ie_shell/trunk/TODO 2009-08-24 21:58:14 UTC (rev 7045) +++ ie_shell/trunk/TODO 2009-08-24 22:24:22 UTC (rev 7046) @@ -6,8 +6,12 @@ door_cnt or doors_cnt ? # of doors or Doors count? 5. load objects in cache and override dirs as well -6. allow for more than one game loaded? - +6. allow for more than one game loaded? +7. create set_translation() fn in core +8. look at options again, make them more ie-file-format-agnostic +9. put some more enums/masks to formats/enums.py +10. case insensitive files searching + Data types: 1. OFFSET/COUNT data type? @@ -17,6 +21,9 @@ 5. Signed data types (SWORD, SDWORD,...). Ugly, Adding unsigned ones would be better 6. allow for name enums desc items with count > 1 (e.g. 100 strrefs in CRE) 7. change all *_desc tuples to lists to allow patching in subclasses for other versions of data file +8. change prints in printme() to fh.write() to allow for better output redirection +9. generalize prints to allow printing to HTML tables, for example. +10. filter out non-printable chars in BYTES or STRn output to prevent garbage hosing the terminal Streams: 1. Base streams on Python's native file interface, so normal files can be used for reading structures and also the streams can be used with normal python functions. This would require moving the read_(resref|word|...) functions elsewhere, though Modified: ie_shell/trunk/infinity/defaults.py =================================================================== --- ie_shell/trunk/infinity/defaults.py 2009-08-24 21:58:14 UTC (rev 7045) +++ ie_shell/trunk/infinity/defaults.py 2009-08-24 22:24:22 UTC (rev 7046) @@ -45,6 +45,8 @@ 'format.mos.print_tiles': [True, "Print MOS tiles"], 'format.mos.print_palettes': [False, "Print MOS palettes"], + 'format.sav.read_data': [False, "When reading SAV file read its data too"], + 'format.tis.print_tiles': [False, "Print TIS tiles"], 'format.tis.print_palettes': [False, "Print TIS palettes"], Modified: ie_shell/trunk/infinity/format.py =================================================================== --- ie_shell/trunk/infinity/format.py 2009-08-24 21:58:14 UTC (rev 7045) +++ ie_shell/trunk/infinity/format.py 2009-08-24 22:24:22 UTC (rev 7046) @@ -371,8 +371,11 @@ size = 4 elif type == 'STRSIZED': # FIXME: encoding - value = obj[key] - size = 4 + len (value) + if obj is not None: + value = obj[key] + size = 4 + len (value) + else: + size = 4 # FIXME: eek! elif type == 'BYTES': size = d['size'] #value = obj[key] Modified: ie_shell/trunk/infinity/formats/__init__.py =================================================================== --- ie_shell/trunk/infinity/formats/__init__.py 2009-08-24 21:58:14 UTC (rev 7045) +++ ie_shell/trunk/infinity/formats/__init__.py 2009-08-24 22:24:22 UTC (rev 7046) @@ -24,6 +24,7 @@ import key import mos import pro +import sav import spl import stor_v10 import stor_v11 Added: ie_shell/trunk/infinity/formats/sav.py =================================================================== --- ie_shell/trunk/infinity/formats/sav.py (rev 0) +++ ie_shell/trunk/infinity/formats/sav.py 2009-08-24 22:24:22 UTC (rev 7046) @@ -0,0 +1,144 @@ +# -*-python-*- +# ie_shell.py - Simple shell for Infinity Engine-based game files +# Copyright (C) 2004-2008 by Jaroslav Benkovsky, <edh...@us...> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +import gzip +from infinity.format import Format, register_format +from infinity.stream import CompressedStream + + +class SAV_Format (Format): + header_desc = ( + { 'key': 'signature', + 'type': 'STR4', + 'off': 0x0000, + 'label': 'Signature' }, + + { 'key': 'version', + 'type': 'STR4', + 'off':0x0004, + 'label': 'Version'}, + ) + + file_desc = ( + { 'key': 'filename', + 'type': 'STRSIZED', + 'off': 0x0000, + 'label': 'Filename'}, + ) + + file2_desc = ( + { 'key': 'uncompressed_size', + 'type': 'DWORD', + 'off': 0x0004, + 'label': 'Uncompressed file size'}, + + { 'key': 'compressed_size', + 'type': 'DWORD', + 'off': 0x0008, + 'label': 'Compressed file size'}, + +# { 'key': 'data_offset', +# 'type': '_BYTE', +# 'off': 0x0000, +# 'label': 'Data offset'}, +# +# { 'key': 'data', +# 'type': '_BYTE', +# 'off': 0x000C, +# 'label': 'Data'}, + + ) + + def __init__ (self): + Format.__init__ (self) + self.expect_signature = 'SAV' + + self.file_list = [] + + + def read (self, stream): + self.read_header (stream) + + off = self.get_struc_size (self.header_desc) + + while True: + obj = {} + try: + self.read_struc (stream, off, self.file_desc, obj) + except: + # Assume all exception to be struct.error due to eof + break + off += len (obj['filename']) + 1 + self.read_struc (stream, off, self.file2_desc, obj) + off += self.get_struc_size (self.file2_desc) + obj['data_offset'] = off + off += obj['compressed_size'] + + self.file_list.append (obj) + + if self.get_option ('format.sav.read_data'): + self.read_all_data (stream) + + def printme (self): + self.print_header () + + i = 0 + for obj in self.file_list: + print 'File #%d' %i + self.print_struc (obj, self.file_desc) + self.print_struc (obj, self.file2_desc) + i = i + 1 + + + + + def read_all_data (self, stream): + for obj in self.file_list: + self.read_data (stream, obj) + # FIXME: uncompress + + def read_data (self, stream, obj): + data = stream.read_blob (obj['data_offset'], obj['compressed_size']) + stream2 = CompressedStream ().open (data) + obj['data'] = stream.read_blob (obj['data_offset'], obj['compressed_size']) + + # FIXME: the following API is ugly + + def get_file_data (self, stream, obj): + # avoid rereading already read data and also do not replace data read from uncompressed stream + # in the case of a CBF file + if obj.has_key ('data'): + return obj['data'] + + return self.read_data (stream, obj) + + # FIXME: this is ugly + + def save_file_data (self, stream, filename, obj): + # FIXME: does not work with CBF files and the outer stream + self.get_file_data (stream, obj) + fh = open (filename, 'w') + fh.write (obj['data']) + fh.close () + + + + + +register_format ('SAV', 'V1.0', SAV_Format) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |