Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - scmark15

Pages: [1]
1
Okay for those who read my "TIM files for those starting out" (http://forums.qhimm.com/index.php?topic=9754.0)
thread my last post had a sample code to use PHP to read 8 bit TIM files. I decided this should have its own thread because
this thread isn't about how TIM files store there data but how to view them using PHP.

What you need to begin:
  -IIS or Apache Server running PHP 5
  -A copy of the script below (Just copy & paste it to notepad and save it as TIMViewer.php)
  -A few TIM files (must be copied to the same directory as the TIMViewer.php script)

Code: [Select]
<html>
<head>
  <title>TIM Viewer</title>
  <style>
    <!--
      body, table, tr, td{
        font-family: courier new;
        font-size:   11px;
      }
    -->
  </style>
</head>
<body>
<?php
if(isset($_GET[&#39;file&#39;])){
  
$infile $_GET[&#39;file&#39;];
}else{
  die(
"Error: no file selected");
}

$curCLUT 1;
if(isset(
$_GET[&#39;clut&#39;])){
  
$curCLUT $_GET[&#39;clut&#39;];
}
$handle fopen($infile, &#39;rb&#39;);

//
// HEX => CONVERT => BINARY
//
function hexbin($strHex) {
  
$strBin = &#39;&#39;;
  
for($i 0$i strlen($strHex); $i++){
    
$strBin .= sprintf("%04s"decbin(hexdec($strHex[$i])));
  }
  return 
$strBin;
}

//
// ABGR[1555] => CONVERT => RGB[888]
//
function getRGB($color){
  
$colorBin hexbin(str_repeat("0"strlen(dechex($color))) . dechex($color));

  
$a1 substr($colorBin01);
  
$b5 substr($colorBin15);
  
$g5 substr($colorBin65);
  
$r5 substr($colorBin115);

  
$alphadec bindec($a1);
  
$bluedec  bindec($b5);
  
$greendec bindec($g5);
  
$reddec   bindec($r5);

  
$a8 $alphadec 8;
  
// Older BGR[1555] to RGB[888] Conversion
  // (Output is slightly darker)
  // $r8 = $reddec * 8;
  // $g8 = $greendec * 8;
  // $b8 = $bluedec * 8;

  // New BGR[1555] to RGB[888] Conversion
  // (Output is slightly brighter)
  
$r8 round(($reddec 8) + ($reddec 31 7));
  
$g8 round(($greendec 8) + ($greendec 31 7));
  
$b8 round(($bluedec 8) + ($bluedec 31 7));

  
// Alpha is ignored
  // $RGBAlpha = strtoupper(str_repeat("0", 2-strlen(dechex($a8))) . dechex($a8));
  
$RGBRed   strtoupper(str_repeat("0"strlen(dechex($r8))) . dechex($r8));
  
$RGBGreen strtoupper(str_repeat("0"strlen(dechex($g8))) . dechex($g8));
  
$RGBBlue  strtoupper(str_repeat("0"strlen(dechex($b8))) . dechex($b8));
  
$RGB $RGBRed $RGBGreen $RGBBlue;
  return 
$RGB;
}

//
// FILE HEADER
//
$data unpack("V2"fread($handle8));
$timMagic = &#39;0x&#39; . dechex($data[1]);
$timType = &#39;0x0&#39; . $data[2];
unset($data);

if(
$timType == 0x08 || $timType == 0x09){
  
//
  // CLUT HEADER
  //
  
$data unpack(&#39;Vlong/v4short&#39;, fread($handle, 12));
  
$clutLength $data[&#39;long&#39;];
  
$clutX      $data[&#39;short1&#39;];
  
$clutY      $data[&#39;short2&#39;];
  
$colorNum   $data[&#39;short3&#39;];
  
$clutCount  $data[&#39;short4&#39;];
  
unset($data);

  
//
  // CLUT DATA
  //
  
for($x 1$x <= $clutCount$x++){
    for(
$i 1$i <= $colorNum$i++){
      
$data unpack(&#39;v&#39;, fread($handle, 2));
      
$clutData[$x][$i] = getRGB($data[1]);
    }
  }
  unset(
$data);
}

//
// IMAGE HEADER
//
$data unpack(&#39;Vlong/v4short&#39;, fread($handle, 12));
$imgLength $data[&#39;long&#39;];
$imgX      $data[&#39;short1&#39;];
$imgY      $data[&#39;short2&#39;];
$imgPitch  $data[&#39;short3&#39;];
$imgHeight $data[&#39;short4&#39;];
unset($data);

//
// IMAGE WIDTH FIX
//
if($timType == 0x08){
  
$imgWidth $imgPitch 4;
  
$imgArea = ($imgPitch 2) * $imgHeight;
}else if(
$timType == 0x09){
  
$imgWidth $imgPitch 2;
  
$imgArea $imgWidth $imgHeight;
}else if(
$timType == 0x02){
  
$imgWidth $imgPitch;
  
$imgArea $imgWidth $imgHeight;
}else if(
$timType == 0x03){
  
$imgWidth $imgPitch 1.5;
  
$imgArea $imgWidth $imgHeight;
}

//
// File Info
//
echo &#39;<h3>File Info</h3>&#39; . "\n";
echo &#39;TIM Header: &#39; . $timMagic . &#39;<br/>&#39; . "\n";
if($timType == 0x08){
  
$bpp = &#39;4bpp&#39;;
}else if($timType == 0x09){
  
$bpp = &#39;8bpp&#39;;
}else if($timType == 0x02){
  
$bpp = &#39;16bpp&#39;;
}else if($timType == 0x03){
  
$bpp = &#39;24bpp&#39;;
}
echo &
#39;TIM Type: &nbsp;&nbsp;&#39; . $timType . &#39; => &#39; . $bpp . &#39;<br/>&#39; . "\n";

echo &#39;<br/>&#39;;
if($timType == 0x08 || $timType == 0x09){
  echo &
#39;<b>CLUT Header</b><br />&#39; . "\n";
  
echo &#39;CLUT Size: &nbsp;&nbsp;&#39; . $clutLength . &#39; Bytes<br/>&#39; . "\n";
  
echo &#39;H. Res: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39; . $clutX . &#39;<br/>&#39; . "\n";
  
echo &#39;V. Res: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39; . $clutY . &#39;<br/>&#39; . "\n";
  
echo &#39;# of Colors: &#39; . $colorNum . &#39;<br/>&#39; . "\n";
  
echo &#39;# of CLUTS: &nbsp;&#39; . $clutCount . &#39;<br/>&#39; . "\n";

  
echo &#39;<br/>&#39; . "\n";

  
echo &#39;<b>CLUT (Color Look-Up Table)</b><br />&#39; . "\n";
  
echo &#39;<table border="0" cellpadding="0" cellspacing="2"><tr>&#39; . "\n";
  
$count 0;
  for(
$i 1$i <= $colorNum$i++){
    
$color $clutData[$curCLUT][$i];
    echo &
#39;<td style="border: #000000 1px solid; background-color: #&#39; . $color . &#39;; height: 16px; text-align: center; width: 16px;">&nbsp;</td>&#39; . "\n";
    
$count++;
    if(
$count == && $colorNum == 16){
      echo &
#39;</tr><tr>&#39; . "\n";
      
$count 0;
    }else if(
$count == 16 && $colorNum == 256){
      echo &
#39;</tr><tr>&#39; . "\n";
      
$count 0;
    }
  }
  echo &
#39;</tr></table>&#39; . "\n";

  
echo &#39;<br/>&#39; . "\n";
}

echo &
#39;<b>Image Header</b><br />&#39; . "\n";
echo &#39;Image Size: &#39; . $imgLength . &#39; Bytes<br/>&#39; . "\n";
echo &#39;Org. X: &nbsp;&nbsp;&nbsp;&nbsp;&#39; . $imgX . &#39;<br/>&#39; . "\n";
echo &#39;Org. Y: &nbsp;&nbsp;&nbsp;&nbsp;&#39; . $imgY . &#39;<br/>&#39; . "\n";
echo &#39;Width: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39; . $imgWidth . &#39;px<br/>&#39; . "\n";
echo &#39;Height: &nbsp;&nbsp;&nbsp;&nbsp;&#39; . $imgHeight . &#39;px<br/>&#39; . "\n";

echo &#39;<br/>&#39; . "\n";
echo &#39;<h3>Output</h3>&#39; . "\n";
echo &#39;<table border="0" cellpadding="0" cellspacing="0" height="&#39; . $imgHeight . &#39;" width="&#39; . $imgWidth . &#39;"><tr>&#39; . "\n";
if($timType == 0x08 || $timType == 0x09){
  
$count 0;
  for(
$i 1$i <= $imgArea$i++){
    if(
$timType == 0x08){
      
$buff fread($handle1);

      
$data unpack(&#39;h&#39;, $buff);
      
$highNibble hexdec($data[1]) + 1;
      unset(
$data);

      
$data unpack(&#39;H&#39;, $buff);
      
$lowNibble hexdec($data[1]) + 1;
      unset(
$data);

      
$count++;
      echo &
#39;<td style="background-color: #&#39; . $clutData[$curCLUT][$highNibble] .&#39;"></td>&#39; . "\n";

      
$count++;
      echo &
#39;<td style="background-color: #&#39; . $clutData[$curCLUT][$lowNibble] .&#39;"></td>&#39; . "\n";
    
}else if($timType == 0x09){
      
$buff fread($handle1);

      
$data unpack(&#39;C&#39;, $buff);
      
$picked $data[1] + 1;
      unset(
$data);

      
$count++;
      echo &
#39;<td style="background-color: #&#39; . $clutData[$curCLUT][$picked] .&#39;"></td>&#39; . "\n";
    
}
    if(
$count == $imgWidth){
      
$count 0;
      echo &
#39;</tr><tr>&#39; . "\n";
    
}
  }
  echo &
#39;</tr></table>&#39; . "\n";
}else if($timType == 0x02){
  
$count 0;
  for(
$i 1$i <= $imgArea$i++){
    
$data unpack(&#39;v&#39;, fread($handle, 2));
    
$rawData getRGB($data[1]);
    unset(
$data);

    
$count++;
    echo &
#39;<td style="background-color: #&#39; . $rawData . &#39;"></td>&#39; . "\n";

    
if($count == $imgWidth){
      
$count 0;
      echo &
#39;</tr><tr>&#39; . "\n";
    
}
  }
}else if(
$timType == 0x03){
  
$count 0;
  for(
$i 1$i <= $imgArea$i++){
    
$data unpack(&#39;C3&#39;, fread($handle, 3));
    
$rawData strtoupper(str_repeat("0"strlen(dechex($data[1]))) . dechex($data[1])) .
               
strtoupper(str_repeat("0"strlen(dechex($data[2]))) . dechex($data[2])) .
               
strtoupper(str_repeat("0"strlen(dechex($data[3]))) . dechex($data[3]));
    unset(
$data);

    
$count++;
    echo &
#39;<td style="background-color: #&#39; . $rawData . &#39;"></td>&#39; . "\n";
    
$rawData = &#39;&#39;;

    
if($count == $imgWidth){
      
$count 0;
      echo &
#39;</tr><tr>&#39; . "\n";
    
}
  }
}else{
  die(
"Error: Invalid TIM file");
}
echo &
#39;</tr></table>&#39; . "\n";
fclose($handle);
?>

</body>
</html>

Usage:
  Open your browser and type in the address of the script ie. "localhost/TIMViewer.php?file=tim.tim"
     Where "tim.tim" is change it to the file name of your TIM file.
     If the file is a 4 bit or an 8 bit TIM add "&clut=x" (x is which clut you wish to use to view the image, default is 1)
        => "localhost/TIMViewer.php?file=mytim.tim&clut=1" (this would view the image with the 1st clut from the mytim.tim file)

Notes:
  -This is not the most efficient coding or fastest loading but it does work.
  -Big TIM files might take a long time to load.
  -This script is writen purely by me and can be edited freely (Please post your updated code if you modify)
  -Script does not show image as any graphic file (it's actually a table <= maybe why it's slow loading)

Tested with:
  - Works with FF6 character faces (4bpp)
  - Works with FF7 character faces (8bpp)
  - Works with FF9 game over screen (16bpp)
  - Works with adobe TIM plugin for all bpp (used to test 24bpp)

----------------------------------------------------------------------------------------------------------

-Enjoy
SCMark15

2
I wanted to see if this could be done....

I made a TIM reader using PHP. It only works for 8bpp images with only 1 CLUT...for now anyway. I got it to work with the FF7 character faces in the psx versions "MENU" folder.

Test Requirements:
-PHP 5 (this is what I used)
-IIS or Apache Server running PHP
-A copy of FF7 for PSX
-A 1x1 GIF image thats completely transparent (must be named "spacer.gif")
            - place it in the same folder as the php script.
            - (its for drawing a table to display the TIM)
 -A copy of the script below
            - Copy it to notepad and save it as TIMReader.php
Code: [Select]
<html>
<head>
  <title></title>
  <style>
    <!--
      body {
       margin:      10px;
       padding:     0px;
       font-family: courier new;
       font-size:   11px;
      }
    -->
  </style>
</head>
<body>
<?php
$file 
"test.tim";
// Dummy out file
$fileHex = &#39;&#39;;

$handle fopen($file"rb") or die("Error: Check your permissions");
while(!
feof($handle)){
  foreach(
unpack("C*"fgets($handle)) as $dec){
    
$tmp dechex($dec);
    
$fileHex .= strtoupper(str_repeat("0"2-strlen($tmp)) . $tmp);
  }
}
fclose($handle);

function 
hexbin($str_hex) {
  
$str_bin FALSE;
  for (
$i=0$i strlen($str_hex); $i++) {
    
$str_bin .= sprintf("%04s"decbin(hexdec($str_hex[$i])));
  }
  return 
$str_bin;
}
// FILE HEADER
//                          file, offset, numchar
$timMagic wordwrap(substr($fileHex08), 2" "true);
$timType  wordwrap(substr($fileHex88), 2" "true);
// CLUT HEADER
$CLUTLength wordwrap(substr($fileHex168), 2" "true);
$PalX       wordwrap(substr($fileHex244), 2" "true);
$PalY       wordwrap(substr($fileHex284), 2" "true);
$NumColors  wordwrap(substr($fileHex324), 2" "true);
$NumCLUTs   wordwrap(substr($fileHex364), 2" "true);
// CLUT DATA ~~~~ offsex starts at 40
$offset 40;
//for($i = 0; $i < $NumCLUTs; $i++){
  
for($i 0$i 256$i++){
    
$colorArray[] = wordwrap(substr($fileHex$offset4), 2" "true);
    
$offset += 4;
  }
//}
// IMAGE HEADER
$IMGLength wordwrap(substr($fileHex$offset8), 2" "true);
$IMGX      wordwrap(substr($fileHex$offset 84), 2" "true);
$IMGY      wordwrap(substr($fileHex$offset 124), 2" "true);
$Pitch     wordwrap(substr($fileHex$offset 164), 2" "true);
$Height    wordwrap(substr($fileHex$offset 204), 2" "true);

// Fix Offset for the next block;
$offset += 24;

// OUTPUT
echo "TIM Header: " $timMagic "<br />" "\n";
echo 
"TIM Type: " $timType "<br />" "\n";
echo 
"<br />" ."\n";
echo 
"CLUT Length: " $CLUTLength "<br />" "\n";
echo 
"PalX: " $PalX "<br />" "\n";
echo 
"PalY: " $PalY "<br />" "\n";
echo 
"# of Colors: " $NumColors "<br />" "\n";
echo 
"# of CLUTs: " $NumCLUTs "<br />" "\n";
echo 
"<br />" ."\n";
$x 0;

// BGR[1555] to RGB[888]
function getRGB($colorBin$int){
  global 
$Palette;

  
$a1 substr($colorBin01);
  
$b5 substr($colorBin15);
  
$g5 substr($colorBin65);
  
$r5 substr($colorBin115);

  
$alphadec bindec($a1);
  
$bluedec bindec($b5);
  
$greendec bindec($g5);
  
$reddec bindec($r5);

  
$a8 $alphadec 8;
  
// Older BGR[1555] to RGB[888] Conversion
  // (Output is slightly darker)
  // $r8 = $reddec * 8;
  // $g8 = $greendec * 8;
  // $b8 = $bluedec * 8;

  // New BGR[1555] to RGB[888] Conversion
  // (Output is slightly brighter)
  
$r8 round(($reddec 8) + ($reddec 31 7));
  
$g8 round(($greendec 8) + ($greendec 31 7));
  
$b8 round(($bluedec 8) + ($bluedec 31 7));

  
// Alpha is ignored
  // $RGBAlpha = strtoupper(str_repeat("0", 2-strlen(dechex($a8))) . dechex($a8));
  
$RGBRed   strtoupper(str_repeat("0"2-strlen(dechex($r8))) . dechex($r8));
  
$RGBGreen strtoupper(str_repeat("0"2-strlen(dechex($g8))) . dechex($g8));
  
$RGBBlue  strtoupper(str_repeat("0"2-strlen(dechex($b8))) . dechex($b8));

  
$RGB = &#39;#&#39; . $RGBRed . $RGBGreen . $RGBBlue;
  
$Palette[$int] = $RGB;
  return 
$RGB;
}

foreach(
$colorArray as $color){
  
$tmp explode(" "$color);
  
$colorLE $tmp[1] . $tmp[0];
  unset(
$tmp);
  echo 
"Color " strtoupper(str_repeat("0"2-strlen(dechex($x))) . dechex($x)) . ": " $color "\n";
  echo &
#39; -> &#39; . "\n";
  
$colorBin hexbin($colorLE);
  echo 
$colorBin;
  echo &
#39; -> &#39; . "\n";
  
echo getRGB($colorBin$x);
  echo &
#39;<br />&#39; . "\n";
  
$x++;
}
echo 
"<br />" ."\n";
echo 
"IMG Length: " $IMGLength "<br />" "\n";
echo 
"IMGX: " $IMGX "<br />" "\n";
echo 
"IMGY: " $IMGY "<br />" "\n";
echo 
"Pitch: " $Pitch "<br />" "\n";
echo 
"Height: " $Height "<br />" "\n";
echo 
"<br />" ."\n";

$tmp explode(" "$Pitch);
$Pitch $tmp[1] . $tmp[0];
$Width hexdec($Pitch) * 2;
unset(
$tmp);
$tmp explode(" "$Height);
$tHeight $tmp[1] . $tmp[0];
$High hexdec($tHeight);
$RawLength $High $Width;
echo &
#39;<table border="0" cellpadding="0" cellspacing="0"><tr>&#39; ."\n";
$count 0;
for(
$i 0$i $RawLength$i++){
  
$IMGRaw substr($fileHex$offset2);
  
$offset += 2;
  
$picked hexdec($IMGRaw);
  echo &
#39;<td style="background-color: &#39; . $Palette[$picked] . &#39;;><img src="spacer.gif" border="0" height="1" width="1" /></td>&#39; . "\n";
  
$count++;
  if(
$count == $Width){
    echo &
#39;</tr></tr>&#39; ."\n";
    
$count 0;
  }
}
echo &
#39;</tr></table>&#39;;
?>

</body>
</html>

To use: copy the TIM file to the same folder as the script and rename it to "test.tim"
Run the script to see if it worked.

This is only a work in progress, so I appologize for my messy code (I wasn't trying to impress ^_^)
I hope to add functionality to work with Multi-CLUT tims as well as 4, 16 & 24 bpp also.

SCMark15

P.S.
Any feedback or comments are welcome anytime. I need to know if this worked for you, or what
other files you tried it out on. I'll update this when I have more time to play around with it.

-later

3
I'm always forgetting to mention something ^_^

If anyone wants a copy of Yu_Ri 0.99e in english drop me an email at <[email protected]>
just make sure to add "NEED YU_RI" as the Subject or I won't read it.

Yu_Ri is a TIM, BMP extractor... it searches through big and small files for images.
It will take a multi CLUT TIM and open an image for each CLUT to view as well as save/multi-save
to BMP or TIFF. Version 0.99e includes GIF and JPEG ripping plugins.

Yu_Ri 0.99e is the last version of yu_ri released and is hard to find most websites only
have version 0.99c. I translated 90% of it to english for personal use but I'm willing to share ^_^

-later


4
:o I forgot to note that you have to change the hex in the CLUT/Raw Image Data (4, 8 & 16 bit palettes)  to Big Endian before converting it to binary to get A BBBBB GGGGG RRRRR
because its stored in Little Endian as GGG RRRRR A BBBBB GG. :-D

Code: [Select]
For example... Little Endian 1F 00 (Binary: 000 11111 0 00000 00) -> Big Endian: 00 1F  (Binary: 0 00000 00000 11111)
this will output pure red.

Code: [Select]
   HEX  ->  HEX  -> BINARY              -> COLOR -> COLOR-REF
   LE   ->  BE   -> A BBBBB GGGGG RRRRR ->   -   ->     -
  -----------------------------------------------------------
  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED   -> 0000
  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN -> 0001
  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  -> 0010
  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE -> 0011

I just thought people who didn't know anything or not enough about TIM files might enjoy this so I thought I'd share.
I only used a 4x4 image with 4 colors because it was easier to figure out then a smaller image and a bigger image had
too much to sort through. As for odd pixeled images I think I tried once and I couldn't get it to display, maybe because of
the CLUT data, or BPP I tried... I can't remember, I'll have to look into that ^_^

Please note: that these are my notes and may not be 100% correct...so if anyone could or wants to add/update
these notes please do so and share with the community, especially me... could always use some more info & feedback.

Oh, and if they want to add some of these notes to the wiki I have no problem with that at all.

Peace,
scmark15
<[email protected]>

5
Here is some notes I made using a hex editor and playing around...
Code: [Select]
Everything below is from this 4x4 pixel image with 4 colors (Red, Green, Blue & White)...

+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+


--------- 4-Bit TIM (Paletted)-------------

-- HEADER ---------------------------------
  Format:  10 00 00 00  TIM Magic
  BPP:     08 00 00 00  4bpp

-- CLUT DATA HEADER------------------------
  Length:  2C 00 00 00  44 bytes (32 bytes/palette + 12 bytes for this header)
  palX:    00 00        0px
  palY:    00 00        0px
  colr#:   10 00        16 (Always 16)
  #CLUT:   01 00        1 CLUT

-- CLUT - 2 byte (ABGR[1555] Color) little endian-------
   HEX  ->  HEX  -> BINARY              -> COLOR -> COLOR-REF
   LE   ->  BE   -> A BBBBB GGGGG RRRRR ->   -   ->     -
  -----------------------------------------------------------
  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED   -> 0000
  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN -> 0001
  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  -> 0010
  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE -> 0100

  There is only 4 Colors in palette rest is "Black" padding -> 00 00
    00 00 -> 0 00000 00000 00000 -> BLACK -> 1000
    00 00 -> 0 00000 00000 00000 -> BLACK -> 1001
    00 00 -> 0 00000 00000 00000 -> BLACK -> 1010
  ...repeat until this CLUT is a total of 32 bytes/16 color entries (last index: 00 00 -> 0 00000 00000 00000 -> BLACK -> 1111)

  (Example: We only have 4 colors so there will be 24 bytes of padding or
            "00 00" 12 times (PADDING: 00 00 -> 0 00000 00000 00000 -> BLACK --> XXXX)

-- IMAGE HEADER ---------------------------
  Length:  14 00 00 00  20 bytes (1 byte for each 2 pixel set + 12 bytes for this header)
  Hres:    C0 03        960
  Vres:    00 00        0
  Width:   01 00        4px (multiplied by 4 to get actual)
  Height:  04 00        4px

-- IMAGE DATA (Like 8-bit TIM, REFERENCED, only 4 bits instead of 8 bits)----------------
  HEX -> BINARY    -> PX2Cr | PX1Cr
      -> px2  px1  ->   -   |   -
  ------------------------------------------------
  00  -> 0000 0000 -> RED   | RED
  11  -> 0001 0001 -> GREEN | GREEN

  00  -> 0000 0000 -> RED   | RED
  11  -> 0001 0001 -> GREEN | GREEN

  22  -> 0010 0010 -> BLUE  | BLUE
  33  -> 0100 0100 -> WHITE | WHITE

  22  -> 0010 0010 -> BLUE  | BLUE
  33  -> 0100 0100 -> WHITE | WHITE


  Read 2 pixels at a time but second pixel is output'd first (ie right to left)
    1st byte...
      1st 4-bit set -> 2nd pixel
      2nd 4-bit set -> 1st pixel

    2nd byte...
      3rd 4-bit set -> 4th pixel
      4th 4-bit set -> 3rd pixel

    3rd byte...
      5th 4-bit set -> 6th pixel
      6th 4-bit set -> 5th pixel

    4th byte...
      7th 4-bit set -> 8th pixel
      8th 4-bit set -> 7th pixel

    Visual Example (4 x 2 px image):
    +-------+-------+-------+-------+
    |  2nd  |  1st  |  4th  |  3rd  |
    +-------+-------+-------+-------+
    |  6th  |  5th  |  8th  |  7th  |
    +-------+-------+-------+-------+

  So... 00 -> Output is: RED   | RED
        11 -> Output is: GREEN | GREEN
        01 -> Output is: GREEN | RED
        10 -> Output is: RED   | GREEN
         ^-- RED is 0 and GREEN is 1

IMAGE (1 CLUT):
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+


====================================================================
--------- 8-Bit TIM (Paletted)-------------

-- HEADER ---------------------------------
  Format:  10 00 00 00  TIM Magic
  BPP:     09 00 00 00  8bpp

-- CLUT DATA HEADER------------------------
  Length:  0C 02 00 00  524 bytes (512 bytes/palette + 12 bytes for this header)
  palX:    00 00        0px
  palY:    00 00        0px
  colr#:   00 01        256 (Always 256)
  #CLUT:   01 00        1 CLUT

-- CLUT - 2 byte (ABGR[1555] Color) little endian -------
  *Each CLUT or Color LookUp Table is 256 colors or 512 bytes
  
   HEX  ->  HEX  -> BINARY              -> COLOR -> COLOR-REF
   LE   ->  BE   -> A BBBBB GGGGG RRRRR ->   -   ->     -
  ------------------------------------------------------------
  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED   -> color00
  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN -> color01
  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  -> color02
  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE -> color03

  There is only 4 Colors in palette rest is "Black" padding -> 00 00 ...
    00 00 -> 0 00000 00000 00000 -> BLACK -> color04
    00 00 -> 0 00000 00000 00000 -> BLACK -> color05
  ...repeat until this CLUT is a total of 512 bytes/256 color entries

  (Example: We only have 4 colors so there will be 504 bytes of padding or
            "00 00" 252 times (PADDING: 00 00 -> 0 00000 00000 00000 -> BLACK -> colorXX)

-- IMAGE HEADER ---------------------------
  Length:  1C 00 00 00  28 bytes (1 byte for each pixel + 12 bytes for this header)
  Hres:    C0 03        960
  Vres:    00 00        0
  Width:   02 00        4px (multiplied by 2 to get actual)
  Height:  04 00        4px

-- IMAGE DATA (Just like paletted BMP, REFERENCE each color from CLUT) --
 HEX -> REF     -> COLOR
 -----------------------
  00 -> color00 -> RED
  00 -> color00 -> RED
  01 -> color01 -> GREEN
  01 -> color01 -> GREEN

  00 -> color00 -> RED
  00 -> color00 -> RED
  01 -> color01 -> GREEN
  01 -> color01 -> GREEN

  02 -> color02 -> BLUE
  02 -> color02 -> BLUE
  03 -> color03 -> WHITE
  03 -> color03 -> WHITE

  02 -> color02 -> BLUE
  02 -> color02 -> BLUE
  03 -> color03 -> WHITE
  03 -> color03 -> WHITE

IMAGE (1 CLUT):
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+


====================================================================
------- 16-Bit TIM (NO CLUT DATA)----------

-- HEADER ---------------------------------
  Format:  10 00 00 00  TIM Magic
  BPP:     02 00 00 00  16bpp

-- IMAGE DATA HEADER-----------------------
  Length:  2C 00 00 00  44 bytes (2 bytes for each pixel + 12 bytes for this header)
  Hres:    C0 03        960
  Vres:    00 00        0
  Width:   04 00        4px
  Height:  04 00        4px

-- RAW IMAGE DATA - 2 byte (ABGR[1555] Color) little endian-------
   HEX  ->  HEX  -> BINARY              -> COLOR
   LE   ->  BE   -> A BBBBB GGGGG RRRRR ->   -
  -----------------------------------------------
  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED
  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED
  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN
  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN

  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED
  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED
  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN
  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN

  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE
  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE
  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE
  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE

  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE
  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE
  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE
  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE

IMAGE:
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+


====================================================================  
-------- 24-Bit TIM (NO CLUT DATA)---------
 NOTE: Some TIM programs don't support 24-bit TIMs
       Example...Yu_Ri doesn't but TIM viewer does

-- HEADER ---------------------------------
  Format:  10 00 00 00  TIM Magic
  BPP:     03 00 00 00  24bpp

-- IMAGE DATA HEADER ----------------------
  Length:  3C 00 00 00  60 bytes (3 bytes for each pixel + 12 bytes for this header)
  Hres:    C0 03        960
  Vres:    00 00        0
  Width:   06 00        4px (Divided by 1.5 to get actual)
  Height:  04 00        4px

-- RAW IMAGE DATA - 3 byte RGB[888] big endian ----
  HEX      -> COLOR
  RR GG BB ->   -
  -----------------
  FF 00 00 -> Red
  FF 00 00 -> Red
  00 FF 00 -> Green
  00 FF 00 -> Green

  FF 00 00 -> Red
  FF 00 00 -> Red
  00 FF 00 -> Green
  00 FF 00 -> Green

  00 00 FF -> Blue
  00 00 FF -> Blue
  FF FF FF -> White
  FF FF FF -> White

  00 00 FF -> Blue
  00 00 FF -> Blue
  FF FF FF -> White
  FF FF FF -> White

IMAGE:
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Red  |  Red  | Green | Green |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+
|  Blue |  Blue | White | White |
+-------+-------+-------+-------+


Updated: for those who just wanna copy and paste to have a copy (see my next post to see what was fixed)

6
Thanks Cyb! I picked up some books that my father recommended, he also recommended some webpages that show examples and source. Unfortunently though he's grown accustomed to working with Microsoft Products (the company he works for has deals with microsoft, one of the CEO works for MS also) but he told me to start with Borland C++ and then give Visual C++ a try a little later down the road, and he also recommended a while back to learn C# (that's why I dabbled with it).

Anyways...Time to crack open some books

Thanks again Cyb!
Scmark15


7
Thanks Cyb!

I was just messing around with Tile Molester and found them accidently, they weren't found
with any TIM viewer/scanner (Yuri 0.99e, Tim Viewer, PSXMC, etc...) that I had.

I realized that they were actually 16bpp after when I viewed them the second time after reading
qhimms wiki on TIM files with the extra 1400 (approx) bytes pasted at the end (to see if the
missing tiles would appear). I just found them by accident with the 15bpp BGR (555) codec setting
first, they display the same (or there is an un-noticable difference). In Tile Molester they are not
colored correctly  at 16bpp BGRA (5551) or any other display codec but at 16bpp ABGR (1555)....
I'm not including the 15bpp (555) setting ^_^.

Just thought that others may wish to view them ^_^.

---------------------------------------------------------------------------------------------------------------------------------------

I have Visual Studio (6 & 2008 .Net) as well as Borlands C++ & Delphi (My old mans a
programer/systems analyst). I have very little programming experience (I know HTML, PHP and a
little hex) but want to learn C++, I've played with MS Visual C# .Net and Visual Basic as well as
Borlands Delphi but have no idea where to start with C++, like should I start with Borland C++ or
MS Visual C++, what is the difference. Any recommendations on language and/or books for
beginners would be greatly appreciated.

!!Thanks again!!,
scmark15

---------------------------------------------------------------------------------------------------------------------------------------
PS Cyb,

Thanks for the code! I'll save it for later.

8
I was bored and decided to play with Tile Molester, I found the Change Disc Images & Game over screen...
*Note: I used Zidane_2's ff9_extractor and db_extract programs to tear apart my ff9.img...

Quote
I redownload img and db extractors to:
http://zidane_games.webhost.ru/FF9_TOOLS.rar

And upload new version of the "battle scene viewer":
http://zidane_games.webhost.ru/New_viewer.rar

In new version i fix old bug with textures ))

Archive contain old and new versions and 2 files for example.

Code: [Select]
Dir 01 file 2 (Standard 16bpp TIM File):
Game Over Screen
Height: 224px
Width: 320px

Code: [Select]
Dir 01 files 7-10:
Change Disc 1-4
...after a little cut and paste...
Height: 224px
Width: 320px
...One thing I noticed is that the right half is missing 19 (8x8pixel) tiles from the bottom right of all of them...


*Edit .... Searched through the original ff9.img file (too big to open with tile molester) using my hex editor and
cut out about 1400 bytes and pasted it at the end of the 7th file in the 01 directory saved it as a new file and
tried to view it again and the missing tiles are there now. I have no idea why it got cut off, maybe a problem with
Zande_2's ff9_extractor, I don't know C++ so I can't tell ^_^ (my original ripped 7th file is 143, 360 bytes).



Best viewed settings for change disc images...
Codec: 16bpp ABGR (1555) *Corrected*
Mode: 2-Dimensional
Zoom: 100%
Width: 20 (8x8 pixel) tiles
Height: ?????? (don't feel like counting)

The image will be cut in half with the right half of the image below the left half.

I know a little hex but I really gotta learn Visual C++ so I write my own custom TIM/file viewers.
Any recommendations on books/commented source (I like the cut, delete, paste method of learning also) that would help, I'd greatly appreciate it!

Thanks,
scmark15

9
I found this program awhile back and translated it into english. It's called YURI. It can search and view most TIM files within other files. It can also save them as BMP or TIFF files individually or all at once. Not sure if this is the kind of thing you were looking for though...
http://www.geocities.com/scmark15/yuri.html

*Modified*
Note: the version of the program I have is not one you can find on the net very easily. The version commonly found is 0.99c, and the version I have and translated is 0.99e.

I removed the program. If you'd like a copy just drop me an email: [email protected]

Pages: [1]