DEADSOFTWARE

mempool is optional now
[d2df-sdl.git] / src / game / g_textures.pas
index fba31e47a6c3ce8bee637f07cc4bf5dcce966124..f129b9e219d9ff88a224951a8bbddba784fff022 100644 (file)
@@ -1,10 +1,27 @@
-{$MODE DELPHI}
+(* Copyright (C)  DooM 2D:Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE ../shared/a_modes.inc}
 unit g_textures;
 
 interface
 
 uses
-  e_graphics, BinEditor;
+  SysUtils, Classes,
+  {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
+  e_graphics, MAPDEF, ImagingTypes, Imaging, ImagingUtility;
 
 Type
   TLevelTexture = record
@@ -20,7 +37,7 @@ Type
 
   TLevelTextureArray = Array of TLevelTexture;
 
-  TAnimation = class(TObject)
+  TAnimation = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
   private
     ID:            DWORD;
     FAlpha:        Byte;
@@ -40,15 +57,15 @@ Type
     constructor Create(FramesID: DWORD; Loop: Boolean; Speed: Byte);
     destructor  Destroy(); override;
     procedure   Draw(X, Y: Integer; Mirror: TMirrorType);
-    procedure   DrawEx(X, Y: Integer; Mirror: TMirrorType; RPoint: TPoint;
+    procedure   DrawEx(X, Y: Integer; Mirror: TMirrorType; RPoint: TDFPoint;
                        Angle: SmallInt);
     procedure   Reset();
     procedure   Update();
     procedure   Enable();
     procedure   Disable();
     procedure   Revert(r: Boolean);
-    procedure   SaveState(Var Mem: TBinMemoryWriter);
-    procedure   LoadState(Var Mem: TBinMemoryReader);
+    procedure   SaveState(st: TStream);
+    procedure   LoadState(st: TStream);
     function    TotalFrames(): Integer;
 
     property    Played: Boolean read FPlayed;
@@ -69,21 +86,24 @@ Type
 
 function g_Texture_CreateWAD(var ID: DWORD; Resource: String): Boolean;
 function g_Texture_CreateFile(var ID: DWORD; FileName: String): Boolean;
-function g_Texture_CreateWADEx(TextureName: ShortString; Resource: String): Boolean;
+function g_Texture_CreateWADEx(TextureName: ShortString; Resource: String; altrsrc: AnsiString=''): Boolean;
 function g_Texture_CreateFileEx(TextureName: ShortString; FileName: String): Boolean;
 function g_Texture_Get(TextureName: ShortString; var ID: DWORD): Boolean;
 procedure g_Texture_Delete(TextureName: ShortString);
 procedure g_Texture_DeleteAll();
 
+function g_CreateFramesImg (ia: TDynImageDataArray; ID: PDWORD; Name: ShortString; BackAnimation: Boolean = False): Boolean;
+
 function g_Frames_CreateWAD(ID: PDWORD; Name: ShortString; Resource: String;
                             FWidth, FHeight, FCount: Word; BackAnimation: Boolean = False): Boolean;
 function g_Frames_CreateFile(ID: PDWORD; Name: ShortString; FileName: String;
                              FWidth, FHeight, FCount: Word; BackAnimation: Boolean = False): Boolean;
-function g_Frames_CreateMemory(ID: PDWORD; Name: ShortString; pData: Pointer;
+function g_Frames_CreateMemory(ID: PDWORD; Name: ShortString; pData: Pointer; dataSize: LongInt;
                                FWidth, FHeight, FCount: Word; BackAnimation: Boolean = False): Boolean;
+function g_Frames_Dup(NewName, OldName: ShortString): Boolean;
 //function g_Frames_CreateRevert(ID: PDWORD; Name: ShortString; Frames: string): Boolean;
-function g_Frames_Get(var ID: DWORD; FramesName: ShortString): Boolean;
-function g_Frames_GetTexture(var ID: DWORD; FramesName: ShortString; Frame: Word): Boolean;
+function g_Frames_Get(out ID: DWORD; FramesName: ShortString): Boolean;
+function g_Frames_GetTexture(out ID: DWORD; FramesName: ShortString; Frame: Word): Boolean;
 function g_Frames_Exists(FramesName: String): Boolean;
 procedure g_Frames_DeleteByName(FramesName: ShortString);
 procedure g_Frames_DeleteByID(ID: DWORD);
@@ -91,11 +111,13 @@ procedure g_Frames_DeleteAll();
 
 procedure DumpTextureNames();
 
+function g_Texture_Light(): Integer;
+
 implementation
 
 uses
-  g_game, e_log, g_basic, SysUtils, g_console, wadreader,
-  g_language;
+  g_game, e_log, g_basic, g_console, wadreader,
+  g_language, GL, utils, xstreams;
 
 type
   _TTexture = record
@@ -145,28 +167,26 @@ end;
 function g_Texture_CreateWAD(var ID: DWORD; Resource: String): Boolean;
 var
   WAD: TWADFile;
-  FileName,
-  SectionName,
-  ResourceName: String;
+  FileName: String;
   TextureData: Pointer;
   ResourceLength: Integer;
 begin
   Result := False;
-  g_ProcessResourceStr(Resource, FileName, SectionName, ResourceName);
+  FileName := g_ExtractWadName(Resource);
 
   WAD := TWADFile.Create;
   WAD.ReadFile(FileName);
 
-  if WAD.GetResource(SectionName, ResourceName, TextureData, ResourceLength) then
+  if WAD.GetResource(g_ExtractFilePathName(Resource), TextureData, ResourceLength) then
   begin
-    if e_CreateTextureMem(TextureData, ID) then
+    if e_CreateTextureMem(TextureData, ResourceLength, ID) then
       Result := True
     else
       FreeMem(TextureData);
   end
   else
   begin
-    e_WriteLog(Format('Error loading texture %s', [Resource]), MSG_WARNING);
+    e_WriteLog(Format('Error loading texture %s', [Resource]), TMsgType.Warning);
     //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
   end;
   WAD.Free();
@@ -177,49 +197,61 @@ begin
   Result := True;
   if not e_CreateTexture(FileName, ID) then
   begin
-    e_WriteLog(Format('Error loading texture %s', [FileName]), MSG_WARNING);
+    e_WriteLog(Format('Error loading texture %s', [FileName]), TMsgType.Warning);
     Result := False;
   end;
 end;
 
-function g_Texture_CreateWADEx(TextureName: ShortString; Resource: String): Boolean;
+function texture_CreateWADExInternal (TextureName: ShortString; Resource: String; showmsg: Boolean): Boolean;
 var
   WAD: TWADFile;
-  FileName,
-  SectionName,
-  ResourceName: String;
+  FileName: String;
   TextureData: Pointer;
   find_id: DWORD;
   ResourceLength: Integer;
 begin
-  g_ProcessResourceStr(Resource, FileName, SectionName, ResourceName);
+  FileName := g_ExtractWadName(Resource);
 
   find_id := FindTexture();
 
   WAD := TWADFile.Create;
   WAD.ReadFile(FileName);
 
-  if WAD.GetResource(SectionName, ResourceName, TextureData, ResourceLength) then
+  if WAD.GetResource(g_ExtractFilePathName(Resource), TextureData, ResourceLength) then
   begin
-    Result := e_CreateTextureMem(TextureData, TexturesArray[find_id].ID);
-    if Result then
+    result := e_CreateTextureMem(TextureData, ResourceLength, TexturesArray[find_id].ID);
+    if result then
     begin
-      e_GetTextureSize(TexturesArray[find_id].ID, @TexturesArray[find_id].Width,
-                       @TexturesArray[find_id].Height);
+      e_GetTextureSize(TexturesArray[find_id].ID, @TexturesArray[find_id].Width, @TexturesArray[find_id].Height);
       TexturesArray[find_id].Name := LowerCase(TextureName);
     end
     else
+    begin
       FreeMem(TextureData);
+    end;
   end
   else
   begin
-    e_WriteLog(Format('Error loading texture %s', [Resource]), MSG_WARNING);
+    if showmsg then
+    begin
+      e_WriteLog(Format('Error loading texture %s', [Resource]), TMsgType.Warning);
+    end;
     //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
-    Result := False;
+    result := false;
   end;
   WAD.Free();
 end;
 
+function g_Texture_CreateWADEx(TextureName: ShortString; Resource: String; altrsrc: AnsiString=''): Boolean;
+begin
+  if (Length(altrsrc) > 0) then
+  begin
+    result := texture_CreateWADExInternal(TextureName, altrsrc, false);
+    if result then exit;
+  end;
+  result := texture_CreateWADExInternal(TextureName, Resource, true);
+end;
+
 function g_Texture_CreateFileEx(TextureName: ShortString; FileName: String): Boolean;
 var
   find_id: DWORD;
@@ -233,7 +265,7 @@ begin
     e_GetTextureSize(TexturesArray[find_id].ID, @TexturesArray[find_id].Width,
                      @TexturesArray[find_id].Height);
   end
-  else e_WriteLog(Format('Error loading texture %s', [FileName]), MSG_WARNING);
+  else e_WriteLog(Format('Error loading texture %s', [FileName]), TMsgType.Warning);
 end;
 
 function g_Texture_Get(TextureName: ShortString; var ID: DWORD): Boolean;
@@ -350,7 +382,7 @@ begin
   Result := True;
 end;
 
-function CreateFramesMem(pData: Pointer; ID: PDWORD; Name: ShortString;
+function CreateFramesMem(pData: Pointer; dataSize: LongInt; ID: PDWORD; Name: ShortString;
                          FWidth, FHeight, FCount: Word; BackAnimation: Boolean = False): Boolean;
 var
   find_id: DWORD;
@@ -366,10 +398,10 @@ begin
     else SetLength(FramesArray[find_id].TexturesID, FCount);
 
   for a := 0 to FCount-1 do
-    if not e_CreateTextureMemEx(pData, FramesArray[find_id].TexturesID[a],
+    if not e_CreateTextureMemEx(pData, dataSize, FramesArray[find_id].TexturesID[a],
                                 a*FWidth, 0, FWidth, FHeight) then
     begin
-      FreeMem(pData);
+      //!!!FreeMem(pData);
       Exit;
     end;
 
@@ -389,32 +421,80 @@ begin
   Result := True;
 end;
 
+function g_CreateFramesImg (ia: TDynImageDataArray; ID: PDWORD; Name: ShortString; BackAnimation: Boolean = False): Boolean;
+var
+  find_id: DWORD;
+  a, FCount: Integer;
+begin
+  result := false;
+  find_id := FindFrame();
+
+  FCount := length(ia);
+
+  //e_WriteLog(Format('+++ creating %d frames [%s]', [FCount, Name]), MSG_NOTIFY);
+
+  if FCount < 1 then exit;
+  if FCount <= 2 then BackAnimation := False;
+  if BackAnimation then
+    SetLength(FramesArray[find_id].TexturesID, FCount+FCount-2)
+  else
+    SetLength(FramesArray[find_id].TexturesID, FCount);
+
+  //e_WriteLog(Format('+++ creating %d frames, %dx%d', [FCount, ia[0].width, ia[0].height]), MSG_NOTIFY);
+
+  for a := 0 to FCount-1 do
+  begin
+    if not e_CreateTextureImg(ia[a], FramesArray[find_id].TexturesID[a]) then exit;
+    //e_WriteLog(Format('+++   frame %d, %dx%d', [a, ia[a].width, ia[a].height]), MSG_NOTIFY);
+  end;
+
+  if BackAnimation then
+  begin
+    for a := 1 to FCount-2 do
+    begin
+      FramesArray[find_id].TexturesID[FCount+FCount-2-a] := FramesArray[find_id].TexturesID[a];
+    end;
+  end;
+
+  FramesArray[find_id].FrameWidth := ia[0].width;
+  FramesArray[find_id].FrameHeight := ia[0].height;
+  if Name <> '' then
+    FramesArray[find_id].Name := LowerCase(Name)
+  else
+    FramesArray[find_id].Name := '<noname>';
+
+  if ID <> nil then ID^ := find_id;
+
+  result := true;
+end;
+
 function g_Frames_CreateWAD(ID: PDWORD; Name: ShortString; Resource: string;
                             FWidth, FHeight, FCount: Word; BackAnimation: Boolean = False): Boolean;
 var
   WAD: TWADFile;
-  FileName,
-  SectionName,
-  ResourceName: string;
+  FileName: string;
   TextureData: Pointer;
   ResourceLength: Integer;
 begin
   Result := False;
 
-  g_ProcessResourceStr(Resource, FileName, SectionName, ResourceName);
+  // models without "advanced" animations asks for "nothing" like this; don't spam log
+  if (Length(Resource) > 0) and ((Resource[Length(Resource)] = '/') or (Resource[Length(Resource)] = '\')) then exit;
+
+  FileName := g_ExtractWadName(Resource);
 
   WAD := TWADFile.Create();
   WAD.ReadFile(FileName);
 
-  if not WAD.GetResource(SectionName, ResourceName, TextureData, ResourceLength) then
+  if not WAD.GetResource(g_ExtractFilePathName(Resource), TextureData, ResourceLength) then
   begin
     WAD.Free();
-    e_WriteLog(Format('Error loading texture %s', [Resource]), MSG_WARNING);
+    e_WriteLog(Format('Error loading texture %s', [Resource]), TMsgType.Warning);
     //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
     Exit;
   end;
 
-  if not CreateFramesMem(TextureData, ID, Name, FWidth, FHeight, FCount, BackAnimation) then
+  if not CreateFramesMem(TextureData, ResourceLength, ID, Name, FWidth, FHeight, FCount, BackAnimation) then
   begin
     WAD.Free();
     Exit;
@@ -425,10 +505,10 @@ begin
   Result := True;
 end;
 
-function g_Frames_CreateMemory(ID: PDWORD; Name: ShortString; pData: Pointer;
+function g_Frames_CreateMemory(ID: PDWORD; Name: ShortString; pData: Pointer; dataSize: LongInt;
                                FWidth, FHeight, FCount: Word; BackAnimation: Boolean = False): Boolean;
 begin
-  Result := CreateFramesMem(pData, ID, Name, FWidth, FHeight, FCount, BackAnimation);
+  Result := CreateFramesMem(pData, dataSize, ID, Name, FWidth, FHeight, FCount, BackAnimation);
 end;
 
 {function g_Frames_CreateRevert(ID: PDWORD; Name: ShortString; Frames: string): Boolean;
@@ -454,6 +534,30 @@ begin
  Result := True;
 end;}
 
+function g_Frames_Dup(NewName, OldName: ShortString): Boolean;
+var
+  find_id, b: DWORD;
+  a, c: Integer;
+begin
+  Result := False;
+
+  if not g_Frames_Get(b, OldName) then Exit;
+
+  find_id := FindFrame();
+
+  FramesArray[find_id].Name := LowerCase(NewName);
+  FramesArray[find_id].FrameWidth := FramesArray[b].FrameWidth;
+  FramesArray[find_id].FrameHeight := FramesArray[b].FrameHeight;
+
+  c := High(FramesArray[b].TexturesID);
+  SetLength(FramesArray[find_id].TexturesID, c+1);
+
+  for a := 0 to c do
+    FramesArray[find_id].TexturesID[a] := FramesArray[b].TexturesID[a];
+
+  Result := True;
+end;
+
 procedure g_Frames_DeleteByName(FramesName: ShortString);
 var
   a: DWORD;
@@ -512,7 +616,7 @@ begin
   FramesArray := nil;
 end;
 
-function g_Frames_Get(var ID: DWORD; FramesName: ShortString): Boolean;
+function g_Frames_Get(out ID: DWORD; FramesName: ShortString): Boolean;
 var
   a: DWORD;
 begin
@@ -535,7 +639,7 @@ begin
     g_FatalError(Format(_lc[I_GAME_ERROR_FRAMES], [FramesName]));
 end;
 
-function g_Frames_GetTexture(var ID: DWORD; FramesName: ShortString; Frame: Word): Boolean;
+function g_Frames_GetTexture(out ID: DWORD; FramesName: ShortString; Frame: Word): Boolean;
 var
   a: DWORD;
 begin
@@ -581,15 +685,15 @@ procedure DumpTextureNames();
 var
   i: Integer;
 begin
-  e_WriteLog('BEGIN Textures:', MSG_NOTIFY);
+  e_WriteLog('BEGIN Textures:', TMsgType.Notify);
   for i := 0 to High(TexturesArray) do
-    e_WriteLog('   '+IntToStr(i)+'. '+TexturesArray[i].Name, MSG_NOTIFY);
-  e_WriteLog('END Textures.', MSG_NOTIFY);
+    e_WriteLog('   '+IntToStr(i)+'. '+TexturesArray[i].Name, TMsgType.Notify);
+  e_WriteLog('END Textures.', TMsgType.Notify);
 
-  e_WriteLog('BEGIN Frames:', MSG_NOTIFY);
+  e_WriteLog('BEGIN Frames:', TMsgType.Notify);
   for i := 0 to High(FramesArray) do
-    e_WriteLog('   '+IntToStr(i)+'. '+FramesArray[i].Name, MSG_NOTIFY);
-  e_WriteLog('END Frames.', MSG_NOTIFY);
+    e_WriteLog('   '+IntToStr(i)+'. '+FramesArray[i].Name, TMsgType.Notify);
+  e_WriteLog('END Frames.', TMsgType.Notify);
 end;
 
 { TAnimation }
@@ -697,7 +801,7 @@ begin
   FEnabled := True;
 end;
 
-procedure TAnimation.DrawEx(X, Y: Integer; Mirror: TMirrorType; RPoint: TPoint;
+procedure TAnimation.DrawEx(X, Y: Integer; Mirror: TMirrorType; RPoint: TDFPoint;
                             Angle: SmallInt);
 begin
   if not FEnabled then
@@ -718,71 +822,120 @@ begin
   Reset();
 end;
 
-procedure TAnimation.SaveState(Var Mem: TBinMemoryWriter);
+procedure TAnimation.SaveState (st: TStream);
+begin
+  if (st = nil) then exit;
+
+  utils.writeSign(st, 'ANIM');
+  utils.writeInt(st, Byte(0)); // version
+  // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
+  utils.writeInt(st, Byte(FCounter));
+  // Òåêóùèé êàäð
+  utils.writeInt(st, LongInt(FCurrentFrame));
+  // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
+  utils.writeBool(st, FPlayed);
+  // Alpha-êàíàë âñåé òåêñòóðû
+  utils.writeInt(st, Byte(FAlpha));
+  // Ðàçìûòèå òåêñòóðû
+  utils.writeInt(st, Byte(FBlending));
+  // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
+  utils.writeInt(st, Byte(FSpeed));
+  // Çàöèêëåíà ëè àíèìàöèÿ
+  utils.writeBool(st, FLoop);
+  // Âêëþ÷åíà ëè
+  utils.writeBool(st, FEnabled);
+  // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
+  utils.writeInt(st, Byte(FMinLength));
+  // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
+  utils.writeBool(st, FRevert);
+end;
+
+procedure TAnimation.LoadState (st: TStream);
+begin
+  if (st = nil) then exit;
+
+  if not utils.checkSign(st, 'ANIM') then raise XStreamError.Create('animation chunk expected');
+  if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid animation chunk version');
+  // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
+  FCounter := utils.readByte(st);
+  // Òåêóùèé êàäð
+  FCurrentFrame := utils.readLongInt(st);
+  // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
+  FPlayed := utils.readBool(st);
+  // Alpha-êàíàë âñåé òåêñòóðû
+  FAlpha := utils.readByte(st);
+  // Ðàçìûòèå òåêñòóðû
+  FBlending := utils.readBool(st);
+  // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
+  FSpeed := utils.readByte(st);
+  // Çàöèêëåíà ëè àíèìàöèÿ
+  FLoop := utils.readBool(st);
+  // Âêëþ÷åíà ëè
+  FEnabled := utils.readBool(st);
+  // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
+  FMinLength := utils.readByte(st);
+  // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
+  FRevert := utils.readBool(st);
+end;
+
+
 var
-  sig: DWORD;
-begin
-  if Mem = nil then
-    Exit;
+  ltexid: GLuint = 0;
 
-// Ñèãíàòóðà àíèìàöèè:
-  sig := ANIM_SIGNATURE; // 'ANIM'
-  Mem.WriteDWORD(sig);
-// Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè:
-  Mem.WriteByte(FCounter);
-// Òåêóùèé êàäð:
-  Mem.WriteInt(FCurrentFrame);
-// Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì:
-  Mem.WriteBoolean(FPlayed);
-// Alpha-êàíàë âñåé òåêñòóðû:
-  Mem.WriteByte(FAlpha);
-// Ðàçìûòèå òåêñòóðû:
-  Mem.WriteBoolean(FBlending);
-// Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè:
-  Mem.WriteByte(FSpeed);
-// Çàöèêëåíà ëè àíèìàöèÿ:
-  Mem.WriteBoolean(FLoop);
-// Âêëþ÷åíà ëè:
-  Mem.WriteBoolean(FEnabled);
-// Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ:
-  Mem.WriteByte(FMinLength);
-// Îáðàòíûé ëè ïîðÿäîê êàäðîâ:
-  Mem.WriteBoolean(FRevert);
-end;
-
-procedure TAnimation.LoadState(Var Mem: TBinMemoryReader);
+function g_Texture_Light(): Integer;
+const
+  Radius: Integer = 128;
 var
-  sig: DWORD;
+  tex, tpp: PByte;
+  x, y, a: Integer;
+  dist: Double;
 begin
-  if Mem = nil then
-    Exit;
-
-// Ñèãíàòóðà àíèìàöèè:
-  Mem.ReadDWORD(sig);
-  if sig <> ANIM_SIGNATURE then // 'ANIM'
+  if ltexid = 0 then
   begin
-    raise EBinSizeError.Create('TAnimation.LoadState: Wrong Animation Signature');
+    GetMem(tex, (Radius*2)*(Radius*2)*4);
+    tpp := tex;
+    for y := 0 to Radius*2-1 do
+    begin
+      for x := 0 to Radius*2-1 do
+      begin
+        dist := 1.0-sqrt((x-Radius)*(x-Radius)+(y-Radius)*(y-Radius))/Radius;
+        if (dist < 0) then
+        begin
+          tpp^ := 0; Inc(tpp);
+          tpp^ := 0; Inc(tpp);
+          tpp^ := 0; Inc(tpp);
+          tpp^ := 0; Inc(tpp);
+        end
+        else
+        begin
+          //tc.setPixel(x, y, Color(cast(int)(dist*255), cast(int)(dist*255), cast(int)(dist*255)));
+          if (dist > 0.5) then dist := 0.5;
+          a := round(dist*255);
+          if (a < 0) then a := 0 else if (a > 255) then a := 255;
+          tpp^ := 255; Inc(tpp);
+          tpp^ := 255; Inc(tpp);
+          tpp^ := 255; Inc(tpp);
+          tpp^ := Byte(a); Inc(tpp);
+        end;
+      end;
+    end;
+
+    glGenTextures(1, @ltexid);
+    //if (tid == 0) assert(0, "VGL: can't create screen texture");
+
+    glBindTexture(GL_TEXTURE_2D, ltexid);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    //GLfloat[4] bclr = 0.0;
+    //glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, bclr.ptr);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Radius*2, Radius*2, 0, GL_RGBA{gltt}, GL_UNSIGNED_BYTE, tex);
   end;
-// Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè:
-  Mem.ReadByte(FCounter);
-// Òåêóùèé êàäð:
-  Mem.ReadInt(FCurrentFrame);
-// Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì:
-  Mem.ReadBoolean(FPlayed);
-// Alpha-êàíàë âñåé òåêñòóðû:
-  Mem.ReadByte(FAlpha);
-// Ðàçìûòèå òåêñòóðû:
-  Mem.ReadBoolean(FBlending);
-// Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè:
-  Mem.ReadByte(FSpeed);
-// Çàöèêëåíà ëè àíèìàöèÿ:
-  Mem.ReadBoolean(FLoop);
-// Âêëþ÷åíà ëè:
-  Mem.ReadBoolean(FEnabled);
-// Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ:
-  Mem.ReadByte(FMinLength);
-// Îáðàòíûé ëè ïîðÿäîê êàäðîâ:
-  Mem.ReadBoolean(FRevert);
+
+  result := ltexid;
 end;
 
 end.