The current conversion script (adding to a Type 1 / Type 2 converter script that goes some 15 years back):
Code: Select all
#!/usr/bin/perl -0777
use open IO=> ':raw';
$opaque= pack "C", 255;
sub addalpha {
return pack '(a4)*', map {$_.$opaque} unpack '(a3)*', shift;
}
while (<>) {
unless (($base= $ARGV) =~s/\.TEX$//i) {
warn "$ARGV has an unrecognized file extension\n";
next;
}
($version, $texType, $W, $H, $x, $mipLevels, $x, $x)= unpack "I*", substr $_, 0, 32;
if (3 != $version) {
if (2 != $version) {
if (6 != $version) {
if (13 != $version) {
warn "$ARGV is not a TEX file\n";
next;
}
}
}
}
#$W=$W+$W;
#$H=$H/2;
warn "version $version\n";
warn "texType $texType\n";
warn "$W x $H\n";
warn "mip levels $mipLevels\n";
$suffix= "";
@shift= 0 .. $mipLevels;
@W= map {$W >> $_} (@shift,@shift); # doubled for offsets into texType 2 with miplevels
@H= map {$H >> $_} (@shift,@shift);
$pixW= $texType == 3 ?4 :1;
@off= ($sum= 0);
for (0..$#W) {
push @off, $sum+= $W[$_]*$pixW*$H[$_];
}
for $mip (0 .. 0) {
# for $mip (0 .. $mipLevels) { # We're only interested in the largest version of the texture
$W= $W[$mip];
$H= $H[$mip];
if ($mip) {
$suffix= -$mip;
}
$out= "$base$suffix.bmp";
# likely BMP values
$offset= 54;
$size= $offset + $W*$H*4;
$ID2= 40;
$planes= 1;
$bpp= 32;
$compression= 0;
$SizeImage= $W*$H;
$XPPM= 2834;
$YPPM= 2834;
$ColorsUsed= 0;
$ColorsImportant= 0;
$colormap= "";
# override some of these on a per-tex-type basis
if (1 == $texType || 2 == $texType) {
@color= @col= unpack "C*", substr $_, 32, 256*3;
if (2 == $version) {
@color= @col= unpack "C*", substr $_, 24, 256*3;
}
for $n (0..255) {
# bmp colors are BGR instead of RGB
for $m (0..2) {
$color[($n*3)+$m]= $col[($n*3)+2-$m];
}
}
if (1 == $texType) {
$offset= 54 + 256*4; # 256 color palette
$size= $offset+$W*$H;
$bpp= 8;
$ColorsUsed= 256;
$ColorsImportant= 256;
$colormap= addalpha pack 'C*', @color;
$texture= pack "(a$W)*", reverse unpack "(a$W)*", substr $_, 800+$off[$mip], $W*$H;
} else {
$wh= $W*$H;
my @image= unpack "C*", pack "(a$W)*", reverse unpack "(a$W)*", substr $_, 800+$off[$mip], $wh;
my @opacity= unpack "(a1)*", pack "(a$W)*", reverse unpack "(a$W)*", substr $_, 800+$off[$mip+1+$mipLevels], $wh;
my @rgb= unpack "(a3)*", pack "C*", @color;
$texture= pack "(a4)*", map {"$rgb[$image[$_]]$opacity[$_]"} 0..($wh-1);
}
} elsif (3 == $texType) {
$W4= $W*4; # width of scanline
$texture= pack "(a$W4)*", reverse unpack "(a$W4)*", substr $_, 32+$off[$mip], $W4*$H;
} elsif (6 == $texType) {
#PS2 texture format
@color= @col= unpack "C*", substr $_, 0x38, 256*4;
$CurrOfs = 1;
for $i (1 .. 255){
$SwitchI = ($i / 8)%4;
if ( 1 == $SwitchI ) { $vSum = 8; }
elsif ( 2 == $SwitchI ) { $vSum = -8; }
else { $vSum = 0; }
$storeAddr = $i + $vSum ;
$color[($storeAddr*4)+0] = $col[($CurrOfs*4)+0];
$color[($storeAddr*4)+1] = $col[($CurrOfs*4)+1];
$color[($storeAddr*4)+2] = $col[($CurrOfs*4)+2];
$color[($storeAddr*4)+3] = $col[($CurrOfs*4)+3];
$CurrOfs += 1;
}
for $n (0..256*4-1) {
$col[$n]=$color[$n];
}
for $n (0..255) {
# bmp colors are BGR instead of RGB
$color[($n*4)+0]= $col[($n*4)+2];
$color[($n*4)+1]= $col[($n*4)+1];
$color[($n*4)+2]= $col[($n*4)+0];
$color[($n*4)+3]= 255;
}
$offset= 54 + 256*4; # 256 color palette
$size= $offset+$W*$H;
$bpp= 8;
$ColorsUsed= 256;
$ColorsImportant= 256;
$colormap= pack 'C*', @color;
@texout = @rawtex = unpack "C*", substr $_, (0x38 + 31 + 0x100*4)+$off[$mip], $W*$H;
$block_location = 0;
$byte_num = 0;
$swap_selector = 0;
$posY = 0;
$column_location = 0;
for $y (0..$H-1) {
for $x (0..$W-1) {
$block_location = ($y & -16) * $W + ($x & -16) * 2;
$swap_selector = (( ($y + 2) >> 2) & 0x1) * 4;
$posY = ((($y & -4) >> 1) + ($y & 1)) & 0x7;
$column_location = $posY * $W * 2 + (($x + $swap_selector) & 0x7) * 4;
$byte_num = (( $y >> 1) & 1) + ( ( $x >> 2) & 2);
$texout[($y * $W) + $x] = $rawtex[$block_location + $column_location + $byte_num + 1];
}
}
@texrows = @rawtexrows= unpack "(a$W)*", pack 'C*', @texout;
$texture= pack "(a$W)*", reverse @texrows;
} elsif (13 == $texType) {
#Xbox (original) texture format
@color= @col= unpack "C*", substr $_, 0x18, 256*4;
#The palette is BMP-correct as-is
$offset= 0x18 + 256*4; # 256 color palette
$size= $offset+$W*$H;
$bpp= 8;
$ColorsUsed= 256;
$ColorsImportant= 256;
$colormap= pack 'C*', @color;
@texout = @rawtex = unpack "C*", substr $_, (0x18 + 0x100*4)+$off[$mip], $W*$H;
@texrows = @rawtexrows= unpack "(a$W)*", pack 'C*', @texout;
$texture= pack "(a$W)*", reverse @texrows;
}
else {
warn "$ARGV: unsupported tex file type: $texType\n";
next;
}
$header= "BM".pack "IssIIIIssIIIIII", $size, 0, 0, $offset, $ID2, $W, $H, $planes, $bpp, $compression, $SizeImage, $XPPM, $YPPM, $ColorsUsed, $ColorsImportant;
open OUT, "> $out" or die "can't write to $out";
print OUT $header;
print OUT $colormap;
print OUT $texture;
close OUT;
}
}
) and works for that, but the unswizzling algorithm isn't applicable for Type 13. When tried, this is the result I get: