ok so set up our c:\temp directory bye extracting our file BoneObject.hsp) x, }4 k! Y/ k" t
1. to c:\temp
5 t q8 p7 a/ C$ q5 q; V8 b2. create a new text document called astro.bms
8 m L* W1 r/ r2 Y: l7 |- ]! H3. and place the newest version of quickbms in the folder also.: O, m+ H2 n9 p
" O$ h. D( X7 b3 N# X7 nOk so open up BoneObject.hsp in your hex editor and lets take a look at it.
3 \# t! y K1 m: m
( q; A/ |. Y2 F! Jgood we have some plain text.+ C h5 l4 }/ H- O
you will notice I highlighted the first 4 bytes 20 50 53 48 or " PSH" that is a space followed bye P S H.
! A& S) Z7 y& `. E* S$ o/ t* h9 U" Rhmm that seems familiar that is the file extension only backwards. this is know as the idstring
6 m& y1 s& {- C/ Aso up until now you would think to write in bms
; k; f3 t2 w! T0 G- V, R( uget IDSTRING long
7 V4 b# W8 v) o9 P- y6 xthere is nothing wrong with that but there is a better command
* U8 c. l* b ?/ X: A7 u7 N. |idstring " PSH"8 `/ L ?6 ~5 s* @) l; ^" o/ w6 B2 I
make sure you include the quotes.
9 R& [# e* B q2 j! S& W X/ jso open your bms string and on the first line type# M. q" P; E% Z* v
idstring " PSH"
" n$ ^9 X: I7 U; ?the reason this command is better is it will tell the program not to run if it does not find that string don't try to extract that file.$ X, |& ?$ U# b: d" C
"aka noob proofing it"3 Z* e9 F7 }" V" s3 y7 v; O, ?: `
& z$ E4 c, h- c3 o8 n p9 r h9 LOk so now lets look at what we can read I see % _; {! O5 t! ~) W3 S0 l
Datas\Texture\BoneObject\npc_nagoya_octopus01_body.dds , Datas\Texture\BoneObject\Toon.bmp , Datas\Texture\BoneObject\Toon_a.bmp , Datas\Texture\BoneObject\Toon_zero.bmp
9 d* T6 B3 ^& P1 J+ H' @6 C U4 Zso I will assume there are 4 files in this archive.
! ^3 l* p+ h; ] X8 O. Uwell lets look at the next 4 bytes and see what it is 01 00 00 00 hmm that is equal to 00 00 00 01 or 1 and we have more files in this archive than that so we do not know what this represents/ W+ U: p; T3 |! L, h' m* F! ]: j# n
so lets write that in bms language. Q+ q d1 h0 Z7 ~2 w: s
get UNK1 long
9 M: f4 v- r, \, Y1 }: [6 zthis saves those 4 bytes as the variable UNK1.- w! V" k" W9 L- @% @1 @
& N P9 ]" L" l; T4 k9 R$ wok the next 4 bytes are 04 00 00 00 hmm this translates into 00 00 00 04 or 4
$ q/ G; F) z+ ?: C: dhey that is the number of files we counted so lets write that in bms# Y: b9 I0 E) N
get FILES long+ a, w0 a2 {% x, t$ ]
this saves those 4 bytes as the variable FILES.
( v* B, I( b8 l# E# y4 z' W" q
2 O+ t3 ^+ i d. h) Mthe next 4 bytes are 00 00 00 00 well that is equal to zero so for now I will write that in bms ~& ]7 l6 A3 g) Q! }
get NULL1 long
+ z* ^# p" l& w5 m# K6 m& f, `this saves those 4 bytes as the variable NULL1
2 E" P6 c6 U7 `/ l3 y( h/ ^% Y
! C, D1 C7 i# W+ B4 N. |( D7 [ok now we have reached the first file name Datas\Texture\BoneObject\npc_nagoya_octopus01_body.dds
4 Y& a) K: v( ?) p/ v/ ~5 K3 D% mthis is 0x36 bytes long but wait there was no indicator like the last file that told us how long the name is how do we write this?; T6 q! `, E5 ^( o- C1 Y
well lets look for a pattern e( W' E+ ~1 o4 X, r& c* T4 d
Datas\Texture\BoneObject\npc_nagoya_octopus01_body.dds is 0x36) q A G- Z8 C6 \2 p! `1 U1 i
Datas\Texture\BoneObject\Toon.bmp is 0x21
8 W2 {( @+ ^' C2 q9 f& v, Q. PDatas\Texture\BoneObject\Toon_a.bmp is 0x23
+ q. t* z7 i9 K7 E% i' vDatas\Texture\BoneObject\Toon_zero.bmp is 0x26! r- z* a% o( D; I- K4 ]3 t& ~) M1 w
hmm I don't see anything that makes that a pattern.% q- ^! e1 d& R
but I do see all the names are followed bye a lot of zero's. how long is the name + the zeros of each file?1 |2 y: }6 u& d& _; Q
Datas\Texture\BoneObject\npc_nagoya_octopus01_body.dds + 0's is 0x80! G K$ e2 r/ @' S( D8 m& r
Datas\Texture\BoneObject\Toon.bmp + 0's is 0x80
2 k5 R8 R- H" N. Y7 g1 bDatas\Texture\BoneObject\Toon_a.bmp + 0's is 0x803 h; s. h) ~7 z4 S
Datas\Texture\BoneObject\Toon_zero.bmp + 0's is 0x80* c9 C& V6 W! h* o
hey they are all the same size when I include the 0's2 M( w# `5 Y% g
so in bms I would write this as- A6 Y n6 w8 I. K+ _! L# t
getdstring NAME 0x80
; ]$ G. I& m% ?" u6 b8 u e7 f1 g# Lthis tells it to grab 0x80 bytes and store the text value of it
/ ?4 c* j4 E% nand as an added feature it will automatically remove trailing 0's 4 E) q9 f/ v5 \" ^
! Z4 w5 o/ t+ c0 @& x( `) ]ok so now we have 0xC bytes before I see the next file name& C( m5 T5 s6 p# Y3 C8 O3 i" W
which is 3 long values& r; S: e$ ?0 @/ g) A/ O, K- |5 x" n
so lets write those in and we will figure out what they represent later.% N5 E! @. n+ u0 q0 D6 f
get UNK2 long, a. |5 C. D" A% [: {: J# _
get UNK3 long
/ K2 U" A, M$ N- y* _, O: Q$ ~+ uget UNK4 long' l3 i& F. R% E0 ?0 Q0 T Y; Q
( k, X5 k1 Q! W% P2 u3 L8 ook so now we see the name again
. r7 N. d6 T! Q: [* u' ]9 M! Q4 Z! hwe have our pattern so lets write our script based on what we learned' \8 @: `) F6 X- D# @3 @3 @6 }9 n
so it would look like this up until now
6 h* o2 \( ?4 ?" Z
6 f% E7 Z/ k. m, e/ U( w$ WCode:3 E- r0 F+ Z5 y9 w+ j
idstring " PSH"
5 h3 R: m2 C1 f: bget UNK1 long6 `2 t- x& U; ~7 C* h7 @" H
get FILES long; S+ L6 Z$ Z0 f# d
get NULL1 long2 O3 H/ T9 _" a# B3 B8 Z
for i = 0 < FILES
3 r5 L3 o) g& l2 y, ]; P; {* Q8 Ugetdstring NAME 0x808 l8 d. A& f9 F6 M7 S9 t1 b
get UNK2 long
% a J2 J' y0 [& W% h; ]7 nget UNK3 long, D$ p( p( {4 h7 ^( }+ H. o
get UNK4 long0 ^& S- k) N( b) D9 b& `
clog NAME OFFSET ZSIZE SIZE4 M3 C7 \, n6 W: H# S
next i
' S5 z" {1 T0 A' N' C
: ?5 p. s- I6 r% P# O
- l; v( ^9 ], o, Z; T1 jok this may look complex but it is almost identical to the first tutorial file except we added 1 more variable
- U& Q. R+ [! @: N8 YZSIZE this represents the compressed file size while SIZE represents the decompressed file size
# s: ]- P& B% A& w# gand we also changed the log command to clog to represent it is a compressed file.8 l* l" f2 J8 ?) e C6 W! ?6 J2 R
: J1 M& o- m( O9 a
ok so now we have our loop and the commands to extract our files but we still need to fill in the variables. f" E6 O" P9 J" o
OFFSET ZSIZE SIZE
, C# C2 N* a& A( n3 [so that means our 3 unknown values must represent that but how do we know what order they are in?
% i( p7 d+ S6 C; s t# Z( U: f; `" q4 R }. g1 C) z/ P/ f
Well ill let you in on a cool trick follow the file loop to the end start at Datas\Texture\BoneObject\npc_nagoya_octopus01_body.dds and highlight the whole 0x80 length- G5 P8 h5 U! a2 O
then add our 3 unknown variables so that means we are highlighting 0x8C for our length. the first file is from 0x10 - 0x9B
; Y+ K0 K2 I2 I9 O0 k$ L. e- ^% vso now do this for the rest of the files and you end up at highlighting 0x1B4 - 0x23F: }( ?$ ^# j, c/ O9 L8 k9 A. w3 ~
! D- D$ a# ]6 c eok so we reached the end of our loop now what?* f: I- I' Y: ]& i) h; n) q* P
well the next 2 bytes are 78 9C and this is an archive extractors best friend when you see this at the start of a file.& _" u! U$ N [9 l7 r7 s1 P9 b; S8 f
78 9C represents the standard zlib compression header / V& n! }# q" `. I0 ~
ok so this means our first file starts there which is at offset 0x240) p0 m2 N! w$ @3 B" |$ \
* G/ x3 q y4 }" n( i1 {$ \7 Gwell lets go back to our first file in the list and look at those unknown variables.
3 F, S* Q- I; |( A. ?, O24 72 00 00 is = 00 00 72 24 = 0x7224
8 W% S6 j( `8 F4 P80 00 02 00 is = 00 02 00 80 = 0x20080
5 U% O* h y# A- `/ L1 V40 02 00 00 is = 00 00 02 40 = 0x240
1 W7 U; @# D! v+ nI think we have a winner so the third variable is 0x240 aka the offset
+ |3 l: o. k" \- O! u+ w& Eso lets update our script
: n) W1 b1 R9 X! Z3 D* ~
4 C8 M* A6 x# l, d) K4 k7 O
( `; d1 _/ @' s! L) A3 E# pCode:/ R6 z* j$ ^2 _ D' K3 S( Y# n
idstring " PSH"
' I8 M" u6 A: ~$ I' K# g9 E! ]9 Bget UNK1 long
2 }( q/ S% h" p* X4 Iget FILES long+ f: y2 e' b$ R! \' ~
get NULL1 long
4 @' R+ W7 g1 @$ m2 z( m4 Gfor i = 0 < FILES
3 ~( y) K. Q4 {getdstring NAME 0x80
; l) J3 V8 s5 f) Qget UNK2 long
/ @; q$ F# ]; N( lget UNK3 long
% [( N$ B$ q* | ?" N" H: oget OFFSET long2 o' G* K7 i* t% n& [/ z2 o
clog NAME OFFSET ZSIZE SIZE
# Z1 k& x$ D' Z9 i, d* ]( k3 Z7 jnext i5 [. r* G! Z ]. A9 x8 h3 ^( o
9 x. Q* E7 d0 @4 e6 {" I; l- O8 J8 t* w
now that just leaves ZSIZE and SIZE
) ]( S# w% B8 H: n% `+ Xwell bye process of elimination the decompressed file must be bigger than the compressed file so we compare the 2 variables
* B! E# J) v2 p! U0 B$ k5 B24 72 00 00 is = 00 00 72 24 = 0x7224
& h. {+ f4 z3 ~80 00 02 00 is = 00 02 00 80 = 0x20080
8 |5 Q% e. Z( h0 c- N g2 @well 0x20080 is definitely bigger so we now know the last 2 variables& t9 v: ]5 b: ]: v% @8 S- W
5 y! ?$ U* x0 N7 ^/ m0 w+ X8 B ]. h/ [
Code:2 o+ q$ m3 M, G5 k; O
idstring " PSH"5 d) T8 R# e8 d; ]: Z
get UNK1 long* T( O7 p) D/ ]' m4 e7 l" w
get FILES long( |; ^ \2 F- [
get NULL1 long
9 }- G* B' W1 dfor i = 0 < FILES
5 g+ F1 W/ M7 Q$ p6 X- M* c8 l( agetdstring NAME 0x80
; Z) a: c, u0 ~, O, mget ZSIZE long4 x+ k3 {: k1 a4 W9 A
get SIZE long# D0 `9 F6 w# P4 s9 i* g
get OFFSET long
, }5 C. d" _ ?& ^1 [ ]1 jclog NAME OFFSET ZSIZE SIZE
?0 D. s3 p/ z. S+ ]0 K0 b5 z- Z& |next i# o) Y1 h3 m% v0 n
0 K7 B/ Z4 x4 q& [$ [5 P
9 k6 }4 x4 Z) e5 d2 c8 fnow try our code out on the file7 X/ `/ {* _& N1 O
open the command prompt and change to the directory( {, s, E- |" r1 q
c:\temp' v6 |% D; T& p; b. d' \, ]* ]
now type
* c1 e: j" y$ X4 Equickbms.exe -l astro.bms BoneObject.hsp . T, [4 d2 [. t) R/ i4 ^
yay it listed our files without any errors now lets try extracting them# b$ k7 {* Y" `; t* F% O
create a folder called extract
' w" s7 F, h& t9 m, q" Fand type7 _, P8 T# i9 ]7 w* f
quickbms.exe astro.bms BoneObject.hsp extract
3 e' V/ V& V/ X: l, x7 j- Z3 Eif we look in there we now have folders and in those folders are 4 pictures ( _: o3 n% x6 e3 P) ~5 D
we did it.
- s* r" u0 [5 D3 v1 ^, A: n" R5 F3 ^3 i% k3 F0 O. c' c
Let me know if you want more pictures or any way I can improve the tutorials.8 B3 ~: P6 M! }& I
: A' J9 d: f& x2 P8 n, q
3 C5 a0 t& l, V/ s9 E _
Last edited by chrrox on Tue Jun 09, 2009 2:33 pm, edited 1 time in total. |