]> Chaos Git - console/RCOMage.git/commitdiff
Integrate an experimental GIM image conversion tool - it breaks on a lot, and everyth...
authorchaoskagami <chaos.kagami@gmail.com>
Fri, 17 Oct 2014 01:42:12 +0000 (21:42 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Fri, 17 Oct 2014 01:42:12 +0000 (21:42 -0400)
INSTALL
compile [new file with mode: 0755]
src/Makefile.am
src/gimtool.c [new file with mode: 0644]
src/gimtool.h [new file with mode: 0644]
src/main.c
src/rcodump.c
src/rcodump.h

diff --git a/INSTALL b/INSTALL
index 7d1c323beae76333f523f6df31c47a87f5597edb..2099840756e6302d837dcd51b5dcd6262f7adb16 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,8 +1,8 @@
 Installation Instructions
 *************************
 
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
+Inc.
 
    Copying and distribution of this file, with or without modification,
 are permitted in any medium without royalty provided the copyright
@@ -12,8 +12,8 @@ without warranty of any kind.
 Basic Installation
 ==================
 
-   Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package.  The following
+   Briefly, the shell command `./configure && make && make install'
+should configure, build, and install this package.  The following
 more-detailed instructions are generic; see the `README' file for
 instructions specific to this package.  Some packages provide this
 `INSTALL' file but do not implement all of the features documented
@@ -226,6 +226,11 @@ order to use an ANSI C compiler:
 
 and if that doesn't work, install pre-built binaries of GCC for HP-UX.
 
+   HP-UX `make' updates targets which have the same time stamps as
+their prerequisites, which makes it generally unusable when shipped
+generated files such as `configure' are involved.  Use GNU `make'
+instead.
+
    On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
 parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
 a workaround.  If GNU CC is not installed, it is therefore recommended
@@ -304,9 +309,10 @@ causes the specified `gcc' to be used as the C compiler (unless it is
 overridden in the site shell script).
 
 Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug.  Until the bug is fixed you can use this workaround:
+an Autoconf limitation.  Until the limitation is lifted, you can use
+this workaround:
 
-     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+     CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
 
 `configure' Invocation
 ======================
@@ -362,4 +368,3 @@ operates.
 
 `configure' also accepts some other, not widely useful, options.  Run
 `configure --help' for more details.
-
diff --git a/compile b/compile
new file mode 100755 (executable)
index 0000000..531136b
--- /dev/null
+++ b/compile
@@ -0,0 +1,347 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2012-10-14.11; # UTC
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" ""       $nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+  file=$1
+  case $file in
+    / | /[!/]*) # absolute file, and not a UNC file
+      if test -z "$file_conv"; then
+       # lazily determine how to convert abs files
+       case `uname -s` in
+         MINGW*)
+           file_conv=mingw
+           ;;
+         CYGWIN*)
+           file_conv=cygwin
+           ;;
+         *)
+           file_conv=wine
+           ;;
+       esac
+      fi
+      case $file_conv/,$2, in
+       *,$file_conv,*)
+         ;;
+       mingw/*)
+         file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+         ;;
+       cygwin/*)
+         file=`cygpath -m "$file" || echo "$file"`
+         ;;
+       wine/*)
+         file=`winepath -w "$file" || echo "$file"`
+         ;;
+      esac
+      ;;
+  esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+    if test -f "$dir/lib$lib.a"; then
+      found=yes
+      lib=$dir/lib$lib.a
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+  # Assume a capable shell
+  lib_path=
+  shared=:
+  linker_opts=
+  for arg
+  do
+    if test -n "$eat"; then
+      eat=
+    else
+      case $1 in
+       -o)
+         # configure might choose to run compile as 'compile cc -o foo foo.c'.
+         eat=1
+         case $2 in
+           *.o | *.[oO][bB][jJ])
+             func_file_conv "$2"
+             set x "$@" -Fo"$file"
+             shift
+             ;;
+           *)
+             func_file_conv "$2"
+             set x "$@" -Fe"$file"
+             shift
+             ;;
+         esac
+         ;;
+       -I)
+         eat=1
+         func_file_conv "$2" mingw
+         set x "$@" -I"$file"
+         shift
+         ;;
+       -I*)
+         func_file_conv "${1#-I}" mingw
+         set x "$@" -I"$file"
+         shift
+         ;;
+       -l)
+         eat=1
+         func_cl_dashl "$2"
+         set x "$@" "$lib"
+         shift
+         ;;
+       -l*)
+         func_cl_dashl "${1#-l}"
+         set x "$@" "$lib"
+         shift
+         ;;
+       -L)
+         eat=1
+         func_cl_dashL "$2"
+         ;;
+       -L*)
+         func_cl_dashL "${1#-L}"
+         ;;
+       -static)
+         shared=false
+         ;;
+       -Wl,*)
+         arg=${1#-Wl,}
+         save_ifs="$IFS"; IFS=','
+         for flag in $arg; do
+           IFS="$save_ifs"
+           linker_opts="$linker_opts $flag"
+         done
+         IFS="$save_ifs"
+         ;;
+       -Xlinker)
+         eat=1
+         linker_opts="$linker_opts $2"
+         ;;
+       -*)
+         set x "$@" "$1"
+         shift
+         ;;
+       *.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+         func_file_conv "$1"
+         set x "$@" -Tp"$file"
+         shift
+         ;;
+       *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+         func_file_conv "$1" mingw
+         set x "$@" "$file"
+         shift
+         ;;
+       *)
+         set x "$@" "$1"
+         shift
+         ;;
+      esac
+    fi
+    shift
+  done
+  if test -n "$linker_opts"; then
+    linker_opts="-link$linker_opts"
+  fi
+  exec "$@" $linker_opts
+  exit 1
+}
+
+eat=
+
+case $1 in
+  '')
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
+    func_cl_wrapper "$@"      # Doesn't return...
+    ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+       # configure might choose to run compile as 'compile cc -o foo foo.c'.
+       # So we strip '-o arg' only if arg is an object.
+       eat=1
+       case $2 in
+         *.o | *.obj)
+           ofile=$2
+           ;;
+         *)
+           set x "$@" -o "$2"
+           shift
+           ;;
+       esac
+       ;;
+      *.c)
+       cfile=$1
+       set x "$@" "$1"
+       shift
+       ;;
+      *)
+       set x "$@" "$1"
+       shift
+       ;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no '-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # '.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
index 0cc9d7f0a2853b6573eb3bcd5f369049d044274a..41f4ac4e1b4c5512ff2c525fd6111ece576bda00 100644 (file)
@@ -38,7 +38,9 @@ rcomage_SOURCES = \
                vsmx.c \
                vsmx.h \
                rlzpack.h \
-               strfuncs.h
+               strfuncs.h \
+               gimtool.c \
+               gimtool.h
 
 
 rcomage_LDADD = $(top_builddir)/7z/lib7z.la \
diff --git a/src/gimtool.c b/src/gimtool.c
new file mode 100644 (file)
index 0000000..11611e1
--- /dev/null
@@ -0,0 +1,477 @@
+//*                                                                 *//
+//* gimconv.c - Rough GIM <-> BMP converter. Not fully complete.    *//
+//* Converts GIM to BMP and viceversa, intended to be used within   *//
+//* the RCOmage fork I'm coding                                     *//
+
+//* Mostly based on the code in GIMSharp - useful, but C#-y. That's *//
+//* not a good thing, IMO. There's far too much support code for    *//
+//* data reads in C-ish ways, and using streams like fread          *//
+//*                                                                 *//
+
+//* Things being derpy at the moment - Argb8888. Why? IDK.          *//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "gimtool.h"
+
+char* unswizzle(char* data, int width, int height, int bpp) {
+       width = (width * bpp) >> 3;
+
+       char* dest = (char*)calloc(sizeof(char), width*height);
+
+       int rowblocks = (width / 16);
+
+       int dstoff = 0;
+
+       int x, y;
+
+       for (y = 0; y < height; y++)
+       {
+               for (x = 0; x < width; x++)
+               {
+                       int blockX = x / 16;
+                       int blockY = y / 8;
+
+                       int blockIndex = blockX + ((blockY) * rowblocks);
+                       int blockAddress = blockIndex * 16 * 8;
+
+                       dest[dstoff] = data[blockAddress + (x - blockX * 16) + ((y - blockY * 8) * 16)];
+                       dstoff++;
+               }
+       }
+
+       return dest;
+}
+
+void dump_bitmap(char* fname, char* data32bpp, int width, int height) {
+
+       // Bitmap info.
+       bitmapv4_header bmp_inh;
+
+       bmp_inh.bmpinfohead_size = sizeof(bitmapv4_header);
+       bmp_inh.width = width;
+       bmp_inh.height = height;
+       bmp_inh.color_planes = 1;
+       bmp_inh.bpp = 32;
+       bmp_inh.compression = 3;
+       bmp_inh.image_size = width*32*height;
+       bmp_inh.ppm_w = 0;
+       bmp_inh.ppm_h = 0;
+       bmp_inh.colors = 0;
+       bmp_inh.important_col = 0;
+       bmp_inh.redmask = 0x00ff0000;
+       bmp_inh.bluemask = 0x0000ff00;
+       bmp_inh.greenmask = 0x000000ff;
+       bmp_inh.alphamask = 0xff000000;
+       bmp_inh.colsptype = 0x206E6957;
+       bmp_inh.reserved0 = bmp_inh.reserved1 = bmp_inh.reserved2 = bmp_inh.reserved3 = bmp_inh.reserved4 = bmp_inh.reserved5 = bmp_inh.reserved6 = bmp_inh.reserved7 = bmp_inh.reserved8 = 0;
+       bmp_inh.gamma_r = 0;
+       bmp_inh.gamma_g = 0;
+       bmp_inh.gamma_b = 0;
+
+
+       // File header.
+       bitmap_header bmp_h;
+
+       bmp_h.magic1 = 'B';
+       bmp_h.magic2 = 'M';
+       bmp_h.reserved = 0;
+       bmp_h.offset = sizeof(bitmap_header) + sizeof(bitmapv4_header);
+       bmp_h.filesize = sizeof(bitmap_header) + sizeof(bitmapv4_header) + (width*height*4);
+
+       // Write shit out.
+       FILE* out = fopen(fname, "wb");
+       fwrite(&bmp_h, 1, sizeof(bitmap_header), out);
+       fwrite(&bmp_inh, 1, sizeof(bitmapv4_header), out);
+       fwrite(data32bpp, 1, (width*height*4), out);
+       fclose(out);
+}
+
+// Used for palletes too.
+char* decode_Rgb565(char* data, int width, int height) {
+       int size = (width * height);
+
+       char* output = (char*)calloc(sizeof(char), 4*size); // 32bpp so 4
+
+       // Cast data to a ushort pointer.
+       uint16_t* pointer = (uint16_t*)data;
+
+       int i;
+       for(i=0; i < size; i++) {
+               output[i*4 + 3] = 0xFF;
+               output[i*4 + 2] = (char)(((pointer[i] >> 0)  & 0x1F) * 0xFF / 0x1F);
+               output[i*4 + 1] = (char)(((pointer[i] >> 5)  & 0x3F) * 0xFF / 0x3F);
+               output[i*4 + 0] = (char)(((pointer[i] >> 11) & 0x1F) * 0xFF / 0x1F);
+       }
+
+       return output;
+}
+
+char* decode_Argb1555(char* data, int width, int height) {
+       int size = (width * height);
+
+       char* output = (char*)calloc(sizeof(char), 4*size); // 32bpp so 4
+
+       // Cast data to a ushort pointer.
+       uint16_t* pointer = (uint16_t*)data;
+       
+       int i;
+       for(i=0; i < size; i++) {
+               output[i*4 + 3] = (char)(((pointer[i] >> 15) & 0x01) * 0xFF);
+               output[i*4 + 2] = (char)(((pointer[i] >> 0)  & 0x1F) * 0xFF / 0x1F);
+               output[i*4 + 1] = (char)(((pointer[i] >> 5)  & 0x1F) * 0xFF / 0x1F);
+               output[i*4 + 0] = (char)(((pointer[i] >> 10) & 0x1F) * 0xFF / 0x1F);
+       }
+
+       return output;
+}
+
+char* decode_Argb4444(char* data, int width, int height) {
+       int size = (width * height);
+
+       char* output = (char*)calloc(sizeof(char), 4*size); // 32bpp so 4
+
+       // Cast data to a ushort pointer.
+       uint16_t* pointer = (uint16_t*)data;
+
+       int i;
+       for(i=0; i < size; i++) {
+               output[i*4 + 3] = (char)(((pointer[i] >> 12) & 0x0F) * 0xFF / 0x0F);
+               output[i*4 + 2] = (char)(((pointer[i] >> 0)  & 0x0F) * 0xFF / 0x0F);
+               output[i*4 + 1] = (char)(((pointer[i] >> 4)  & 0x0F) * 0xFF / 0x0F);
+               output[i*4 + 0] = (char)(((pointer[i] >> 8)  & 0x0F) * 0xFF / 0x0F);
+       }
+
+       return output;
+}
+
+char* decode_Argb8888(char* data, int width, int height) {
+       int size = (width * height);
+
+       char* output = (char*)calloc(sizeof(char), 4*size); // 32bpp so 4
+
+       // Cast data to a ushort pointer.
+       uint32_t* pointer = (uint32_t*)data;
+       uint32_t* out = (uint32_t*)output;
+
+       int i;
+       for(i=0; i < size; i++) {
+               out[i] = pointer[i];
+       }
+
+       return output;
+}
+
+char* decode_Index4(char* data, char* palette, int width, int height) {
+       int size = (width * height);
+
+       char* output = (char*)calloc(sizeof(char), 4*size); // 32bpp so 4
+
+       uint32_t* out = (uint32_t*)output;
+       uint32_t* pal = (uint32_t*)palette;
+
+       int i;
+       for(i=0; i < size; i += 2) {
+               int px1  = data[i / 2] & 0xF;
+               int px2  = data[i / 2] >> 4 & 0xF;
+               out[i]   = pal[px1];
+               out[i+1] = pal[px2];
+       }
+
+       return output;
+}
+
+char* decode_Index8(char* data, char* palette, int width, int height) {
+       int size = (width * height);
+
+       char* output = (char*)calloc(sizeof(char), 4*size); // 32bpp so 4
+
+       uint32_t* out = (uint32_t*)output;
+       uint32_t* pal = (uint32_t*)palette;
+
+       int i;
+       for(i=0; i < size; i++) {
+               out[i] = pal[data[i]];
+       }
+
+       return output;
+}
+
+OutData* ReadData(char* data, int length) {
+
+       // Data Used Here
+       int32_t offset = 0x10;
+       int32_t prevOffset = offset;
+       int32_t textureOffset = 0;
+       int32_t palleteOffset = 0;
+       uint16_t width = 0, height = 0;
+       char datFmt = Unknown;
+       char palFmt = Unknown;
+       uint16_t pal_ents = 0;
+       int32_t eofOffset = 0;
+       int32_t hasMeta = 0;
+       int32_t swizzled = 0;
+
+       // Read all the meta blocks.
+       while (offset < length) {
+
+               // EOF Block
+               if (data[offset] == 0x02) {
+                       eofOffset = ((int32_t*)(&data[offset+0x04]))[0] + 16;
+
+                       //fprintf(stderr, "[%x] eofOffset: %x\n", offset, eofOffset);
+
+                       offset +=   ((int32_t*)(&data[offset+0x08]))[0];
+               }
+
+               // Metadata Chunk
+               else if (data[offset] == 0x03) {
+                       // We actually skip this.
+                       offset +=   ((int32_t*)(&data[offset+0x08]))[0];
+               }
+
+               // Texture Data Chunk
+               else if (data[offset] == 0x04) {
+                       datFmt = (char)data[offset + 0x14];
+
+                       swizzled = ((uint16_t*)(&data[offset+0x16]))[0];
+
+                       width  = ((uint16_t*)(&data[offset+0x18]))[0];
+                       height = ((uint16_t*)(&data[offset+0x1A]))[0];
+
+                       if (width % 16 != 0) {
+                               width += (16 - (width % 16));
+                       }
+                       if (height % 8 != 0) {
+                               height += (8 - (height % 8));
+                       }
+
+
+                       textureOffset = offset + 0x50;
+
+                       //fprintf(stderr, "[%x] texture: f:%u w:%i h:%i swz:%i off:%x\n", offset, datFmt, width, height, swizzled, textureOffset);
+
+                       offset +=   ((int32_t*)(&data[offset+0x08]))[0];
+
+               }
+
+               // Pallete Chunk
+               else if (data[offset] == 0x05) {
+                       palFmt = (char)data[offset + 0x14];
+
+                       pal_ents = ((uint16_t*)(&data[offset+0x18]))[0];
+
+                       palleteOffset = offset + 0x50;
+
+                       //fprintf(stderr, "[%x] pallete: f:%u ent:%u off:%x\n", offset, palFmt, pal_ents, palleteOffset);
+
+                       offset +=   ((int32_t*)(&data[offset+0x08]))[0];
+
+               }
+
+               // Metadata Chunk
+               else if (data[offset] == 0xff) {
+                       hasMeta = 1;
+                       size_t metaOff = 0x10;
+
+                       // Seek to end of string for each piece of data
+                       int i=0;
+
+                       while(data[offset+metaOff+i]) {
+                               if(data[offset+metaOff+i] == 0)
+                                       break;
+                               i++;
+                       }
+                       metaOff += i + 1; i = 0;
+
+                       while(data[offset+metaOff+i]) {
+                               if(data[offset+metaOff+i] == 0)
+                                       break;
+                               i++;
+                       }
+                       metaOff += i + 1; i = 0;
+
+                       while(data[offset+metaOff+i]) {
+                               if(data[offset+metaOff+i] == 0)
+                                       break;
+                               i++;
+                       }
+                       metaOff += i + 1; i = 0;
+
+                       while(data[offset+metaOff+i]) {
+                               if(data[offset+metaOff+i] == 0)
+                                       break;
+                               i++;
+                       }
+                       metaOff += i + 1; i = 0;
+
+                       //fprintf(stderr, "[%x] Meta\n", offset);
+
+                       offset +=   ((int32_t*)(&data[offset+0x08]))[0];
+               }
+
+               // Invalid Chunk
+               else {
+                       fprintf(stderr, "Sanity test: Chunk type failed.\n");
+                       //fprintf(stderr, "Type: %u\n", data[offset]);
+                       return NULL;
+               }
+
+               // Make sure chunks aren't moving us backwards.
+               if ((int)offset <= (int)prevOffset) {
+                       fprintf(stderr, "Sanity test: forwards offset failed.\n");
+                       //fprintf(stderr, "Off:%x Fwd:%x\n", offset, prevOffset);
+                       return NULL;
+               }
+               prevOffset = offset;
+       }
+
+       // Sanity test
+       if (offset != eofOffset) {
+               fprintf(stderr, "Sanity test: Offset != eof failed.\n");
+               //printf("Off: %u EOF: %u\n", offset, eofOffset);
+               return NULL;
+       }
+
+       char* texture_data = &data[textureOffset];
+
+       if(swizzled) {
+               switch (datFmt) {
+                       case Rgb565:
+                       case Argb1555:
+                       case Argb4444:
+                               texture_data = unswizzle(texture_data, width, height, 16);
+                               break;
+                       case Argb8888:
+                               texture_data = unswizzle(texture_data, width, height, 32);
+                               break;
+                       case Index4:
+                               texture_data = unswizzle(texture_data, width, height, 4);
+                               break;
+                       case Index8:
+                               texture_data = unswizzle(texture_data, width, height, 8);
+                               break; 
+               }
+       }
+
+       char* newData = NULL;
+
+       char* palData = NULL;
+
+       if(datFmt == Index8) {
+               // Extract pallete
+               switch (palFmt) {
+                       case Rgb565:
+                               palData = decode_Rgb565( &data[palleteOffset],  256, 1);
+                               break;
+                       case Argb1555:
+                               palData = decode_Argb1555(&data[palleteOffset], 256, 1);
+                               break;
+                       case Argb4444:
+                               palData = decode_Argb4444(&data[palleteOffset], 256, 1);
+                               break;
+                       case Argb8888:
+                               palData = decode_Argb8888(&data[palleteOffset], 256, 1);
+                               break;
+               }
+       }
+
+       if(datFmt == Index4) {
+               // Extract pallete
+               switch (palFmt) {
+                       case Rgb565:
+                               palData = decode_Rgb565(&data[palleteOffset],   16, 1);
+                               break;
+                       case Argb1555:
+                               palData = decode_Argb1555(&data[palleteOffset], 16, 1);
+                               break;
+                       case Argb4444:
+                               palData = decode_Argb4444(&data[palleteOffset], 16, 1);
+                               break;
+                       case Argb8888:
+                               palData = decode_Argb8888(&data[palleteOffset], 16, 1);
+                               break;
+               }
+       }
+
+       switch (datFmt) {
+               case Rgb565:
+                       newData = decode_Rgb565(texture_data, width, height);
+                       break;
+               case Argb1555:
+                       newData = decode_Argb1555(texture_data, width, height);
+                       break;
+               case Argb4444:
+                       newData = decode_Argb4444(texture_data, width, height);
+                       break;
+               case Argb8888:
+                       newData = decode_Argb8888(texture_data, width, height);                 
+                       break;
+               case Index4:
+                       newData = decode_Index4(texture_data, palData, width, height);                  
+                       break;
+               case Index8:
+                       newData = decode_Index8(texture_data, palData, width, height);
+                       break;
+               case Unknown:
+                       // Invalid format.
+                       return NULL;
+       }
+
+       OutData* out = (OutData*)calloc(sizeof(OutData), 1);
+
+       out->data = newData;
+       out->width = width;
+       out->height = height;
+
+       return out;
+}
+
+uint8_t GIMExport(char* data, size_t len, char* file_out) {
+       // Convert to a more rational format.
+       OutData* data_converted = ReadData(data, len);
+
+       if(data_converted == NULL) {
+               //fprintf(stderr, "GIM data has issues - dying.\n");
+               return -1;
+       }
+
+       // Export to bitmap.
+       dump_bitmap(file_out, data_converted->data, data_converted->width, data_converted->height);
+
+       return 0;
+}
+
+
+uint8_t GIMToBMP(char* file_in, char* file_out) {
+       FILE* input = fopen(file_in, "rb");
+       
+       // Get length.
+       fseek(input, 0, SEEK_END);
+       size_t size = ftell(input);
+       fseek(input, 0, SEEK_SET);
+
+       // Read in RAW data.
+       char* input_data = (char*)calloc(sizeof(char), size);
+       fread(input_data, 1, size, input);
+       
+       return GIMExport(input_data, size, file_out);
+}
+
+#ifdef STANDALONE_GIMTOOL
+
+int main(int argc, char** argv) {
+       if(argc < 3) {
+               printf("Usage: %s GIM BMP\n", argv[0]);
+               return 1;
+       }
+       else {
+               GIMToBMP(argv[1], argv[2]);
+               return 0;
+       }
+}
+
+#endif
diff --git a/src/gimtool.h b/src/gimtool.h
new file mode 100644 (file)
index 0000000..0c1437c
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __GIMTOOL_H__
+#define __GIMTOOL_H__
+
+#define Rgb565    0x00
+#define Argb1555  0x01
+#define Argb4444  0x02
+#define Argb8888  0x03
+#define Index4    0x04
+#define Index8    0x05
+#define Unknown   0xFF
+
+typedef struct __attribute__((packed)) {
+       char magic1;
+       char magic2;
+       uint32_t filesize;
+       uint32_t reserved;
+       uint32_t offset;
+} bitmap_header;
+
+typedef struct __attribute__((packed)) {
+       uint32_t bmpinfohead_size;      // Should be 40.
+       int32_t width;
+       int32_t height;
+       uint16_t color_planes;          // Should be 1.
+       uint16_t bpp;                           // For our purposes, 32bpp
+       uint32_t compression;           // Compression Method
+       uint32_t image_size;            // RAW image size, e.g. w*h*bpp
+       int32_t ppm_w;                          // PPM width
+       int32_t ppm_h;                          // PPM height
+       uint32_t colors;                        // Pallete colors - 0 for 2^n
+       uint32_t important_col;         // Important colors. Set to 0.
+       uint32_t redmask;                       // 44
+       uint32_t greenmask;                     // 48
+       uint32_t bluemask;                      // 52
+       uint32_t alphamask;                     // 56
+       uint32_t colsptype;                     // 60
+       uint32_t reserved0;                     // 64
+       uint32_t reserved1;                     // 68
+       uint32_t reserved2;                     // 72
+       uint32_t reserved3;                     // 76
+       uint32_t reserved4;                     // 80
+       uint32_t reserved5;                     // 84
+       uint32_t reserved6;                     // 88
+       uint32_t reserved7;                     // 92
+       uint32_t reserved8;                     // 96
+       uint32_t gamma_r;
+       uint32_t gamma_g;       
+       uint32_t gamma_b;
+} bitmapv4_header;
+
+typedef struct {
+       int width;
+       int height;
+       char* data;
+} OutData;
+
+char* unswizzle(char* data, int width, int height, int bpp);
+void dump_bitmap(char* fname, char* data32bpp, int width, int height);
+
+char* decode_Rgb565(char* data, int width, int height);
+char* decode_Argb1555(char* data, int width, int height);
+char* decode_Argb4444(char* data, int width, int height);
+char* decode_Argb8888(char* data, int width, int height);
+char* decode_Index4(char* data, char* palette, int width, int height);
+char* decode_Index8(char* data, char* palette, int width, int height);
+
+OutData* ReadData(char* data, int length);
+uint8_t GIMExport(char* data, size_t len, char* file_out);
+uint8_t GIMToBMP(char* file_in, char* file_out);
+
+#endif
index 15f2f0ec9a28edd2530a3f2a0b240b3bbcbb9d54..4ae9bb442749a88ca4d77f4bc7336cd090ce20f2 100644 (file)
@@ -183,6 +183,8 @@ main_help ()
          "                   gimconv command to execute; defaults to 'gimconv'.\n"
          "    --gimconv-flags <flags>\n"
          "                   Additional flags to pass to gimconv.\n"
+         "    --gimtool-exp  (EXPERIMENTAL) Use a new internal GIM->BMP converter\n"
+         "                   As fair warning, it currently has issues with some GIMs.\n"
          "    --conv-vag     Convert VAG files to WAV.\n"
          "    --decode-vsmx  Decode VSMX/JSX files to textual format.\n"
          "    --no-decomp-warn\n"
@@ -379,6 +381,7 @@ main_dump (void)
   RcoDumpGimconvOpts gimconvOpts;
   uint8_t sConvVag = FALSE;
   uint8_t sConvVsmx = FALSE;
+  uint8_t sGimtoolExp = FALSE;
 
   int i;
 
@@ -387,6 +390,7 @@ main_dump (void)
   retrieve_from_opts (TRUE, 13, "--output-txt", "bool", &sTextOutput,
       "--conv-gim", "text", &gimconvOpts.ext, "--gimconv-cmd", "text",
       &gimconvOpts.cmd, "--gimconv-flags", "text", &gimconvOpts.extFlags,
+      "--gimtool-exp", "bool", &sGimtoolExp,
       "--conv-vag", "bool", &sConvVag, "--decode-vsmx", "bool", &sConvVsmx,
       "--resdir", "text", &sResDir, "--images", "text", &sResImgDir, "--sounds",
       "text", &sResSndDir, "--models", "text", &sResMdlDir, "--vsmx", "text",
@@ -396,7 +400,7 @@ main_dump (void)
 #ifndef WIN32
   if (gimconvOpts.ext) {
     warning
-       ("gimconv support is only available on Windows, as stuff only gets compiled for that platform and Sony doesn't give away source code (duh).");
+       ("gimconv support is only available on Windows, as hackers and sony don't seem to like linux tools. Try --gimtool-exp, which isn't complete and chokes on a lot of GIM files. It's better than nothing, right? ;P");
     gimconvOpts.ext = NULL;
   }
 #endif
@@ -452,18 +456,18 @@ main_dump (void)
        if (!gimconvOpts.ext)
          arg = NULL;
        dump_resources (rco->labels, rco->tblImage, RCOXML_TABLE_IMG_FMT,
-           pathPrefix, arg);
+           pathPrefix, arg, sGimtoolExp);
       }
       if (!sResSndDir || strcmp (sResSndDir, "-")) {
        RCO_PRINT_PATH (pathPrefix, sResSndDir);
        dump_resources (rco->labels, rco->tblSound, RCOXML_TABLE_SOUND_FMT,
-           pathPrefix, (void *) sConvVag);
+           pathPrefix, (void *) sConvVag, NULL);
        sndDumped = TRUE;
       }
       if (!sResMdlDir || strcmp (sResMdlDir, "-")) {
        RCO_PRINT_PATH (pathPrefix, sResMdlDir);
        dump_resources (rco->labels, rco->tblModel, RCOXML_TABLE_MODEL_FMT,
-           pathPrefix, NULL);
+           pathPrefix, NULL, NULL);
       }
 
       if (!sResTxtDir || strcmp (sResTxtDir, "-")) {
index bfb620f5f8d963f1001d8456ce96fe4110fc1a8d..8ffc1a147b2c39be6a462212562ec6fd10c39bab 100644 (file)
@@ -28,6 +28,7 @@
 #include "rcomain.h"
 #include "xml.h"
 #include "strfuncs.h"
+#include "gimtool.h"
 
 #include "rcodump.h"
 #include "vaghandler.h"
@@ -197,6 +198,109 @@ dump_output_gimconv (char *dest, void *buf, rRCOEntry * entry, void *arg)
 #endif
 }
 
+uint8_t
+dump_output_gimtool_exp (char *dest, void *buf, rRCOEntry *entry, void* arg)
+{
+  char tmpName[255];
+  static uint32_t successes = 0, failures = 0;
+  uint8_t ret;
+
+  if (failures <= 5 || successes > 0) {
+
+    get_temp_fname (tmpName, "gim");
+
+    FILE *fp = fopen (tmpName, "wb");
+
+    if (!fp)
+      return FALSE;
+
+    // try to apply gim patch
+    if (entry->srcLenUnpacked > 0x28) {
+      // dirty code - we'll leave here, since the internal converter will have
+      // nicer code :P
+      uint32_t *i32;
+      uint8_t es = FALSE;
+
+      i32 = (uint32_t *) buf;
+      if (*i32 == 0x4D49472E)
+       es = TRUE;              // .GIM
+
+      if (*i32 == 0x2E47494D || *i32 == 0x4D49472E) {
+       uint16_t i, i2;
+
+       i = *(uint16_t *) ((char *) buf + 0x10);
+       i2 = *(uint16_t *) ((char *) buf + 0x20);
+       if (es) {
+         i = ENDIAN_SWAP (i);
+         i2 = ENDIAN_SWAP (i2);
+       }
+       if (i == 2 && i2 == 3) {
+         uint32_t sz = *(uint32_t *) ((char *) buf + 0x14), sz2;
+
+         i32 = (uint32_t *) ((char *) buf + 0x24);
+         sz2 = *i32;
+         if (es) {
+           sz = ENDIAN_SWAP (sz);
+           sz2 = ENDIAN_SWAP (sz2);
+         }
+         if (sz - 0x10 != sz2) {
+           info ("Note: Applied GIM patch when using Gimtool-exp to dump '%s'.",
+               dest);
+           sz2 = sz - 0x10;
+           if (es)
+             sz2 = ENDIAN_SWAP (sz2);
+           *i32 = sz2;
+         }
+       }
+      }
+    }
+
+    filewrite (fp, buf, entry->srcLenUnpacked);
+    fclose (fp);
+
+       int tmppos;
+       for(tmppos=0; tmppos < strlen(dest); tmppos++) {
+               if(dest[tmppos] == '.' && (strlen(dest) - tmppos) > 3 && dest[tmppos+1] == 'g' && dest[tmppos+2] == 'i' && dest[tmppos+3] == 'm') {
+                       dest[tmppos+1] = 'b';
+                       dest[tmppos+2] = 'm';
+                       dest[tmppos+3] = 'p';
+
+                       break;
+               }
+       }
+
+    ret = ! GIMToBMP(tmpName, dest);
+
+    remove (tmpName);
+
+    if (!ret) {
+      warning
+         ("gimtool-exp failed to process GIM.  Resource being dumped as GIM instead.");
+      failures++;
+      if (failures > 5 && successes == 0) {
+       warning
+           ("Gimtool-exp failed too many times without success - disabling Gimtool-exp (GIMs will not be converted).");
+      }
+    }
+  } else
+    ret = FALSE;
+
+  if (!ret) {
+    char tmpDest[260];
+
+    strcpy (tmpDest, dest);
+    char *dot = strrchr (tmpDest, '.');
+
+    if (!dot)
+      dot = tmpDest + strlen (tmpDest);
+    strcpy (dot, ".gim");
+
+    return dump_output_data (tmpDest, buf, entry, NULL);
+  } else
+    successes++;
+  return ret;
+}
+
 uint8_t
 dump_output_vsmxdec (char *dest, void *buf, rRCOEntry * entry, void *arg)
 {
@@ -220,7 +324,7 @@ dump_output_vsmxdec (char *dest, void *buf, rRCOEntry * entry, void *arg)
 
 void
 dump_resources (char *labels, rRCOEntry * parent, const RcoTableMap extMap,
-    char *pathPrefix, void *outputFilterArg)
+    char *pathPrefix, void *outputFilterArg, int optional)
 {
   // TODO: remove text crap from this function
   if (!parent || !parent->numSubentries)
@@ -278,9 +382,13 @@ dump_resources (char *labels, rRCOEntry * parent, const RcoTableMap extMap,
        of = dump_output_wav;
       else if (entry->id == RCO_TABLE_IMG &&
          ((rRCOImgModelEntry *) entry->extra)->format == RCO_IMG_GIM)
-       of = dump_output_gimconv;
+      of = dump_output_gimconv;
     }
 
+       if (optional == 1 && entry->id == RCO_TABLE_IMG &&
+         ((rRCOImgModelEntry *) entry->extra)->format == RCO_IMG_GIM)
+      of = dump_output_gimtool_exp;
+
     info ("Dumping resource '%s'...", label);
 
     if (entry->id == RCO_TABLE_SOUND && !outputFilterArg) {
index e387ee947bcd527025e68b06789f094c4569a588..3346184a9e9a817f044745b9402625e6f5b06ef7 100644 (file)
@@ -21,7 +21,7 @@ typedef struct {
 uint8_t dump_resource (char *dest, rRCOEntry * entry, OutputDumpFunc outputfunc,
     void *outputfuncArg);
 void dump_resources (char *labels, rRCOEntry * parent, const RcoTableMap extMap,
-    char *pathPrefix, void *outputFilterArg);
+    char *pathPrefix, void *outputFilterArg, int optional);
 void dump_text_resources (char *labels, rRCOEntry * parent, uint8_t writeHeader,
     char *pathPrefix, uint8_t bWriteXML);
 uint8_t dump_output_data (char *dest, void *buf, rRCOEntry * entry, void *arg);