unit Convert;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Gauges;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Label1: TLabel;
    Image1: TImage;
    Button1: TButton;
    Button2: TButton;
    LabeledEdit1: TLabeledEdit;
    Gauge1: TGauge;
    StaticText1: TStaticText;
    StaticText2: TStaticText;
    ColorBox1: TColorBox;
    ColorBox2: TColorBox;
    ColorBox3: TColorBox;
    ColorBox4: TColorBox;
    StaticText4: TStaticText;
    StaticText5: TStaticText;
    StaticText6: TStaticText;
    StaticText7: TStaticText;
    Image2: TImage;
    StaticText3: TStaticText;
    StaticText8: TStaticText;
    Image3: TImage;
    ComboBox1: TComboBox;
    ComboBox2: TComboBox;
    ComboBox3: TComboBox;
    ComboBox4: TComboBox;
    StaticText9: TStaticText;
    StaticText10: TStaticText;
    Image4: TImage;
    StaticText11: TStaticText;
    StaticText12: TStaticText;
    Button3: TButton;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    procedure Button1Click(Sender: TObject);
    procedure ColorBox1Change(Sender: TObject);
    procedure ColorBox2Change(Sender: TObject);
    procedure ColorBox3Change(Sender: TObject);
    procedure ColorBox4Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  LogPal = record
    lpal: TLogPalette;
    dummy: array[0..255] of TPaletteEntry;
  end;

var
  counter_file, sprites_in_col,sprites_in_row,number_sprite,FileHandle,FileSize,i,ii : Integer;
  Buffer : array[0..65535] of Byte;
  next_letter, byte1: Byte;
  tab_col_after_conv, tab_colors: array[0..3] of TColor;
  FileNameOrg, FileNameOut: String;
  SysPal: LogPal;
  col0, col1, col2, col3: TColor;
  x1,y1,x2,y2: Integer;
  number_sprite_src, number_sprite_dest, x1_dest,y1_dest,x2_dest,y2_dest: Integer;
  IsRemove: Boolean;
  IsFileRead: Boolean;

procedure ShowSprites();
begin
    for number_sprite:=0 to (FileSize div 64)-1 do
      for ii:=0 to 20 do
        for i:=0 to 2 do
          with Form1.Image1.Canvas do begin
            byte1:= Buffer[number_sprite*64+i+ii*3];

            sprites_in_row:= (number_sprite mod 10)*25;
            sprites_in_col:= (number_sprite div 10)*22;

            MoveTo(sprites_in_row+i*8, sprites_in_col+ii);

            Brush.Color:=0;
            Pen.Color:= tab_colors[(byte1 shr 6) and 3]; LineTo(sprites_in_row+i*8+2, sprites_in_col+ii);
            Pen.Color:= tab_colors[(byte1 shr 4) and 3]; LineTo(sprites_in_row+i*8+4, sprites_in_col+ii);
            Pen.Color:= tab_colors[(byte1 shr 2) and 3]; LineTo(sprites_in_row+i*8+6, sprites_in_col+ii);
            Pen.Color:= tab_colors[(byte1 shr 0) and 3]; LineTo(sprites_in_row+i*8+8, sprites_in_col+ii);
          end;
end;

procedure ShowOneSprite(sprite: Integer);
begin
      tab_col_after_conv[0]:= tab_colors[Form1.ComboBox1.ItemIndex];
      tab_col_after_conv[1]:= tab_colors[Form1.ComboBox2.ItemIndex];
      tab_col_after_conv[2]:= tab_colors[Form1.ComboBox3.ItemIndex];
      tab_col_after_conv[3]:= tab_colors[Form1.ComboBox4.ItemIndex];
      Form1.Image3.Visible:= True;
      Form1.Image2.Width:= 24; Form1.Image2.Height:= 21;
      Form1.StaticText8.Caption:= IntToStr(sprite);
      for ii:=0 to 20 do
        for i:=0 to 2 do
          with Form1.Image2.Canvas do begin
            byte1:= Buffer[sprite*64+i+ii*3];
            MoveTo(i*8, ii);
            Pen.Color:= tab_col_after_conv[(byte1 shr 6) and 3]; LineTo(i*8+2, ii);
            Pen.Color:= tab_col_after_conv[(byte1 shr 4) and 3]; LineTo(i*8+4, ii);
            Pen.Color:= tab_col_after_conv[(byte1 shr 2) and 3]; LineTo(i*8+6, ii);
            Pen.Color:= tab_col_after_conv[(byte1 shr 0) and 3]; LineTo(i*8+8, ii);
          end;
      Form1.Image2.Width:= 105; Form1.Image2.Height:= 105;
      Form1.Image3.Visible:= False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then begin
    Gauge1.Progress:= 0;
    LabeledEdit1.Text:=OpenDialog1.FileName;
    FileHandle:= FileOpen(OpenDialog1.FileName, fmOpenRead);
    FileSize:= FileSeek(FileHandle, 0, 2);
    FileSeek(FileHandle, 0, 0);
    FileRead(FileHandle, Buffer, FileSize);
    StaticText2.Caption:= ' Size of the file = '+IntToStr(FileSize);
    StaticText1.Caption:= 'Number of SPRITES = '+IntToStr(FileSize div 64);

    ShowSprites();
    ShowOneSprite(0);

    FileClose(FileHandle);
    IsFileRead:= TRUE;
  end;
end;

procedure TForm1.ColorBox1Change(Sender: TObject);
begin
  tab_colors[0]:= ColorBox1.Selected;
  ShowSprites();
end;

procedure TForm1.ColorBox2Change(Sender: TObject);
begin
  tab_colors[1]:= ColorBox2.Selected;
  ShowSprites();
end;

procedure TForm1.ColorBox3Change(Sender: TObject);
begin
  tab_colors[2]:= ColorBox3.Selected;
  ShowSprites();
end;

procedure TForm1.ColorBox4Change(Sender: TObject);
begin
  tab_colors[3]:= ColorBox4.Selected;
  ShowSprites();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  tab_colors[0]:= Form1.ColorBox1.Selected;
  tab_colors[1]:= Form1.ColorBox2.Selected;
  tab_colors[2]:= Form1.ColorBox3.Selected;
  tab_colors[3]:= Form1.ColorBox4.Selected;
end;

procedure copybmp(var bmp:TBitmap; var i,j: integer);
var x,y: integer;
begin

 for y:=0 to 20 do
  for x:=0 to 23 do
   bmp.Canvas.Pixels[x+i*24,y+j*24] := Form1.Image1.Canvas.Pixels[x+j*25,y+i*22];

end;


procedure Save_All_Sprites_As_One_BMP;
var bmp: TBitmap;
    i, j: integer;
begin

 // create bitmap
 bmp:=TBitmap.Create;
 bmp.PixelFormat:=pf24bit;
 bmp.Width:=12*24; bmp.Height:=10*24;

 // clear bitmap
 with bmp.Canvas do begin
  pen.Color:= Form1.Image1.Canvas.Pixels[0,0]; brush.Color:= Form1.image1.Canvas.Pixels[0,0];
  rectangle(0,0,bmp.Width,bmp.Height);
 end;

 // copy all sprites to bitmap
 Form1.Gauge1.MaxValue:= 11*11;
 for i:=0 to 10 do
  for j:=0 to 10 do begin
    copybmp(bmp,i,j);
    Form1.Gauge1.Progress:= i*11;
  end;

 // save bitmap and free memory
 bmp.SaveToFile('all_sprites.bmp');
 bmp.Free;

 // show it's finish
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
    if not IsFileRead then exit;

    if CheckBox1.Checked then Save_All_Sprites_As_One_BMP();

    Gauge1.MaxValue:= (FileSize div 64);

    if CheckBox2.Checked then begin
      counter_file:= 0;
      next_letter:= 96;
      FileNameOrg:= 'sprite_';

      for number_sprite:=0 to (FileSize div 64)-1 do begin
        ShowOneSprite(number_sprite);

        repeat
          if (counter_file mod 10) = 0 then begin
            inc(next_letter);
            if chr(next_letter)='{' then begin
              next_letter:= 97;
              FileNameOrg:= FileNameOrg+'z';
            end;
          end;
          FileNameOut:= FileNameOrg+chr(next_letter)+'_';
          FileNameOut:= FileNameOut+IntToStr(counter_file)+'.bmp';
          inc(counter_file);
        until not FileExists(FileNameOut);

        Image2.Picture.Bitmap.PixelFormat:= pf8bit; // ustaw 256-kolorową palete

        SysPal.lPal.palVersion:=$300;
        SysPal.lPal.palNumEntries:=256;
        GetSystemPaletteEntries(Image2.Canvas.Handle,0,256,SysPal.lpal.palPalEntry);
        col0:= ColorBox1.Selected;
        col1:= ColorBox2.Selected;
        col2:= ColorBox3.Selected;
        col3:= ColorBox4.Selected;
        SysPal.dummy[0].peRed:=   (col0 and $000000FF) shr 0;
        SysPal.dummy[0].peGreen:= (col0 and $0000FF00) shr 8;
        SysPal.dummy[0].peBlue:=  (col0 and $00FF0000) shr 16;
        SysPal.dummy[0].peFlags:= pc_explicit;

        SysPal.dummy[1].peRed:=   (col1 and $000000FF) shr 0;
        SysPal.dummy[1].peGreen:= (col1 and $0000FF00) shr 8;
        SysPal.dummy[1].peBlue:=  (col1 and $00FF0000) shr 16;
        SysPal.dummy[1].peFlags:= pc_explicit;

        SysPal.dummy[2].peRed:=   (col2 and $000000FF) shr 0;
        SysPal.dummy[2].peGreen:= (col2 and $0000FF00) shr 8;
        SysPal.dummy[2].peBlue:=  (col2 and $00FF0000) shr 16;
        SysPal.dummy[2].peFlags:= pc_explicit;

        SysPal.dummy[3].peRed:=   (col3 and $000000FF) shr 0;
        SysPal.dummy[3].peGreen:= (col3 and $0000FF00) shr 8;
        SysPal.dummy[3].peBlue:=  (col3 and $00FF0000) shr 16;
        SysPal.dummy[3].peFlags:= pc_explicit;

        for i:= 4 to 255 do begin
          SysPal.dummy[i].peRed:=     0;
          SysPal.dummy[i].peGreen:=   0;
          SysPal.dummy[i].peBlue:=    0;
          SysPal.dummy[i].peFlags:= pc_explicit;
        end;

        Image2.Picture.Bitmap.Palette:= CreatePalette(SysPal.lpal);

        Image2.Picture.SaveToFile(FileNameOut);

        Gauge1.Progress:= number_Sprite+1;
      end;
    end
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin

  if IsFileRead then begin
    if Button=mbLeft  then ShowOneSprite((X div 25)+(Y div 22)*10);

    if Button=mbRight then
      if not IsRemove then begin
        x1:= (X div 25)*25; y1:= (Y div 22)*22;
        x2:= x1+24;         y2:= y1+21;
        Image4.Canvas.Pen.Color:= clBlack;
        Image4.Canvas.Rectangle(0,0,27,23);
        Image4.Canvas.CopyRect(Rect(2,2,25,22),Form1.Image1.Canvas,Rect(x1,y1,x2,y2));
        Image4.Left:= Image1.Left+x1-2;
        Image4.Top:=  Image1.Top+y1-2;
        Image4.Visible:= TRUE;
        number_sprite_src:= (X div 25)+(Y div 22)*10;
        IsRemove:= TRUE;
      end else begin
        x1_dest:= (X div 25)*25; y1_dest:= (Y div 22)*22;
        x2_dest:= x1_dest+24;    y2_dest:= y1_dest+21;
        Image1.Canvas.CopyRect(Rect(x1,y1,x2,y2),Form1.Image1.Canvas,Rect(x1_dest,y1_dest,x2_dest,y2_dest));
        Image1.Canvas.CopyRect(Rect(x1_dest,y1_dest,x2_dest,y2_dest),Form1.Image4.Canvas,Rect(2,2,25,22));
        Image4.Visible:= FALSE;
        number_sprite_dest:= (X div 25)+(Y div 22)*10;
        for i:= 0 to 63 do begin
          byte1:= buffer[number_sprite_src*64+i];
          buffer[number_sprite_src*64+i]:= buffer[number_sprite_dest*64+i];
          buffer[number_sprite_dest*64+i]:= byte1
        end;
        IsRemove:= FALSE;
      end;
    end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
    if not IsFileRead then exit;
    FileHandle:= FileOpen(LabeledEdit1.Text, fmOpenWrite);
    FileSize:= FileSeek(FileHandle, 0, 2);
    FileSeek(FileHandle, 0, 0);
    FileWrite(FileHandle, Buffer, FileSize);
    FileClose(FileHandle);
end;

end.
