From 3b53c7c20d2e5feb761ea6895bd2a1cb92eee6b7 Mon Sep 17 00:00:00 2001
From: BoBo_Fett <93382571+JKBoBoFett@users.noreply.github.com>
Date: Wed, 21 Dec 2022 06:07:00 -0500
Subject: [PATCH] Added 24 + 32 bit support

---
 BMP_IO.pas        | 157 +++++++++++++++++++++++++++++-------
 BMParrays.pas     |  64 ++++++++++-----
 EditMTS.dfm       | 156 ++++++++++++++++++++++++++++++++++++
 EditMTS.pas       |  65 +++++++++++++++
 EditMat.dfm       |  26 ++++--
 EditMat.pas       | 200 ++++++++++++++++++++++++++++++++++++++++++----
 GloabalVars.pas   |   9 +++
 MAIN.PAS          | 179 +++++++++++++++++++++++++----------------
 MAIN.dfm          | Bin 10639 -> 10589 bytes
 MATImage.pas      | 164 +++++++++++++++++++++++++++++++++----
 Mat16.DPR         |  20 +++--
 Mat16.dproj       |  42 ++--------
 Mat16.dproj.local |  16 ++--
 Mat16.dres        | Bin 4740 -> 0 bytes
 Mat16.res         | Bin 4768 -> 4768 bytes
 Util.pas          |  28 ++++++-
 about_unit.dfm    | Bin 74112 -> 74112 bytes
 gobform.dfm       | Bin 1974 -> 1971 bytes
 gobform.pas       |  53 ++----------
 gobgoo.pas        | 102 ++++++++++++++++++++++-
 20 files changed, 1036 insertions(+), 245 deletions(-)
 create mode 100644 EditMTS.dfm
 create mode 100644 EditMTS.pas
 create mode 100644 GloabalVars.pas
 delete mode 100644 Mat16.dres

diff --git a/BMP_IO.pas b/BMP_IO.pas
index 8872575..25af964 100644
--- a/BMP_IO.pas
+++ b/BMP_IO.pas
@@ -124,6 +124,8 @@ procedure Save32bitA(ABitmap: TBitmap;Alpha:boolean; const AFileName: string);
 procedure Save16bitA1555BMP(ABitmap: TBitmap; const AFileName: string);
 function GetPaddedRowSize(bpp,width:integer):integer;
 procedure BMP_Save(Abitmap:Tbitmap; filename: string);
+function BMPFMTtoStr(Format:TBMPFORMAT):string;
+function Convert32bitTo16bit(bmp32:Tbitmap):Tbitmap;
 var
 inputBMPFormat:TBMPFORMAT;
 
@@ -252,15 +254,17 @@ function BMP_Open(filename: string): Tbitmap;
       if (bmfmask.GreenMask = 2016) then  // 16-bit 565 format
       begin
         rin_bitmap.PixelFormat := pf16bit;  //allways define pf first
+        rin_bitmap.HandleType :=  bmDIB;
         rin_bitmap.Width := bminfo.Width;
         rin_bitmap.Height := bminfo.Height;
         formatgood := True;
         inputBMPFormat:=bf16bit565;
       end;
 
-      if (bmfmask.GreenMask = 240) then  // 16-bit 4444 format
+      if (bmfmask.GreenMask = 240) or (bmfmask.GreenMask = 3840) then  // 16-bit 4444 format
       begin
         rin_bitmap.PixelFormat := pf32bit;  //VCL doesn't support display of 4444 so we'll convert to 32bit
+        rin_bitmap.HandleType :=  bmDIB;
         rin_bitmap.SetSize(bminfo.Width,bminfo.Height);
         formatgood := true;
         if hasAlpha then inputBMPFormat:=bf16bitA444  //can read alpha format in header since we are loading an externally created bitmap
@@ -271,6 +275,7 @@ function BMP_Open(filename: string): Tbitmap;
     if (bminfo.Compression = BI_RGB) or (bmfmask.GreenMask = 992) then  //BI_RGB 1555 doesn't have a fieldmask header
     begin
       rin_bitmap.PixelFormat := pf15bit;  //allways define pf first
+      rin_bitmap.HandleType :=  bmDIB;
       rin_bitmap.Width := bminfo.Width;
       rin_bitmap.Height := bminfo.Height;
       formatgood := True;
@@ -289,7 +294,7 @@ function BMP_Open(filename: string): Tbitmap;
      if (rin_bitmap.PixelFormat = pf32bit) and (bmfmask.GreenMask = 240) then
      begin
 
-       rin_bitmap.AlphaFormat:=afdefined;
+       rin_bitmap.AlphaFormat:=afIgnored;  {setting as defined seems to cause pre multiplication after conversion}
        for j := rin_bitmap.Height - 1 downto 0 do
           begin
             inrow := rin_bitmap.ScanLine[j];
@@ -320,15 +325,16 @@ function BMP_Open(filename: string): Tbitmap;
     seek(f, bmhead.BitmapOffset); //warp to bitmap data
 
     rin_bitmap.PixelFormat := pf24bit;  //allways define pf first
+    rin_bitmap.HandleType :=  bmDIB;
     rin_bitmap.Width := bminfo.Width;
     rin_bitmap.Height := bminfo.Height;
     formatgood := True; //FIX ME
-
+    inputBMPFormat:=bf24bit;
     //read in bitmap
     for i := bminfo.Height - 1 downto 0 do
       BlockRead(f, rin_bitmap.Scanline[i]^, bminfo.Width * 3);
 
-    Result := rin_bitmap;
+    Result.Assign(rin_bitmap);
     CloseFile(f);
   end; // end of 24-bit
 
@@ -349,9 +355,11 @@ function BMP_Open(filename: string): Tbitmap;
     seek(f, bmhead.BitmapOffset); //warp to bitmap data
 
     rin_bitmap.PixelFormat := pf32bit;  //allways define pf first
+    rin_bitmap.HandleType :=  bmDIB;
     rin_bitmap.Width := bminfo.Width;
     rin_bitmap.Height := bminfo.Height;
     formatgood := True; //FIX ME
+    inputBMPFormat:=bf32bit;
 
     //read in bitmap
     if (bminfo.Compression = BI_RGB) or (bmfmask.GreenMask = $0000FF00) then
@@ -386,29 +394,29 @@ function BMP_Open(filename: string): Tbitmap;
 
 
 
-    png := TPngImage.Create();
-
-
+//    png := TPngImage.Create();
+//
+//
     Result.Assign(rin_bitmap);
     CloseFile(f);
-
-    png.Assign(rin_bitmap);
-    png.CreateAlpha;
-
-    for J:=0 to rin_bitmap.Height - 1 do
-      begin
-      BMPInRow := rin_bitmap.ScanLine[J];
-      RowAlpha := png.AlphaScanline[J];
-        for i:=0 to rin_bitmap.Width - 1 do
-          RowAlpha[i] := BMPInRow[i].rgbReserved;
-
-
-
-
-      end;
-
-
-    png.SaveToFile('D:\TestBMP\Test32Save.png');
+//
+//    png.Assign(rin_bitmap);
+//    png.CreateAlpha;
+//
+//    for J:=0 to rin_bitmap.Height - 1 do
+//      begin
+//      BMPInRow := rin_bitmap.ScanLine[J];
+//      RowAlpha := png.AlphaScanline[J];
+//        for i:=0 to rin_bitmap.Width - 1 do
+//          RowAlpha[i] := BMPInRow[i].rgbReserved;
+//
+//
+//
+//
+//      end;
+//
+//
+//    png.SaveToFile('D:\TestBMP\Test32Save.png');
    // Save32bitA(Result,hasAlpha,'D:\TestBMP\Test32Save.bmp');
    //Result.SaveToFile('D:\TestBMP\Test32Save.bmp');
   end; // end of 32-bit
@@ -765,6 +773,73 @@ procedure Save16bit565(ABitmap: TBitmap; const AFileName: string);
 
 end;
 
+procedure Save16bit4444(ABitmap: TBitmap; const AFileName: string);
+const
+  PixelCountMax = 65536;  // 2048 MAX WIDTH
+type
+  TRGBQuadArray = array[0..PixelCountMax - 1] of TRGBQuad;
+  pRGBQuadArray = ^TRGBQuadArray;
+var
+  FS: TFileStream;
+  BFH: TBMPHeader;
+  BIH: TBMPInfo;
+  BIHEX:TBMPInfoV4ext;
+  y,w: Integer;
+  sl: PWordArray;
+  RGBQuadLineArray: pRGBQuadArray;
+  DestRGBA:tagRGBQuad;
+  Dest16bitPixel:word;
+begin
+  FS := TFileStream.Create(AFileName, fmCreate);
+  try
+
+    // Bitmap file header
+    FillChar(BFH, SizeOf(BFH), 0);
+    BFH.tag := $4D42;  // BM
+    BFH.filesize := 2 * ABitmap.Width * ABitmap.Height + SizeOf(BFH) + SizeOf(BIH)+ SizeOf(BIHEX);
+    BFH.BitmapOffset := SizeOf(BFH) + SizeOf(BIH) + SizeOf(BIHEX);
+    FS.Write(BFH, SizeOf(BFH));
+
+    // Bitmap info header
+    FillChar(BIH, SizeOf(BIH), 0);
+    BIH.Size := SizeOf(BIH)+SizeOf(BIHEX);
+    BIH.Width := ABitmap.Width;
+    BIH.Height := ABitmap.Height;
+    BIH.Planes := 1;
+    BIH.BitsPerPixel := 16;
+    BIH.Compression := BI_BITFIELDS;
+    BIH.SizeOfBitmap := 2 * (ABitmap.Width * ABitmap.Height);
+    FillChar(BIHEX, SizeOf(BIHEX), 0);
+    BIHEX.RedMask:=$F000;
+    BIHEX.GreenMask:=$F00;
+    BIHEX.BlueMask:=$F0;
+    BIHEX.AlphaMask:=$F;
+    FS.Write(BIH, SizeOf(BIH));
+    FS.Write(BIHEX, SizeOf(BIHEX));
+
+    // Pixels
+    for y := ABitmap.Height - 1 downto 0 do
+    begin
+      RGBQuadLineArray := ABitmap.ScanLine[y];
+      for w := 0 to ABitmap.Width - 1 do
+        begin
+        DestRGBA.rgbRed:=RGBQuadLineArray[w].rgbRed shr 4;
+        DestRGBA.rgbGreen:=RGBQuadLineArray[w].rgbGreen shr 4;
+        DestRGBA.rgbBlue:=RGBQuadLineArray[w].rgbBlue shr 4;
+        DestRGBA.rgbReserved:=RGBQuadLineArray[w].rgbReserved shr 4;
+
+        Dest16bitPixel:=DestRGBA.rgbRed shl 12 or DestRGBA.rgbGreen shl 8 or DestRGBA.rgbBlue shl 4 or DestRGBA.rgbReserved shl 0;
+        FS.Write(Dest16bitPixel, sizeof(word));
+        end;
+      //FS.Write(sl^, 2 * ABitmap.Width);
+    end;
+
+  finally
+    FS.Free;
+  end;
+
+end;
+
 
 procedure Save32bitA(ABitmap: TBitmap;Alpha:boolean; const AFileName: string);
 var
@@ -798,10 +873,13 @@ procedure Save32bitA(ABitmap: TBitmap;Alpha:boolean; const AFileName: string);
     FillChar(BIHEX, SizeOf(BIHEX), 0);
     BIHEX.AlphaMask:=$00000000;
       if Alpha then
-        BIHEX.AlphaMask:=$FF000000;
+    BIHEX.AlphaMask:=$FF000000;
+   // BIHEX.RedMask:= $000000FF;
     BIHEX.RedMask:=  $00FF0000;
     BIHEX.GreenMask:=$0000FF00;
     BIHEX.BlueMask:= $000000FF;
+    //BIHEX.BlueMask:=  $00FF0000;
+
     BIHEX.CSType:=  $73524742;
     FS.Write(BIH, SizeOf(BIH));
     FS.Write(BIHEX, SizeOf(BIHEX));
@@ -845,14 +923,39 @@ procedure BMP_Save(Abitmap:Tbitmap; filename: string);
     Save16bit565(Abitmap, filename);
     end;
 
+   if BMPFormat = bf24bit then
+    begin
+    Abitmap.SaveToFile(filename);
+    end;
+
    if BMPFormat = bf32bit then
     begin
     Save32bitA(Abitmap,true, filename);
+    //Save16bit4444(Abitmap, filename); {not tested}
     end;
 
+end;
 
+function BMPFMTtoStr(Format:TBMPFORMAT):string;
+begin
+//TBMPFormat = (bf8bit, bf16bitX1555, bf16bitA1555, bf16bitX444,bf16bitA444, bf16bit565, bf24bit, bf32bit, bfCustom);
+ case Format of
+   bf8bit: result:='bf8bit';
+   bf16bitX1555: result:='bf16bitX1555';
+   bf16bitA1555: result:='bf16bitA1555';
+   bf16bitX444: result:='bf16bitX444';
+   bf16bitA444: result:='bf16bitA444';
+   bf16bit565: result:='bf16bit565';
+   bf24bit: result:='bf24bit';
+   bf32bit: result:='bf32bit';
+   bfCustom: result:='bfCustom';
+ end;
+end;
 
-
+function Convert32bitTo16bit(bmp32:Tbitmap):Tbitmap;
+begin
 
 end;
+
+
 end.
diff --git a/BMParrays.pas b/BMParrays.pas
index 39af2d4..9bb47da 100644
--- a/BMParrays.pas
+++ b/BMParrays.pas
@@ -1,7 +1,7 @@
 unit BMParrays;
 //because imagelist use will remap pallete
 interface
-uses Windows,Graphics, SysUtils, Classes,MATHeaders,ColorMap,CMPHeaders,util,System.IOUtils,Dialogs,BMP_IO;
+uses Windows,Graphics, SysUtils, Classes,MATHeaders,ColorMap,CMPHeaders,util,System.IOUtils,Dialogs,BMP_IO,System.StrUtils;
 
  Type
 
@@ -21,7 +21,7 @@   TBMPARRAY = class(TPersistent)
 
       procedure setformat(fmt:string);
     public
-
+    name:Ansistring;
     isTransparent:Boolean;
     procedure ConvertBMPPal;
     procedure RemapArrayfromCMP(cmp: TCMP);
@@ -211,6 +211,7 @@ function TBMPARRAY.GetCellColorIndex(Cellindex:Integer):Integer;
  inrow32: PRGBQuad;
  row16:PWordArray;
  j,i:integer;
+
  begin
   BMPAlpha:=Tbitmap.create;
   BMPAlpha.Assign(CellBitmaps[index]);
@@ -240,7 +241,6 @@ function TBMPARRAY.GetCellColorIndex(Cellindex:Integer):Integer;
    BMPAlpha.Free;
   end;
 
-
 function TBMPARRAY.GetMip(Cellindex,Mipindex:Integer):Tbitmap;
  begin
   Result:=Tbitmap.create;
@@ -312,7 +312,7 @@ destructor TBMPARRAY.Destroy;
 
 
   CMPData:=default(TCMPPal);
-
+  name:='';
   inherited;
 end;
 
@@ -343,15 +343,17 @@ destructor TBMPARRAY.Destroy;
  Splitted: TArray<String>;
  tempBitmap:Tbitmap;
  begin
- gpath := ExtractFilePath(filename);
- tempBitmap:=Tbitmap.create;
- AssignFile(Txt, filename);
+
+  gpath := ExtractFilePath(filename);
+  AssignFile(Txt, filename);
   Reset(Txt);
 
   while not Eof(Txt) do
   begin
    Readln(Txt, s);
    Splitted := s.Split([':']);
+    if Splitted[0] = 'FILENAME' then
+     self.name:=trim(Splitted[1]);
    if Splitted[0] = 'FORMAT' then
     self.setformat(trim(Splitted[1]));
    if Splitted[0] = 'TRANSPARENT' then
@@ -368,15 +370,19 @@ destructor TBMPARRAY.Destroy;
        Splitted := s.Split(['|']);
        if fileexists(gpath+Splitted[0]) then
          begin
-         tempBitmap.LoadFromFile(gpath+Splitted[0]);
+         //tempBitmap.LoadFromFile(gpath+Splitted[0]);
+         tempBitmap:=(BMP_Open(gpath+Splitted[0])); //function creates bmp
          self.AddCellFromBMP(tempBitmap);
+         //tempBitmap.Free;
          self.ConvertBMPPal;
          for K := 1 to length(Splitted)-1 do
            begin
             if fileexists(gpath+Splitted[K]) then
               begin
-               tempBitmap.LoadFromFile(gpath+Splitted[K]);
+               //tempBitmap.LoadFromFile(gpath+Splitted[K]);
+               tempBitmap:=(BMP_Open(gpath+Splitted[K])); //function creates bmp
                self.AddSubMipMapFromBMP(tempBitmap);
+              // tempBitmap.Free;
               end;
            end;
          end
@@ -385,12 +391,10 @@ destructor TBMPARRAY.Destroy;
       end;
      end;
 
-
   end;
   CloseFile(Txt);
   tempBitmap.Free;
   tempBitmap:=nil;
-  // Splitted := MyString.Split([':']);
  end;
 
  procedure TBMPARRAY.SaveMTS(filename: string);
@@ -398,8 +402,15 @@ destructor TBMPARRAY.Destroy;
  i,j,k: integer;
  OutFile: textfile;
  savebitmap: Tbitmap;
- mname,gpath,mpath: string;
+ mname,gpath,mpath: Ansistring;
  begin
+ {filename needs to be the mat filename}
+  if (UpperCase(ExtractFileExt(filename)) <> '.MAT') then
+  begin
+   raise Exception.Create('Save MTS wrong file type');
+  end;
+
+
   AssignFile(OutFile, ChangeFileExt(filename, '.mat16s'));
   Rewrite(OutFile);
 
@@ -416,7 +427,9 @@ destructor TBMPARRAY.Destroy;
 
    for J := 0 to self.GetCellCount - 1 do
       begin
+      //savebitmap:=Tbitmap.Create;
       savebitmap:=(self.GetCell(J));
+      //savebitmap.Assign(self.GetCell(J));
       mname      := ExtractName(filename);
       mname      := TPath.GetFileNameWithoutExtension(mname);
       mname      := mname+'_Cell'+inttostr(j);
@@ -425,11 +438,15 @@ destructor TBMPARRAY.Destroy;
 
       Write(OutFile,mname);
 
-//      if saveBitmap.PixelFormat = pf32bit then
-//         SaveTransparentBitmap(saveBitmap, mpath) //work around for saving Tbitmap with alpha
-//
-//      else
-//        saveBitmap.SaveToFile(mpath);
+       if (UpperCase(ExtractFileExt(mpath)) <> '.BMP') then
+        begin
+         raise Exception.Create('Save MTS Cell wrong file type');
+        end;
+
+         if not ContainsText(mpath,'_Cell') then
+          begin
+           raise Exception.Create('Save MTS Cell wrong file type');
+          end;
 
       BMP_Save(saveBitmap, mpath);
 
@@ -441,6 +458,7 @@ destructor TBMPARRAY.Destroy;
         begin
           //savebitmap := Tbitmap.Create;
           savebitmap:=(self.GetMip(J,K));
+          //savebitmap.Assign(self.GetCell(J));
           mname      := ExtractName(filename);
           mname      := TPath.GetFileNameWithoutExtension(mname);
           mname      := mname+'_Cell'+inttostr(j)+'_Mip'+inttostr(K);
@@ -453,7 +471,17 @@ destructor TBMPARRAY.Destroy;
 //             SaveTransparentBitmap(saveBitmap, mpath) //work around for saving Tbitmap with alpha
 //
 //          else
-//           saveBitmap.SaveToFile(mpath);
+//         saveBitmap.SaveToFile(mpath);
+        if  (UpperCase(ExtractFileExt(mpath)) <> '.BMP') then
+                begin
+                 raise Exception.Create('Save MTS MIP wrong file type');
+                end;
+
+         if not ContainsText(mpath,'_Mip') then
+          begin
+           raise Exception.Create('Save MTS Cell wrong file type');
+          end;
+
           BMP_Save(saveBitmap, mpath);
 
           saveBitmap.Free;
diff --git a/EditMTS.dfm b/EditMTS.dfm
new file mode 100644
index 0000000..cf6d8f4
--- /dev/null
+++ b/EditMTS.dfm
@@ -0,0 +1,156 @@
+object EditMTSForm: TEditMTSForm
+  Left = 0
+  Top = 0
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsSingle
+  Caption = 'EditMTSForm'
+  ClientHeight = 334
+  ClientWidth = 518
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -13
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  PixelsPerInch = 120
+  TextHeight = 16
+  object Label1: TLabel
+    Left = 224
+    Top = 14
+    Width = 80
+    Height = 16
+    Hint = 'mats can have up to 16 cells'
+    Caption = 'Cells (LOD 0):'
+    ParentShowHint = False
+    ShowHint = True
+  end
+  object Label2: TLabel
+    Left = 368
+    Top = 14
+    Width = 120
+    Height = 16
+    Hint = 'mats can have up to 3 mips for each cell'
+    Caption = 'MIP chain (LOD 1-3):'
+    ParentShowHint = False
+    ShowHint = True
+  end
+  object Label3: TLabel
+    Left = 8
+    Top = 14
+    Width = 75
+    Height = 16
+    Caption = 'Mat Preview:'
+  end
+  object CellsListBox: TListBox
+    Left = 224
+    Top = 36
+    Width = 113
+    Height = 153
+    TabOrder = 0
+  end
+  object MipsListBox: TListBox
+    Left = 368
+    Top = 36
+    Width = 113
+    Height = 153
+    TabOrder = 1
+  end
+  object Panel1: TPanel
+    Left = 8
+    Top = 36
+    Width = 128
+    Height = 128
+    BevelInner = bvLowered
+    TabOrder = 2
+    object Image1: TImage
+      Left = 2
+      Top = 2
+      Width = 124
+      Height = 124
+      Align = alClient
+      Proportional = True
+      Stretch = True
+      ExplicitLeft = 0
+      ExplicitTop = 28
+    end
+  end
+  object OKButton: TButton
+    Left = 229
+    Top = 283
+    Width = 75
+    Height = 25
+    Caption = 'OK'
+    ModalResult = 1
+    TabOrder = 3
+  end
+  object Options: TGroupBox
+    Left = 10
+    Top = 195
+    Width = 503
+    Height = 82
+    Caption = 'Options'
+    TabOrder = 4
+    object Label4: TLabel
+      Left = 14
+      Top = 21
+      Width = 134
+      Height = 16
+      Caption = 'Internal bitmap format:'
+    end
+    object MipRadioGroup: TRadioGroup
+      Left = 214
+      Top = 23
+      Width = 161
+      Height = 46
+      Caption = 'MIP maps to Auto-create'
+      Columns = 4
+      ItemIndex = 0
+      Items.Strings = (
+        '0'
+        '1'
+        '2'
+        '3')
+      TabOrder = 0
+    end
+    object AddCellButton: TButton
+      Left = 396
+      Top = 28
+      Width = 75
+      Height = 25
+      Hint = 'bmp must match internal format'
+      Caption = 'Add Cell'
+      ParentShowHint = False
+      ShowHint = True
+      TabOrder = 1
+    end
+    object FormatComboBox: TComboBox
+      Left = 14
+      Top = 43
+      Width = 185
+      Height = 24
+      TabOrder = 2
+      Text = 'Select Internal Format'
+      Items.Strings = (
+        '8-bit '
+        '8-bit Transparent'
+        '16-bit 565'
+        '16-bit 1555 Transparent'
+        '16-bit 4444 (custom engine)')
+    end
+  end
+  object LoadButton: TButton
+    Left = 83
+    Top = 283
+    Width = 75
+    Height = 25
+    Caption = 'load mts'
+    ModalResult = 1
+    TabOrder = 5
+    OnClick = LoadButtonClick
+  end
+  object OpenPic: TOpenPictureDialog
+    Left = 176
+    Top = 112
+  end
+end
diff --git a/EditMTS.pas b/EditMTS.pas
new file mode 100644
index 0000000..3a33bf0
--- /dev/null
+++ b/EditMTS.pas
@@ -0,0 +1,65 @@
+unit EditMTS;
+
+interface
+
+uses
+  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtDlgs, Vcl.StdCtrls, Vcl.ExtCtrls;
+
+type
+  TEditMTSForm = class(TForm)
+    Label1: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    CellsListBox: TListBox;
+    MipsListBox: TListBox;
+    Panel1: TPanel;
+    Image1: TImage;
+    OKButton: TButton;
+    Options: TGroupBox;
+    Label4: TLabel;
+    MipRadioGroup: TRadioGroup;
+    AddCellButton: TButton;
+    FormatComboBox: TComboBox;
+    OpenPic: TOpenPictureDialog;
+    LoadButton: TButton;
+    procedure LoadButtonClick(Sender: TObject);
+  private
+    { Private declarations }
+  public
+    { Public declarations }
+  end;
+
+var
+  EditMTSForm: TEditMTSForm;
+
+implementation
+
+{$R *.dfm}
+
+procedure TEditMTSForm.LoadButtonClick(Sender: TObject);
+var
+ Txt: TextFile;
+ s,gpath:string;
+ Splitted: TArray<String>;
+begin
+  OpenPic.Filter:='mat16 script|*.mat16s;';
+
+if Openpic.Execute then
+  begin
+   gpath := ExtractFilePath(OpenPic.filename);
+  AssignFile(Txt, OpenPic.filename);
+  Reset(Txt);
+
+  while not Eof(Txt) do
+  begin
+   Readln(Txt, s);
+
+  end;
+
+  CloseFile(Txt);
+  end;
+
+end;
+
+end.
diff --git a/EditMat.dfm b/EditMat.dfm
index c6ff9bb..07299c9 100644
--- a/EditMat.dfm
+++ b/EditMat.dfm
@@ -120,11 +120,14 @@ object EditMatForm: TEditMatForm
       TabOrder = 0
     end
     object AddCellButton: TButton
-      Left = 396
-      Top = 28
-      Width = 75
+      Left = 398
+      Top = 17
+      Width = 91
       Height = 25
+      Hint = 'bmp must match internal format'
       Caption = 'Add Cell'
+      ParentShowHint = False
+      ShowHint = True
       TabOrder = 1
       OnClick = AddCellButtonClick
     end
@@ -141,8 +144,21 @@ object EditMatForm: TEditMatForm
         '8-bit Transparent'
         '16-bit 565'
         '16-bit 1555 Transparent'
-        '16-bit 4444'
-        '32-bit')
+        '16-bit 4444 (custom engine)'
+        '24-bit 888 (custom engine)'
+        '32-bit 8888 (custom engine)')
+    end
+    object RemoveCellButton: TButton
+      Left = 397
+      Top = 47
+      Width = 92
+      Height = 25
+      Hint = 'Removes selected cell'
+      Caption = 'Remove Cell'
+      ParentShowHint = False
+      ShowHint = True
+      TabOrder = 3
+      OnClick = RemoveCellButtonClick
     end
   end
   object OpenPic: TOpenPictureDialog
diff --git a/EditMat.pas b/EditMat.pas
index a5f0787..4e68761 100644
--- a/EditMat.pas
+++ b/EditMat.pas
@@ -23,6 +23,7 @@   TEditMatForm = class(TForm)
     AddCellButton: TButton;
     FormatComboBox: TComboBox;
     Label4: TLabel;
+    RemoveCellButton: TButton;
     procedure FormShow(Sender: TObject);
     procedure CellsListBoxClick(Sender: TObject);
     procedure MipsListBoxClick(Sender: TObject);
@@ -31,6 +32,8 @@   TEditMatForm = class(TForm)
     procedure Update;
     procedure FormatComboBoxClick(Sender: TObject);
     procedure OKButtonClick(Sender: TObject);
+    procedure RemoveCellButtonClick(Sender: TObject);
+    procedure CreateMipMapsFromCell(BMPArray:Tbmparray;CellBMP:Tbitmap);
   private
     { Private declarations }
   public
@@ -65,7 +68,7 @@ procedure TEditMatForm.AddCellButtonClick(Sender: TObject);
        if UpperCase(ExtractFileExt(Openpic.FileName)) = '.BMP' then
     begin
 
-      loadbmp.HandleType := bmDIB;
+      //loadbmp.HandleType := bmDIB;
 
 
 
@@ -76,11 +79,11 @@ procedure TEditMatForm.AddCellButtonClick(Sender: TObject);
 
 
     // 8 bit non transparent
-    if (FormatComboBox.ItemIndex = 0) then
+    if (FormatComboBox.ItemIndex < 2) then
      begin
        if fmt <> pf8bit then
         begin
-        showmessage('bitmap is not 8-bit');
+        showmessage('bitmap is '+BMPFMTtoStr(inputBMPFormat)+' not 8-bit');
         exit;
         end
 
@@ -88,7 +91,14 @@ procedure TEditMatForm.AddCellButtonClick(Sender: TObject);
         begin
         editA.AddCellFromBMP(loadbmp);
         editA.ConvertBMPPal;
-        editA.fmt:= '8-bit INDEXED';
+        if (FormatComboBox.ItemIndex = 0) then
+         editA.fmt:= '8-bit INDEXED'
+        else
+          begin
+          editA.fmt:= '8-bit trans INDEXED';
+          MipRadioGroup.Enabled:=false;
+          MipRadioGroup.ItemIndex :=0;
+          end;
         end;
      end;
 
@@ -96,7 +106,7 @@ procedure TEditMatForm.AddCellButtonClick(Sender: TObject);
      begin
        if inputBMPFormat <> bf16bit565  then
         begin
-        showmessage('bitmap is not 16-bit RGB565');
+        showmessage('bitmap is '+BMPFMTtoStr(inputBMPFormat)+' not 16-bit RGB565');
         exit;
         end
 
@@ -111,7 +121,7 @@ procedure TEditMatForm.AddCellButtonClick(Sender: TObject);
      begin
        if inputBMPFormat <> bf16bitA1555 then
         begin
-        showmessage('bitmap is not 16-bit ARGB1555');
+        showmessage('bitmap is '+BMPFMTtoStr(inputBMPFormat)+' not 16-bit ARGB1555');
         exit;
         end
 
@@ -119,14 +129,17 @@ procedure TEditMatForm.AddCellButtonClick(Sender: TObject);
         begin
         editA.AddCellFromBMP(loadbmp);
         editA.fmt:= '16-bit ARGB1555';
+        MipRadioGroup.Enabled:=false;
+        MipRadioGroup.ItemIndex :=0;
         end;
      end;
 
+    {internal format is actually 32-bit here}
     if (FormatComboBox.ItemIndex = 4) then
      begin
-       if (inputBMPFormat <> bf16bitA444)  then
+       if (inputBMPFormat <> bf16bitA444) and (inputBMPFormat <> bf32bit) then
         begin
-        showmessage('bitmap is not 16-bit ARGB4444');
+        showmessage('bitmap is '+BMPFMTtoStr(inputBMPFormat)+' not 32-bit or 16-bit RGBA4444');
         exit;
         end
 
@@ -134,14 +147,68 @@ procedure TEditMatForm.AddCellButtonClick(Sender: TObject);
         begin
         editA.AddCellFromBMP(loadbmp);
         editA.fmt:= '16-bit RGBA4444';
+        MipRadioGroup.Enabled:=false;
+        MipRadioGroup.ItemIndex :=0;
         end;
      end;
 
+    if (FormatComboBox.ItemIndex = 5) then
+     begin
+       if (inputBMPFormat <> bf24bit) then
+        begin
+        showmessage('bitmap is '+BMPFMTtoStr(inputBMPFormat)+' not 24-bit');
+        exit;
+        end
+
+      else
+        begin
+        editA.AddCellFromBMP(loadbmp);
+        editA.fmt:= '24-bit RGB';
+        end;
+     end;
+
+    if (FormatComboBox.ItemIndex = 6) then
+     begin
+       if (inputBMPFormat <> bf32bit) then
+        begin
+        showmessage('bitmap is '+BMPFMTtoStr(inputBMPFormat)+' not 32-bit');
+        exit;
+        end
+
+      else
+        begin
+        editA.AddCellFromBMP(loadbmp);
+        editA.fmt:= '32-bit RGBA';
+        MipRadioGroup.Enabled:=false;
+        MipRadioGroup.ItemIndex :=0;
+        end;
+     end;
+
+
       resize.HandleType :=  bmDIB;
       size:=1;
 
      if IsBMPmipsOK(loadbmp) then
        begin
+
+       if (loadbmp.Height > 256) or (loadbmp.Width > 256) then
+          begin
+            with TTaskDialog.Create(self) do
+            try
+              Caption := 'Mat16';
+              Title := 'Create Mip-Maps';
+              Text := 'Do you want to continue even though JK doesnt support Mip-Maps for images >256?';
+              CommonButtons := [tcbYes, tcbNo];
+              DefaultButton := tcbNo;
+              MainIcon := tdiNone;
+              if Execute then
+                if ModalResult = mrNo then
+                  MipRadioGroup.ItemIndex:=0;;
+            finally
+              Free;
+            end;
+          end;
+
         for i := 0 to (MipRadioGroup.ItemIndex - 1) do
           begin
           size:=size / 2;
@@ -160,12 +227,12 @@ procedure TEditMatForm.AddCellButtonClick(Sender: TObject);
              begin
              // resample:= Conv24bitTo16(resize,3,2,3);
               resample:= DitherTo16(resize);
-              editA.AddSubMipMapFromBMP( resample);
+              editA.AddSubMipMapFromBMP(resample);
               resample.free;
              end;
 
-
-
+             if fmt = pf24bit then
+               editA.AddSubMipMapFromBMP(resize);
 
           end;
         end;
@@ -217,7 +284,8 @@ procedure TEditMatForm.FormClose(Sender: TObject; var Action: TCloseAction);
 MipsListBox.Clear;
 
 // if assigned(image1.Picture.Bitmap) then image1.Picture.Bitmap.Free;
-//image1.Picture.Bitmap:=nil;
+image1.Picture:=nil;
+
 end;
 
 
@@ -235,10 +303,19 @@ procedure TEditMatForm.Update;
   if editA.GetCellCount = 0 then
    begin
    OKButton.ModalResult:=mrCancel;
+   RemoveCellButton.Enabled:=false;
+   FormatComboBox.Enabled:=true;
+   MipRadioGroup.Enabled:=true;
     if FormatComboBox.ItemIndex = -1 then
-     AddCellButton.Enabled:=false
+     begin
+     AddCellButton.Enabled:=false;
+     //RemoveCellButton.Enabled:=false;
+     end
     else
+     begin
      AddCellButton.Enabled:=true;
+     //RemoveCellButton.Enabled:=true;
+     end;
    end
   else
    begin
@@ -250,6 +327,7 @@ procedure TEditMatForm.Update;
        MipRadioGroup.ItemIndex := editA.GetMipCount;
        MipRadioGroup.Enabled:=false;
        AddCellButton.Enabled:=true;
+       RemoveCellButton.Enabled:=true;
      end;
 
  if editA.GetCellCount >= 16 then
@@ -261,16 +339,38 @@ procedure TEditMatForm.Update;
          FormatComboBox.ItemIndex:=0;
 
        if ContainsText(editA.fmt, '8-bit trans INDEXED') then
+         begin
          FormatComboBox.ItemIndex:=1;
+         MipRadioGroup.Enabled:=false;
+         MipRadioGroup.ItemIndex :=0;
+         end;
 
       if ContainsText(editA.fmt, '16-bit RGB565') then
          FormatComboBox.ItemIndex:=2;
 
      if ContainsText(editA.fmt, '16-bit ARGB1555') then
+        begin
          FormatComboBox.ItemIndex:=3;
+         MipRadioGroup.Enabled:=false;
+         MipRadioGroup.ItemIndex :=0;
+        end;
 
-     if ContainsText(editA.fmt, 'RGBA') then
+     if ContainsText(editA.fmt, 'RGBA4444') then
+         begin
          FormatComboBox.ItemIndex:=4;
+         MipRadioGroup.Enabled:=false;
+         MipRadioGroup.ItemIndex :=0;
+         end;
+
+     if ContainsText(editA.fmt, '24-bit RGB') then
+         FormatComboBox.ItemIndex:=5;
+
+     if ContainsText(editA.fmt, '32-bit RGBA') then
+         begin
+         FormatComboBox.ItemIndex:=6;
+         MipRadioGroup.Enabled:=false;
+         MipRadioGroup.ItemIndex :=0;
+         end;
 
       FormatComboBox.Enabled:=false;
       end;
@@ -325,4 +425,76 @@ procedure TEditMatForm.OKButtonClick(Sender: TObject);
 
 end;
 
+procedure TEditMatForm.RemoveCellButtonClick(Sender: TObject);
+var
+CellIndexToRemove,i:Integer;
+NewBMPArray:Tbmparray;
+tempBMP:tbitmap;
+begin
+NewBMPArray:=Tbmparray.Create;
+NewBMPArray.fmt:=editA.fmt;
+
+for i := 0 to (CellsListBox.Items.Count - 1) do
+ if CellsListBox.Selected[i] then  CellIndexToRemove:=i;
+
+for i := 0 to (editA.GetCellCount - 1) do
+  begin
+   if i<>CellIndexToRemove then
+     begin
+     tempBMP:=edita.GetCell(i); {function creates bmp}
+     NewBMPArray.AddCellFromBMP( tempBMP );
+
+     if ContainsText(NewBMPArray.fmt,'INDEXED') then
+        NewBMPArray.ConvertBMPPal;
+     CreateMipMapsFromCell( NewBMPArray,tempBMP );
+     tempBMP.Free;
+     tempBMP:=nil;
+     end;
+  end;
+
+edita.Assign(NewBMPArray);
+NewBMPArray.Free;
+update;
+end;
+
+procedure TEditMatForm.CreateMipMapsFromCell(BMPArray:Tbmparray;CellBMP:Tbitmap);
+var
+resize,resample:tbitmap;
+size:double;
+i:Integer;
+fmt:TPixelFormat;
+begin
+  resize := Tbitmap.Create;
+  resize.HandleType :=  bmDIB;
+  size:=1;
+  fmt:= CellBMP.PixelFormat;
+     if IsBMPmipsOK(CellBMP) then
+       begin
+        for i := 0 to (MipRadioGroup.ItemIndex - 1) do
+          begin
+          size:=size / 2;
+          scaleimage(CellBMP,resize,size); //converts bmps to 24bit
+
+           //reduce colors back to 8-bit using original pallette
+           //https://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Imaging.GIFImg.TDitherMode
+           if fmt = pf8bit then
+             begin
+              resample:=ReduceColors(resize,rmPalette,dmNearest,8,CellBMP.Palette);  //palette must still exist after conversion
+              BMPArray.AddSubMipMapFromBMP(resample);
+              resample.free;
+             end;
+
+            if fmt = pf16bit then
+             begin
+             // resample:= Conv24bitTo16(resize,3,2,3);
+              resample:= DitherTo16(resize);
+              BMPArray.AddSubMipMapFromBMP( resample);
+              resample.free;
+             end;
+
+          end;
+        end;
+resize.Free;
+end;
+
 end.
diff --git a/GloabalVars.pas b/GloabalVars.pas
new file mode 100644
index 0000000..0f903d5
--- /dev/null
+++ b/GloabalVars.pas
@@ -0,0 +1,9 @@
+unit GloabalVars;
+
+interface
+
+var
+jkpath:    string;
+implementation
+
+end.
diff --git a/MAIN.PAS b/MAIN.PAS
index e1c8a9d..337ebdc 100644
--- a/MAIN.PAS
+++ b/MAIN.PAS
@@ -4,7 +4,7 @@ interface
 
 uses
   SysUtils, Windows, Messages, Classes, Graphics, Controls,
-  Forms, Dialogs, StdCtrls, ImgList, Menus, Grids, ComCtrls, ExtCtrls,
+  Forms, vcl.Dialogs, StdCtrls, ImgList, Menus, Grids, ComCtrls, ExtCtrls,
   Buttons, ToolWin, ExtDlgs, Util, clipbrd, ShellAPI,
    gobgoo, Registry, SaveDLGUnit, adpMRU,
   System.ImageList,MATImage,BMParrays,ColorMap,MATHeaders,CMPHeaders, System.IOUtils,StrUtils,Set8bitFormatOnOpen,BMP_IO;
@@ -62,8 +62,6 @@ type
     GroupBox1: TGroupBox;
     ViewasTransparent1: TMenuItem;
     ViewTiled2: TMenuItem;
-    CloseImage1: TMenuItem;
-    N3:      TMenuItem;
     Panel2:  TPanel;
     Zoom1:   TMenuItem;
     In1:     TMenuItem;
@@ -141,6 +139,7 @@ type
     procedure updateCMPcomboBox(container:string);
     procedure TrackBarChange;
     procedure Createnewmatfrombmps1Click(Sender: TObject);
+    procedure EditMTS1Click(Sender: TObject);
   end;
 
 var
@@ -150,7 +149,6 @@ var
   numframes: integer;
   savefname: string;
   addcell:   boolean;
-  jkpath:    string;
   motspath:  string;
   isbatch:   boolean;
    adpMRU: TadpMRU;
@@ -160,7 +158,7 @@ var
 implementation
 
 uses about_unit, Batch,
-   gobform, ViewtileUnit, mess_frm,options, EditMat;
+   gobform, ViewtileUnit, mess_frm,options, EditMat,EditMTS,GloabalVars;
 
 {$R *.DFM}
 
@@ -208,12 +206,21 @@ begin
   BMPArray.Assign(BMPA);
     tempBMP:=(BMPArray.GetCell(0));
 
-    if (Mat.GetMatFormat=(TFormat.RGBA4444)) or (Mat.GetMatFormat=(TFormat.RGBA5551))  then
+    if (Mat.GetMatFormat=(TFormat.RGBA4444)) or (Mat.GetMatFormat=(TFormat.RGBA5551)) or (Mat.GetMatFormat=(TFormat.RGBA8888)) then
     begin
-    tempBMP:=(BMPArray.GetAlphaCellForDisplay(0));
+    PremultiplyAlpha(tempBMP);
     Draw32bitImageOnGrid(tempBMP);
     end;
 
+  if Mat.GetMatFormat=(TFormat.RGB888) then
+     begin
+     Image1.Picture.Bitmap.Assign(tempBMP);
+     if tempBMP.PixelFormat =pf8bit then
+    begin
+      Image1.Picture:=nil;
+    end;
+     end;
+
   if Mat.GetMatFormat=(TFormat.ARGB1555) then
     begin
     Draw16bitImageOnGrid(tempBMP);
@@ -310,11 +317,17 @@ begin
    tmpBMP:=(BMPArray.GetBMP(Cell_TrackBar.Position,Mip_TrackBar.Position));
 
    if (tmpBMP.PixelFormat = pf32bit)  then
-       Draw32bitImageOnGrid(tmpBMP);
+       begin
+        PremultiplyAlpha(tmpBMP);
+        Draw32bitImageOnGrid(tmpBMP);
+       end;
 
    if (tmpBMP.PixelFormat = pf16bit)  then
        image1.picture.Bitmap.Assign(tmpBMP);
 
+  if (tmpBMP.PixelFormat = pf24bit)  then
+       image1.picture.Bitmap.Assign(tmpBMP);
+
    if (bitmap.PixelFormat = pfCustom)  then //ARGB1555
        Draw16bitImageOnGrid(tmpBMP);
 
@@ -350,6 +363,7 @@ end;
 procedure TMainForm.FileSaveAs(Sender: TObject);
  var
 Mat: TMAT;
+MatName:string;
 begin
   Screen.Cursor := crHourGlass;
   SaveDialog.FileName := ChangeExt(OpenDialog.FileName, '');
@@ -370,7 +384,8 @@ begin
 
     if UpperCase(ExtractFileExt(SaveDialog.FileName)) = '.MAT16S' then
     begin
-      BMPArray.SaveMTS(SaveDialog.FileName);
+      MatName:=ChangeFileExt(SaveDialog.FileName, '.mat');
+      BMPArray.SaveMTS(MatName);
     end;
 
   end;
@@ -608,49 +623,80 @@ begin
 end;
 
 procedure TMainForm.BatchConvertBMPs1Click(Sender: TObject);
-//var
-//  I, Count:    integer;
-//  BatchBitmap: TBitmap;
-//  savename, mcfname: string;
-//  StartTime, EndTime: DWORD;
+var
+  I:    integer;
+  LoadBMParray:TBMParray;
+  LoadMat: TMAT;
+  gpath, mpath: string;
+
 begin
-  // isbatch:=TRUE;
+ OpenDialogBatch.Filter     :=
+    'mat16 script with bitmaps|*mat16s';
+Screen.Cursor := crHourGlass;
 
-  MATSaveDlg.Show;
-  isbatch := True;
+  if OpenDialogBatch.Execute then
+  begin
+    Screen.Cursor := crHourGlass;
 
-end;
+    BatchForm.ProgressBar1.Position := 0;
+    BatchForm.Show;
 
+    BatchForm.Memo1.Lines.Clear;
+    BatchForm.Memo1.Lines.Add(IntToStr(OpenDialogBatch.Files.Count) +
+      ' File(s) selected to convert');
 
-procedure TMainForm.BatchConvertMATBMP1Click(Sender: TObject);
+    BatchForm.ProgressBar1.Max := OpenDialogBatch.Files.Count-1;
 
- var
+    for I := 0 to OpenDialogBatch.Files.Count - 1 do
+     begin
+      BatchForm.ProgressBar1.Position := i;
+
+      if UpperCase(ExtractFileExt(OpenDialogBatch.Files[I])) = '.MAT16S' then
+        begin
+        LoadBMParray:=TBMPARRAY.Create;
+         try
+          LoadBMParray.OpenMTS(OpenDialogBatch.Files[I]);
+          LoadMat:=TMAT.CreateFromBMPArray(LoadBMParray);
+          mpath:=ExtractFilePath(OpenDialogBatch.Files[I])+LoadBMParray.name;
+          if  (UpperCase(ExtractFileExt(mpath)) <> '.MAT') then
+                begin
+                 raise Exception.Create('Save MAT wrong file type '+mpath);
+                end;
+          LoadMat.SaveMat(ExtractFilePath(OpenDialogBatch.Files[I])+LoadBMParray.name);
+         except
+          On e:exception do
+           begin
+            ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
+            LoadBMParray.Free;
+            LoadMat.Free;
+            Screen.Cursor := crDefault;
+            exit;
+           end;
+         end;
+        BatchForm.Memo1.Lines.Add('Saved MAT: '+ExtractFilePath(OpenDialogBatch.Files[I])+LoadBMParray.name );
+        LoadBMParray.Free;
+        LoadMat.Free;
+        end;
+     end;
+  end;
+  BatchForm.Memo1.Lines.Add('-Done-');
+  Screen.Cursor := crDefault;
+end;
+
+procedure TMainForm.BatchConvertMATBMP1Click(Sender: TObject);
+var
   i,j,k: integer;
-  savebitmap: Tbitmap;
-  bestcmp, gpath, mpath, fext, mname: string;
-//  f: file;
   Mat: TMAT;
- //  matFormatHeader:TMatHeader;
-   pos:longint;
-   tempA:TBMPArray;
-   MatInfoList:Tstringlist;
+  pos:longint;
+  tempA:TBMPArray;
 begin
 
 OpenDialogBatch.Filter     :=
     'mat texture (*.mat)|*.MAT';
- // savebitmap := Tbitmap.Create;
-  gpath := ExtractFilePath(label1.Caption);
-  fext  := ExtractName(label1.Caption);
-  fext  := ChangeFileExt(fext, '');
-  gpath := gpath + fext;
-  Screen.Cursor := crHourGlass;
-  CreateDir(gpath);
-  //BatchForm.Show;
+Screen.Cursor := crHourGlass;
 
-  i:=0;
   if OpenDialogBatch.Execute then
   begin
-    gpath := ExtractFilePath(OpenDialogBatch.Files[I]);
     Screen.Cursor := crHourGlass;
 
     BatchForm.ProgressBar1.Position := 0;
@@ -660,42 +706,16 @@ OpenDialogBatch.Filter     :=
     BatchForm.Memo1.Lines.Add(IntToStr(OpenDialogBatch.Files.Count) +
       ' File(s) selected to convert');
 
-
     BatchForm.ProgressBar1.Max := OpenDialogBatch.Files.Count-1;
-   // starttime := GetTickCount;
-    for I := 0 to OpenDialogBatch.Files.Count - 1 do
-    begin
-    BatchForm.ProgressBar1.Position := i;
-
-    bestcmp    := GetbestCMP(OpenDialogBatch.Files[I], jkpath);
-
-    pos:=GetGOBFileOffset(jkpath,bestcmp);
-    MainCMP.LoadCMPFromFile(jkpath, pos);
-
-   // mainform.gridPalette.Repaint;
-
-    Mat:=TMAT.Create(TFormat.BMP);
-    Mat.SetCMP(defCmppal);
-    tempA:= Mat.LoadFromFile(OpenDialogBatch.Files[I]);
-
-     mess.Memo1.lines.Add(OpenDialogBatch.Files[I]);
-     MatInfoList:=Mat.HeadersToJSON;
-     mess.Memo1.lines.AddStrings(MatInfoList);
-
-     tempA.SaveMTS(OpenDialogBatch.Files[I]);
-     BatchForm.Memo1.Lines.Add('Saved: '
-      + TPath.GetFileNameWithoutExtension(OpenDialogBatch.Files[I])
-      + ' cmp: ' + bestcmp);
 
-
-    Mat.Free;
-    tempA.Free;
-    MatInfoList.Free;
-  end;
+    for I := 0 to OpenDialogBatch.Files.Count - 1 do
+     begin
+      BatchForm.ProgressBar1.Position := i;
+      BatchForm.Memo1.Lines.Add(GobMatSavetoBMP('', OpenDialogBatch.Files[I],FileOffsets,CMPOffsets,false));
+     end;
   end;
   BatchForm.Memo1.Lines.Add('-Done-');
   Screen.Cursor := crDefault;
-
 end;
 
 procedure TMainForm.Button1Click(Sender: TObject);
@@ -814,6 +834,12 @@ begin
 end;
 
 
+procedure TMainForm.EditMTS1Click(Sender: TObject);
+begin
+  EditMTSForm.Show;
+
+end;
+
 procedure TMainForm.Draw16bitImageOnGrid(bmp:Tbitmap);
 var
 gridBMP,remap:tbitmap;
@@ -839,6 +865,7 @@ procedure TMainForm.Draw32bitImageOnGrid(bmp:Tbitmap);
 gridBMP,remap:tbitmap;
 begin
  gridBMP:=Tbitmap.create;
+ gridBMP.PixelFormat:=pf32bit;
  try
  RenderGrid(gridBMP,bmp.Height,bmp.Width,1,clGray,clLtGray);
  Blend(gridBMP,bmp);
@@ -1353,8 +1380,20 @@ begin
     begin
 
       LoadBMParray:=TBMPARRAY.Create;
+      try
       LoadBMParray.OpenMTS(FileName);
 
+      except
+       On e:exception do
+       begin
+         ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
+         LoadBMParray.Free;
+         Screen.Cursor := crDefault;
+         exit;
+       end;
+
+     end;
+
       Cell_TrackBar.Position := 0;
       image1.Repaint;
 
@@ -1362,9 +1401,7 @@ begin
       LoadMat.matFormat:=LoadMat.StrToFormat(LoadBMParray.fmt);
 
       BMPArrayDisplay(LoadBMParray,LoadMat);  //frees bmpA and Tmat
-
-
-     end;
+    end;
 
     MainForm.Caption := 'Mat16 - ' + extractfilename(FileName);
     adpMRU.AddItem(OpenPic.FileName);
diff --git a/MAIN.dfm b/MAIN.dfm
index 69576ea071baecfa99643aec49035e1e89fd99fc..22ff957aafb6b061fc6edbe9fe8beb3321924556 100644
GIT binary patch
delta 235
zcmeAVz8fU)pNk>H*U{6@%|FPO!9c)kqkt2OtgL@QYMw%(LT+M-LVgj5GBhhz&@Wd=
z$}Lcztjjrb@&y))$rbE8n;lr!a40J|C6**-C^+Zmm8BMyz?Fj(7b}$Hg9JA5)$(zK
zWfo^9<)m_Ku94Zrtg4EtO9NyXL@~&+a(%G&$pH#pva*;eK}sNsC+|{l-<+g)lv&I<
eII|=}!8I>EGcQ#kB(<WXv?x_Uce9mhC<_4Q!A&>-

delta 247
zcmcZ`)E_MHpNk>H*U{6@%|FPO!9bv9qkt2Okf47-YMw%(g0EwULVl5glW)N00+tR=
z5n-pqlH?2p=lr~~)S?oQxO(wsX}(&%%?o9AGD}IJN^5|$m*j(#O|Dn)QdB^b28x5E
z4b74=OF&j>PQJ*mG?`OT#gyAQC%-t=GdD3k)sWpev7jU~KaUL}r~npa_s?_A$xO~>
v7eJ_-ET|yDXgqnMoXln;#RJU34qmA#nF`){nduoNKudIiwru854P^lU8E8za

diff --git a/MATImage.pas b/MATImage.pas
index b7acba7..7a3db2f 100644
--- a/MATImage.pas
+++ b/MATImage.pas
@@ -1,10 +1,10 @@
 unit MATImage;
 
 interface
-uses Windows,Graphics, SysUtils, Classes, MATHeaders, Color16,ColorMap,BMParrays,CMPHeaders,BMP_IO;
+uses Windows,Graphics, SysUtils, Classes, MATHeaders, Color16,ColorMap,BMParrays,CMPHeaders,BMP_IO,System.StrUtils;
 
 Type
-    TFormat = (INDEX,INDEXT,INDEXCMP,INDEXTCMP,COLOR8,RGB565,ARGB1555, RGBA5551, RGBA4444,BMP);
+    TFormat = (INDEX,INDEXT,INDEXCMP,INDEXTCMP,COLOR8,RGB565,ARGB1555, RGBA5551, RGBA4444,RGB888,RGBA8888,BMP);
 
   TMAT = class
     private
@@ -184,6 +184,44 @@ constructor TMAT.Create(format:TFormat);
        alpha_BitDif:=4;
      end;
 
+    if (matFormat =  RGB888) then
+     begin
+       ColorMode:=1;
+
+       bits:=24;
+       redbits:=8;
+       greenbits:=8;
+       bluebits:=8;
+       shiftR:=16;
+       shiftG:=8;
+       shiftB:=0;
+       RedBitDif:=0;
+       GreenBitDif:=0;
+       BlueBitDif:=0;
+       alpha_bpp:=8;
+       alpha_sh:=0;
+       alpha_BitDif:=0;
+     end;
+
+    if (matFormat =  RGBA8888) then
+     begin
+       ColorMode:=2;
+
+       bits:=32;
+       redbits:=8;
+       greenbits:=8;
+       bluebits:=8;
+       shiftR:=24;
+       shiftG:=16;
+       shiftB:=8;
+       RedBitDif:=0;
+       GreenBitDif:=0;
+       BlueBitDif:=0;
+       alpha_bpp:=8;
+       alpha_sh:=0;
+       alpha_BitDif:=0;
+     end;
+
     end;
  end;
  constructor TMAT.CreateFromBMPArray(ABMPARRAY:TBMPARRAY);
@@ -233,7 +271,15 @@ destructor TMAT.Destroy;
  // self.bmap.Free;
   freeandnil(bmap);
   CMPData:=default(TCMPPal);
-
+//  if Bitstream<>nil then
+//     Bitstream.Clear;
+  SetLength(Imagedata16,0, 0);
+  SetLength(Imagedata8, 0, 0);
+
+  SetLength(matTextureHeaderA,0);
+  SetLength(matColorHeaderA,0);
+  SetLength(matMipmapHeaderA,0);
+  SetLength(ImageDataIndex,0);
  inherited;
 end;
 
@@ -324,6 +370,7 @@ procedure TMAT.AddCellFromBMP(bmap: TBitmap);
 
   bmap.free;
 end;
+
 function TMAT.SetSamplePerChannel(SourceRGBA:tagRGBQuad):tagRGBQuad;
 begin
    result.rgbRed:=SourceRGBA.rgbRed shr matFormatHeader.RedBitDif;
@@ -335,8 +382,6 @@ function TMAT.SetSamplePerChannel(SourceRGBA:tagRGBQuad):tagRGBQuad;
     result.rgbReserved:=SourceRGBA.rgbReserved and 1;
 end;
 
-
-
 //Adds pixel data to a Tcolor array
 //each row is a cell that contains main image and any mips for that cell
 procedure TMAT.Convert(IsSubMipMap: Boolean);
@@ -346,6 +391,9 @@ procedure TMAT.Convert(IsSubMipMap: Boolean);
   TRGBQuadArray = array[0..PixelCountMax - 1] of TRGBQuad;
   pRGBQuadArray = ^TRGBQuadArray;
 
+  TRGBTripleArray = ARRAY[Word] of TRGBTriple;
+  pRGBTripleArray = ^TRGBTripleArray;
+
   TByteArray = array[0..32767] of Byte;
   PByteArray = ^TByteArray;
 
@@ -353,9 +401,11 @@ procedure TMAT.Convert(IsSubMipMap: Boolean);
  i,h,w,cellInedx:integer;
  DestRGBA:tagRGBQuad;
  RGBQuadLineArray: pRGBQuadArray;
+ RGBTrippleLineArray:pRGBTripleArray;
  IndexArray: PByteArray;
  row16:PWordArray;
   BMPFormat:TBMPFormat;
+ Dest16bitPixel:word;
 begin
 
 //if IsSubMipMap then
@@ -389,6 +439,7 @@ procedure TMAT.Convert(IsSubMipMap: Boolean);
 
         end;
 
+      {internal 32-bit bmp to 16-bit RGBA 4444}
       if ( (bits = 16) and (bmap.PixelFormat = pf32bit) )then
         begin
           for h := 0 to bmap.Height - 1 do
@@ -396,14 +447,46 @@ procedure TMAT.Convert(IsSubMipMap: Boolean);
              RGBQuadLineArray := bmap.ScanLine[h];
               for w := 0 to bmap.Width - 1 do
                 begin
-                 DestRGBA:=SetSamplePerChannel(RGBQuadLineArray[w]);
-                 self.ImageData16[cellInedx][Self.ImageDataIndex[cellInedx]].Create(DestRGBA.rgbRed,DestRGBA.rgbGreen,DestRGBA.rgbBlue,DestRGBA.rgbReserved,matFormatHeader);
+                 DestRGBA:=SetSamplePerChannel(RGBQuadLineArray^[w]);
+                 Dest16bitPixel:=DestRGBA.rgbRed shl 12 or DestRGBA.rgbGreen shl 8 or DestRGBA.rgbBlue shl 4 or DestRGBA.rgbReserved shl 0;
+                 //Dest16bitPixel:=65535; {all white test}
+                 //Dest16bitPixel:=65520; {all white test 0 alpha}
+                 bitstream.Write(Dest16bitPixel, sizeof(word));
+                // self.ImageData16[cellInedx][Self.ImageDataIndex[cellInedx]].Create(DestRGBA.rgbRed,DestRGBA.rgbGreen,DestRGBA.rgbBlue,DestRGBA.rgbReserved,matFormatHeader);
                  inc(Self.ImageDataIndex[cellInedx]);
                 end; //w
 
           end; //h
       end;
 
+     if ( (bits = 24) and (bmap.PixelFormat = pf24bit) )then
+        begin
+         for h := 0 to bmap.Height - 1 do
+            begin
+             RGBTrippleLineArray := bmap.ScanLine[h];
+             for w := 0 to bmap.Width - 1 do
+                begin
+                bitstream.Write(RGBTrippleLineArray^[w],sizeof(TRGBTriple));
+                inc(Self.ImageDataIndex[cellInedx]);
+                end;
+            end;
+        end;
+
+     if ( (bits = 32) and (bmap.PixelFormat = pf32bit) )then
+        begin
+         for h := 0 to bmap.Height - 1 do
+            begin
+             RGBQuadLineArray := bmap.ScanLine[h];
+             for w := 0 to bmap.Width - 1 do
+                begin
+                bitstream.Write(RGBQuadLineArray^[w],sizeof(TRGBQuad));
+                inc(Self.ImageDataIndex[cellInedx]);
+                end;
+            end;
+
+        end;
+
+
      if ( (bits = 16) and ( (BMPFormat = bf16bitA1555) or (BMPFormat = bf16bit565) ) )then
         begin
           for h := 0 to bmap.Height - 1 do
@@ -438,6 +521,7 @@ procedure TMAT.SaveMat(fname: string);
   I,N: Integer;
   Abytes: array of byte;
 begin
+
  ms := TMemoryStream.Create;
  ms.Write(matFormatHeader, sizeof(matFormatHeader));
 
@@ -472,6 +556,20 @@ procedure TMAT.SaveMat(fname: string);
 
               end;
 
+           if matFormatHeader.bits = 24 then
+              begin
+              SetLength(Abytes, ImageDataIndex[N]*3);
+              bitstream.ReadBuffer(Abytes[0],ImageDataIndex[N]*3);
+              ms.Write(Abytes[0], ImageDataIndex[N]*3);
+              end;
+
+           if matFormatHeader.bits = 32 then
+              begin
+              SetLength(Abytes, ImageDataIndex[N]*4);
+              bitstream.ReadBuffer(Abytes[0],ImageDataIndex[N]*4);
+              ms.Write(Abytes[0], ImageDataIndex[N]*4);
+              end;
+
            if matFormatHeader.bits = 8 then
               begin
               //for I:= 0 to Length(ImageData8[N]) - 1 do
@@ -493,6 +591,10 @@ procedure TMAT.SaveMat(fname: string);
 
       end;
 
+     {8.3 filename bug workaround}
+     if ContainsText(fname,'~1') then
+       fname:= StringReplace(fname, '~1', '_1', [rfReplaceAll, rfIgnoreCase]);
+
  Bitstream.Free;
  ms.SaveToFile(fname);
  Ms.Free;
@@ -651,6 +753,7 @@ function TMAT.LoadFromFile(filename: string;pos: longint=0): TBMPARRAY;
        //add cells
        for i := 0 to matFormatHeader.cel_count - 1  do
           begin
+            if Assigned(self.bmap) then self.bmap.Assign(nil);
             BlockRead(f, matMipmapHeaderA[i], SizeOf(matMipmapHeaderA[i]));
 
             if (matMipmapHeaderA[i].SizeX >8000) or (matMipmapHeaderA[i].SizeX <=0) then
@@ -690,6 +793,8 @@ function TMAT.LoadFromFile(filename: string;pos: longint=0): TBMPARRAY;
        ARGB1555:result.fmt:='16-bit ARGB1555';
        RGBA4444:result.fmt:='16-bit RGBA4444';
        RGBA5551:result.fmt:='16-bit RGBA5551';
+       RGB888:result.fmt:='24-bit RGB';
+       RGBA8888:result.fmt:='32-bit RGBA';
        INDEX:result.fmt:='8-bit INDEXED';
        INDEXT:result.fmt:='8-bit trans INDEXED';
        COLOR8:result.fmt:='8-bit COLOR';
@@ -697,8 +802,9 @@ function TMAT.LoadFromFile(filename: string;pos: longint=0): TBMPARRAY;
        INDEXTCMP:result.fmt:='8-bit INDEXED trans int CMP';
       end;
 
-
- //    bmap.SaveToFile('D:\TestBMP\lastcell.bmp');
+ {$IFDEF DEBUG}
+     bmap.SaveToFile('D:\TestBMP\lastcell.bmp');
+ {$ENDIF}
   imageformat:=matformat;
   tempBMP.Free;
   CloseFile(f);
@@ -716,6 +822,10 @@ function TMAT.StrToFormat(str:string):TFORMAT;
       result:= TFORMAT.ARGB1555;
     if str.Equals('16-bit RGBA4444') then
       result:= TFORMAT.RGBA4444;
+    if str.Equals('24-bit RGB') then
+      result:= TFORMAT.RGB888;
+    if str.Equals('32-bit RGBA') then
+      result:= TFORMAT.RGBA8888;
     if str.Equals('16-bit RGBA5551') then
       result:= TFORMAT.RGBA5551;
     if str.Equals('8-bit INDEXED') then
@@ -744,6 +854,7 @@ procedure TMAT.toBMP(w, h: integer);
   inrow: pRGBQuadArray;
   src:   word;
   cmp:TCMPPal;
+  sl: PUInt64;
 //  Bsrc:byte;
 //  IndexArray: PByteArray;
 begin
@@ -807,17 +918,17 @@ procedure TMAT.toBMP(w, h: integer);
    matformat:=TFormat.RGBA4444;
    bmap.PixelFormat := pf32bit;
    bmap.HandleType :=  bmDIB;
-   bmap.Alphaformat := afDefined;
+   bmap.Alphaformat := afIgnored;  {setting as defined seems to cause pre multiplication after conversion}
     for j := 0 to bmap.Height - 1 do
     begin
       inrow := bmap.ScanLine[j];
       for i := 0 to bmap.Width - 1 do
       begin
         BlockRead(f, src, sizeof(src));
-        inrow[i].rgbRed := ((src and 61440) shr 12) * 17;
-        inrow[i].rgbGreen := ((src and 3840) shr 8) * 17;
-        inrow[i].rgbBlue := ((src and 240) shr 4) * 17;
-        inrow[i].rgbReserved := ((src and 15) shr 0) * 17;
+        inrow^[i].rgbRed := ((src and 61440) shr 12) * 17;
+        inrow^[i].rgbGreen := ((src and 3840) shr 8) * 17;
+        inrow^[i].rgbBlue := ((src and 240) shr 4) * 17;
+        inrow^[i].rgbReserved := ((src and 15) shr 0) * 17;
 
 //        inrow[i].rgbRed := ((src and 61440) shr 12) shl 4;
 //        inrow[i].rgbGreen := ((src and 3840) shr 8) shl 4;
@@ -827,10 +938,31 @@ procedure TMAT.toBMP(w, h: integer);
 
     end;
 
-     //bmap.TransparentColor:= bmap.canvas.pixels[0,0];
-     bmap.TransparentMode:= tmAuto;
    end;
 
+   if (matFormatHeader.bits = 24)  then
+     begin
+     matformat:=TFormat.RGB888;
+     bmap.PixelFormat := pf24bit;
+     bmap.HandleType :=  bmDIB;
+
+     for h := 0 to bmap.Height - 1 do
+         BlockRead(f, bmap.ScanLine[h]^, 3 * bmap.Width);
+     end;
+
+
+    if (matFormatHeader.bits = 32) and (matFormatHeader.ColorMode = 2) and (matFormatHeader.alpha_bpp = 8)   then
+     begin
+     matformat:=TFormat.RGBA8888;
+     bmap.PixelFormat := pf32bit;
+     bmap.HandleType :=  bmDIB;
+     bmap.Alphaformat := afIgnored  ;  {setting as defined seems to cause pre multiplication after conversion}
+
+     for h := 0 to bmap.Height - 1 do
+         BlockRead(f, bmap.ScanLine[h]^, 4 * bmap.Width);
+
+     end;
+
    //indexed
    if (matFormatHeader.bits = 8) and (matFormatHeader.ColorMode = 0) and (matFormatHeader.mat_Type = 2) then
    begin
diff --git a/Mat16.DPR b/Mat16.DPR
index b53bbaa..9234ea0 100644
--- a/Mat16.DPR
+++ b/Mat16.DPR
@@ -1,9 +1,15 @@
 program Mat16;
 
-{$R *.dres}
+
 
 uses
+ {$IFDEF DEBUG}
   FastMM4 in 'FastMM4\FastMM4.pas',
+  FastMM4DataCollector in 'FastMM4\FastMM4DataCollector.pas',
+  FastMM4LockFreeStack in 'FastMM4\FastMM4LockFreeStack.pas',
+  FastMM4Messages in 'FastMM4\FastMM4Messages.pas',
+ {$ENDIF}
+  //FastMM4 in 'FastMM4\FastMM4.pas',
   Forms,
   MAIN in 'MAIN.PAS' {MainForm},
   Batch in 'Batch.pas' {BatchForm},
@@ -23,13 +29,12 @@ uses
   ColorMap in 'ColorMap.pas',
   options in 'options.pas' {OptionsForm},
   CMPHeaders in 'CMPHeaders.pas',
-  FastMM4DataCollector in 'FastMM4\FastMM4DataCollector.pas',
-  FastMM4LockFreeStack in 'FastMM4\FastMM4LockFreeStack.pas',
-  FastMM4Messages in 'FastMM4\FastMM4Messages.pas',
+
   CNDHeaders in 'CNDHeaders.pas',
   Set8bitFormatOnOpen in 'Set8bitFormatOnOpen.pas' {Set8bitFormatForm},
   EditMat in 'EditMat.pas' {EditMatForm},
-  BMP_IO in 'BMP_IO.pas';
+  BMP_IO in 'BMP_IO.pas',
+  GloabalVars in 'GloabalVars.pas';
 
 // MemCheck;
 {$R *.RES}
@@ -47,7 +52,10 @@ MemChk;
  }
  //  ReportMemoryLeaksOnShutdown := DebugHook <> 0;
   // Application.CreateForm(TOptionsForm, OptionsForm);
-   {$INCLUDE FastMM4\FastMM4Options.inc}
+//   {$INCLUDE FastMM4\FastMM4Options.inc}
+ {$IFDEF DEBUG}
+  {$INCLUDE FastMM4\FastMM4Options.inc}
+ {$ENDIF}
   Application.CreateForm(TMainForm, MainForm);
   Application.CreateForm(Tgobview, gobview);
   Application.CreateForm(TViewTiled, ViewTiled);
diff --git a/Mat16.dproj b/Mat16.dproj
index 37963ac..0f392d4 100644
--- a/Mat16.dproj
+++ b/Mat16.dproj
@@ -8,7 +8,7 @@
         <FrameworkType>VCL</FrameworkType>
         <ProjectVersion>19.2</ProjectVersion>
         <Base>True</Base>
-        <Config Condition="'$(Config)'==''">Debug</Config>
+        <Config Condition="'$(Config)'==''">Release</Config>
         <Platform Condition="'$(Platform)'==''">Win32</Platform>
         <TargetedPlatforms>3</TargetedPlatforms>
         <AppType>Application</AppType>
@@ -103,6 +103,10 @@
     <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
         <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
         <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
+        <VerInfo_MajorVer>1</VerInfo_MajorVer>
+        <VerInfo_MinorVer>0</VerInfo_MinorVer>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)</VerInfo_Keys>
+        <Icon_MainIcon>Mat16_Icon.ico</Icon_MainIcon>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
         <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
@@ -192,30 +196,12 @@
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="dflt_Cell0_Mip0.bmp" Configuration="Debug" Class="ProjectFile">
-                    <Platform Name="Win32">
-                        <RemoteDir>.\</RemoteDir>
-                        <Overwrite>true</Overwrite>
-                    </Platform>
-                </DeployFile>
-                <DeployFile LocalName="dflt_Cell0.BMP" Configuration="Debug" Class="ProjectFile">
-                    <Platform Name="Win32">
-                        <RemoteDir>.\</RemoteDir>
-                        <Overwrite>true</Overwrite>
-                    </Platform>
-                </DeployFile>
                 <DeployFile LocalName="Mat16.exe" Configuration="Debug" Class="ProjectOutput">
                     <Platform Name="Win32">
                         <RemoteName>Mat16.exe</RemoteName>
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="dflt_Cell0_Mip1.bmp" Configuration="Debug" Class="ProjectFile">
-                    <Platform Name="Win32">
-                        <RemoteDir>.\</RemoteDir>
-                        <Overwrite>true</Overwrite>
-                    </Platform>
-                </DeployFile>
                 <DeployClass Name="AdditionalDebugSymbols">
                     <Platform Name="OSX32">
                         <Operation>1</Operation>
@@ -951,32 +937,16 @@
             <Form>OptionsForm</Form>
         </DCCReference>
         <DCCReference Include="CMPHeaders.pas"/>
-        <DCCReference Include="FastMM4\FastMM4DataCollector.pas"/>
-        <DCCReference Include="FastMM4\FastMM4LockFreeStack.pas"/>
-        <DCCReference Include="FastMM4\FastMM4Messages.pas"/>
         <DCCReference Include="CNDHeaders.pas"/>
         <DCCReference Include="Set8bitFormatOnOpen.pas">
             <Form>Set8bitFormatForm</Form>
-            <FormType>dfm</FormType>
         </DCCReference>
         <DCCReference Include="EditMat.pas">
             <Form>EditMatForm</Form>
-            <FormType>dfm</FormType>
         </DCCReference>
         <DCCReference Include="BMP_IO.pas"/>
+        <DCCReference Include="GloabalVars.pas"/>
         <None Include="FastMM4\FastMM4Options.inc"/>
-        <RcItem Include="dflt_Cell0.BMP">
-            <ResourceType>BITMAP</ResourceType>
-            <ResourceId>dflt_cell0</ResourceId>
-        </RcItem>
-        <RcItem Include="dflt_Cell0_Mip0.bmp">
-            <ResourceType>BITMAP</ResourceType>
-            <ResourceId>dflt_cell0_mip0</ResourceId>
-        </RcItem>
-        <RcItem Include="dflt_Cell0_Mip1.bmp">
-            <ResourceType>BITMAP</ResourceType>
-            <ResourceId>dflt_cell0_mip1</ResourceId>
-        </RcItem>
         <BuildConfiguration Include="Debug">
             <Key>Cfg_2</Key>
             <CfgParent>Base</CfgParent>
diff --git a/Mat16.dproj.local b/Mat16.dproj.local
index e2ba080..06e6b23 100644
--- a/Mat16.dproj.local
+++ b/Mat16.dproj.local
@@ -19,8 +19,8 @@
     <Transaction>2021/12/09 06:01:32.000.678,E:\Data\Users\8-Track\Desktop\mat16_104\dfltcmp.pas=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
     <Transaction>2021/12/09 06:05:47.000.867,E:\Data\Users\8-Track\Desktop\mat16_104\CMPHeaders.pas=E:\Data\Users\8-Track\Desktop\mat16_104\dfltcmp.pas</Transaction>
     <Transaction>2021/12/28 11:45:15.000.992,=E:\Data\Users\8-Track\Desktop\mat16_104\FastMM4\FastMM4.pas</Transaction>
-    <Transaction>2021/12/28 11:46:18.000.764,=E:\Data\Users\8-Track\Desktop\mat16_104\FastMM4\FastMM4Messages.pas</Transaction>
     <Transaction>2021/12/28 11:46:18.000.719,=E:\Data\Users\8-Track\Desktop\mat16_104\FastMM4\FastMM4LockFreeStack.pas</Transaction>
+    <Transaction>2021/12/28 11:46:18.000.764,=E:\Data\Users\8-Track\Desktop\mat16_104\FastMM4\FastMM4Messages.pas</Transaction>
     <Transaction>2021/12/28 11:46:18.000.658,=E:\Data\Users\8-Track\Desktop\mat16_104\FastMM4\FastMM4DataCollector.pas</Transaction>
     <Transaction>2021/12/28 12:00:51.000.427,=E:\Data\Users\8-Track\Desktop\mat16_104\FastMM4\FastMM4Options.inc</Transaction>
     <Transaction>2022/01/09 18:33:00.000.494,=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
@@ -29,17 +29,23 @@
     <Transaction>2022/01/09 18:34:15.000.139,=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
     <Transaction>2022/01/09 18:34:40.000.164,E:\Data\Users\8-Track\Desktop\mat16_104\CNDHeaders.pas=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
     <Transaction>2022/01/16 12:24:41.000.082,=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
-    <Transaction>2022/01/16 12:28:51.000.440,E:\Data\Users\8-Track\Desktop\mat16_104\Set8bitFormatOnOpen.dfm=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.dfm</Transaction>
     <Transaction>2022/01/16 12:28:51.000.440,E:\Data\Users\8-Track\Desktop\mat16_104\Set8bitFormatOnOpen.pas=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
+    <Transaction>2022/01/16 12:28:51.000.440,E:\Data\Users\8-Track\Desktop\mat16_104\Set8bitFormatOnOpen.dfm=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.dfm</Transaction>
     <Transaction>2022/01/17 07:39:35.000.920,E:\Data\Users\8-Track\Desktop\mat16_104\mat_read.pas=</Transaction>
-    <Transaction>2022/01/17 07:59:06.000.518,=E:\Data\Users\8-Track\Desktop\mat16_104\dflt_Cell0_Mip0.bmp</Transaction>
-    <Transaction>2022/01/17 07:59:06.000.556,=E:\Data\Users\8-Track\Desktop\mat16_104\dflt_Cell0_Mip1.bmp</Transaction>
     <Transaction>2022/01/17 07:59:06.000.487,=E:\Data\Users\8-Track\Desktop\mat16_104\dflt_Cell0.BMP</Transaction>
+    <Transaction>2022/01/17 07:59:06.000.556,=E:\Data\Users\8-Track\Desktop\mat16_104\dflt_Cell0_Mip1.bmp</Transaction>
+    <Transaction>2022/01/17 07:59:06.000.518,=E:\Data\Users\8-Track\Desktop\mat16_104\dflt_Cell0_Mip0.bmp</Transaction>
     <Transaction>2022/01/17 12:06:43.000.549,=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
-    <Transaction>2022/01/17 12:07:17.000.697,E:\Data\Users\8-Track\Desktop\mat16_104\EditMat.dfm=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.dfm</Transaction>
     <Transaction>2022/01/17 12:07:17.000.697,E:\Data\Users\8-Track\Desktop\mat16_104\EditMat.pas=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
+    <Transaction>2022/01/17 12:07:17.000.697,E:\Data\Users\8-Track\Desktop\mat16_104\EditMat.dfm=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.dfm</Transaction>
     <Transaction>2022/01/23 17:21:32.000.083,=E:\Data\Users\8-Track\Desktop\mat16_104\BMP_IO.pas</Transaction>
     <Transaction>2022/01/27 19:34:50.000.726,=E:\Data\Users\8-Track\Desktop\mat16_104\Vcl.Graphics.pas</Transaction>
     <Transaction>2022/01/27 19:51:22.000.595,E:\Data\Users\8-Track\Desktop\mat16_104\Vcl.Graphics.pas=</Transaction>
+    <Transaction>2022/12/09 07:48:40.000.051,=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
+    <Transaction>2022/12/09 07:49:04.000.137,E:\Data\Users\8-Track\Desktop\mat16_104\GloabalVars.pas=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
+    <Transaction>2022/12/14 06:44:08.000.675,=E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas</Transaction>
+    <Transaction>2022/12/14 06:44:49.000.656,E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.dfm=E:\Data\Users\8-Track\Desktop\mat16_104\EditMTS.dfm</Transaction>
+    <Transaction>2022/12/14 06:44:49.000.656,E:\Data\Users\8-Track\Desktop\mat16_104\Unit1.pas=E:\Data\Users\8-Track\Desktop\mat16_104\EditMTS.pas</Transaction>
+    <Transaction>2022/12/15 07:15:57.989,E:\Data\Users\8-Track\Desktop\mat16_104\EditMTS.pas=</Transaction>
   </Transactions>
 </BorlandProject>
diff --git a/Mat16.dres b/Mat16.dres
deleted file mode 100644
index 1fee3bbc0dfb3447c91209fedea49431668e23c4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4740
zcmeH~FKpv>6vsa|ZOTpoo)lmZ;FAJeDZsa7k~L*gPV#ovl$$)MlMDh34AROVz#t$X
zARr(hz@Q)?z#t$XAi$uYz@Q)?AfTWipdc`?V5+>A>ovNoc7Fy2rshRo=lS>Nz2~Q&
zpT7^_g&@oBA?gQm^ey}-BU$zpzwnwj{E3IfucE!-<$mo;o`3ytb0o@(cX);v*vWoY
z^k;8J?l0n(g<vEI1XTh5Fqqv!d<E_dw7#tIB&LjPvnIPr$<ml?CgW4tI~GKOo}eXY
z2y8(`P!cGzPb}Qs-En(+%XYiv=H`a$>uXl46^q4!G)*}_KW9FlGo4O}<CxKCL=;5~
z1_OG%9-U5yFboNT0N?j<T^Gl3ux*=Kt%hlu7>0qa>u8#Ws;Vf8LN1rvJtXVP3$88_
zmdTvOd`dcvIgiIA<1=Pw5tHG7c+h9m>k@U^4B8?6RzNps()K+<uR$O_{bL8OUdOd9
z9PwMPnpl+zRq<_>b&OI8UHq4dD#b#9g2bTY^URkS!`X(`aEaSas5Qov?LNgy3#H`V
zABgk@hL_+^p%zK*+mLTa^cItBO@F(jxxS#joKv}&pv}hQC4QnIntzGvCKT#Z^0g5;
zb4bqUf*y*Urr7vPAodaah<%0vnL~W@6PIz9Y1bq2EIL*hPgk)Ec??OPDl6<Tr4}Sq
z{TY=;jNy(bI}s&$2F>bHtcIv&K*8`)$}WoTkk>47#VR?q!hDl4T5aj4YufV_ew=a~
zCD{E5X8VkCbAZ<9pgNKd%Oh_(<jR)BUXcKFnwuWS%MdH^F~`T02R2$*MQs=;c8P3~
zvFWZ^dMSw&GcNb(s{yT?LjzOJ;1mAIyL<W>Ir+4FZujXApOVv)!~7vXAJ4$yeEjF{
z$I&<Nv()jAaSM;%`HesJEaNf9_)hlju;&=>^NRQN-N*jGF%BH#z%iZ{<M;xO@!<#H
z^ij?G|KFcT-}NOm_IoLjJ9%7Vcir0#4>k6c=zBTT*te-T^l^ti?#Xs?Qez+5w0E`i
I<lp}P4bza5dH?_b

diff --git a/Mat16.res b/Mat16.res
index dda8ecb89890fc6e5bbbcc2515e75e3a89a93345..c1282a4c1d9f9ae01d8c4ff348713074067a98ca 100644
GIT binary patch
delta 18
ZcmZ3Wx<GY80VBi2!u^Z}n++NB1pz&U1>*n!

delta 18
ZcmZ3Wx<GY80VB)A!u^aUn++NB1pz(D1?vC+

diff --git a/Util.pas b/Util.pas
index 665fb71..f1413e5 100644
--- a/Util.pas
+++ b/Util.pas
@@ -2,7 +2,7 @@
 
 interface
 
-uses Windows, Classes, ComCtrls, StdCtrls, SysUtils,vcl.graphics,vcl.controls;
+uses Windows, Classes, ComCtrls, StdCtrls, SysUtils,vcl.graphics,vcl.controls,Vcl.Dialogs;
 
 function ExtractName(path: string): string;
 function ChangeExt(path: string; const newExt: string): string;
@@ -16,6 +16,7 @@ procedure Blend(First,second:Tbitmap);
 procedure TransBlt(dst,src:Tbitmap; color:longint);
 function IsBMPPowerOfTwo(x,y: integer): boolean;
 function IsBMPmipsOK(Abitmap:tbitmap): boolean;
+procedure PremultiplyAlpha(bmp:Tbitmap);
 implementation
 
 function ExtractName(path: string): string;
@@ -204,11 +205,36 @@ procedure Blend(First,second:Tbitmap);
     end;
 
 
+procedure PremultiplyAlpha(bmp:Tbitmap);
+var
+ inrow32: PRGBQuad;
+ j,i:integer;
+begin
+ for j := 0 to bmp.Height - 1 do
+    begin
+      inrow32 := bmp.ScanLine[j];
+      for i := 0 to bmp.Width - 1 do
+      begin
+        with inrow32^ do
+        begin
+            // must pre-multiply the pixel with its alpha channel before drawing
+            rgbRed:=   (rgbRed * rgbReserved) div 255;
+            rgbGreen:= (rgbGreen * rgbReserved) div 255;
+            rgbBlue:=  (rgbBlue * rgbReserved) div 255;
+            inc(inrow32);
+            end;
+       end;
+      end;
+end;
+
+
 function IsBMPmipsOK(Abitmap:tbitmap): boolean;
 begin
   if (Abitmap.Width >= 8) and (Abitmap.Height >=8) and
      (Abitmap.PixelFormat <> pf32bit) then
   result:=true;
+
+
 end;
 
 function IsBMPPowerOfTwo(x,y: integer): boolean;
diff --git a/about_unit.dfm b/about_unit.dfm
index d814836196e6a7564a04c08f97be12b714380d16..464d366dd908abe03f471634364c23e8ef6bce5c 100644
GIT binary patch
delta 26
gcmZoT%+dfvTNqEua=4@>D;OCV8EwBP%ebBy0E5s7`~Uy|

delta 26
gcmZoT%+dfvTNqEua`@$!DHs_T8E(HQ%ebBy0EN2=A^-pY

diff --git a/gobform.dfm b/gobform.dfm
index 451246ff86921407493ac5d9e6679172e0a93d31..233443481de49c259b7e41c35993fd3709d6ea25 100644
GIT binary patch
delta 150
zcmdnSznP!^KNmxYyT4PIr)xNafxyCv{7r%>jNHySnW=dt;h8BV8O+-mHZJ03<l<n3
za91;I-p*LYY8RGSoSBr9%E7?E9^zD5Qj(v?<D8#YmReL2lJAsTz~YmdR>CB~9Fkwa
jY{3Z8%T&qck(!yFQNkoMxtQHpR1jGM(8}a&1_lNIii|Cf

delta 153
zcmdnYzm1>&KNmxYyT4PIr)xNafxwc9{7r(@jNHySnW=dt;h8BV8O)808y9gia<Q>O
zxVem*w=<Tpy7}h;6(wi0^Ej23l;r0bf_V%K>>&_7JA^V~@kvc9VUl1D$uD4zW`vl*
aRLSO%nwg$a!X!93o84FdYJ?Hg2nGQ6v@M4K

diff --git a/gobform.pas b/gobform.pas
index d844171..44eedd5 100644
--- a/gobform.pas
+++ b/gobform.pas
@@ -31,7 +31,7 @@   Tgobview = class(TForm)
     Label15:   TLabel;
     Label16:   TLabel;
     Label17:   TLabel;
-    Button2:   TButton;
+    ConvertToBmp: TButton;
     Label18:   TLabel;
     Label_CMP: TLabel;
     procedure ListBox1Click(Sender: TObject);
@@ -39,8 +39,7 @@   Tgobview = class(TForm)
     procedure opengob(filename: string);
     procedure openbaf(filename: string);
     procedure FormClose(Sender: TObject; var Action: TCloseAction);
-    procedure Button1Click(Sender: TObject);
-    procedure Button2Click(Sender: TObject);
+    procedure ConvertToBmpClick(Sender: TObject);
   private
     { Private declarations }
   public
@@ -55,7 +54,7 @@   Tgobview = class(TForm)
 
 implementation
 
-uses Batch;
+uses Batch,GloabalVars;
 
 {$R *.DFM}
 
@@ -138,7 +137,7 @@ procedure Tgobview.FormShow(Sender: TObject);
  FileOffsets:=bafFilesToArray(filename, '.MAT');
  tempList:=gobFileArrayToList(FileOffsets);
  ListBox1.Items.Assign(tempList);
-tempList.Free;
+ tempList.Free;
 
  end;
 
@@ -158,64 +157,28 @@ procedure Tgobview.opengob(filename: string);
 procedure Tgobview.FormClose(Sender: TObject; var Action: TCloseAction);
 begin
   listbox1.Clear;
-end;
+  SetLength(FileOffsets,0);
+  SetLength(CMPOffsets,0);
 
-procedure Tgobview.Button1Click(Sender: TObject);
-begin
-  main.MainForm.Image1.Picture.Bitmap.Assign(image1.Picture.Bitmap);
- // main.MainForm.LabelWidth.Caption := Label6.Caption;
-  main.MainForm.LabelHeight.Caption := Label17.Caption;
-  main.MainForm.LabelFormat.Caption := label15.Caption;
-  main.MainForm.Label3.Caption := '1';
-  image1.Picture.Bitmap.FreeImage;
-  listbox1.Clear;
-  gobview.Close;
 end;
 
-procedure Tgobview.Button2Click(Sender: TObject);
+procedure Tgobview.ConvertToBmpClick(Sender: TObject);
 var
   i: integer;
-  savebitmap: Tbitmap;
-  bestcmp, gpath, mpath, fext, mname: string;
 begin
- // savebitmap := Tbitmap.Create;
-  gpath := ExtractFilePath(Label_FileName.Caption);
-  fext  := ExtractName(Label_FileName.Caption);
-  fext  := ChangeFileExt(fext, '');
-  gpath := gpath + fext;
   Screen.Cursor := crHourGlass;
-  CreateDir(gpath);
   BatchForm.Show;
-
   BatchForm.ProgressBar1.Max := ListBox1.Items.Count;
 
-
   for i := 0 to (ListBox1.Items.Count - 1) do
   begin
     BatchForm.ProgressBar1.Position := i;
-    //savebitmap := Tbitmap.Create;
-    //savebitmap:=nil;
-    bestcmp    := GetbestCMP(listBox1.Items.Strings[i], Label_FileName.Caption);
- //   ReadCMPfromGOB(Label_FileName.Caption, bestcmp);
-    mainform.gridPalette.Repaint;
-
- //   saveBitmap:=ReadMatfromGOB(Label_FileName.Caption, listBox1.Items.Strings[i]);
-    mname      := ExtractName(listBox1.Items.Strings[i]);
-    mname      := ChangeFileExt(mname, '.BMP');
-    mpath      := gpath + '\' + mname;
-    saveBitmap.SaveToFile(mpath);
-
-    BatchForm.Memo1.Lines.Add('Saved ' + mpath + ' cmp:' + bestcmp);
+    BatchForm.Memo1.Lines.Add(GobMatSavetoBMP(Label_FileName.Caption, listBox1.Items.Strings[i],FileOffsets,CMPOffsets,true));
     application.ProcessMessages;
-
-    saveBitmap.Free;
-
   end;
 
   BatchForm.Memo1.Lines.Add('-Done-');
   Screen.Cursor := crDefault;
-
-  //if Assigned(saveBitmap) then saveBitmap.Free;
 end;
 
 end.
diff --git a/gobgoo.pas b/gobgoo.pas
index ab6d2ef..47fa9bf 100644
--- a/gobgoo.pas
+++ b/gobgoo.pas
@@ -2,7 +2,7 @@
 
 interface
 
-uses  Classes, SysUtils,Vcl.Dialogs,CMPHeaders;
+uses  Classes, SysUtils,Vcl.Dialogs,CMPHeaders,colormap,GloabalVars,MATImage,BMParrays,util,System.StrUtils;
 
 type
 
@@ -48,6 +48,9 @@ function gobFilesToArray(gobfilename: string; filetype:string):TFileOffsets;
 function bafFilesToArray(gobfilename: string; filetype:string):TFileOffsets;
 function bafFilesToList(gobfilename: string; filetype:string):TstringList;
 function gobFileArrayToList(FileOffsets: TFileOffsets):TstringList;
+function GobMatSavetoBMP(gobfile: string; fileinGobName: string;FileOffsets: TFileOffsets;CMPOffsets: TFileOffsets;MatInGob:boolean):String;
+function GobMatToArray(gobfile: string; fileinGobName: string;
+           FileOffsets: TFileOffsets;CMPOffsets: TFileOffsets):TBMPArray;
  //procedure gobview.ListBox1Click(Sender: TObject);
  //TGOB2Directory=class(TContainerFile)
  //gh:TGob2Header;
@@ -139,6 +142,103 @@ function GetGOBArrayOffset(FileOffsets: TFileOffsets; fileinGobName: string):lon
 
 
 {GOB2}
+function GobMatToArray(gobfile: string; fileinGobName: string;
+           FileOffsets: TFileOffsets;CMPOffsets: TFileOffsets):TBMPArray;
+var
+bestcmp:string;
+pos: integer;
+gobCMP:TCMP;
+Mat: TMAT;
+begin
+ gobCMP:=TCMP.create;
+  {load jk or mots cmp}
+   if (UpperCase(ExtractFileExt(gobfile)) = '.GOB') or
+     (UpperCase(ExtractFileExt(gobfile)) = '.GOO') or
+     (UpperCase(ExtractFileExt(gobfile)) = '') then
+     begin
+     bestcmp    := GetbestCMP(fileinGobName, JKPath);
+     pos:=GetGOBArrayOffset(CMPOffsets, bestcmp);
+     gobCMP.LoadCMPFromFile(jkpath, pos);
+     end;
+    {phantom menace cmp}
+   if (UpperCase(ExtractFileExt(gobfile)) = '.BAF') then
+     begin
+     gobCMP.LoadCMPFromBAFFile(gobfile, 336);
+     end;
+
+    Mat:=TMAT.Create(TFormat.BMP);
+    Mat.SetCMP(gobCMP.GetRGB);
+
+     pos:=GetGOBArrayOffset(FileOffsets, fileinGobName);
+     Result:= Mat.LoadFromFile(gobfile, pos);
+
+ Mat.Free;
+ gobCMP.Free;
+ Mat:=nil;
+
+end;
+
+
+function GobMatSavetoBMP(gobfile: string; fileinGobName: string;FileOffsets: TFileOffsets;CMPOffsets: TFileOffsets;MatInGob:boolean):String;
+var
+bestcmp:string;
+pos: integer;
+gobCMP:TCMP;
+Mat: TMAT;
+tempA:TBMPArray;
+gpath, mpath: string;
+begin
+  gobCMP:=TCMP.create;
+  {load jk or mots cmp}
+   if (UpperCase(ExtractFileExt(gobfile)) = '.GOB') or
+     (UpperCase(ExtractFileExt(gobfile)) = '.GOO') or
+     (UpperCase(ExtractFileExt(gobfile)) = '') then
+     begin
+     bestcmp    := GetbestCMP(fileinGobName, JKPath);
+     pos:=GetGOBArrayOffset(CMPOffsets, bestcmp);
+     gobCMP.LoadCMPFromFile(jkpath, pos);
+     end;
+    {phantom menace cmp}
+   if (UpperCase(ExtractFileExt(gobfile)) = '.BAF') then
+     begin
+     gobCMP.LoadCMPFromBAFFile(gobfile, 336);
+     end;
+
+    Mat:=TMAT.Create(TFormat.BMP);
+    Mat.SetCMP(gobCMP.GetRGB);
+
+    if MatInGob then
+     begin
+     pos:=GetGOBArrayOffset(FileOffsets, fileinGobName);
+     tempA:= Mat.LoadFromFile(gobfile, pos);
+     gpath := ExtractFilePath(gobfile);
+     mpath := gpath + ExtractName(fileinGobName);
+     end
+    else
+     begin
+     tempA:= Mat.LoadFromFile(fileinGobName);
+     mpath := fileinGobName;
+     end;
+
+    {8.3 filename bug workaround}
+    if ContainsText(mpath,'~1') then
+        mpath:= StringReplace(mpath, '~1', '_1', [rfReplaceAll, rfIgnoreCase]);
+
+    tempA.SaveMTS(mpath);
+
+    Result:='Saved MTS and bmp(s): '
+      + ExtractName(fileinGobName)
+      + ' cmp: ' + bestcmp;
+
+    Mat.Free;
+    tempA.Free;
+    gobCMP.Free;
+    Mat:=nil;
+    tempA:=nil
+
+ end;
+
+
 procedure opengob(filename: string);
 var //Fi:TFInfo;
   i:   integer;