I'm currently taking another look at those pesky XMA files from Electronic arts, namely from Battlefield: Hardline. ea_multi_xma.exe from HCS doesn't work on these so I tried to write my own parser but strangely it doesn't work.
So here's my work-in-progress. This is an example file: http://*USE_ANOTHER_FILEHOSTING*/3408d63 ... 78/test.7z
. For testing purposes I've manually split the file into the two streams that are present and began testing with the first one. The structure of these streams is fairly simple:
(big endian)
0x00 - 4800000C long
0x04 - channel count
0x06 - frequency short
0x08 - number of samples
0x0c - END - stream structure:
short: 0x4400 - new block marker, 0x4500 stop marker
short: length of block
longlong: dummy (or something else?)
length_of_block - 0xc: stream data
To parse the blocks you just write the stream data and fill the block up to the next 0x800 multiple with zeros to get a complete XMA2 block. Afterwards it should be parsable with xma_parse. However the parsing stops at around 63kb and this is where it gets interesting: This very block has a wrong size (8 bytes short) so I've coded in a workaround that writes the missing 8 bytes into the block but to no avail: parsing stops at this block, no matter if I leave the additional bytes or discard them.
Here is the in-progress script I wrote:
Code: Select all
idstring \x48\x0\x0\xC
endian big
get UNK short
get FREQ short
get UNK long
callfunction getlayers 1
set LAYERS 1
for k = 1 <= LAYERS
log MEMORY_FILE 0 0
set OFFSET 0xc
for i = 1
goto OFFSET
get TEST short
if TEST == 0x4500 # end marker
callfunction wrapup 1
endif
get SIZE short
math SIZE -= 0xc
get DUMMY longlong
savepos OFFSET
set BIAS 0
set ADJUST OFFSET
math ADJUST += SIZE
goto ADJUST
get TEST short
if TEST == 0x4400
elif TEST == 0x4500
else
goto ADJUST
do
get TEST byte
get DUMMY2 threebyte
savepos SIZE2
while TEST != 0x44
xmath BIAS "SIZE2 - 4 - OFFSET - SIZE"
endif
callfunction write 1
#set GO i
#math GO %= LAYERS
#if GO == k
# callfunction write 1
#elif GO == 0
# if k == LAYERS
# callfunction write 1
# endif
#endif
math OFFSET += SIZE
math OFFSET += BIAS
next i
next k
startfunction getlayers
savepos MYOFF
get DUMMY long
set i 0
do
math i += 1
get TEST short
get DUMMY short
while TEST == 0
math i -= 1
set LAYERS i
goto MYOFF
endfunction
startfunction write
goto OFFSET
append
log MEMORY_FILE OFFSET SIZE
append
get MSIZE asize MEMORY_FILE
math MSIZE x= 0x800
math MSIZE -= 1
putVarChr MEMORY_FILE MSIZE 0 # write 0 at end of block
endfunction
startfunction wrapup
get SIZE asize MEMORY_FILE
get NAME basename
string NAME += ".uxma"
log NAME 0 SIZE MEMORY_FILE
cleanexit
endfunction
As you can see, I'm currently treating files as single layer as I don't know how to distinguish between single- and multi-layer files (thus "set LAYERS 1"). Anyway the outcome is the same. The block-commented section ("set GO i" and so on) is for multilayer files and still work-in-progress.
Ok, this is what I got, now I'll need some help. You can parse the res files to uxma but pasing isn't possible.
Anybody has the time and patience to take a look at this? That would be wonderful!