unit uArt;

interface

uses Classes, SysUtils, GR32, Dialogs, Graphics, uHues, uTiledata, Math, uUtilities;

type TArt = class
private
        idxStream, mulStream: TStream;
        miStream, mmStream : TMemoryStream;
        fiStream, fmStream : TFileStream;
public
        loaded: Boolean;
        constructor Create;
        destructor Free;
        procedure Load( idxPath, mulPath : String );
        procedure Save( idxPath, mulPath : String );
        function MapExists( Id : Integer ) : Boolean;
        function StaticExists( Id : Integer ) : Boolean;
        function GetStaticTile( Id : Integer ) : TBitmap32; Overload;
        function GetStaticTile24( Id : Integer ) : TBitmap; Overload;
        function GetStaticTileHeight( Id : Integer ) : Integer;
        function GetStaticTileWidth( Id : Integer ) : Integer;        
        procedure PaintStaticTile( Id, X, Y : Integer; Bitmap : TBitmap32 ); Overload;
        procedure PaintStaticTile24( Id, X, Y, Color : Integer; Bitmap : TBitmap );
        procedure PaintMapTile24( Id, X, Y, ItemColor : Integer; Bitmap : TBitmap ); Overload;
        function GetMapTile( Id: Integer ): TBitmap32;
        procedure LoadMapTile( Id: Integer; FilePath : String );
        procedure LoadStaticTile( Id: Integer; FilePath : String );
        procedure DeleteMap( Id : Integer );
        procedure DeleteStatic( Id : Integer );
        function GetAverageMapColor( Id : Integer ) : Integer;
        function GetAverageStaticColor( Id : Integer ) : Integer;
        procedure ReIndex( idxPath, mulPath : String );
        procedure ShowStaticDetails( Id : Integer );
        procedure SetStaticTag( Id, Tag : Integer );
        function GetStaticCount : Word;
        procedure FillStatics;
        procedure Encrypt( Id : Integer; var IndexRecord : TIndexRecord );
        procedure Decrypt( Id : Integer; var IndexRecord : TIndexRecord );
end;

var
        Art: TArt;

implementation

uses StrLib, uGaugeForm, uMulpatcher;

constructor TArt.Create;
begin
        miStream := TMemoryStream.Create;
        mmStream := TMemoryStream.Create;
        
        loaded := false;
end;

destructor TArt.Free;
begin
        miStream.Free;
        mmStream.Free;
        if MainForm.LowMemory then begin
                fiStream.Free;
                fmStream.Free;
        end;
end;

procedure TArt.Load( idxPath, mulPath : String );
begin
        if not MainForm.LowMemory then begin
                miStream.LoadFromFile( idxPath );
                mmStream.LoadFromFile( mulPath );
                idxStream := miStream;
                mulStream := mmStream;
        end
        else begin
                fiStream := TFileStream.Create( idxPath, fmOpenReadWrite );
                fmStream := TFileStream.Create( mulPath, fmOpenReadWrite );
                idxStream := fiStream;
                mulStream := fmStream;
        end;
        loaded := true;
end;

procedure TArt.Save( idxPath, mulPath : String );
begin
        if not MainForm.LowMemory then begin
                miStream.SaveToFile( idxPath );
                mmStream.SaveToFile( mulPath );
        end;
end;

function TArt.MapExists( Id : Integer ) : Boolean;
var     IndexRec : TIndexRecord;
begin
        idxStream.Seek( Id*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id, IndexRec );

        if ( IndexRec.Offset <> -1 ) and ( IndexRec.Length > 0 ) then
                Result := true
        else
                Result := false;
end;

function TArt.StaticExists( Id : Integer ) : Boolean;
var     IndexRec : TIndexRecord;
begin
        if (Id+$4000)*12 >= idxStream.Size then begin
                Result := False;
                exit;
        end;

        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id+$4000, IndexRec );

        if ( IndexRec.Offset <> -1 ) and ( IndexRec.Length > 0 ) then
                Result := true
        else
                Result := false;
end;

function TArt.GetStaticTile( Id : Integer ) : TBitmap32;
var     Breite, Hoehe : Word;
        IndexRec : TIndexRecord;
begin
        Result := TBitmap32.Create;

        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id+$4000, IndexRec );

        mulStream.Seek( IndexRec.Offset+4, soFromBeginning );
        mulStream.Read( Breite, 2 );
        mulStream.Read( Hoehe, 2 );

        Result.SetSize( Breite, Hoehe );
        Result.Clear( Color32( clWhite ) );
        PaintStaticTile( Id, 0, 0, Result );
end;

function TArt.GetStaticTile24( Id : Integer ) : TBitmap;
var     Breite, Hoehe : Word;
        IndexRec : TIndexRecord;
begin
        Result := TBitmap.Create;

        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id+$4000, IndexRec );

        mulStream.Seek( IndexRec.Offset+4, soFromBeginning );
        mulStream.Read( Breite, 2 );
        mulStream.Read( Hoehe, 2 );

        Result.Width := Breite;
        Result.Height := Hoehe;
        PaintStaticTile24( Id, 0, 0, 0, Result );
end;

function TArt.GetStaticTileHeight( Id : Integer ) : Integer;
var     Breite, Hoehe : Word;
        IndexRec : TIndexRecord;
begin
        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id+$4000, IndexRec );

        mulStream.Seek( IndexRec.Offset+4, soFromBeginning );
        mulStream.Read( Breite, 2 );
        mulStream.Read( Hoehe, 2 );

        Result := Hoehe;
end;

function TArt.GetStaticTileWidth( Id : Integer ) : Integer;
var     Breite, Hoehe : Word;
        IndexRec : TIndexRecord;
begin
        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id+$4000, IndexRec );

        mulStream.Seek( IndexRec.Offset+4, soFromBeginning );
        mulStream.Read( Breite, 2 );
        mulStream.Read( Hoehe, 2 );

        Result := Breite;
end;

procedure TArt.PaintStaticTile( Id, X, Y : Integer; Bitmap : TBitmap32 );
var     Breite, Hoehe : Word;
        LookupList : PWordArray;
        XOffset, RunLength, RunColor: Word;
        Start, XCoord, YCoord : Integer;
        i : Integer;
        IndexRec : TIndexRecord;
begin
        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id+$4000, IndexRec );

        mulStream.Seek( IndexRec.Offset+4, soFromBeginning );
        mulStream.Read( Breite, 2 );
        mulStream.Read( Hoehe, 2 );

        GetMem( LookupList, Hoehe*2 );
        mulStream.Read( LookupList^, Hoehe*2 );
        Start := mulStream.Position;

        for YCoord := 0 to Hoehe-1 do begin
                mulStream.Seek( Start + LookupList^[YCoord]*2, soFromBeginning );
                XCoord := 0;

                mulStream.Read( XOffset, 2 );
                mulStream.Read( RunLength, 2 );

                while ( RunLength <> 0 ) do begin
                        XCoord := XCoord + XOffset;

                        for i := 0 to RunLength-1 do begin
                                mulStream.Read( RunColor, 2 );
                                if ( XCoord+X+i < Bitmap.Width ) and ( YCoord+Y < Bitmap.Height ) and ( XCoord+X >= 0 ) and ( YCoord+Y >= 0 ) and ( RunColor <> 32767 ) then
                                        Bitmap.Pixel[ XCoord+i+X, YCoord+Y ] := Color15to32( RunColor );
                        end;

                        XCoord := XCoord + RunLength;
                        mulStream.Read( XOffset, 2 );
                        mulStream.Read( RunLength, 2 );
                end;
        end;
end;

procedure TArt.PaintStaticTile24( Id, X, Y, Color : Integer; Bitmap : TBitmap );
var     Breite, Hoehe : Word;
        LookupList : PWordArray;
        XOffset, RunLength : Word;
        Start, XCoord, YCoord : Integer;
        i : Integer;
        IndexRec : TIndexRecord;
        ColorArray : PWordArray;
        RunColor : TColor32;
        Red, Blue, Green, Index : Byte;
        PartialHue : Boolean;
begin
        Bitmap.PixelFormat := pf24Bit;
        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id+$4000, IndexRec );

        mulStream.Seek( IndexRec.Offset+4, soFromBeginning );
        mulStream.Read( Breite, 2 );
        mulStream.Read( Hoehe, 2 );

        GetMem( LookupList, Hoehe*2 );
        mulStream.Read( LookupList^, Hoehe*2 );
        Start := mulStream.Position;

        PartialHue := Tiledata.GetStaticFlag( Id, dPARTIALHUE );

        for YCoord := 0 to Hoehe-1 do begin
                mulStream.Seek( Start + LookupList^[YCoord]*2, soFromBeginning );
                XCoord := 0;

                mulStream.Read( XOffset, 2 );
                mulStream.Read( RunLength, 2 );

                while ( RunLength <> 0 ) do begin
                        XCoord := XCoord + XOffset;

                        GetMem( ColorArray, RunLength*2 );
                        mulStream.Read( ColorArray^, RunLength*2 );
                        for i := 0 to RunLength-1 do begin
                                if ( XCoord+X < Bitmap.Width ) and ( YCoord+Y < Bitmap.Height ) and ( XCoord+X >= 0 ) and ( YCoord+Y >= 0 ) then begin
                                        RunColor := Color15to32( ColorArray^[i] );
                                        if RunColor = 0 then RunColor := 1;
                                        if Color = 0 then begin
                                                Bitmap.Canvas.Pixels[ XCoord+i+X, YCoord+Y ] := WinColor( RunColor );
                                        end
                                        else if Color > 0 then begin
                                                if PartialHue then begin
                                                        Red := RedComponent( RunColor );
                                                        Green := GreenComponent( RunColor );
                                                        Blue := BlueComponent( RunColor );
                                                        if (Green = Red) and (Red = Blue) then begin
                                                                Index := Red div 8;
                                                                if Index = 0 then Index := 1;
                                                                Bitmap.Canvas.Pixels[ XCoord+i+X, YCoord+Y ] := WinColor( Max( Color15to32( Hues.GetColor( Color-1, Index ) ), 1 ) );
                                                        end;
                                                end
                                                else begin
                                                        Red := RedComponent( RunColor );
                                                        Index := Red div 8;
                                                        if Index = 0 then Index := 1;
                                                        Bitmap.Canvas.Pixels[ XCoord+i+X, YCoord+Y ] := WinColor( Max( Color15to32( Hues.GetColor( Color-1, Index ) ), 1 ) );
                                                end;
                                        end
                                        else if Color = -1 then begin
                                                Red := RedComponent( RunColor );
                                                Index := Red div 8;
                                                if Index = 0 then Index := 1;                                                
                                                Bitmap.Canvas.Pixels[ XCoord+i+X, YCoord+Y ] := WinColor( Max( Color15to32( Hues.GetColor( $9a, Index ) ), 1 ) );
                                        end;
                                end;
                        end;
                        FreeMem( ColorArray, RunLength*2 );

                        XCoord := XCoord + RunLength;
                        mulStream.Read( XOffset, 2 );
                        mulStream.Read( RunLength, 2 );
                end;
        end;
end;

procedure TArt.PaintMapTile24( Id, X, Y, ItemColor : Integer; Bitmap : TBitmap );
var     YCoord, XCoord : Integer;
        Color : Word;
        IndexRec : TIndexRecord;
        Red, Index : Byte;
        Farbe : TColor32;       
begin
        Bitmap.PixelFormat := pf24Bit;
        idxStream.Seek( Id*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id, IndexRec );

        mulStream.Seek( IndexRec.Offset, soFromBeginning );
        for YCoord := 0 to 21 do begin
                for XCoord := 0 to (YCoord+1)*2-1 do
                        if ( XCoord+X < Bitmap.Width ) and ( YCoord+Y < Bitmap.Height ) and ( XCoord+X >= 0 ) and ( YCoord+Y >= 0 ) then begin
                                mulStream.Read( Color, 2 );
                                Farbe := Color15to32( Color );
                                if Farbe = 0 then Farbe := 1;
                                if ItemColor <> -1 then begin
                                        Bitmap.Canvas.Pixels[ X+21-YCoord+XCoord, Y+YCoord ] := WinColor( Farbe );
                                end
                                else begin
                                        Red := RedComponent( Farbe );
                                        Index := Red div 8;
                                        if Index = 0 then Index := 1;
                                        Bitmap.Canvas.Pixels[ X+21-YCoord+XCoord, Y+YCoord ] := WinColor( Max( Color15to32( Hues.GetColor( $9a, Index ) ), 1 ) );
                                end;
                        end;
        end;
        for YCoord := 0 to 21 do begin
                for XCoord := 0 to 43-YCoord*2 do
                        if ( XCoord+X < Bitmap.Width ) and ( YCoord+Y < Bitmap.Height ) and ( XCoord+X >= 0 ) and ( YCoord+Y >= 0 ) then begin
                                mulStream.Read( Color, 2 );
                                Farbe := Color15to32( Color );
                                if Farbe = 0 then Farbe := 1;
                                if ItemColor <> -1 then begin
                                        Bitmap.Canvas.Pixels[ X+YCoord+XCoord, Y+YCoord+22 ] := WinColor( Farbe );
                                end
                                else begin
                                        Red := RedComponent( Farbe );
                                        Index := Red div 8;
                                        if Index = 0 then Index := 1;                                        
                                        Bitmap.Canvas.Pixels[ X+YCoord+XCoord, Y+YCoord+22 ] := WinColor( Max( Color15to32( Hues.GetColor( $9a, Index ) ), 1 ) );
                                end;
                        end;
        end;
end;

function TArt.GetMapTile( Id : Integer ) : TBitmap32;
var     y, x : Integer;
        Color : Word;
        IndexRec : TIndexRecord;        
begin
        Result := TBitmap32.Create;

        idxStream.Seek( Id*12, soFromBeginning );
        idxStream.Read( IndexRec, sizeof( TIndexRecord ) );

        Decrypt( Id, IndexRec );

        mulStream.Seek( IndexRec.Offset, soFromBeginning );
        Result.SetSize( 44, 44 );
        Result.Clear( Color32( clWhite ) );        
        for y := 0 to 21 do begin
                for x := 0 to (y+1)*2-1 do begin
                        mulStream.Read( Color, 2 );
                        Result.Pixel[ 21-y+x, y ] := Color15to32( Color );
                end;
        end;
        for y := 0 to 21 do begin
                for x := 0 to 43-y*2 do begin
                        mulStream.Read( Color, 2 );
                        Result.Pixel[ y+x, y+22 ] := Color15to32( Color );
                end;
        end;
end;

procedure TArt.LoadMapTile( Id : Integer; FilePath : String );
var     Bitmap : TBitmap;
        x, y : Integer;
        Color32 : Integer;
        Color15 : Word;
        IndexRec : TIndexRecord;
begin
        Bitmap := TBitmap.Create;
        Bitmap.LoadFromFile( FilePath );

        mulStream.Seek( 0, soFromEnd );
        IndexRec.Offset := mulStream.Position;

        for y := 0 to 21 do begin
                for x := 0 to (y+1)*2-1 do begin
                        Color32 := Bitmap.Canvas.Pixels[ 21-y+x, y ];
                        Color15 := ((Color32 and $F80000) shr 19) or ((Color32 and $F800) shr 6) or ((Color32 and $F8) shl 7);
                        mulStream.Write( Color15, 2 );
                end;
        end;
        for y := 0 to 21 do begin
                for x := 0 to 43-y*2 do begin
                        Color32 := Bitmap.Canvas.Pixels[ y+x, y+22 ];
                        Color15 := ((Color32 and $F80000) shr 19) or ((Color32 and $F800) shr 6) or ((Color32 and $F8) shl 7);
                        mulStream.Write( Color15, 2 );
                end;
        end;

        IndexRec.Length := mulStream.Position - IndexRec.Offset;
        IndexRec.Extra := 0;

        Encrypt( Id, IndexRec );

        idxStream.Seek( Id*12, soFromBeginning );
        idxStream.Write( IndexRec, sizeof( TIndexRecord ) );
        Bitmap.Free;
end;

procedure TArt.LoadStaticTile( Id : Integer; FilePath : String );
var     Bitmap : TBitmap;
        x, y, j : Integer;
        LookupList : PWordArray;
        Color32 : Integer;
        Color15 : Word;
        XOffset, RunColor: Word;
        IndexRec, TmpRec : TIndexRecord;
        Header : Integer;
        Breite, Hoehe : Word;
        dStream : TMemoryStream;
        CountColor, CountColorless : Integer;
        Buffer : Array[0..2047] of Word;
begin
        Bitmap := TBitmap.Create;
        Bitmap.LoadFromFile( FilePath );
        Breite := Bitmap.Width;
        Hoehe := Bitmap.Height;

        mulStream.Seek( 0, soFromEnd );
        IndexRec.Offset := mulStream.Position;

        Header := 1234;
        mulStream.Write( Header, 4 );
        mulStream.Write( Breite, 2 );
        mulStream.Write( Hoehe, 2 );

        dStream := TMemoryStream.Create;
        dStream.Seek( 0, soFromBeginning  );

        GetMem( LookupList, Hoehe*2 );

        CountColor := 0;
        CountColorless := 0;
        y := 0;

        while y < Hoehe do begin
                x := 0;
                LookupList^[y] := dStream.Position div 2;
                while x < Breite do begin
                        Color32 := Bitmap.Canvas.Pixels[x,y];
                        Color15 := ((Color32 and $F80000) shr 19) or ((Color32 and $F800) shr 6) or ((Color32 and $F8) shl 7);

                        if ( Color15 = 32767 ) or ( Color15 = 0 ) then begin
                                if CountColor > 0 then begin
                                        XOffset := CountColorless;
                                        RunColor := CountColor;
                                        dStream.Write( XOffset, 2 );
                                        dStream.Write( RunColor, 2 );
                                        for j := 0 to CountColor-1 do
                                                dStream.Write( Buffer[j], 2 );
                                        CountColor := 0;
                                        CountColorless := 1;
                                end
                                else
                                        inc( CountColorless );
                        end
                        else begin
                                Buffer[ CountColor ] := Color15;
                                inc( CountColor );
                        end;
                        inc( x );
                end;
                Header := 0;
                if CountColor <> 0 then begin
                        XOffset := CountColorless;
                        RunColor := CountColor;
                        dStream.Write( XOffset, 2 );
                        dStream.Write( RunColor, 2 );
                        for j := 0 to CountColor-1 do
                                dStream.Write( Buffer[j], 2 );
                end;
                dStream.Write( Header, 4 );
                inc( y );
                CountColor := 0;
                CountColorless := 0;
        end;

        mulStream.Write( LookupList^, Hoehe*2 );
        FreeMem( LookupList, Hoehe*2 );

        dStream.Seek( 0, soFromBeginning );
        mulStream.CopyFrom( dStream, dStream.Size );
        dStream.Free;

        IndexRec.Length := mulStream.Position - IndexRec.Offset;
        IndexRec.Extra := 0;

        while (Id+$4000)*12 > idxStream.Size do begin
                TmpRec.Offset := -1;
                TmpRec.Length := -1;
                TmpRec.Extra := 0;
                Encrypt( Id+$4000, TmpRec );

                idxStream.Seek( 0, soFromEnd );
                idxStream.Write( TmpRec, 12 );
        end;

        Encrypt( Id+$4000, IndexRec );

        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Write( IndexRec, sizeof( TIndexRecord ) );
        Bitmap.Free;
end;

procedure TArt.DeleteMap( Id : Integer );
var     IndexRec : TIndexRecord;
begin
        IndexRec.Offset := -1;
        IndexRec.Length := -1;
        IndexRec.Extra := -1;

        Encrypt( Id, IndexRec );

        idxStream.Seek( Id*12, soFromBeginning );
        idxStream.Write( IndexRec, sizeof( TIndexRecord ) );
end;

procedure TArt.DeleteStatic( Id : Integer );
var     IndexRec : TIndexRecord;
begin
        IndexRec.Offset := -1;
        IndexRec.Length := -1;
        IndexRec.Extra := -1;

        Encrypt( Id+$4000, IndexRec );

        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Write( IndexRec, sizeof( TIndexRecord ) );
end;

function TArt.GetAverageMapColor( Id : Integer ) : Integer;
var     Bitmap : TBitmap32;
        RedCount, GreenCount, BlueCount : Integer;
        Red, Green, Blue : Integer;
        Count : Integer;
        x, y, Hoehe, Breite : Integer;
        Color : TColor32;
begin
        Bitmap := GetMapTile( Id );

        Breite := Bitmap.Width;
        Hoehe := Bitmap.Height;
        Count := 0;

        RedCount := 0;
        GreenCount := 0;
        BlueCount := 0;

        for y := 0 to Hoehe-1 do begin
                for x := 0 to Breite-1 do begin
                        Color := Bitmap.Canvas.Pixels[x,y];
                        if WinColor( Color ) <> $FFFFFF then begin
                                Red := RedComponent( Color );
                                Green := GreenComponent( Color );
                                Blue := BlueComponent( Color );
                                inc( Count );
                                RedCount := RedCount + Red;
                                GreenCount := GreenCount + Green;
                                BlueCount := BlueCount + Blue;
                        end;
                end;
        end;
        Bitmap.Free;

        Red := trunc( RedCount / Count );
        Green := trunc( GreenCount / Count );
        Blue := trunc( BlueCount / Count );
        Result := Color32( Blue, Green, Red );
end;

function TArt.GetAverageStaticColor( Id : Integer ) : Integer;
var     Bitmap : TBitmap32;
        RedCount, GreenCount, BlueCount : Integer;
        Red, Green, Blue : Integer;
        Count : Integer;
        x, y, Hoehe, Breite : Integer;
        Color : TColor32;
begin
        Bitmap := GetStaticTile( Id );

        Breite := Bitmap.Width;
        Hoehe := Bitmap.Height;
        Count := 0;

        RedCount := 0;
        GreenCount := 0;
        BlueCount := 0;

        for y := 0 to Hoehe-1 do begin
                for x := 0 to Breite-1 do begin
                        Color := Bitmap.Canvas.Pixels[x,y];
                        if WinColor( Color ) <> $FFFFFF then begin
                                Red := RedComponent( Color );
                                Green := GreenComponent( Color );
                                Blue := BlueComponent( Color );
                                inc( Count );
                                RedCount := RedCount + Red;
                                GreenCount := GreenCount + Green;
                                BlueCount := BlueCount + Blue;
                        end;
                end;
        end;
        Bitmap.Free;

        Red := trunc( RedCount / Count );
        Green := trunc( GreenCount / Count );
        Blue := trunc( BlueCount / Count );
        Result := Color32( Red, Green, Blue );
end;

procedure TArt.ReIndex( idxPath, mulPath : String );
var     Id, ListId, Count, RandCount, I : Integer;
        iStream, mStream : TFileStream;
        IndexRecord, OldIndexRecord : TIndexRecord;
        Liste : TList;
        B : Byte;
begin
        Randomize;

        if FileExists( idxPath ) then
                DeleteFile( idxPath );
        if FileExists( mulPath ) then
                DeleteFile( mulPath );

        iStream := TFileStream.Create( idxPath, fmCreate );
        mStream := TFileStream.Create( mulPath, fmCreate );
        iStream.Seek( 0, soFromBeginning );
        mStream.Seek( 0, soFromBeginning );

        Count := idxStream.Size div 12;

        IndexRecord.Offset := -1;
        IndexRecord.Length := -1;
        IndexRecord.Extra := -1;

        Liste := TList.Create;
        for Id := 0 to Count-1 do begin
                Liste.Add( Pointer( Id ) );
                iStream.Write( IndexRecord, 12 );
        end;

        GaugeForm.Activate;

        while Liste.Count > 0 do begin
                GaugeForm.SetBalken( Trunc( 100*(Count-Liste.Count)/Count ) );
                ListId := Random( Liste.Count );
                Id := Integer( Liste.Items[ ListId ] );
                Liste.Delete( ListId );

                idxStream.Seek( Id*12, soFromBeginning );
                idxStream.Read( OldIndexRecord, 12 );
                Decrypt( Id, OldIndexRecord );

                RandCount := 4 + Random( 12 );
                for I := 0 to RandCount-1 do begin
                        B := Random( 256 );
                        mStream.Write( B, 1 );
                end;

                iStream.Seek( Id*12, soFromBeginning );
                if (OldIndexRecord.Offset <> -1) and (OldIndexRecord.Length > 0) then begin
                        mulStream.Seek( OldIndexRecord.Offset, soFromBeginning );
                        IndexRecord.Offset := mStream.Position;
                        IndexRecord.Length := OldIndexRecord.Length;
                        IndexRecord.Extra := OldIndexRecord.Extra;
                        mStream.CopyFrom( mulStream, IndexRecord.Length );

                        Encrypt( Id, IndexRecord );
                        iStream.Write( IndexRecord, 12 );
                end
                else begin
                        Encrypt( Id, OldIndexRecord );
                        iStream.Write( OldIndexRecord, 12 );
                end;
        end;

        Liste.Free;
        iStream.Free;
        mStream.Free;
        GaugeForm.Deactivate;
end;

procedure TArt.ShowStaticDetails( Id : Integer );
var     IndexRecord : TIndexRecord;
begin
        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRecord, 12 );
        Decrypt( Id+$4000, IndexRecord );

        showmessage( Format( 'Offset: %d Length: %d Tag: %d', [IndexRecord.Offset,IndexRecord.Length,IndexRecord.Extra] ) );
end;

procedure TArt.SetStaticTag( Id, Tag : Integer );
var     IndexRecord : TIndexRecord;
begin
        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Read( IndexRecord, 12 );
        Decrypt( Id+$4000, IndexRecord );
        IndexRecord.Extra := Tag;
        Encrypt( Id+$4000, IndexRecord );
        idxStream.Seek( (Id+$4000)*12, soFromBeginning );
        idxStream.Write( IndexRecord, 12 );
end;
// Cat und Jon 21.9.2016  - $4000 gelöscht
function TArt.GetStaticCount : Word;
begin
        Result := (idxStream.Size div 12) - $0;
end;
// Cat und Jon 21.09.2016 $8000 zu $10001
procedure TArt.FillStatics;
var     IndexRecord : TIndexRecord;
begin
        while idxStream.Size < 12*($10001 + $4000) do begin
                IndexRecord.Offset := -1;
                IndexRecord.Length := -1;
                IndexRecord.Extra := 0;

                Encrypt( idxStream.Size div 12, IndexRecord );
                idxStream.Seek( 0, soFromEnd );
                idxStream.Write( IndexRecord, 12 );
        end;
end;

procedure TArt.Encrypt( Id : Integer; var IndexRecord : TIndexRecord );
begin
        if MainForm.cbME.Checked then begin
                if not MainForm.MulCrypt.EncryptIndexRecordArt( Id, IndexRecord ) then begin
                        MainForm.cbME.Checked := False;
                end;
        end;
end;

procedure TArt.Decrypt( Id : Integer; var IndexRecord : TIndexRecord );
begin
        if MainForm.cbME.Checked then begin
                if not MainForm.MulCrypt.DecryptIndexRecordArt( Id, IndexRecord ) then begin
                        MainForm.cbME.Checked := False;
                end;
        end;
end;

end.

