uses Crt, Graph,Strings;

type
  sprite_array =  array [0..2000] of pointer;
var
  Gd, Gm: Integer;

  sprites: sprite_array;
  blocksize:array [0..2000] of longint;

{
Generic sprite conversion utility

This version uses the BGI to load a sprite file, and convert it into
640x350x16 mode.  Note that you cannot create sprites with more than
16 colors and expect it to look right after converting it.  To do this
correctly, draw using the first 16 colors only.  If you modify the
palette, you will need to chnage it yourself using the first 16 colors
in the palette variable.

This program can be used as a generic conversion program.   Simply replace
the BGI graphics commands with any similar commands from another graphics
library.

The main commands you will need to change are:
    initialization routines
    putpixel
    imagesize   (calculates the number of bytes required in an image)
    farmalloc   (WGT calculates the size and allocates the memory for you,
		other libraries may not.   You will have to be flexible
		here.)
    getimage
    putimage
    getpalette
    setrgbpalette
    cleardevice
    bar


 Note that the Pascal version is much slower than the C version since
 I used blockread.
 }

 function FileExists(FileName: String): Boolean;
{ Boolean function that returns True if the file exists;otherwise,
   it returns False. Closes the file if it exists. }
var
  F: File;
begin
  {$I-}
  Assign(F, FileName);
  Reset(F);
  Close(F);
  {$I+}
  FileExists := (IOResult = 0) and (FileName <> '');
 end;  { FileExists }

procedure convertsprites(infilename,outfilename:string);
var
filein:Text; { 256 color sprite file }
fileout:File; { converted sprite file }
palette:array [1..768] of char; { 256 * 3 (RGB values) }
size: longint;
maxcolor,maxsprite:integer;
temp:pointer;
a,b,i,j,spritemade:integer;
buf: array [1..13] of char;  { Used for header }
x,y:integer; { Screen location }
col:char;  { Pixel color }
c1,c2:char;
result:integer;
startingsprite:integer;

begin


    { Open the files }
if FileExists(infilename) then
   begin
    Assign(filein,infilename);
    Reset(filein);
    Assign(fileout,outfilename);
    Rewrite(fileout,1);

    Read(filein,c1);
    Read(filein,c2);
    a:=256*ord(c2)+ord(c1);
     { Get the version number, and change the startingsprite accordingly.
     If version <= 3, maxsprite contains the maximum number of sprites
     that can be stored in a file.  If version > 4, maxsprite contains
     the number of the highest sprite in the file. (empty sprites at
     the end are not kept in the file. }
    if (a <= 3) then
      startingsprite := 1
    else startingsprite := 0;    { Version 4 starts at sprite 0 }

    for i:=1 to 13 do
    read(filein,buf[i]); { sprite header }

    if (buf=' Sprite File ') then { see if it is a sprite file }
       begin
        for i:=1 to 768 do
         read(filein,palette[i]); { Read in 256 color palette }
	maxcolor:=getmaxcolor+1;
	blockwrite(fileout,maxcolor,2); { Write the number of colors stored in file }

        blockwrite(fileout,palette,maxcolor*3);
        { write palette }

        Read(filein,c1);
        Read(filein,c2);
        maxsprite:=256*ord(c2)+ord(c1);  { maximum sprites in this file }
	blockwrite(fileout,maxsprite,2);
	for i:= startingsprite to maxsprite do
           begin { load them in }
            Read(filein,c1);
            Read(filein,c2);
            spritemade:=256*ord(c2)+ord(c1); { flag to see if sprite exists }
	    blockwrite(fileout,spritemade,2);
	    if (spritemade = 1) then
	       begin
		SetFillStyle(SolidFill,0);
		bar(0,0,319,199);  { maximum sprite size }
                Read(filein,c1);
                Read(filein,c2);
                a:=256*ord(c2)+ord(c1); { width }
                Read(filein,c1);
                Read(filein,c2);
                b:=256*ord(c2)+ord(c1); { height }
		blockwrite(fileout,a,2); { put width and height }
		blockwrite(fileout,b,2);

		{ Read in the image data. Each byte represents a color
		from 0-255. Obviously converting sprites that use more colors
		than the current mode allows will not work. Draw sprites using
		only the first colors (eg 0-16), up to maxcolors of the mode you're using. }
		for y:=0 to b-1 do
		  for x:=0 to a-1 do
                     begin
                      read(filein,col);
		      putpixel(x,y,ord(col));
                     end;

		size := imagesize(0, 0, a-1, b-1); { get byte size of image }
		getmem(temp,size);
                if (temp = nil) then
		     begin
                      closegraph;
		      writeln('Error: not enough heap space in convertsprites.');
		      halt(1);
		     end;
		getimage(0, 0, a-1, b-1,temp^); { Get the image in new mode }
		blockwrite(fileout,temp^,size); { Write the data in getimage format }
	        freemem(temp,size);
	       end;
           end;
           Close(filein);
           Close(fileout);
       end;
    end
  else
     begin
	   closegraph;
	   writeln('Could not open 256 color sprite file');
	   halt(1);
     end;
end;

procedure freesprites(freespr:sprite_array);
var
i:integer;
width,height:integer;
begin

for i:=0 to 2000 do
  begin
  if freespr[i] <> nil then
    freemem(freespr[i],blocksize[i]);
  end;
end;



procedure loadsprites(infilename:string;var loadspr:sprite_array);
var
filein:file;   { converted color sprite file }
maxcolor,maxsprite:integer;
size:longint;
temp: pointer;
a,b,i,j,spritemade:integer;
red,green,blue:char;
buf:Pchar;
pal:palettetype;
begin
    { Open the files }
    if FileExists(infilename) then
     begin
      Assign(filein,infilename);
      Reset(filein,1);
      blockread(filein,maxcolor,2);

      getpalette(pal);
      for i:=0 to maxcolor-1 do
        begin
          blockread(filein,red,1);
          blockread(filein,green,1);
          blockread(filein,blue,1);
          setrgbpalette(pal.colors[i],ord(red),ord(green),ord(blue));
      end;

      blockread(filein,maxsprite,2);   { maximum sprites in this file }

	for i := 0 to maxsprite-1 do { load them in }
	   begin
	    blockread(filein,spritemade,2); { flag to see if sprite exists }
	    if (spritemade = 1) then
	       begin
		blockread(filein,a,2); { get width and height }
		blockread(filein,b,2);

		size := imagesize(0, 0, a-1, b-1); { get byte size of image }
                blocksize[i]:=size;
                getmem(loadspr[i],size);
		if (loadspr[i] = nil) then
		    begin
		      closegraph;
		      writeln('Error: not enough heap space in loadsprites().');
		      freesprites(loadspr);
		      halt(1);
		   end;
                blockread(filein,loadspr[i]^,size);
	       end
	     else loadspr[i]:=nil;

         end;
    close(filein);
  end;
end;



procedure testsprites;
{ Loops through 10 sprites, displaying them on the screen
 using the putimage method. Press a key to go to the next sprite. }
var
i,j:integer;
begin

for i:=0 to 10 do
  begin
  cleardevice;

   if sprites[i] <> nil then
     begin
     for j:=1 to 20 do
       putimage(random(getmaxx),random(getmaxy),sprites[i]^,NormalPut);
       { Put the converted image on the screen }
     while not keypressed do;
     readkey;
     end;
  end;
end;

begin
  Gd:= VGA;
  Gm:= VGAMED;

  InitGraph(Gd, Gm, '');
  if GraphResult <> grOk then
    Halt(1);


   convertsprites('sprtconv.spr','out.spr');
   loadsprites('out.spr',sprites);
   testsprites;
   freesprites(sprites);


   { clean up }
   CloseGraph;
end.

