From 3df0ea8cfbd4450d5b5d6b725d4af103657690f9 Mon Sep 17 00:00:00 2001
From: Benjamin Collins <kion@dashgl.com>
Date: Sun, 16 Aug 2020 07:55:59 +0900
Subject: [PATCH] export

---
 NinjaModel.py   | 47 +++++++++++++++--------
 NinjaTexture.py | 99 +++++++++++++++++++++++++++----------------------
 __init__.py     |  9 ++++-
 3 files changed, 92 insertions(+), 63 deletions(-)

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()