#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pytable

import datetime
import heapq
import shutil
import struct
import sys
import os

ROMNAME = "1046 - Megaman & Bass (E).gba"

POINTER_BEGIN = 0x506300
POINTER_END   = 0x5069A8
TEXT_END 	  = 0x06902F
NEW_OFFSET	  = 0x7E7B00

def buffer_pointers(fd):
	pointers = []
	fd.seek(POINTER_BEGIN, 0)
	
	while fd.tell() < POINTER_END + 4:
		pointers.append(struct.unpack('<L', fd.read(4))[0] - 0x08000000)
		
	return pointers	

def extract(file = "1046 - Megaman & Bass (E).gba"):
	
	if not os.path.isdir('Texto Original'):
		os.mkdir('Texto Original')
		
	if not os.path.isdir('Texto Traduzido'):
		os.mkdir('Texto Traduzido')
		
	print '>>> Extraindo...'
	
	table = pytable.normal_table('mega_table.tbl')
	table.add_items('08=\r\n', '03=<N/Y>', '05=<FIM2>\r\n', '06=<FIM1>\r\n')

	fd = open(file, 'rb')
	out = open('Texto Original/mega_text.txt', 'wb')
	
	pointers = buffer_pointers(fd)
	
	for x in range(len(pointers)):
		fd.seek(pointers[x], 0)
		x = 0
		while True:
			byte = fd.read(1)
			if byte == '\x00':
				out.write('<00>')
				break				
			x += 1
			if byte in table:
				out.write(table[byte])
			elif byte == '\x15': # Nova janela
				out.write('<NC>')
			elif byte == '\x14':
				bytes = fd.read(2)
				x += 2
				out.write('<CLR %04X>' % struct.unpack('<H', bytes)[0])						
			elif byte == '\x10': # Barulho das letras
				byte = fd.read(1)
				x += 1
				out.write('<SFX %02X>' % struct.unpack('B', byte)[0])
			elif byte == '\x0a': # Posição
				bytes = fd.read(2)
				x += 2
				out.write('<POS %04X>' % struct.unpack('<H', bytes)[0])	
			elif byte == '\x07': # Tempo de espera
				byte = fd.read(1)
				x += 1
				out.write('<ESP %02X>' % struct.unpack('B', byte)[0])					
			elif byte == '\x02': # Velocidade em que as letras aparecem
				byte = fd.read(1)
				x += 1
				out.write('<VEL %02X>' % struct.unpack('B', byte)[0])				
			elif byte == '\x01': # Cor
				byte = fd.read(1)
				x += 1
				out.write('<COR %02X>' % struct.unpack('B', byte)[0])				
			else:
				out.write('<%02X>' % struct.unpack('B', byte)[0])
	
		out.write("\r\n-----------------------------------\r\n")
		
	out.close()
	fd.close()
	
	print '>>> Pronto!'
	
	return
	
def write_pointers(fd, pointers):
	fd.seek(POINTER_BEGIN, 0)
	
	for x in range(len(pointers) - 1):
		fd.write(struct.pack('<L', (pointers[x] | 0x08000000)))
		
	return 		
	
def insert(file = "1046 - Megaman & Bass (E).gba"):

	print '>>> Inserindo...'

	table = pytable.normal_table('mega_table.tbl')
	table.add_items('03=N/Y', '05=FIM2', '06=FIM1', '15=NC', '01=COR',
					'02=VEL', '07=ESP', '0A=POS', '10=SFX', '14=CLR')
	table.set_mode('inverted')
	
	pointers = [NEW_OFFSET]
	
	shutil.copy(file, 'M&B Textos Modificados.gba')	
	
	out = open('M&B Textos Modificados.gba', 'r+b')
	iin = open('Texto Traduzido/mega_text.txt', 'rb')
	
	out.seek(NEW_OFFSET,0)	
	for line in iin:
		line = line.strip()
		if not line:
			out.write('\x08')
		elif line == '-----------------------------------':
			pointers.append(out.tell())
		else:
			tag = [None]
			x = 0
			while x < len(line):
				if line[x] == '<':
					y = x
					while True:
						if line[y] != '>': 
							y += 1
						else:
							break
					if line[x+1:y] in table:
						tag = line[x+1:y].split(' ')
						out.write(table[line[x+1:y]])
					else:
						tag = line[x+1:y].split(' ')
						if len(tag) == 1:
							out.write(chr(int(tag[0], 16) & 0xFF))
						else:
							if tag[0] in ('COR', 'VEL', 'ESP', 'SFX'):
								out.write(table[tag[0]])
								out.write(chr(int(tag[1], 16) & 0xFF))
							elif tag[0] in ('POS', 'CLR'):
								out.write(table[tag[0]])
								out.write(struct.pack('<H', int(tag[1], 16)))
							else:
								raise 'Erro na tag %s' % line[x+1:y]
					x = y + 1
				else:
					out.write(table[line[x]])
					x += 1
			if tag[0] not in ('FIM1', 'FIM2', '00'):
				out.write('\x08')
				
	write_pointers(out, pointers)

	iin.close()
	out.close()
	
	print '>>> Pronto!'

	return
	


CREDITS_POINTER = 0x507464
NEW_OFFSET2 = 0x7e0000
	
def extract_credits(out = 'mega_credits.txt'):
	table = pytable.normal_table('mega_table.tbl')

	iin = open(ROMNAME, 'r+b')
	out = open(out, 'wb')

	iin.seek(CREDITS_POINTER, 0)
	header = struct.unpack('<L', iin.read(4))[0]
	
	pts_ = (header & 0xff) * (header >> 8 & 0xff)
	pointers = []
	
	for x in range(pts_/4):
		pointer = struct.unpack('<L', iin.read(4))[0]
		pointers.append(pointer - (0x08000000 if pointer != 0 else 0))
		

	for x in pointers:
		if x != 0:
			iin.seek(x, 0)
			lenght = ord(iin.read(1))
			color = ord(iin.read(1))		
			out.write('<%02X>' %color)
			for x in range(lenght):
				byte = iin.read(1)
				if byte in table:
					out.write(table[byte])
				else:
					out.write('<%02X>' %ord(byte))
				
		out.write('\r\n--------------\r\n')
		
	out.close()
	iin.close()
	
def insert_credits(iin = 'mega_credits.txt'):

	table = pytable.normal_table('mega_table.tbl')
	table.set_mode('inverted')
	
	pointers = []
	
	out = open(ROMNAME, 'r+b')
	iin = open(iin, 'rb')
	
	out.seek(NEW_OFFSET2,0)	
	for line in iin:
		offset = out.tell()
		line = line.strip()
		if not line:
			pointers.append(0)
		elif line == '--------------':
			pass
		else:
			color = int(line[1:3], 16) & 0xFF
			line = line[4:]
			lenght = len(line)
			
			out.write(chr(lenght))
			out.write(chr(color))
			
			tag = [None]
			x = 0
			while x < len(line):
				if line[x] == '<':
					y = x
					while True:
						if line[y] != '>': 
							y += 1
						else:
							break
					if line[x+1:y] in table:
						tag = line[x+1:y].split(' ')
						out.write(table[line[x+1:y]])
					else:
						tag = line[x+1:y].split(' ')
						if len(tag) == 1:
							out.write(chr(int(tag[0], 16) & 0xFF))
						else:
							if tag[0] in ('COR', 'VEL', 'ESP', 'SFX'):
								out.write(table[tag[0]])
								out.write(chr(int(tag[1], 16) & 0xFF))
							elif tag[0] in ('POS', 'CLR'):
								out.write(table[tag[0]])
								out.write(struct.pack('<H', int(tag[1], 16)))
							else:
								raise 'Erro na tag %s' % line[x+1:y]
					x = y + 1
				else:
					out.write(table[line[x]])
					x += 1
					
			pointers.append(offset | 0x08000000)
		
	out.seek(CREDITS_POINTER+4, 0)
	for x in pointers:
		out.write(struct.pack('<L', x))
		
	out.close()
	iin.close()
	
if __name__ == '__main__':
	
	print '>>> Copyright 2010 - Monkeys Traduções'.decode('utf-8')
	print '>>> Megaman & Bass\' Texts Pwner'	
	
	choose =  raw_input(">>>\n\t [1] Extrair Texto \n\t [2] Inserir Texto \n\t [3] Extrair Creditos \n\t [4] Inserir Creditos \n\t [5] Sair \n>>> ")

	if int(choose) == 1:
		extract()
	elif int(choose) == 2:
		insert()
	elif int(choose) == 3:
		extract_credits()
	elif int(choose) == 4:
		insert_credits()
	else:
		sys.exit(1)
	sys.exit(1)
