[Python] All-in-one import hexer. Version 2! GUI and multiple file support!

Started by ForOhFor Error, April 07, 2011, 12:40:57 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

We already have working programs to hex imports from games with MDL0s into usable models. However, these programs are fairly slow, only fix one MDL0 at a time, and, well, there's 3 of the things thatn eed to be run separately.

I am doing my first full program, based in python, to remedy that situation. It will combine the 3 steps (header, materials, polygons) into one program, which will hex every model in a brres file.

And, since it's in Python instead of Gamemaker, it's much faster than the existing programs.

It will be useful for, say, hexing those bothersome okami models.

UPDATE LOG:

V 2.0:
-Added a GUI
-Added multi-BRRES support
-Now overwrites input files


Program completed, download here:

http://dl.dropbox.com/u/5869687/Python%20Model%20Hexer%202%20%28GUI%29.zip

Old version:
http://dl.dropbox.com/u/5869687/Python%20Model%20Hexer%20-%20Complete.zip

TO DO BEFORE FULL RELEASE:
Done
In progress
Bug fixing
Not started

- Opening file, translating into a usable string
- Locating all MDL0s and logging their locations
- Creation of a module to store long functions
- MDL0 header fixing function
- MDL0 material fixing function
- MDL0 polygon fixing function
- Launching these functions through a main program
- Translating usable hex back to a savable format
- Saving the file


I may need some help along the way, just for the locating of specific values in the hex data.

FC: 2191-7379-6272

Nice. This will help a lot.
Good luck, if you need it ;)

April 07, 2011, 01:30:41 AM #2 Last Edit: April 07, 2011, 01:35:01 AM by ForOhFor Error
Thanks!
(Also, note that, not only being my first utility program, I've never really manually hexed anything before :P)

I've made some progress, but have a small problem:

How a certain block should look like after the header fix (From the existing fixing program):
Sorry but you are not allowed to view spoiler contents.


How it does look:
Sorry but you are not allowed to view spoiler contents.


No clue what's causing it...
but that's the only difference once both have been header fixed.

FC: 2191-7379-6272

how are you handeling the values??
are the values being handeled floats or ints??

it's possible you could be handeling a float as an int

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.


April 07, 2011, 08:28:25 PM #5 Last Edit: April 07, 2011, 08:34:19 PM by Tcll
ah

here, the full mdl0 header should look like this:
note: this is reading from it


       #<<header>>
       magic = fr.read(4)
       if magic == 'MDL0': #check if valad
           print 'MDL0 file is valad' #check
           #--header (part1)--

           strtbl_offset = ui(fr.read(4))
           sections = ui(fr.read(4))
           nodes_offset = si(fr.read(4))*(0-1)
           #list offsets to relocation table groups
           definits_list = ui(fr.read(4))
           bones_list = ui(fr.read(4))
           vertices_list = ui(fr.read(4))
           normals_list = ui(fr.read(4))
           colors_list = ui(fr.read(4))
           uv_points_list = ui(fr.read(4))
           materials_list = ui(fr.read(4))
           shader_conf_list = ui(fr.read(4))
           objects_list = ui(fr.read(4))
           textures_list = ui(fr.read(4))
           pallets_list = ui(fr.read(4))
           #--header (part2)--
           string_offset = ui(fr.read(4))
           header_length = ui(fr.read(4)) #64
           header_offset = ui(fr.read(4))
           #--displayed in brawlbox:--
           unknown_1 = fr.read(4)
           unknown_2 = fr.read(4)
           NumVertices = ui(fr.read(4))
           NumFaces = ui(fr.read(4))
           unknown_3 = fr.read(4)
           NumNodes = ui(fr.read(4))
           version = hex(fr.read(4)) #no idea how to handle
           unknown_4 = fr.read(4)
           MinX,MinY,MinZ = fl(fr.read(4)),fl(fr.read(4)),fl(fr.read(4))
           MaxX,MaxY,MaxZ = fl(fr.read(4)),fl(fr.read(4)),fl(fr.read(4))
           NumNodes2 = fr.read(4) #(Copy?)
       #<</header>>


here's the common functions being used:

#--<<common functions>>--
import struct as St
def L(this): return St.unpack('>l', this)[0] #return a long int
def hex(this): return this.encode('hex') #return the hex value of a char
def ui(this): return int(this.encode('hex'),16) #return an unsigned 8bit, 16bit, or 32bit int (most common)
def si(this): return int(long(this.encode('hex'),16)-2**32) #return a signed 8bit, 16bit, or 32bit int
def bfl(this): return St.unpack("<f", this)[0] #return a big endian 32bit float
def fl(this): return St.unpack(">f", this)[0] #return a 32bit float (highly common)
#--<</common functions>>--

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

That code from your Universal Model Converter?
Thing is, I'm just using this here (the tutorial):
http://www.smashboards.com/showthread.php?t=263127
as a guide for what to change, using code to do the steps.
:/

FC: 2191-7379-6272

if you're having any problems understanding how to code for the MDL0,
you can look into my WIP template for HexEdit:
http://brawlimports.proboards.com/index.cgi?board=templates&action=display&thread=12

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

Quote from: ForOhFor Error on April 07, 2011, 08:36:13 PM
That code from your Universal Model Converter?
yea...

you can use it to see how to write the values

btw,
use St.pack
not St.unpack as in the functions

use the L() function when writing something like '00 00 00 09'
if you use ui(), you'll just get '09'
I like to use chr(int(h,16)) alot,
and I use chr(0) for padding

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

April 07, 2011, 08:56:41 PM #9 Last Edit: April 07, 2011, 08:57:49 PM by ForOhFor Error
Well, here's the code I'm using in the MDL0 fixing module:
import string
def fixHeader(Data,indexNum):
   data2 = Data
   logThis = Data[indexNum+88:indexNum+96]
   newDat = Data[0:indexNum+16]
   newDat += "00000009ffffff80"
   newDat += Data[len(newDat):len(newDat)+(8*6)]
   newDat += Data[len(newDat)+16:len(newDat)+56]
   newDat += Data[len(newDat)+8:len(newDat)+24]
   newDat += "ffffffc0"
   newDat += Data[len(newDat):len(newDat)+40]
   newDat += logThis
   newDat += Data[len(newDat):]
   return newDat
def fixHeaderPt2(Data,indexNum):
   savey = Data[indexNum+(4*8):indexNum+(5*8)]
   startOfDefHead = int(savey,16)-12
   newDat = Data[0:indexNum+startOfDefHead*2]
   newDat += "ffffffff"*3
   newDat += Data[len(newDat):]
   return newDat


I call fixHeader() first, with my logged position of the MDL0 file (indexNum) and the data of the brres file, saved as a string (Data) as arguments (This does all the steps in the text tutorial, excluding adding 3 'FFFFFFFF's), set a new data string (newdata) to the returned string then call fixHeaderPt2() to add the 3 'FFFFFFFF's and set newdata to that. Here's the main program's code:

import os
import string
import ___MDL0Fix___
from tkFileDialog import askopenfilename
from tkFileDialog import asksaveasfilename
newData = ""
brres = askopenfilename( filetypes=[
('Brawl Resource Archive','*.brres')
] , )
f = open(brres,'rb')
data = f.read().encode('hex')
if data[0:8] == "62726573":
   print("Valid BRRES confirmed")
else:
   print "Not a valid file. Passing exception to end program."
   x = 1/0
numMdl0s = data.count("4d444c30")
indexLoc = []
start = 0
print numMdl0s,"MDL0 format models found"
for x in range(0,numMdl0s):
   offset = data[start+8:len(data)].find("4d444c30")
   start += offset+8
   indexLoc.append(start)
   print "MDL0 found at",start
print numMdl0s,"MDL0 format models found"
newdata = data
for x in range(0,numMdl0s):
   print "Fixing MDL0 header...(1/2)"
   newdata = ___MDL0Fix___.fixHeader(newdata,indexLoc[x])
   print "Fixing MDL0 header...(2/2)"
   newdata = ___MDL0Fix___.fixHeaderPt2(newdata,indexLoc[x])
   print "MDL0 header fixed!"
f.close()
outputName = asksaveasfilename( filetypes=[
('Brawl Resource Archive','*.brres')
] , )+'.brres'
f = open(outputName, 'wb')
print "Saving Output..."
f.write(newdata.decode('hex'))
f.close()
print "Output Saved!"
quity = input("Press enter to quit!")


Of course, that's just what I have so far.
The problematic part is that the output from this program differs from the fixed product of the existing MDL0 header fixer :/

FC: 2191-7379-6272


that's some complicated code you got there
it'd be a shame if something were to happen to it... lol

but I see you're storing the file in a var...
that might be your complication...

you'll notice I'm just using:
fr.read(4)
fr.read(4)
fr.read(4)

you could use:
fw.write(var1)
fw.write(var2)
fw.write(var3)

I find it alot more simpler and organized to do than all that fancy code-work with a stored data var

I'm not too sure of your prob since I'm seeing that :/
that would take me a while to figure out...

I'm on a minecraft server right now,
so I'm not too into the coding stuff...

doesn't mean I can't lend over some info though :)

use my code to figure out how to write the specific data types to the header
(weather to write int(), float(), long(), etc...)
glad your using len() for alot of it

btw, been wanting to say this for so long:
your ava is freakin WIN!!! <3 <3

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

I don't know if it can be of any use to you, but I have the Game Maker source files of FortWaffles' original programs >.> (GM8 decompiler works wonders)

Quote from: Difegue on April 07, 2011, 09:20:21 PM
I don't know if it can be of any use to you, but I have the Game Maker source files of FortWaffles' original programs >.> (GM8 decompiler works wonders)

I can haz plz =D

I've been wanting to look at FW's src codes for quite a while :D

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.

April 07, 2011, 09:34:54 PM #13 Last Edit: April 07, 2011, 09:36:01 PM by Difegue
Sure, I'll copy-paste the scripts... They're written in Game Maker Code, so ask me if you don't understand a function or something:

Sorry but you are not allowed to view spoiler contents.


If it's of any use to you, I'll post the codes for the Matrix and Polygon fixers  ;)

Quote from: Difegue on April 07, 2011, 09:34:54 PM
If it's of any use to you, I'll post the codes for the Matrix and Polygon fixers  ;)

all of them plz

hmm, GM code looks like a mix of C++ and Py
interesting

[spoiler]Quote: Friedslick6
you have been through a lot of hassle. I've watched every topic you posted on this, and most of them seemed to disintegrate gradually.
But the coolest part was that you didn't stop working on it despite that.

Quote: Internet Explorer
you're doing more with your life right now than probably most other people around you. You're a valuable asset to the Smash community. So yeah, you should be proud.

quote: Greg
You do have a gift which I've seen many developers use to their advantage. You can become a great coder, and with all of those ideas I think you can really build something great.