Enhanced WiiWare extractor
As I wasn't quite satisfied with the procedure to extract the contents of extracted WiiWare *.wad images, I wrote my own script. The basis is just a U-8 archive extractor, but it does more than just extract/decompress it's contents:
- it searches for a U-8 archive within a file, dumps the data before the found identifier and processes the U-8
- it analyzes the content of each file from the U-8 after dumping it into memory:
-> if the data has an "LZ77" identifier, it automatically decompresses the contents
-> if the data has an "IMD5" identifier, it looks for either a "BNS " (sound) or "LZ77" identifier. If the latter is found, it decompresses the content
- the above two steps also apply to files that are no U-8 archives but have these three identifiers.
If you have ever worked with WAD WiiWare images, you know that the process of extracting everything can be rather tedious. This script will fasten the process a bit.
Just to get an idea what the potential is:
- when you extract the 00000000.app, the banner.bin, icon.bin and sound.bin are already decompressed. If the sound.bin wasn't compressed, it's already named sound.bin.bns and ready to be played in Winamp with the vgmstream input
- when you extract some other U-8 archive, all the contents will be fully decompressed, even if they start with the LZ77 identifier and not with 0x10/0x11.
- you can throw in LZ77-compressed files with either 0x10/0x11 or "LZ77" identifier and decompress them. Any found data with IMD5 identifier will be analyzed further.
- you can throw in files with "IMD5" identifier and the content will be decompressed.
So after all, this is quite a powerful script.
Code: Select all
# enhanced WiiWare extractor
# supported formats: U-8 archives, LZ77-compressed files ("LZ77" or 0x10/0x11 identifier) and files with "IMD5" identifier
# - if LZ77-compressed data is found in an IMD5 file within a U-8 archive or if the IMD5 file is the input, it is automatically decompressed
# - if a BNS sound file is found in a IMD5 file within a U-8 archive or if the IMD5 file is the input, it is automatically extracted
# - if the input is an LZ77-compressed file (all identifiers), it is decompressed and analyzed further with the above criteria
# (c) 2012-07-08 by AlphaTwentyThree of XeNTaX
set SUBFOLDER 1 # decide if you want to take the archive name as root folder (U-8 only)
if SUBFOLDER == 1
get AFOLDER basename
string AFOLDER += "/"
endif
endian big
comtype COMP_LZ77WII
FindLoc OFFSET string \x55\xaa\x38\x2d 0 ""
get SIZE asize
if OFFSET == "" # something else -> test in MEM2
log MEMORY_FILE 0 0
goto 0
get TEST byte
if TEST == 0x10
endian little
get ZSIZE threebyte
endian big
clog MEMORY_FILE2 0 SIZE ZSIZE
elif TEST == 0x11
get ZSIZE threebyte
clog MEMORY_FILE2 0 SIZE ZSIZE
else
log MEMORY_FILE2 0 SIZE
endif
get WNAME basename
callfunction testMEM2 1
else
if OFFSET != 0
get NAME basename
string NAME += ".dump"
if SUBFOLDER == 1
set WNAME AFOLDER
string WNAME += NAME
else
set WNAME NAME
endif
log WNAME 0 OFFSET
endif
math SIZE -= OFFSET
putVarChr MEMORY_FILE SIZE 0
log MEMORY_FILE 0 0
append
log MEMORY_FILE OFFSET SIZE # plain U-8 archive
append
callfunction processU8 1
endif
startfunction processU8
goto 0 MEMORY_FILE
idstring \x55\xaa\x38\x2d MEMORY_FILE # U-8
get OFF_INFO long MEMORY_FILE
get INFOSIZE long MEMORY_FILE
get UNK long MEMORY_FILE
callfunction getFiles 1 # number of files
set OFFNAMES FILES
math OFFNAMES *= 0xc
math OFFNAMES += OFF_INFO
set FOLDER ""
for i = 1 <= FILES
goto OFF_INFO MEMORY_FILE # FID in main U-8
get FIDENT byte MEMORY_FILE
get OFF_NAME threebyte MEMORY_FILE
get OFFSET long MEMORY_FILE
get SIZE long MEMORY_FILE # compressed size
savepos OFF_INFO MEMORY_FILE # continue from here after if
math OFF_NAME += OFFNAMES
goto OFF_NAME MEMORY_FILE
get NAME string MEMORY_FILE
if FIDENT == 1
callfunction setFolder 1
else # file decompression or copy to MEMORY_FILE2
set WNAME FOLDER
string WNAME += NAME # complete name
goto OFFSET MEMORY_FILE
get IDENT byte MEMORY_FILE
log MEMORY_FILE2 0 0
if IDENT == 0x10
endian little
get ZSIZE threebyte MEMORY_FILE
endian big
clog MEMORY_FILE2 OFFSET SIZE ZSIZE MEMORY_FILE # decompress to MEM2
print "ok"
elif IDENT == 0x11
get ZSIZE threebyte MEMORY_FILE
clog MEMORY_FILE2 OFFSET SIZE ZSIZE MEMORY_FILE
print "ok"
else # no matter what else
log MEMORY_FILE2 OFFSET SIZE MEMORY_FILE
print "ok"
endif
get SIZE asize MEMORY_FILE2
if SIZE >= 4
callfunction testMEM2 1
else
log WNAME 0 SIZE MEMORY_FILE2
endif
endif
next i
endfunction
startfunction testMEM2
get SIZE asize MEMORY_FILE2
set OFFSET 0
goto 0 MEMORY_FILE2
getDstring IDENT 4 MEMORY_FILE2
if IDENT == "IMD5" # test for BNS or LZ77
goto 0x20 MEMORY_FILE2
getDstring IDENT 4 MEMORY_FILE2
if IDENT = "BNS "
set OFFSET 0x20
math SIZE -= OFFSET
string WNAME += ".bns"
log WNAME OFFSET SIZE MEMORY_FILE2
elif IDENT == "LZ77"
set OFFSET 0x24
math SIZE -= OFFSET
get TYPE byte MEMORY_FILE2
if TYPE == 0x10
endian little
endif
get ZSIZE threebyte MEMORY_FILE2
endian big
string WNAME += ".decomp"
clog WNAME OFFSET SIZE ZSIZE MEMORY_FILE2
else
set OFFSET 0x20
math SIZE -= OFFSET
string WNAME += ".imd"
log WNAME OFFSET SIZE MEMORY_FILE2 # change nothing
endif
else
if IDENT == "BNS "
string WNAME += ".bns"
endif
get SIZE asize MEMORY_FILE2
log WNAME 0 SIZE MEMORY_FILE2 # change nothing
endif
endfunction
startfunction setFOLDER
if SUBFOLDER == 1
set FOLDER AFOLDER
string FOLDER += NAME
if NAME != ""
string FOLDER += "/"
endif
else
if NAME != ""
set FOLDER NAME
string FOLDER += "/"
else set FOLDER ""
endif
endif
endfunction
startfunction getFiles
set TEST OFF_INFO
goto TEST MEMORY_FILE
for
get IDENT1 byte MEMORY_FILE
get IDENT2 byte MEMORY_FILE
if IDENT2 > 0
break
else
math TEST += 0xc
goto TEST MEMORY_FILE
endif
next
savepos FILES MEMORY_FILE
math FILES -= 2
math FILES -= OFF_INFO
math FILES /= 0xc
endfunction