Subversion Repositories spacemission

Rev

Rev 41 | Rev 43 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 daniel-mar 1
unit ComLevelReader;
2
 
3
interface
4
 
40 daniel-mar 5
uses
6
  Classes;
7
 
27 daniel-mar 8
const
9
  NumEnemyTypes = 7;
10
 
14 daniel-mar 11
type
12
  TEnemyType = (
13
    etUnknown,
14
    etEnemyAttacker,
15
    etEnemyAttacker2,
16
    etEnemyAttacker3,
17
    etEnemyMeteor,
18
    etEnemyUFO,
19
    etEnemyUFO2,
20
    etEnemyBoss
21
  );
22
 
23
  TEnemyAdvent = record
24
    enemyType: TEnemyType;
25
    x: integer;
26
    y: integer;
27
    lifes: integer;
28
  end;
29
 
40 daniel-mar 30
  TLevelData = class(TPersistent)
27 daniel-mar 31
  strict private
32
    procedure SortEnemies;
40 daniel-mar 33
  strict protected
34
    procedure AssignTo(Dest: TPersistent); override;
14 daniel-mar 35
  public
40 daniel-mar 36
    RasterErzwingen: boolean;
14 daniel-mar 37
    LevelEditorLength: integer;
42 daniel-mar 38
    LevelName: string;
39
    LevelAuthor: string;
14 daniel-mar 40
    EnemyAdventTable: array of TEnemyAdvent;
27 daniel-mar 41
    function IndexOfEnemy(x,y:integer;enemyType:TEnemyType;lifes:integer): integer;
42
    procedure AddEnemy(x,y:integer;enemyType:TEnemyType;lifes:integer);
43
    procedure DeleteEnemy(i: integer); overload;
44
    procedure DeleteEnemy(x,y:integer;enemyType:TEnemyType;lifes:integer); overload;
45
    function CountEnemies: integer;
46
    function HasBoss: boolean;
14 daniel-mar 47
    procedure Clear;
40 daniel-mar 48
    procedure LoadFromStrings(sl: TStrings); // version 0.3 - version 1.2 files
49
    procedure LoadFromFile(filename: string); // version 0.2 - version 1.2 files
50
    procedure SaveToStrings(sl: TStrings);
51
    procedure SaveToFile(filename: string);
52
    destructor Destroy; override;
14 daniel-mar 53
  end;
54
 
40 daniel-mar 55
  TGameMode = (gmUnknown, gmLevels, gmRandom);
56
 
57
  TSaveData = class(TPersistent)
58
  strict protected
59
    procedure AssignTo(Dest: TPersistent); override;
60
  public
61
    Score: integer;
62
    Life: integer;
63
    Level: integer;
64
    GameMode: TGameMode;
65
    LevelData: TLevelData;
66
    procedure Clear;
67
    procedure LoadFromStrings(sl: TStrings);
68
    procedure LoadFromFile(filename: string);
69
    procedure SaveToStrings(sl: TStrings);
70
    procedure SaveToFile(filename: string);
71
    destructor Destroy; override;
72
  end;
73
 
17 daniel-mar 74
function GetLevelFileName(lev: integer): string;
75
 
14 daniel-mar 76
implementation
77
 
78
uses
40 daniel-mar 79
  SysUtils, StrUtils, Global;
14 daniel-mar 80
 
27 daniel-mar 81
const
82
  DefaultLevelLength = 1200;
83
 
17 daniel-mar 84
function GetLevelFileName(lev: integer): string;
85
begin
31 daniel-mar 86
  result := OwnDirectory+'Levels\Level '+inttostr(lev)+'.lev'; // Version 0.3+ Level Files
17 daniel-mar 87
  if not FileExists(Result) then
31 daniel-mar 88
    result := OwnDirectory+'Levels\Lev'+inttostr(lev)+'A1.lev'; // Version 0.2 Level Files
17 daniel-mar 89
end;
90
 
14 daniel-mar 91
{ TLevelData }
92
 
40 daniel-mar 93
procedure TLevelData.AssignTo(Dest: TPersistent);
94
var
95
  DestLevelData: TLevelData;
96
  i: integer;
97
begin
98
  DestLevelData := Dest as TLevelData;
99
  if Assigned(DestLevelData) then
100
  begin
101
    DestLevelData.RasterErzwingen := Self.RasterErzwingen;
102
    DestLevelData.LevelEditorLength := Self.LevelEditorLength;
42 daniel-mar 103
    DestLevelData.LevelName := Self.LevelName;
104
    DestLevelData.LevelAuthor := Self.LevelAuthor;
40 daniel-mar 105
    SetLength(DestLevelData.EnemyAdventTable, Length(Self.EnemyAdventTable));
106
    for i := 0 to Length(Self.EnemyAdventTable) do
107
    begin
108
      DestLevelData.EnemyAdventTable[i] := Self.EnemyAdventTable[i];
109
    end;
110
  end
111
  else
112
  begin
113
    inherited;
114
  end;
115
end;
116
 
14 daniel-mar 117
procedure TLevelData.Clear;
118
begin
119
  SetLength(EnemyAdventTable, 0);
27 daniel-mar 120
  LevelEditorLength := DefaultLevelLength;
42 daniel-mar 121
  LevelName := '';
122
  LevelAuthor := '';
14 daniel-mar 123
end;
124
 
27 daniel-mar 125
function TLevelData.CountEnemies: integer;
126
begin
127
  result := Length(EnemyAdventTable);
128
end;
129
 
130
procedure TLevelData.DeleteEnemy(i: integer);
131
var
132
  j: integer;
133
begin
134
  for j := i+1 to CountEnemies-1 do
135
  begin
136
    EnemyAdventTable[j-1] := EnemyAdventTable[j];
137
  end;
138
  SetLength(EnemyAdventTable, Length(EnemyAdventTable)-1);
139
end;
140
 
141
procedure TLevelData.DeleteEnemy(x, y: integer; enemyType: TEnemyType;
142
  lifes: integer);
143
begin
144
  DeleteEnemy(IndexOfEnemy(x, y, enemyType, lifes));
145
end;
146
 
40 daniel-mar 147
destructor TLevelData.Destroy;
148
begin
149
  Clear;
150
  inherited;
151
end;
152
 
27 daniel-mar 153
function TLevelData.HasBoss: boolean;
154
var
155
  i: integer;
156
begin
157
  for i := 0 to Length(EnemyAdventTable) - 1 do
158
  begin
159
    if EnemyAdventTable[i].enemyType = etEnemyBoss then
160
    begin
161
      result := true;
162
      exit;
163
    end;
164
  end;
165
  result := false;
166
end;
167
 
168
procedure TLevelData.AddEnemy(x,y:integer;enemyType:TEnemyType;lifes:integer);
169
begin
170
  SetLength(EnemyAdventTable, Length(EnemyAdventTable)+1);
28 daniel-mar 171
 
172
  if enemyType = etEnemyMeteor then lifes := 0;
40 daniel-mar 173
  if RasterErzwingen then
174
  begin
175
    if x mod RasterW <> 0 then raise Exception.CreateFmt('X-Koordinate muss ohne Rest durch %d teilbar sein', [RasterW]);
176
    if y mod RasterH <> 0 then raise Exception.CreateFmt('Y-Koordinate muss ohne Rest durch %d teilbar sein', [RasterH]);
177
  end;
178
  if lifes > MaxPossibleEnemyLives then lifes := MaxPossibleEnemyLives;
28 daniel-mar 179
 
27 daniel-mar 180
  EnemyAdventTable[Length(EnemyAdventTable)-1].x         := x;
181
  EnemyAdventTable[Length(EnemyAdventTable)-1].y         := y;
182
  EnemyAdventTable[Length(EnemyAdventTable)-1].enemyType := enemyType;
183
  EnemyAdventTable[Length(EnemyAdventTable)-1].lifes     := lifes;
184
end;
185
 
186
function TLevelData.IndexOfEnemy(x, y: integer; enemyType: TEnemyType;
187
  lifes: integer): integer;
188
var
189
  i: integer;
190
begin
191
  for i := 0 to Length(EnemyAdventTable) - 1 do
192
  begin
193
    if (EnemyAdventTable[i].x = x) and
194
       (EnemyAdventTable[i].y = y) and
195
       (EnemyAdventTable[i].enemyType = enemyType) and
196
       (EnemyAdventTable[i].lifes = lifes) then
197
    begin
198
      result := i;
199
      exit;
200
    end;
201
  end;
202
  result := -1;
203
end;
204
 
40 daniel-mar 205
procedure TLevelData.LoadFromStrings(sl: TStrings);
14 daniel-mar 206
var
207
  curline: integer;
17 daniel-mar 208
  z, act: integer;
40 daniel-mar 209
  sl2: TStringList;
27 daniel-mar 210
  tmpX, tmpY, tmpLifes: integer;
211
  tmpEnemy: TEnemyType;
30 daniel-mar 212
  tmpRest: string;
40 daniel-mar 213
  ergebnis: string;
14 daniel-mar 214
begin
27 daniel-mar 215
  Clear;
216
 
42 daniel-mar 217
  RasterErzwingen := true; // wichtig für AddEnemy()
40 daniel-mar 218
 
42 daniel-mar 219
  LevelEditorLength := DefaultLevelLength;
220
  LevelName := '';
221
  LevelAuthor := '';
222
 
40 daniel-mar 223
  if sl.Strings[0] = '; SpaceMission 0.3' then
224
  begin
225
    {$REGION 'Backwards compatibility level format 0.3 (convert to 0.4)'}
226
    sl.Strings[0] := '; SpaceMission 0.4';
227
    sl.Insert(1, '; LEV-File');
228
    {$ENDREGION}
229
  end;
230
 
231
  if (sl.Strings[0] = '; SpaceMission 0.4') and
232
     (sl.Strings[1] = '; LEV-File') then
233
  begin
234
    {$REGION 'Backwards compatibility level format 0.4 (convert to 1.0)'}
235
    sl2 := TStringList.Create;
236
    try
237
      z := 0;
238
      act := 0;
239
      while z < sl.Count do
240
      begin
241
        inc(z);
242
        if z > 2 then inc(act);
243
        if act = 5 then act := 1;
244
        ergebnis := sl.Strings[z-1];
245
        if ergebnis = '; SpaceMission 0.4' then
246
          sl2.Add('; SpaceMission 1.0')
247
        else
248
        begin
249
          if (ergebnis = '30000') and (z = 3) then
250
            sl2.Add(IntTostr(DefaultLevelLength))
251
          else
252
          begin
253
            //if not (((ergebnis = '0') and (z = 4)) or ((ergebnis = '-624') and (z = 5)) or ((ergebnis = '222') and (z = 6)) or ((ergebnis = '3') and (z = 7))) then
254
            if (z < 4) or (z > 7) then
255
            begin
256
              if act = 4 then
257
                sl2.Add(inttostr(strtoint(ergebnis) + 32 - (5 * (strtoint(ergebnis) div 37))))
258
              else
259
                sl2.Add(Ergebnis);
260
            end;
261
          end;
262
        end;
263
      end;
264
      sl.Text := sl2.Text;
265
    finally
266
      FreeAndNil(sl2);
267
    end;
268
    {$ENDREGION}
269
  end;
270
 
271
  if (sl.Strings[0] = '; SpaceMission 1.0') and
272
     (sl.Strings[1] = '; LEV-File') then
273
  begin
274
    {$REGION 'Level format 1.0'}
275
    LevelEditorLength := StrToInt(sl.Strings[2]);
276
    curline := 3;
277
    while curline < sl.Count do
278
    begin
279
      tmpEnemy := TEnemyType(strtoint(sl.Strings[curline]));
280
      Inc(curline);
281
      tmpX := strtoint(sl.Strings[curline]);
282
      Inc(curline);
283
      tmpY := strtoint(sl.Strings[curline]);
284
      Inc(curline);
285
      tmpLifes := strtoint(sl.Strings[curline]);
286
      Inc(curline);
287
      AddEnemy(tmpX, tmpY, tmpEnemy, tmpLifes);
288
    end;
289
    {$ENDREGION}
290
  end
291
  else if (SameText(sl.Strings[0], '[SpaceMission Level, Format 1.2]')) or
292
          (SameText(sl.Strings[0], '[SpaceMission Savegame, Format 1.2]')) then
293
  begin
294
    RasterErzwingen := SameText(sl.Strings[0], '[SpaceMission Level, Format 1.2]');
295
    {$REGION 'Level format 1.2'}
296
    for curline := 1 to sl.Count-1 do
297
    begin
298
      // 1234567890123456789012345678901234567890
299
      // 123456 123456 123456 123456 123456 ; Kommentar
300
      if (sl.Strings[curline].Trim = '') or
301
         (Copy(sl.Strings[curline], 1, 1) = ';') then
302
        // Do nothing
303
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Width' then
304
      begin
305
        LevelEditorLength := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
306
      end
42 daniel-mar 307
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Name' then
308
      begin
309
        LevelName := TrimRight(Copy(sl.Strings[curline], 8, Length(sl.Strings[curline])))
310
      end
311
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Author' then
312
      begin
313
        LevelAuthor := TrimRight(Copy(sl.Strings[curline], 8, Length(sl.Strings[curline])))
314
      end
40 daniel-mar 315
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Enemy' then
316
      begin
317
        tmpEnemy := TEnemyType(strtoint(TrimRight(Copy(sl.Strings[curline], 8, 6))));
318
        tmpX     := strtoint(TrimRight(Copy(sl.Strings[curline], 15, 6)));
319
        tmpY     := strtoint(TrimRight(Copy(sl.Strings[curline], 22, 6)));
320
        tmpLifes := strtoint(TrimRight(Copy(sl.Strings[curline], 29, 6)));
321
        tmpRest  := Copy(sl.Strings[curline], 36, Length(sl.Strings[curline])-36+1);
322
        if (Copy(tmpRest, 1, 1) <> ';') and (Trim(tmpRest) <> '') then
323
          raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
324
        AddEnemy(tmpX, tmpY, tmpEnemy, tmpLifes);
325
      end;
326
    end;
327
    {$ENDREGION}
328
  end
329
  else
330
  begin
331
    raise Exception.Create('Level-Format nicht unterstützt oder Datei ist beschädigt');
332
  end;
333
 
334
  SortEnemies; // Sortierung nach X-Koordinate ist sehr wichtig für das Spiel!
335
end;
336
 
337
procedure TLevelData.LoadFromFile(filename: string);
338
var
339
  sl: TStringList;
340
  i, j: integer;
341
  temp: string;
342
  m: array[1..6] of tstrings;
343
begin
15 daniel-mar 344
  sl := TStringList.Create;
14 daniel-mar 345
  try
17 daniel-mar 346
    if EndsText('A1.lev', filename) then
347
    begin
30 daniel-mar 348
      {$REGION 'Backwards compatibility level format 0.2 (split into 5-6 files; convert to 0.3)'}
17 daniel-mar 349
      m[1] := TStringList.create;
350
      m[2] := TStringList.create;
351
      m[3] := TStringList.create;
352
      m[4] := TStringList.create;
353
      m[5] := TStringList.create;
354
      m[6] := TStringList.create;
355
      try
356
        for i := 1 to 6 do
357
        begin
358
          filename[Length(filename)-4] := IntToStr(i)[1]; // ...A2.sav, ...A3.sav, etc.
359
          if FileExists(filename) then
360
            m[i].loadfromfile(filename);
361
        end;
362
        m[1].strings[0] := '-624';
363
        if m[6].Text = '' then m[6].Text := '30000';
14 daniel-mar 364
 
17 daniel-mar 365
        sl.Add('; SpaceMission 0.3');
366
        sl.Add(temp);
367
        for j := 0 to m[1].count-2 do
368
        begin
369
          for i := 0 to m[1].count-2 do
370
          begin
371
            if strtoint(m[1].strings[i]) > strtoint(m[1].strings[i+1]) then
372
            begin
373
              m[1].exchange(i, i+1);
374
              m[2].exchange(i, i+1);
375
              m[3].exchange(i, i+1);
376
              m[4].exchange(i, i+1);
377
              m[5].exchange(i, i+1);
378
            end;
379
          end;
380
        end;
381
        for i := 0 to m[3].count-1 do
382
        begin
383
          for j := 1 to 4 do
384
          begin
385
            if j = 1 then sl.Add(m[3].strings[i]);
386
            if j = 2 then sl.Add(m[1].strings[i]);
387
            if j = 3 then sl.Add(m[2].strings[i]);
388
            if j = 4 then sl.Add(m[4].strings[i]);
389
          end;
390
        end;
391
      finally
392
        FreeAndNil(m[1]);
393
        FreeAndNil(m[2]);
394
        FreeAndNil(m[3]);
395
        FreeAndNil(m[4]);
396
        FreeAndNil(m[5]);
397
        FreeAndNil(m[6]);
398
      end;
399
      {$ENDREGION}
400
    end
401
    else
14 daniel-mar 402
    begin
17 daniel-mar 403
      sl.LoadFromFile(filename);
404
    end;
405
 
40 daniel-mar 406
    LoadFromStrings(sl);
14 daniel-mar 407
  finally
15 daniel-mar 408
    FreeAndNil(sl);
14 daniel-mar 409
  end;
410
end;
411
 
40 daniel-mar 412
procedure TLevelData.SaveToStrings(sl: TStrings);
15 daniel-mar 413
var
414
  i: integer;
14 daniel-mar 415
begin
40 daniel-mar 416
  sl.Clear;
417
  sl.Add('[SpaceMission Level, Format 1.2]');
41 daniel-mar 418
  sl.Add('Width  ' + IntToStr(LevelEditorLength));
42 daniel-mar 419
  if LevelName   <> '' then sl.Add('Name   ' + LevelName);
420
  if LevelAuthor <> '' then sl.Add('Author ' + LevelAuthor);
40 daniel-mar 421
  SortEnemies;
422
  for i := 0 to Length(EnemyAdventTable)-1 do
423
  begin
30 daniel-mar 424
    sl.Add(
40 daniel-mar 425
      'Enemy'.PadRight(6, ' ')+
30 daniel-mar 426
      ' '+
40 daniel-mar 427
      IntToStr(Ord(EnemyAdventTable[i].enemyType)).PadRight(6, ' ')+
428
      ' '+
429
      IntToStr(EnemyAdventTable[i].x).PadRight(6, ' ')+
430
      ' '+
431
      IntToStr(EnemyAdventTable[i].y).PadRight(6, ' ')+
432
      ' '+
433
      IntToStr(EnemyAdventTable[i].lifes).PadRight(6, ' ')+
30 daniel-mar 434
      ' '
435
    );
40 daniel-mar 436
  end;
437
end;
438
 
439
procedure TLevelData.SaveToFile(filename: string);
440
var
441
  sl: TStringList;
442
begin
443
  sl := TStringList.Create;
444
  try
445
    SaveToStrings(sl);
15 daniel-mar 446
    sl.SaveToFile(filename);
447
  finally
448
    FreeAndNil(sl);
449
  end;
14 daniel-mar 450
end;
451
 
27 daniel-mar 452
procedure TLevelData.SortEnemies;
453
var
454
  i, n: integer;
455
  e: TEnemyAdvent;
456
begin
457
  // Bubble Sort Algorithmus
458
  for n := Length(EnemyAdventTable) downto 2 do
459
  begin
460
    for i := 0 to n - 2 do
461
    begin
462
      if
463
        // Sort by X-coord (important for the game!)
464
        (EnemyAdventTable[i].x > EnemyAdventTable[i+1].x)
465
        or
466
        // Sort by Y-coord (just cosmetics)
467
        ((EnemyAdventTable[i].x = EnemyAdventTable[i+1].x) and (EnemyAdventTable[i].y > EnemyAdventTable[i+1].y))
468
      then
469
      begin
470
        e := EnemyAdventTable[i];
471
        EnemyAdventTable[i] := EnemyAdventTable[i + 1];
472
        EnemyAdventTable[i + 1] := e;
473
      end;
474
    end;
475
  end;
476
end;
477
 
40 daniel-mar 478
{ TSaveData }
479
 
480
procedure TSaveData.AssignTo(Dest: TPersistent);
481
var
482
  DestSaveData: TSaveData;
483
begin
484
  DestSaveData := Dest as TSaveData;
485
  if Assigned(DestSaveData) then
486
  begin
487
    DestSaveData.Score := Self.Score;
488
    DestSaveData.Life := Self.Life;
489
    DestSaveData.Level := Self.Level;
490
    DestSaveData.GameMode := Self.GameMode;
491
    if not Assigned(DestSaveData.LevelData) then DestSaveData.LevelData := TLevelData.Create;
492
    DestSaveData.LevelData.Assign(Self.LevelData);
493
  end
494
  else
495
  begin
496
    inherited;
497
  end;
498
end;
499
 
500
procedure TSaveData.Clear;
501
begin
502
  Score := 0;
503
  Life := 0;
504
  Level := 0;
505
  GameMode := gmUnknown;
506
  FreeAndNil(LevelData);
507
end;
508
 
509
destructor TSaveData.Destroy;
510
begin
511
  Clear;
512
  inherited;
513
end;
514
 
515
procedure TSaveData.SaveToStrings(sl: TStrings);
516
var
517
  sl2: TStringList;
518
begin
519
  sl2 := TStringList.Create;
520
  try
521
    sl.Add('[SpaceMission Savegame, Format 1.2]');
522
    sl.Add('Score  ' + IntToStr(Score));
523
    sl.Add('Lives  ' + IntToStr(Life));
524
    sl.Add('Level  ' + IntToStr(Level));
525
    sl.Add('Mode   ' + IntToStr(Ord(GameMode)));
526
    LevelData.SaveToStrings(sl2);
527
    sl2.Delete(0); // Signature
528
    sl.AddStrings(sl2);
529
  finally
530
    FreeAndNil(sl2);
531
  end;
532
end;
533
 
534
procedure TSaveData.LoadFromStrings(sl: TStrings);
535
var
536
  curline: Integer;
537
begin
538
  if (sl.Strings[0] = '; SpaceMission 1.0') and
539
     (sl.Strings[1] = '; SAV-File') then
540
  begin
541
    Score    := StrToInt(sl.Strings[2]);
542
    Life     := StrToInt(sl.Strings[3]);
543
    Level    := StrToInt(sl.Strings[4]);
544
    GameMode := TGameMode(StrToInt(sl.Strings[5]));
545
    if Assigned(LevelData) then FreeAndNil(LevelData);
546
  end
547
  else if SameText(sl.Strings[0], '[SpaceMission Savegame, Format 1.2]') then
548
  begin
549
    Score    := 0;
550
    Life     := 0;
551
    Level    := 0;
552
    GameMode := gmUnknown;
553
    for curline := 1 to sl.Count-1 do
554
    begin
555
      // 1234567890123456789012345678901234567890
556
      // 123456 123456 123456 123456 123456 ; Kommentar
557
      if (sl.Strings[curline].Trim = '') or
558
         (Copy(sl.Strings[curline], 1, 1) = ';') then
559
        // Do nothing
560
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Score' then
561
      begin
562
        Score := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
563
      end
564
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Lives' then
565
      begin
566
        Life := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
567
      end
568
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Level' then
569
      begin
570
        Level := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
571
      end
572
      else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Mode' then
573
      begin
574
        GameMode := TGameMode(StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6))))
575
      end;
576
    end;
577
    if Assigned(LevelData) then FreeAndNil(LevelData);
578
    LevelData := TLevelData.Create;
579
    LevelData.LoadFromStrings(sl);
580
  end
581
  else
582
  begin
583
    raise Exception.Create('Spielstand-Format nicht unterstützt oder Datei beschädigt');
584
  end;
585
end;
586
 
587
procedure TSaveData.LoadFromFile(filename: string);
588
var
589
  sl: TStringList;
590
begin
591
  sl := TStringList.Create;
592
  try
593
    sl.LoadFromFile(filename);
594
    LoadFromStrings(sl);
595
  finally
596
    FreeAndNil(sl);
597
  end;
598
end;
599
 
600
procedure TSaveData.SaveToFile(filename: string);
601
var
602
  sl: TStringList;
603
begin
604
  sl := TStringList.Create;
605
  try
606
    SaveToStrings(sl);
607
    sl.SaveToFile(filename);
608
  finally
609
    FreeAndNil(sl);
610
  end;
611
end;
612
 
14 daniel-mar 613
end.