diff --git a/.gitattributes b/.gitattributes
index 3d66b4bc0880f0df4f802b214bfd87366bc8d08e..1ccfedf40087b51be9b6bff13d7699e1e996b316 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -245,6 +245,7 @@ testfont binary
 /src/modules/Image/encodings/pvr.c foreign_ident
 /src/modules/Image/encodings/ras.c foreign_ident
 /src/modules/Image/encodings/tga.c foreign_ident
+/src/modules/Image/encodings/tim.c foreign_ident
 /src/modules/Image/encodings/wbf.c foreign_ident
 /src/modules/Image/encodings/x.c foreign_ident
 /src/modules/Image/encodings/xbm.c foreign_ident
diff --git a/src/modules/Image/encodings/Makefile.in b/src/modules/Image/encodings/Makefile.in
index 37708d200994c86affd05c4da64916830755c3ae..37737a38c4d4b103f32db2a6712ea6de72cd69b3 100644
--- a/src/modules/Image/encodings/Makefile.in
+++ b/src/modules/Image/encodings/Makefile.in
@@ -1,7 +1,7 @@
-# $Id: Makefile.in,v 1.30 2000/02/24 01:11:22 marcus Exp $
+# $Id: Makefile.in,v 1.31 2000/03/21 06:13:23 peter Exp $
 SRCDIR=@srcdir@
 VPATH=@srcdir@:@srcdir@/../../..:../../..
-OBJS = gif.o gif_lzw.o pnm.o x.o xwd.o png.o any.o bmp.o tga.o pcx.o xbm.o _xpm.o ilbm.o iff.o xcf.o hrz.o avs.o psd.o gd.o wbf.o ras.o pvr.o
+OBJS = gif.o gif_lzw.o pnm.o x.o xwd.o png.o any.o bmp.o tga.o pcx.o xbm.o _xpm.o ilbm.o iff.o xcf.o hrz.o avs.o psd.o gd.o wbf.o ras.o pvr.o tim.o
 
 @SET_MAKE@
 
diff --git a/src/modules/Image/encodings/tim.c b/src/modules/Image/encodings/tim.c
new file mode 100644
index 0000000000000000000000000000000000000000..fada58f2ca0b6f009816a1e3fee9eafff1eba16c
--- /dev/null
+++ b/src/modules/Image/encodings/tim.c
@@ -0,0 +1,241 @@
+#include "global.h"
+#include "image_machine.h"
+#include <math.h>
+#include <ctype.h>
+
+#include "stralloc.h"
+RCSID("$Id: tim.c,v 1.1 2000/03/21 06:13:23 peter Exp $");
+#include "pike_macros.h"
+#include "object.h"
+#include "constants.h"
+#include "interpret.h"
+#include "svalue.h"
+#include "threads.h"
+#include "array.h"
+#include "mapping.h"
+#include "error.h"
+#include "operators.h"
+#include "stralloc.h"
+#include "builtin_functions.h"
+#include "module_support.h"
+
+
+#include "image.h"
+
+extern struct program *image_program;
+
+/*
+**! module Image
+**! submodule TIM
+**!
+**! 	Handle decoding of TIM images.
+**! 
+**! 	TIM is the framebuffer format of the PSX game system.
+**! 	It is a simple, uncompressed, truecolor or CLUT format. 
+*/
+
+//FIXME: Add to ANY.
+//FIXME: header_only doesn't get the width and height.
+
+/*
+**! method object decode(string data)
+**! method object decode_alpha(string data)
+**! method mapping decode_header(string data)
+**! method mapping _decode(string data)
+**!	decodes a TIM image
+**!
+**!	The <ref>decode_header</ref> and <ref>_decode</ref>
+**!	has these elements:
+**!
+**!	<pre>
+**!        "image":object            - image object    \- not decode_header
+**!	   "alpha":object            - decoded alpha   /
+**!	   
+**!	   "type":"image/x-tim"      - image type
+**!	   "xsize":int               - horisontal size in pixels
+**!	   "ysize":int               - vertical size in pixels
+**!	   "attr":int		     - texture attributes
+**!	</pre>
+*/
+
+#define MODE_CLUT4              0
+#define MODE_CLUT8              1
+#define MODE_DC15               2
+#define MODE_DC24               3
+#define MODE_MIXED              4
+#define FLAG_CLUT               8
+
+static void tim_decode_rect(INT32 attr, unsigned char *src, rgb_group *dst,
+			    INT32 stride, unsigned int h, unsigned int w)
+{
+  INT32 cnt = h * w;
+  switch(attr&7) {
+   case MODE_DC15:
+     while(cnt--) {
+       unsigned int p = src[0]|(src[1]<<8);
+       dst->b = ((p&0x7c00)>>7)|((p&0x7000)>>12);
+       dst->g = ((p&0x03e0)>>2)|((p&0x0380)>>7);
+       dst->r = ((p&0x001f)<<3)|((p&0x001c)>>2);
+       src+=2;
+       dst++;
+     }
+     break;
+  }
+}
+
+static void pvr_decode_alpha_rect(INT32 attr, unsigned char *src,
+				  rgb_group *dst, INT32 stride,
+				  unsigned int h, unsigned int w)
+{
+  INT32 cnt = h * w;
+  switch(attr&7) {
+   case MODE_DC15:
+     while(cnt--) {
+       if(src[1]&0x80)
+	 dst->b = dst->g = dst->r = ~0;
+       else
+	 dst->b = dst->g = dst->r = 0;
+       src+=2;
+       dst++;
+     }
+     break;
+  }
+}
+
+void img_tim_decode(INT32 args, int header_only)
+{
+   struct pike_string *str;
+   unsigned char *s;
+   int n = 0;
+   INT32 len, attr;
+   unsigned int h, w, x;
+
+   get_all_args("Image.TIM._decode", args, "%S", &str);
+   s=(unsigned char *)str->str;
+   len=str->len;
+   pop_n_elems(args-1);
+
+   if(len < 12 || (s[0] != 0x10 || s[2] != 0 || s[3] != 0))
+     error("not a TIM texture\n");
+   else if(s[2] != 0)
+     error("unknown version of TIM texture\n");     
+
+   push_text("type");
+   push_text("image/x-tim");
+   n++;
+
+   attr = s[4]|(s[5]<<8)|(s[6]<<16)|(s[7]<<24);
+
+   push_text("attr");
+   push_int(attr);
+   n++;
+
+   if(!header_only) {
+     int hasalpha=0, bpp=0;
+     struct object *o;
+     struct image *img;
+     INT32 clut=0;
+
+     if(attr&FLAG_CLUT)
+       error("TIM with CLUT not supported\n");
+
+     /* note: The size part of the CLUT is still present, so it will
+      * take one word. */
+
+     switch(attr&7) {
+      case MODE_DC15:
+	//dx and dy word ignored
+	w = s[16]|(s[17]<<8);
+	h = s[18]|(s[19]<<8);
+	bpp = 2;
+	hasalpha = 1;
+	break;
+      case MODE_DC24:
+	error("24bit TIMs not supported\n");
+      case MODE_CLUT4:
+      case MODE_CLUT8:
+   	error("palette TIMs not supported\n");
+      case MODE_MIXED:
+   	error("mixed TIMs not supported\n");
+      default:
+	error("unknown TIM format\n");
+     }
+
+     s += 20;
+     len -= 20;
+
+     push_text("xsize");
+     push_int(w);
+     n++;   
+     push_text("ysize");
+     push_int(h);
+     n++;   
+     printf("w: %d, h: %d\n", w, h);
+
+     if(len < (INT32)(bpp*(h*w)))
+       error("short pixel data\n");
+
+     push_text("image");
+     push_int(w);
+     push_int(h);
+     o=clone_object(image_program,2);
+     img=(struct image*)get_storage(o,image_program);
+     push_object(o);
+     n++;
+     
+     tim_decode_rect(attr, s, img->img, 0, h, w);
+
+     if(hasalpha) {
+       push_text("alpha");
+       push_int(w);
+       push_int(h);
+       o=clone_object(image_program,2);
+       img=(struct image*)get_storage(o,image_program);
+       push_object(o);
+       n++;
+       
+       pvr_decode_alpha_rect(attr, s, img->img, 0, h, w);
+     }
+   }
+
+   f_aggregate_mapping(2*n);
+
+   stack_swap();
+   pop_stack();
+}
+
+static void image_tim_f_decode(INT32 args)
+{
+   img_tim_decode(args,0);
+   push_string(make_shared_string("image"));
+   f_index(2);
+}
+
+static void image_tim_f_decode_alpha(INT32 args)
+{
+   img_tim_decode(args,0);
+   push_string(make_shared_string("alpha"));
+   f_index(2);
+}
+
+void image_tim_f_decode_header(INT32 args)
+{
+   img_tim_decode(args,1);
+}
+
+void image_tim_f__decode(INT32 args)
+{
+   img_tim_decode(args,0);
+}
+
+void init_image_tim()
+{
+  ADD_FUNCTION( "decode",  image_tim_f_decode,  tFunc(tStr,tObj), 0);
+  ADD_FUNCTION( "decode_alpha",  image_tim_f_decode_alpha,  tFunc(tStr,tObj), 0);
+  ADD_FUNCTION( "_decode", image_tim_f__decode, tFunc(tStr,tMapping), 0);
+  ADD_FUNCTION( "decode_header", image_tim_f_decode_header, tFunc(tStr,tMapping), 0);
+}
+
+void exit_image_tim()
+{
+}
diff --git a/src/modules/Image/initstuff.h b/src/modules/Image/initstuff.h
index 52883bb964db7343d6d7e6ee663ac2ef777a0b39..6379305073b55325b3255adb0102019fc09720d4 100644
--- a/src/modules/Image/initstuff.h
+++ b/src/modules/Image/initstuff.h
@@ -35,6 +35,7 @@ IMAGE_SUBMODULE("_PSD",  init_image_psd,  exit_image_psd  )
 IMAGE_SUBMODULE("PVR",   init_image_pvr,  exit_image_pvr  )
 IMAGE_SUBMODULE("RAS",   init_image_ras,  exit_image_ras  ) 
 IMAGE_SUBMODULE("TGA",   init_image_tga,  exit_image_tga  ) 
+IMAGE_SUBMODULE("TIM",   init_image_tim,  exit_image_tim  )
 IMAGE_SUBMODULE("X",     init_image_x,    exit_image_x    ) 
 IMAGE_SUBMODULE("XBM",   init_image_xbm,  exit_image_xbm  ) 
 IMAGE_SUBMODULE("_XCF",  init_image_xcf,  exit_image_xcf  )