unit frmMenuunt;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  frmDebuggerUnt, Profile, AtariControls, StdCtrls, ExtCtrls,
  Grids, ComCtrls, HandTIA;

Const
  ConfigFile     = 'PCAEWIN.INI';
  CRLF           = #13 + #10;

type
// ------------------------------------------------------

  TInitSound     = Procedure;
  TSoundBuf      = Packed Array[0..1] Of Pointer;

// ------------------------------------------------------
  TfrmMenu = class(TForm)
    sbMain: TStatusBar;
    sgMain: TStringGrid;
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    procedure sgMainDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure sgMainDblClick(Sender: TObject);
    procedure sgMainMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure sgMainClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    Cols     : Integer;
    Rows     : Integer;
    FileList : TList;
//    Procedure MainMenuHelp;
    Procedure LoadStringGrid;
  public
    { Public declarations }
    Procedure SaveConfiguration(Var Config: ConfigRec; Version: String);
//    Procedure SetBankInfo(BankType: Char; Var Game: TSave);
    Procedure ProcessChosenCart(Ch: Char; Item: TFileListItem);
    Procedure InitConfig(Var Config: ConfigRec;
                         SoundBufSize,Playback_Freq: Word;
                         Version: String);
  end;

var
  frmMenu : TfrmMenu;

implementation

{$R *.DFM}

Uses INIFiles,SPUnit,HexWrite,frmInfoUnt, frmMainunt,
  frmAltMenuUnt, ZipMstr;

Const
  DisplayColWidth: Array[TDisplayScheme] Of Byte = (16,15,14,12,11,10,40,40);

Var OldController: TController;

Procedure TfrmMenu.InitConfig(Var Config: ConfigRec;
                     SoundBufSize,Playback_Freq: Word;
                     Version: String);
Var
  F    : TINIFile;
  St   : String;
  W,H  : Integer;
  I    : Integer;
  Band : TCoolBand;

Begin
  Config.DoSound            := True;
  Config.FrameRate          := 60;
  Config.SoundBufSize       := SoundBufSize;
  Config.PlaybackRate       := Playback_Freq;
  Config.AutoCenter         := False;
  Config.MaxCols            := 320;
  Config.MaxRows            := 200;
  Config.ScreenModeWidth    := 80;
  Config.ScreenModeHeight   := 25;
  Config.ScreenModeDepth    := 1;
  Config.MenuColorScheme    := csGameType;
  Config.MenuForeColor1     := clBlack;
  Config.MenuForeColor2     := clBlack;
  Config.MenuBackColor1     := clSilver;
  Config.MenuBackColor2     := clWhite;
  Config.MenuDisplayScheme  := dsNameExt4;
  Config.GameResolution     := gr320x200;
  Config.Pitfall2DSP        := False;
  Config.GamePath           := '';
  Config.ScreenShotPath     := '';
  Config.BoxFrontScanPath   := '';
  Config.BoxBackScanPath    := '';
  Config.BoxSideScanPath    := '';
  Config.CartScanPath       := '';
  Config.ManualPath         := '';
  Config.HideAllOnZoomfull  := False;
  Config.ShowFPS            := False;

  { Initalize controller interfaces }

  InterfaceHandler.AddInterface(TMouseInterface.Create);
  InterfaceHandler.AddInterface(TKeyboardInterface.Create);
  InterfaceHandler.AddInterface(TDigitalInterface.Create('Digital'));
//  InterfaceHandler.AddInterface(New(PJoystickInterface,Init));
//  InterfaceHandler.AddInterface(New(PGrIPInterface,Init));
//  InterfaceHandler.AddInterface(New(PSideWinderInterface,Init));
{  InterfaceHandler.AddInterface(New(PLogitechInterface,Init));}
//  InterfaceHandler.AddInterface(New(PExternalInterface,Init));

  If FileExists(ExtractFilePath(Application.ExeName) + ConfigFile) Then
  Begin
    F := TINIFile.Create(ExtractFilePath(Application.ExeName) + ConfigFile);
    Config.MaxCols           := F.ReadInteger('GENERAL','MAXCOLS',320);
    Config.MaxRows           := F.ReadInteger('GENERAL','MAXROWS',200);
    Config.DoSound           := F.ReadBool('GENERAL','DOSOUND',False);
    Config.FrameRate         := F.ReadInteger('GENERAL','FRAMERATE',60);
    Config.SoundBufSize      := F.ReadInteger('GENERAL','SOUNDBUFSIZE',SoundBufSize);
    Config.PlaybackRate      := F.ReadInteger('GENERAL','PLAYBACKRATE',Playback_Freq);
    Config.AutoCenter        := F.ReadBool('GENERAL','AUTOCENTER',False);
    Config.ScreenModeWidth   := F.ReadInteger('GENERAL','SCREENMODEWIDTH',80);
    Config.ScreenModeHeight  := F.ReadInteger('GENERAL','SCREENMODEHEIGHT',25);
    Config.ScreenModeDepth   := F.ReadInteger('GENERAL','SCREENMODEDEPTH',8);
    Config.MenuColorScheme   := TColorScheme(F.ReadInteger('GENERAL','MENUCOLORSCHEME',LongInt(csGameType)));
    Config.MenuForeColor1    := F.ReadInteger('GENERAL','MENUFORECOLOR1',clBlack);
    Config.MenuForeColor2    := F.ReadInteger('GENERAL','MENUFORECOLOR2',clBlack);
    Config.MenuBackColor1    := F.ReadInteger('GENERAL','MENUBACKCOLOR1',clSilver);
    Config.MenuBackColor2    := F.ReadInteger('GENERAL','MENUBACKCOLOR2',clWhite);
    Config.MenuDisplayScheme := TDisplayScheme(F.ReadInteger('GENERAL','MENUDISPLAYSCHEME',LongInt(dsNameExt4)));
    Config.GameResolution    := TGameRes(F.ReadInteger('GENERAL','GAMERESOLUTION',LongInt(gr320x200)));
    Config.Pitfall2DSP       := F.ReadBool('GENERAL','PITFALL2DSP',False);
    Config.GamePath          := F.ReadString('GENERAL','GAMEPATH',ExtractFilePath(Application.EXEName));
    Config.ScreenShotPath    := F.ReadString('GENERAL','SHOTPATH',ExtractFilePath(Application.EXEName));
    Config.BoxFrontScanPath  := F.ReadString('GENERAL','BOXFRONTSCANPATH',ExtractFilePath(Application.EXEName));
    Config.BoxBackScanPath   := F.ReadString('GENERAL','BOXBACKSCANPATH',ExtractFilePath(Application.EXEName));
    Config.BoxSideScanPath   := F.ReadString('GENERAL','BOXSIDESCANPATH',ExtractFilePath(Application.EXEName));
    Config.CartScanPath      := F.ReadString('GENERAL','CARTSCANPATH',ExtractFilePath(Application.EXEName));
    Config.ManualPath        := F.ReadString('GENERAL','MANUALPATH',ExtractFilePath(Application.EXEName));
    Config.UseDefaultSize    := F.ReadBool('GENERAL','USEDEFAULTSIZE',True);
    Config.HideAllOnZoomFull := F.ReadBool('GENERAL','HIDEALLONZOOMFULL',False);
    Config.ShowFPS           := F.ReadBool('GENERAL','SHOWFPS',False);
    Config.ZoomMode          := F.ReadInteger('GENERAL','ZOOMMODE',1);

    FontName                 := F.ReadString('GENERAL','FONTNAME',FontName);
    FontSize                 := F.ReadInteger('GENERAL','FONTSIZE',FontSize);
    Font.Name                := F.ReadString('GENERAL','MENUFONTNAME',Font.Name);
    Font.Size                := F.ReadInteger('GENERAL','MENUFONTSIZE',Font.Size);
    frmMain.CoolBar1.Height  := F.ReadInteger('GENERAL','COOLBARHEIGHT',frmMain.CoolBar1.Height);
    I := 0;
    While I < frmMain.CoolBar1.Bands.Count Do
    Begin
      Band := TCoolBand(frmMain.CoolBar1.Bands.Items[I]);
      Band.Break := F.ReadBool('GENERAL','COOLBANDBREAK' + IntToStr(I),Band.Break);
      Band.Width := F.ReadInteger('GENERAL','COOLBANDWIDTH' + IntToStr(I),Band.Width);
      Inc(I);
    End; // While
    frmMain.ToolBar1.Left    := F.ReadInteger('GENERAL','TOOLBAR1LEFT',frmMain.ToolBar1.Left);
    frmMain.ToolBar1.Top     := F.ReadInteger('GENERAL','TOOLBAR1TOP',frmMain.ToolBar1.Top);
    frmMain.ToolBar2.Left    := F.ReadInteger('GENERAL','TOOLBAR2LEFT',frmMain.ToolBar2.Left);
    frmMain.ToolBar2.Top     := F.ReadInteger('GENERAL','TOOLBAR2TOP',frmMain.ToolBar2.Top);
    frmAltMenu.Font.Name     := Font.Name;
    frmAltMenu.Font.Size     := Font.Size;
    St                       := UpperCase(F.ReadString('GENERAL','MENUFONTSTYLE',''));
    Font.Style := [];
    If Pos('B',St) <> 0 Then Font.Style := Font.Style + [fsBold];
    If Pos('I',St) <> 0 Then Font.Style := Font.Style + [fsItalic];
    If Pos('U',St) <> 0 Then Font.Style := Font.Style + [fsUnderline];
    If Pos('S',St) <> 0 Then Font.Style := Font.Style + [fsStrikeout];
    frmAltMenu.Font.Style := Font.Style;
    If frmMain.UseDirectDraw Then frmMain.DDFullScreen := F.ReadBool('GENERAL','FULLSCREEN',False);
    If frmMain.UseDirectDraw Then frmMain.TVScreen     := F.ReadBool('GENERAL','TVSCREEN',False);
    WindowState := wsNormal;
    W := F.ReadInteger('GENERAL','MENUWIDTH',Width);
    H := F.ReadInteger('GENERAL','MENUHEIGHT',Height);
    If (W > 200) And (W <= Screen.Width)  Then Width  := W;
    If (H > 200) And (H <= Screen.Height) Then Height := H;
    W := F.ReadInteger('GENERAL','ALTMENUWIDTH',Width);
    H := F.ReadInteger('GENERAL','ALTMENUHEIGHT',Height);
    If (W > 200) And (W <= Screen.Width)  Then frmAltMenu.Width  := W;
    If (H > 200) And (H <= Screen.Height) Then frmAltMenu.Height := H;
    If F.ReadBool('GENERAL','MENUMAXIMIZED',(WindowState = wsMaximized)) Then WindowState := wsMaximized;
    If F.ReadBool('GENERAL','ALTMENUMAXIMIZED',(frmAltMenu.WindowState = wsMaximized)) Then frmAltMenu.WindowState := wsMaximized;
    Config.AlternateGameMenu := F.ReadBool('GENERAL','ALTGAMEMENU',False);
    For I := Integer(Low(TMenuSort)) To Integer(High(TMenuSort)) Do
    Begin
      W := F.ReadInteger('GENERAL','ALTMENUWIDTH' + IntToStr(I),frmAltMenu.sgMain.ColWidths[I]);
      If W < 4 Then W := 4;
      If W <= frmAltMenu.sgMain.Width Then frmAltMenu.sgMain.ColWidths[I] := W;
    End; // For I
    frmAltMenu.Sort    := TMenuSort(F.ReadInteger('GENERAL','ALTMENUSORT',Integer(frmAltMenu.Sort)));
    frmAltMenu.SortAsc := F.ReadBool('GENERAL','ALTMENUSORTASC',frmAltMenu.SortAsc);

    { Load controller interface information }

    InterfaceHandler.LoadConfiguration(F);
    F.Free;
  End
  Else SaveConfiguration(Config,Version);
  If Not ((Config.MaxRows - 200) In [0,4,15,50,105]) Then Config.MaxRows := 200;
End; { TfrmMenu.InitConfig }

Procedure TfrmMenu.SaveConfiguration(Var Config: ConfigRec; Version: String);
Var
  F    : TINIFile;
  St   : String;
  I    : Integer;
  Band : TCoolBand;

Begin
  F := TINIFile.Create(ExtractFilePath(Application.ExeName) + ConfigFile);
  F.WriteInteger('GENERAL','MAXCOLS',Config.MaxCols);
  F.WriteInteger('GENERAL','MAXROWS',Config.MaxRows);
  F.WriteBool('GENERAL','DOSOUND',Config.DoSound);
  F.WriteInteger('GENERAL','FRAMERATE',Config.FrameRate);
  F.WriteInteger('GENERAL','SOUNDBUFSIZE',Config.SoundBufSize);
  F.WriteInteger('GENERAL','PLAYBACKRATE',Config.PlaybackRate);
  F.WriteBool('GENERAL','AUTOCENTER',Config.AutoCenter);
  F.WriteInteger('GENERAL','SCREENMODEWIDTH',Config.ScreenModeWidth);
  F.WriteInteger('GENERAL','SCREENMODEHEIGHT',Config.ScreenModeHeight);
  F.WriteInteger('GENERAL','SCREENMODEDEPTH',Config.ScreenModeDepth);
  F.WriteInteger('GENERAL','MENUCOLORSCHEME',LongInt(Config.MenuColorScheme));
  F.WriteInteger('GENERAL','MENUFORECOLOR1',Config.MenuForeColor1);
  F.WriteInteger('GENERAL','MENUFORECOLOR2',Config.MenuForeColor2);
  F.WriteInteger('GENERAL','MENUBACKCOLOR1',Config.MenuBackColor1);
  F.WriteInteger('GENERAL','MENUBACKCOLOR2',Config.MenuBackColor2);
  F.WriteInteger('GENERAL','MENUDISPLAYSCHEME',LongInt(Config.MenuDisplayScheme));
  F.WriteInteger('GENERAL','GAMERESOLUTION',LongInt(Config.GameResolution));
  F.WriteBool('GENERAL','PITFALL2DSP',Config.Pitfall2DSP);
  F.WriteBool('GENERAL','USEDEFAULTSIZE',Config.UseDefaultSize);
  F.WriteBool('GENERAL','HIDEALLONZOOMFULL',Config.HideAllOnZoomFull);
  F.WriteBool('GENERAL','SHOWFPS',Config.ShowFPS);
  F.WriteInteger('GENERAL','ZOOMMODE',Config.ZoomMode);

  F.WriteString('GENERAL','FONTNAME',FontName);
  F.WriteInteger('GENERAL','FONTSIZE',FontSize);
  F.WriteString('GENERAL','MENUFONTNAME',Font.Name);
  F.WriteInteger('GENERAL','MENUFONTSIZE',Font.Size);
  F.WriteInteger('GENERAL','COOLBARHEIGHT',frmMain.CoolBar1.Height);
  F.WriteInteger('GENERAL','TOOLBAR1LEFT',frmMain.ToolBar1.Left);
  F.WriteInteger('GENERAL','TOOLBAR1TOP',frmMain.ToolBar1.Top);
  F.WriteInteger('GENERAL','TOOLBAR2LEFT',frmMain.ToolBar2.Left);
  F.WriteInteger('GENERAL','TOOLBAR2TOP',frmMain.ToolBar2.Top);
  I := 0;
  While I < frmMain.CoolBar1.Bands.Count Do
  Begin
    Band := TCoolBand(frmMain.CoolBar1.Bands.Items[I]);
    F.WriteBool('GENERAL','COOLBANDBREAK' + IntToStr(I),Band.Break);
    F.WriteInteger('GENERAL','COOLBANDWIDTH' + IntToStr(I),Band.Width);
    Inc(I);
  End; // While
  St := '';
  If fsBold      In Font.Style Then St := St + 'B';
  If fsItalic    In Font.Style Then St := St + 'I';
  If fsUnderline In Font.Style Then St := St + 'U';
  If fsStrikeout In Font.Style Then St := St + 'S';
  F.WriteString('GENERAL','MENUFONTSTYLE',St);
  F.WriteBool('GENERAL','FULLSCREEN',frmMain.DDFullScreen);
  F.WriteBool('GENERAL','TVSCREEN',frmMain.TVScreen);
  F.WriteString('GENERAL','GAMEPATH',Config.GamePath);
  F.WriteString('GENERAL','SHOTPATH',Config.ScreenShotPath);
  F.WriteString('GENERAL','BOXFRONTSCANPATH',Config.BoxFrontScanPath);
  F.WriteString('GENERAL','BOXBACKSCANPATH',Config.BoxBackScanPath);
  F.WriteString('GENERAL','BOXSIDESCANPATH',Config.BoxSideScanPath);
  F.WriteString('GENERAL','CARTSCANPATH',Config.CartScanPath);
  F.WriteString('GENERAL','MANUALPATH',Config.ManualPath);
  If WindowState <> wsMaximized Then
  Begin
    F.WriteInteger('GENERAL','MENUWIDTH',Width);
    F.WriteInteger('GENERAL','MENUHEIGHT',Height);
  End;
  If frmAltMenu.WindowState <> wsMaximized Then
  Begin
    F.WriteInteger('GENERAL','ALTMENUWIDTH',frmAltMenu.Width);
    F.WriteInteger('GENERAL','ALTMENUHEIGHT',frmAltMenu.Height);
  End;
  F.WriteBool('GENERAL','MENUMAXIMIZED',(WindowState = wsMaximized));
  F.WriteBool('GENERAL','ALTMENUMAXIMIZED',(frmAltMenu.WindowState = wsMaximized));
  F.WriteBool('GENERAL','ALTGAMEMENU',Config.AlternateGameMenu);
  For I := Integer(Low(TMenuSort)) To Integer(High(TMenuSort)) Do  
   F.WriteInteger('GENERAL','ALTMENUWIDTH' + IntToStr(I),frmAltMenu.sgMain.ColWidths[I]);
  F.WriteInteger('GENERAL','ALTMENUSORT',Integer(frmAltMenu.Sort));
  F.WriteBool('GENERAL','ALTMENUSORTASC',frmAltMenu.SortAsc);
  InterfaceHandler.SaveConfiguration(F);
  F.UpdateFile;
  F.Free;
End; { TfrmMenu.SaveConfiguration }
(*
Procedure TfrmMenu.MainMenuHelp;
Begin
  Window.Screen.TextColor(LightGray);
  Window.Screen.TextBackGround(Blue);
  Window.Screen.ClrScr;
  Window.Screen.GotoXY(3,1);  Window.Screen.Write('Run options');

  Window.Screen.GotoXY(5,3);  Window.Screen.Write('<Esc> ............................ Quit');
  Window.Screen.GotoXY(5,4);  Window.Screen.Write('Arrow keys or Joystick ........... Move selection');
  Window.Screen.GotoXY(5,5);  Window.Screen.Write('<Enter> or Joystick button 1 ..... Run 2K/4K/Atari 8K/Atari 16K cart');
  Window.Screen.GotoXY(5,6);  Window.Screen.Write('A ................................ Run Activision 16K cart');
  Window.Screen.GotoXY(5,7);  Window.Screen.Write('M ................................ Run M-Network 8K RAM cart');
  Window.Screen.GotoXY(5,8);  Window.Screen.Write('P ................................ Run Parker Bros. 8K cart');
  Window.Screen.GotoXY(5,9);  Window.Screen.Write('R ................................ Run Atari super-chip cart');
  Window.Screen.GotoXY(5,10); Window.Screen.Write('T ................................ Run TigerVision cart');
  Window.Screen.GotoXY(5,11); Window.Screen.Write('2 ................................ Run Pitfall II cart');
  Window.Screen.GotoXY(3,13); Window.Screen.Write('Game options');
  Window.Screen.GotoXY(5,14); Window.Screen.Write('F1 ............................... Help/status screen');
  Window.Screen.GotoXY(5,15); Window.Screen.Write('F2 ............................... Reset game');
  Window.Screen.GotoXY(5,16); Window.Screen.Write('F3 ............................... Toggle NTSC/PAL palette');
  Window.Screen.GotoXY(5,17); Window.Screen.Write('F4 ............................... Select game');
  Window.Screen.GotoXY(5,18); Window.Screen.Write('F5 ............................... Color/BW switch');
  Window.Screen.GotoXY(5,19); Window.Screen.Write('F6/F7 ............................ Player 1/2 difficulty');
  Window.Screen.GotoXY(5,20); Window.Screen.Write('F8 ............................... Save game info to profile file');
  Window.Screen.GotoXY(5,21); Window.Screen.Write('F9 ............................... Capture screen to .BMP file');
  Window.Screen.GotoXY(5,22); Window.Screen.Write('F10 .............................. Toggle vertical autocentering');
  Window.Screen.GotoXY(5,23); Window.Screen.Write('F11 .............................. Save game to disk');
  Window.Screen.GotoXY(5,24); Window.Screen.Write('F12 .............................. Load saved game from disk');
  Window.Screen.GotoXY(5,25); Window.Screen.Write('=,- .............................. Shift screen up or down');
  Window.ReadKey;
  Window.Screen.TextColor(LightGray);
  Window.Screen.TextBackGround(Blue);
  Window.Screen.ClrScr;
End; { TfrmMenu.MainMenuHelp }
*)
procedure TfrmMenu.FormCreate(Sender: TObject);
begin
//  InitConfig(Config,128,31400,Version);
  MenuInfo.Title       := '';
  MenuInfo.FileName    := '';
  MenuInfo.ZipFileName := '';
  FileList             := TList.Create;
  Scaled               := False;  
end;

procedure TfrmMenu.FormResize(Sender: TObject);
begin
  LoadStringGrid;
end; // TfrmMenu.FormResize

procedure TfrmMenu.FormShow(Sender: TObject);
Var
  S     : TSearchRec;
  Cont  : TController;
  Item  : TFileListItem;
  Item1 : TFileListItem;
  I,J   : Integer;
  St1   : String;
  St2   : String;
  Z     : ZipDirEntry;  

begin
  Caption           := 'PCAE ' + Version;
  Cols              := 1;
  Rows              := 1;
//  MenuInfo.FileName := '';
//  MenuInfo.Title    := '';

  // If there are any entries, get rid of them

  While FileList.Count > 0 Do
  Begin
    TFileListItem(FileList[0]).Free;
    FileList.Delete(0);
  End; // While

  // Locate all the .BIN and .PAL files

  If ParamCount > 0 Then Path := ParamStr(1) Else Path := Config.GamePath;
  If (Path <> '') And Not (Path[Length(Path)] In [':','\']) Then Path := Path + '\';

  // Locate all .BIN and .PAL files 

  If FindFirst(Path + '*.BIN',faArchive,S) = 0 Then
  Repeat
    Item := TFileListItem.Create;
    FileList.Add(Item);
    Item.Name         := S.Name;
    Item.Size         := S.Size;
    Item.ScreenShot   := False;
    Item.BoxFrontScan := False;
    Item.BoxBackScan  := False;
    Item.BoxSideScan  := False;
    Item.CartScan     := False;
    Item.Manual       := False;
    Item.Extras       := '';
    FindProfile(S.Name,Cont,MenuInfo.Pos200,MenuInfo.Pos204,MenuInfo.Pos215,MenuInfo.Pos250,MenuInfo.Pos305,Item.Prof);
    If (Item.Prof <> Nil) And (Item.Prof.RealName <> '')
     Then Item.RNam := Item.Prof.RealName
     Else Item.RNam := Item.Name;
  Until FindNext(S) <> 0;

  If FindFirst(Path + '*.PAL',faArchive,S) = 0 Then
  Repeat
    Item := TFileListItem.Create;
    FileList.Add(Item);
    Item.Name         := S.Name;
    Item.Size         := S.Size;
    Item.ScreenShot   := False;
    Item.BoxFrontScan := False;
    Item.BoxBackScan  := False;
    Item.BoxSideScan  := False;
    Item.CartScan     := False;
    Item.Manual       := False;
    Item.Extras       := '';
    FindProfile(S.Name,Cont,MenuInfo.Pos200,MenuInfo.Pos204,MenuInfo.Pos215,MenuInfo.Pos250,MenuInfo.Pos305,Item.Prof);
    If (Item.Prof <> Nil) And (Item.Prof.RealName <> '')
     Then Item.RNam := Item.Prof.RealName
     Else Item.RNam := Item.Name;
  Until FindNext(S) <> 0;

  // Locate all .ZIP files, and locate all .BIN and .PAL files in those files

  If FindFirst(Path + '*.ZIP',faArchive,S) = 0 Then
  Repeat
    frmMain.ZipMaster1.ZipFilename := Path + S.Name;
    I := 0;
    While I < frmMain.ZipMaster1.ZipContents.Count Do
    Begin
      Z := PZipDirEntry(frmMain.ZipMaster1.ZipContents.Items[I])^;
      Z.FileName := UpperCase(Z.FileName);
      If (ExtractFileExt(Z.FileName) = '.BIN') Or
         (ExtractFileExt(Z.FileName) = '.PAL') Then
      Begin
        Item := TFileListItem.Create;
        FileList.Add(Item);
        Item.Name         := ExtractFileName(Z.FileName);
        Item.ZIPName      := Path + S.Name;
        Item.Size         := Z.UncompressedSize;
        Item.BoxFrontScan := False;
        Item.BoxBackScan  := False;
        Item.BoxSideScan  := False;
        Item.CartScan     := False;
        Item.Manual       := False;
        Item.Extras       := '';
      End;
      Inc(I);
    End; // While
  Until FindNext(S) <> 0;

  // Sort the file list in ascending alphabetical order

  For I := 0 To FileList.Count - 2 Do
  Begin
    Item := FileList[I];
    For J := I + 1 To FileList.Count - 1 Do
    Begin
      Item1 := FileList[J];
      St1 := UpperCase(Item.RNam);
      St2 := UpperCase(Item1.RNam);
      If St2 < St1 Then
      Begin
        FileList[I] := Item1;
        FileList[J] := Item;
        Item        := Item1;
      End;
    End; // For J
  End; // For I

  // Show if there were any files found

  If FileList.Count = 0 Then
  Begin
//    MenuInfo.FileName := '';
    Close;
  End
  Else
  Begin
    LoadStringGrid;
    InterfaceHandler.ActivateInterfaces;
    Game.Controller := OldController;
  End;
  Repaint;
end; // TfrmMenu.FormShow

Procedure TfrmMenu.LoadStringGrid;
Var
  I,X,Y : Integer;
  Item  : TFileListItem;
  Count : Integer;

Begin

  // Important to do this because this can be called by FormCreate, before FileList
  // has been created

  If FileList <> Nil Then Count := FileList.Count Else Count := 0;
  sgMain.DefaultColWidth  := 20 * Canvas.TextWidth('M');
  sgMain.DefaultRowHeight := Canvas.TextHeight('Mg') + 4;

  Rows := ((sgMain.Height - GetSystemMetrics(SM_CXHSCROLL) - 4) Div (sgMain.DefaultRowHeight + sgMain.GridLineWidth));
  If Rows > Count Then Rows := Count;
  If Rows > 0 Then Cols := Count Div Rows Else Cols := 0;
  If (Rows > 0) And (Count / Rows > Cols) Then Inc(Cols);

  sgMain.RowCount := Rows;
  sgMain.ColCount := Cols;
  I := 0;
  For X := 0 To Cols - 1 Do
  Begin
    For Y := 0 To Rows - 1 Do
    Begin
      If I < Count Then
      Begin
        Item := FileList[I];
        If Config.MenuDisplayScheme In [dsRealNameLeft,dsRealNameCenter]
         Then sgMain.Cells[X,Y] := Item.RNam
         Else sgMain.Cells[X,Y] := Item.Name;
        Inc(I);
      End;
    End; // For Y
  End; // For X
  sgMainClick(Self);
End; // TfrmMenu.LoadStringGrid

procedure TfrmMenu.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  If frmInfo.Visible Then frmInfo.Close;
  InterfaceHandler.DeactivateInterfaces;
end;

Procedure TfrmMenu.ProcessChosenCart(Ch: Char; Item: TFileListItem);
Var
  St   : String;
  J    : Integer;
  Code : Integer;

Begin
  MenuInfo.FileName    := Path + Item.Name;
  MenuInfo.ZipFileName := Item.ZIPName;
  MenuInfo.Title       := Item.RNam;
  If Ch = #13 Then
  Begin
    OldController := Game.Controller;
    Ch := MenuKey[FindProfile(Item.Name,MenuInfo.Cont,MenuInfo.Pos200,MenuInfo.Pos204,
           MenuInfo.Pos215,MenuInfo.Pos250,MenuInfo.Pos305,MenuInfo.ProfileRec)];
    If MenuInfo.Cont <> crUnknown Then Game.Controller := MenuInfo.Cont;
  End;
  If Ch In ['T','A','2','R','P','M','G','V','O'] Then SetBankInfo(Ch,Game)
  Else
  Begin
    Case Ch Of
'3': Begin                               { 32-in-1 }
      Game.Cart := ct32In1;
      St := InputBox('Set game title','Enter game title:',IntToStr(Game.MegaBoyNum));
      Val(St,J,Code);
      If (J >= 0) And (J <= 31) Then Game.MegaBoyNum := J;
    End;
    Else
      Game.Cart := ct4k;
      If Item.Size = 8192  Then SetBankInfo('8',Game);        { Standard 8k }
      If Item.Size = 10495 Then SetBankInfo('2',Game);        { Pitfall II }
      If (Item.Size Mod 8448) = 0 Then SetBankInfo('S',Game); { Starpath }
      If Item.Size = 12288 Then SetBankInfo('C',Game);        { CBS RAM-Plus }
      If Item.Size = 16384 Then SetBankInfo('6',Game);        { Standard 16k }
    End; { Case }
  End;
End; // TfrmMenu.ProcessChosenCart

procedure TfrmMenu.FormKeyPress(Sender: TObject; var Key: Char);
Var
  I    : Integer;
  Item : TFileListItem;

begin
  Case UpCase(Key) Of
    #13,#27,'A','G','R','P','M','T','2','3','V','O':
    Begin
      If UpCase(Key) In [#13,'A','G','R','P','M','T','2','3','V','O'] Then
      Begin
        I := sgMain.Col * sgMain.RowCount + sgMain.Row;
        If (I >= 0) And (I < FileList.Count) Then
        Begin
          Item := FileList[I];
          ProcessChosenCart(Key,Item);
        End;
      End
      Else MenuInfo.FileName := '';
      Close;
    End;
  End; // Case
end;

procedure TfrmMenu.sgMainDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
Var
  F,B   : TColor;
  I     : Integer;
  Item  : TFileListItem;
  St    : String;
  W0,W1 : Integer;

  Procedure ChooseColor(X,Y: Integer);
  Begin
    If (sgMain.Col = X) And (sgMain.Row = Y) Then
    Begin
      F := clHighlightText;
      B := clHighlight;
    End
    Else
    Begin
      St := Item.RNam;
      Case Config.MenuColorScheme Of
      csGameType:
      Begin
        Case Item.Size Of
2048,4096: F := clBlack;
  8192: F := clTeal;
  8448: F := clRed;
 10495: F := clGreen;
 16384: F := clYellow;
        Else
          F := clNavy;
        End; { Case }
        If (Item.Size Mod 8448) = 0 Then F := clRed;
        B := clSilver;
      End;
      csAlphabetical:
      Begin
        If (Ord(St[1]) And 1) <> 0 Then
        Begin
          F := Config.MenuForeColor1;
          B := Config.MenuBackColor1;
        End
        Else
        Begin
          F := Config.MenuForeColor2;
          B := Config.MenuBackColor2;
        End;
      End;
      csEvery3:
      Begin
        If ((Y Div 3) And 1) <> 0 Then
        Begin
          F := Config.MenuForeColor1;
          B := Config.MenuBackColor1;
        End
        Else
        Begin
          F := Config.MenuForeColor2;
          B := Config.MenuBackColor2;
        End;
      End;
      csEvery4:
      Begin
        If ((Y Div 4) And 1) <> 0 Then
        Begin
          F := Config.MenuForeColor1;
          B := Config.MenuBackColor1;
        End
        Else
        Begin
          F := Config.MenuForeColor2;
          B := Config.MenuBackColor2;
        End;
      End;
      csEvery5:
      Begin
        If ((Y Div 5) And 1) <> 0 Then
        Begin
          F := Config.MenuForeColor1;
          B := Config.MenuBackColor1;
        End
        Else
        Begin
          F := Config.MenuForeColor2;
          B := Config.MenuBackColor2;
        End;
      End;
      csEvery6:
      Begin
        If ((Y Div 6) And 1) <> 0 Then
        Begin
          F := Config.MenuForeColor1;
          B := Config.MenuBackColor1;
        End
        Else
        Begin
          F := Config.MenuForeColor2;
          B := Config.MenuBackColor2;
        End;
      End;
      Else
        F := clBlack;
        B := clSilver;
      End; { Case }
    End;
  End; // ChooseColor

begin
  I := ACol * sgMain.RowCount + ARow;
  If (I >= 0) And (I < FileList.Count) Then
  Begin
    Item := FileList[I];
    ChooseColor(ACol,ARow);
    sgMain.Canvas.Font.Color  := F;
    sgMain.Canvas.Brush.Color := B;
    sgMain.Canvas.FillRect(Rect);
    St := Item.RNam;
    sgMain.Canvas.Font.Name  := Font.Name;
    sgMain.Canvas.Font.Size  := Font.Size;
    sgMain.Canvas.Font.Style := Font.Style;

    If Config.MenuDisplayScheme <> dsRealNameCenter
     Then sgMain.Canvas.TextOut(Rect.Left + 2,Rect.Top + 2,St)
     Else
     Begin
       W0 := sgMain.Canvas.TextWidth(St);
       W1 := Rect.Right - Rect.Left - 4;
       If W0 <= W1
        Then sgMain.Canvas.TextOut(Rect.Left + 2 + ((W1 - W0) Div 2),Rect.Top + 2,St)
        Else sgMain.Canvas.TextOut(Rect.Left + 2,Rect.Top + 2,St)
     End;
  End;
end;

procedure TfrmMenu.sgMainDblClick(Sender: TObject);
Var
  I    : Integer;
  Item : TFileListItem;

begin
  I := sgMain.Col * sgMain.RowCount + sgMain.Row;
  If (I >= 0) And (I < FileList.Count) Then
  Begin
    Item := FileList[I];
    ProcessChosenCart(#13,Item);
    Close;
  End;
end;

procedure TfrmMenu.sgMainMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var
  I    : Integer;
  Item : TFileListItem;
  St   : String;

begin
  If Button = mbRight Then
  Begin
    X := X Div (sgMain.DefaultColWidth + sgMain.GridLineWidth);
    Y := Y Div (sgMain.DefaultRowHeight + sgMain.GridLineWidth);
    I := (X + sgMain.LeftCol) * sgMain.RowCount + Y;
    If (I >= 0) And (I < FileList.Count) And (X < sgMain.ColCount) And (Y < sgMain.RowCount) Then
    Begin
      Item := FileList[I];
      St := Item.RNam;
      frmInfo.Caption  := St;
      If Not frmInfo.Visible Then frmInfo.Show;
      frmInfo.LoadImages(Item.Name);
    End;
  End;
end;

procedure TfrmMenu.sgMainClick(Sender: TObject);
Var
  I     : Integer;
  Item  : TFileListItem;
  St    : String;
  Count : Integer;

begin

  // Important to do this because this can be called by FormCreate, before FileList
  // has been created

  If FileList <> Nil Then Count := FileList.Count Else Count := 0;
  I := sgMain.Col * sgMain.RowCount + sgMain.Row;
  If (I >= 0) And (I < Count) Then
  Begin
    Item := FileList[I];
    If (Item.Prof <> Nil) And (Item.Prof.RealName <> '')
     Then St := Item.Prof.RealName + '  [' + Item.Name + ']'
     Else St := Item.Name;
    St := St + '   ' + IntToStr(Item.Size) + ' bytes';
    sbMain.Panels[0].Text := St;
  End;
end;

procedure TfrmMenu.FormDestroy(Sender: TObject);
begin
  While FileList.Count > 0 Do
  Begin
    TFileListItem(FileList[0]).Free;
    FileList.Delete(0);
  End; // While
  FileList.Free;
end;

end.

// ----------------------------------------------------------------------
// PCAE and PCAEWin - PC Atari Emulator - Atari 2600 emulator
// Copyright (C) 2000 John Dullea
//
//  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 2 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, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------
