Subversion Repositories plumbers

Rev

Rev 10 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit GameBinStruct;
  2.  
  3. {$A-}
  4.  
  5. interface
  6.  
  7. const
  8.   SCENEID_PREVDECISION = -1;
  9.   SCENEID_ENDGAME      = 32767;
  10.  
  11. type
  12.   PCoord = ^TCoord;
  13.   TCoord = packed record
  14.     x: Word;
  15.     y: Word;
  16.   end;
  17.  
  18.   PActionDef = ^TActionDef;
  19.   TActionDef = packed record
  20.     scoreDelta: Integer;
  21.     nextSceneID: SmallInt;  // will jump to the scene with the name "SC<nextSceneID>"
  22.                             // 7FFF (32767) = end game
  23.                             // FFFF (   -1) = go back to the last decision
  24.     sceneSegment: SmallInt; // 0 = scene from beginning, 1 = decision page
  25.     cHotspotTopLeft: TCoord;
  26.     cHotspotBottomRight: TCoord;
  27.   end;
  28.  
  29.   PAnsiFileName = ^TAnsiFileName;
  30.   TAnsiFileName = array[0..13] of AnsiChar;
  31.  
  32.   PSceneDef = ^TSceneDef;
  33.   TSceneDef = packed record
  34.     numPics: Word;
  35.     pictureIndex: Word;
  36.     numActions: Word;
  37.     szSceneFolder: TAnsiFileName; // Foldername *must* be "SCxx" (case sensitive) where xx stands for a 2 digit ID
  38.     szDialogWav:   TAnsiFileName;
  39.     szDecisionBmp: TAnsiFileName;
  40.     actions: array[0..2] of TActionDef;
  41.   end;
  42.  
  43.   PPictureDef = ^TPictureDef;
  44.   TPictureDef = packed record
  45.     duration: Word; // deciseconds
  46.     szBitmapFile: TAnsiFileName;
  47.   end;
  48.  
  49.   PGameBinFile = ^TGameBinFile;
  50.   TGameBinFile = packed record
  51.     unknown1: array[0..6] of Word;
  52.     numScenes: Word;
  53.     numPics: Word;
  54.     unknown2: array[0..1] of Word;
  55.     scenes: array[0..99] of TSceneDef;        // Scenes start at 0x0016
  56.     pictures: array[0..1999] of TPictureDef;  // Pictures start at 0x2596
  57.     function AddSceneAtEnd(SceneID: integer): PSceneDef;
  58.     procedure DeleteScene(SceneIndex: integer);
  59.     procedure SwapScene(IndexA, IndexB: integer);
  60.     procedure DeletePicture(PictureIndex: integer);
  61.     procedure SwapPicture(IndexA, IndexB: integer);
  62.     function AddPictureBetween(Index: integer): PPictureDef;
  63.   end;
  64.  
  65. procedure _WriteStringToFilename(x: PAnsiFileName; s: AnsiString);
  66.  
  67. implementation
  68.  
  69. uses
  70.   Windows, SysUtils, Math;
  71.  
  72. procedure _WriteStringToFilename(x: PAnsiFileName; s: AnsiString);
  73. begin
  74.   ZeroMemory(x, Length(x^));
  75.   StrPLCopy(x^, s, Length(x^));
  76. end;
  77.  
  78. function TGameBinFile.AddSceneAtEnd(SceneID: integer): PSceneDef;
  79. begin
  80.   if Self.numScenes >= Length(Self.scenes) then raise Exception.Create('No more space for another scene');
  81.   if sceneID >= Length(Self.scenes) then raise Exception.Create('SceneID is too large.');
  82.   result := @Self.scenes[Self.numScenes];
  83.   ZeroMemory(result, SizeOf(TSceneDef));
  84.   _WriteStringToFilename(@result.szSceneFolder, AnsiString(Format('SC%.2d', [sceneID])));
  85.   Inc(Self.numScenes);
  86. end;
  87.  
  88. procedure TGameBinFile.DeleteScene(SceneIndex: integer);
  89. begin
  90.   if ((SceneIndex < 0) or (SceneIndex >= Length(Self.scenes))) then raise Exception.Create('Invalid scene index');
  91.   If SceneIndex < Length(Self.scenes)-1 then
  92.   begin
  93.     CopyMemory(@Self.scenes[SceneIndex], @Self.scenes[SceneIndex+1], (Length(Self.scenes)-SceneIndex-1)*SizeOf(TSceneDef));
  94.   end;
  95.   ZeroMemory(@Self.scenes[Length(Self.scenes)-1], SizeOf(TSceneDef));
  96. end;
  97.  
  98. procedure TGameBinFile.SwapScene(IndexA, IndexB: integer);
  99. var
  100.   bakScene: TSceneDef;
  101. begin
  102.   if IndexA = IndexB then exit;
  103.   if ((Min(IndexA, IndexB) < 0) or (Max(IndexA, IndexB) >= Length(Self.scenes))) then raise Exception.Create('Invalid scene index');
  104.   CopyMemory(@bakScene, @Self.scenes[IndexA], SizeOf(TSceneDef));
  105.   CopyMemory(@Self.scenes[IndexA], @Self.scenes[IndexB], SizeOf(TSceneDef));
  106.   CopyMemory(@Self.scenes[IndexB], @bakScene, SizeOf(TSceneDef));
  107. end;
  108.  
  109. procedure TGameBinFile.DeletePicture(PictureIndex: integer);
  110. var
  111.   iScene: integer;
  112. begin
  113.   if (PictureIndex < 0) or (PictureIndex >= Length(Self.pictures)) then raise Exception.Create('Invalid picture index');
  114.  
  115.   for iScene := 0 to Self.numScenes-1 do
  116.   begin
  117.     if (PictureIndex >= Self.scenes[iScene].pictureIndex) and
  118.        (PictureIndex <= Self.scenes[iScene].pictureIndex + Self.scenes[iScene].numPics - 1) then
  119.     begin
  120.       Dec(Self.scenes[iScene].numPics);
  121.     end
  122.     else if (PictureIndex < Self.scenes[iScene].pictureIndex) then
  123.     begin
  124.       Dec(Self.scenes[iScene].pictureIndex);
  125.     end;
  126.   end;
  127.  
  128.   If PictureIndex < Length(Self.pictures)-1 then
  129.   begin
  130.     CopyMemory(@Self.pictures[PictureIndex], @Self.pictures[PictureIndex+1], (Length(Self.pictures)-PictureIndex-1)*SizeOf(TPictureDef));
  131.   end;
  132.   ZeroMemory(@Self.pictures[Length(Self.pictures)-1], SizeOf(TPictureDef));
  133. end;
  134.  
  135. procedure TGameBinFile.SwapPicture(IndexA, IndexB: integer);
  136. var
  137.   bakPicture: TPictureDef;
  138. begin
  139.   // QUE: should we forbid that a picture between "scene borders" are swapped?
  140.  
  141.   if IndexA = IndexB then exit;
  142.   if ((Min(IndexA, IndexB) < 0) or (Max(IndexA, IndexB) >= Length(Self.pictures))) then raise Exception.Create('Invalid picture index');
  143.  
  144.   CopyMemory(@bakPicture, @Self.pictures[IndexA], SizeOf(TPictureDef));
  145.   CopyMemory(@Self.pictures[IndexA], @Self.pictures[IndexB], SizeOf(TPictureDef));
  146.   CopyMemory(@Self.pictures[IndexB], @bakPicture, SizeOf(TPictureDef));
  147. end;
  148.  
  149. function TGameBinFile.AddPictureBetween(Index: integer): PPictureDef;
  150. var
  151.   iScene: integer;
  152. begin
  153.   if Self.numPics >= Length(Self.pictures) then raise Exception.Create('No more space for another picture');
  154.   if ((Index < 0) or (Index >= Length(Self.pictures))) then raise Exception.Create('Invalid picture index');
  155.  
  156.   for iScene := 0 to Self.numScenes-1 do
  157.   begin
  158.     if (Index >= Self.scenes[iScene].pictureIndex) and
  159.        (index <= Self.scenes[iScene].pictureIndex + Max(0,Self.scenes[iScene].numPics - 1)) then
  160.     begin
  161.       Inc(Self.scenes[iScene].numPics);
  162.     end
  163.     else if (index < Self.scenes[iScene].pictureIndex) then
  164.     begin
  165.       Inc(Self.scenes[iScene].pictureIndex);
  166.     end;
  167.   end;
  168.  
  169.   result := @Self.pictures[Index];
  170.   CopyMemory(@Self.pictures[Index+1], result, (Length(Self.pictures)-Index-1)*SizeOf(TPictureDef));
  171.   ZeroMemory(result, SizeOf(TPictureDef));
  172. end;
  173.  
  174. end.
  175.