diff --git a/NinjaModel.py b/NinjaModel.py index ddc836d..3c18a69 100644 --- a/NinjaModel.py +++ b/NinjaModel.py @@ -32,9 +32,10 @@ from NinjaBone import NinjaBone class NinjaModel: # { - def __init__(self, filename): # { + def __init__(self, filename): # File Information + self.name = filename self.path = 'input/' + filename self.file = open(self.path, 'rb') self.length = os.path.getsize(self.path) @@ -52,22 +53,23 @@ class NinjaModel: # { self.face_list = [] return None - # } - def parse(self): # { - - while self.file.tell() < self.length: # { + def parse(self): + + print("Execute parse") + + while self.file.tell() < self.length: bytes = self.file.read(4) - if(bytes == 'NJTL') : + if(bytes == b'NJTL') : print('Found Ninja Texture List') bytes = self.file.read(4) len = struct.unpack('I', bytes)[0] pos = self.file.tell() + len self.readNjtl() self.file.seek(pos, 0) - elif (bytes == 'NJCM') : + elif (bytes == b'NJCM') : print('Found Ninja Chunk Model') bytes = self.file.read(4) len = struct.unpack('I', bytes)[0] @@ -75,14 +77,11 @@ class NinjaModel: # { self.pof = self.file.tell() self.readNjcm(None) self.file.seek(pos, 0) - elif (bytes == 'NMDM') : + elif (bytes == b'NMDM') : print('Found Ninja Direct Motion') - - - # } + print("End Parse") return None - # } def readNjtl(self): pof = self.file.tell() @@ -97,14 +96,21 @@ class NinjaModel: # { str_ofs.append(m[0] + pof) for ofs in str_ofs: - str = '' + name = '' self.file.seek(ofs, 0) while 1: # { ch = self.file.read(1) - if(ch == '\0'): + if(ch == b'\0'): break - str += ch - self.tex_list.append(str) + name += ch.decode() + f = open('output/' + name + '.png', 'rb') + bytes = f.read() + f.close() + self.tex_list.append({ + 'name' : name, + 'data' : bytes + }) + print(self.tex_list) return None def readNjcm(self, parentBone): @@ -410,4 +416,13 @@ class NinjaModel: # { #end While return None + + def export(self): + print("EXPORTING DMF!!!") + pre, ext = os.path.splitext(self.name) + pre = pre.replace('/', '_') + f = open('output/' + pre + '.DMF', 'wb') + f.write(b'DASH') + f.close() + return None diff --git a/NinjaTexture.py b/NinjaTexture.py index 646172b..f822d2c 100644 --- a/NinjaTexture.py +++ b/NinjaTexture.py @@ -76,9 +76,7 @@ class NinjaTexture: # { return None def parse(self): - print("Parsing the texture file") bytes = self.file.read(4) - print(bytes) if bytes == b'PVMH': self.readPvm() @@ -89,7 +87,7 @@ class NinjaTexture: # { self.readPvr() for tex in self.tex_list: - if tex['bitmap'] is None: + if not tex['complete']: continue imgName = "output/" + tex['name'] + '.png' w = png.Writer(tex['width'], tex['height'], greyscale=False, alpha=True,compression=9) @@ -115,7 +113,10 @@ class NinjaTexture: # { for i in range(tex_count): bytes = self.file.read(2) p = struct.unpack('H', bytes) - tex = { 'id' : p[0] } + tex = { + 'id' : p[0], + 'complete' : False + } if flags & 0x08: bytes = self.file.read(0x1c) @@ -151,15 +152,12 @@ class NinjaTexture: # { p = struct.unpack('I', bytes) save_pos = self.file.tell() pvrt_len = p[0] - print("Reading Texture: %d" % tex['id']) tex['bitmap'] = self.readPvr(tex) self.file.seek(pvrt_len + save_pos, 0) return None def readPvr(self, tex): - print(tex) - # Read Header bytes = self.file.read(8) p = struct.unpack('BBHHH', bytes) @@ -169,19 +167,10 @@ class NinjaTexture: # { self.width = p[3] self.height = p[4] - print("Color Format: %d" % self.color_format) - print("Data Format: %d" % self.data_format) - print("Width: %d" % self.width) - print("Height: %d" % self.height) - self.isTwiddled = False self.isMipmap = False self.isCompressed = False - self.codebook_size = 0 - self.mipWidth = self.width - self.mipHeight = self.height - tex['complete'] = False - + self.codebook_size = 256 self.bitmap = [[0 for x in range(self.width * 4)] for y in range(self.height)] twiddled = ( @@ -200,6 +189,13 @@ class NinjaTexture: # { NinjaTexture.SMALLVQ_MM ) + compressed = ( + NinjaTexture.VQ, + NinjaTexture.VQ_MM, + NinjaTexture.SMALLVQ, + NinjaTexture.SMALLVQ_MM + ) + palette = ( NinjaTexture.PALETTIZE4, NinjaTexture.PALETTIZE4_MM, @@ -213,34 +209,14 @@ class NinjaTexture: # { NinjaTexture.ABGR_MM ) + if self.data_format in compressed: + self.isCompressed = True + if self.data_format in twiddled: self.isTwiddled = True if self.data_format in mipmap: self.isMipmap = True - - if self.data_format == NinjaTexture.VQ: - self.isCompressed = true - self.mipWidth = self.width / 2 - self.mipHeight = self.height / 2 - if self.width <= 16: - self.codebook_size = 16 - elif self.width == 32: - self.codebook_size = 32 - elif self.width == 64: - self.codebook_size = 128 - else: - self.codebook_size = 256 - elif self.data_format == NinjaTexture.VQ_MM: - self.isCompressed = true - self.mipWidth = self.width / 2 - self.mipHeight = self.height / 2 - if self.width <= 16: - self.codebook_size = 16 - elif self.width == 32: - self.codebook_size = 64 - else: - self.codebook_size = 256 if self.data_format in palette: print("NEED TO DEFINE A PALETTE!!!") @@ -249,9 +225,25 @@ class NinjaTexture: # { if self.data_format in not_supported: print("THIS DATA FORMAT IS NOT SUPPORTED") sys.exit() + + if self.data_format == NinjaTexture.SMALLVQ: + if self.width <= 16: + self.codebook_size = 16 + elif self.width == 32: + self.codebook_size = 32 + elif self.width == 64: + self.codebook_size = 128 + else: + self.codebook_size = 256 + elif self.data_format == NinjaTexture.SMALLVQ_MM: + if self.width <= 16: + self.codebook_size = 16 + elif self.width == 32: + self.codebook_size = 64 + else: + self.codebook_size = 256 if self.isCompressed: - print("Reading codebook") self.codebook = [] for i in range(self.codebook_size): bytes = self.file.read(8) @@ -266,10 +258,8 @@ class NinjaTexture: # { rgba = self.ARGB_4444(color[p]) entry.append(rgba) self.codebook.append(entry) - print(self.codebook) if self.isMipmap: - print("Seeking passed mipmaps") seek_ofs = self.get_mipmap_size() self.file.read(seek_ofs) @@ -292,13 +282,32 @@ class NinjaTexture: # { self.bitmap[y][x*4 + 1] = rgba[1] self.bitmap[y][x*4 + 2] = rgba[2] self.bitmap[y][x*4 + 3] = rgba[3] + tex['complete'] = True elif self.isCompressed: - for y in range(self.height / 2): - for x in range(self.width / 2): + for y in range(int(self.height / 2)): + for x in range(int(self.width / 2)): i = self.untwiddle(x, y) self.file.seek(self.startOfs + i , 0) b = self.file.read(1) index = struct.unpack('B', b)[0] + rgba = self.codebook[index] + self.bitmap[y*2 + 0][x*8 + 0] = rgba[0][0] + self.bitmap[y*2 + 0][x*8 + 1] = rgba[0][1] + self.bitmap[y*2 + 0][x*8 + 2] = rgba[0][2] + self.bitmap[y*2 + 0][x*8 + 3] = rgba[0][3] + self.bitmap[y*2 + 0][x*8 + 4] = rgba[1][0] + self.bitmap[y*2 + 0][x*8 + 5] = rgba[1][1] + self.bitmap[y*2 + 0][x*8 + 6] = rgba[1][2] + self.bitmap[y*2 + 0][x*8 + 7] = rgba[1][3] + self.bitmap[y*2 + 1][x*8 + 0] = rgba[2][0] + self.bitmap[y*2 + 1][x*8 + 1] = rgba[2][1] + self.bitmap[y*2 + 1][x*8 + 2] = rgba[2][2] + self.bitmap[y*2 + 1][x*8 + 3] = rgba[2][3] + self.bitmap[y*2 + 1][x*8 + 4] = rgba[3][0] + self.bitmap[y*2 + 1][x*8 + 5] = rgba[3][1] + self.bitmap[y*2 + 1][x*8 + 6] = rgba[3][2] + self.bitmap[y*2 + 1][x*8 + 7] = rgba[3][3] + tex['complete'] = True return self.bitmap diff --git a/__init__.py b/__init__.py index 194c59e..aab342f 100644 --- a/__init__.py +++ b/__init__.py @@ -28,7 +28,12 @@ from NinjaTexture import NinjaTexture model_file = 'OBJ/IKAL.NJ' texture_file = 'OBJ/IKAL.PVM' -nj = NinjaModel(model_file) -#nj.parse() +print("1. READING TEXTURE FILE") tx = NinjaTexture(texture_file) tx.parse() +print("2. READING MODEL FILE") +nj = NinjaModel(model_file) +print("parse") +nj.parse() +print("export") +nj.export()