private static void CheckADir(RvDir dbDir, bool report)
        {
            if (_cacheSaveTimer.Elapsed.TotalMinutes > Settings.CacheSaveTimePeriod)
            {
                _bgw.ReportProgress(0, "Saving Cache");
                DB.Write();
                _bgw.ReportProgress(0, "Saving Cache Complete");
                _cacheSaveTimer.Reset();
                _cacheSaveTimer.Start();
            }

            string fullDir = dbDir.FullName;
            if (report)
                _bgw.ReportProgress(0, new bgwText2(fullDir));

            DatStatus chechingDatStatus = dbDir.IsInToSort ? DatStatus.InToSort : DatStatus.NotInDat;

            // this is a temporary rvDir structure to store the data about the actual directory/files we are scanning
            // we will first populate this variable with the real file data from the directory, and then compare it
            // with the data in dbDir.
            RvDir fileDir = null;


            Debug.WriteLine(fullDir);

            FileType ft = dbDir.FileType;

            #region "Populate fileDir"

            // if we are scanning a ZIP file then populate scanDir from the ZIP file
            switch (ft)
            {
                case FileType.Zip:
                    {
                        fileDir = new RvDir(ft);

                        // open the zip file
                        ZipFile checkZ = new ZipFile();

                        ZipReturn zr = checkZ.ZipFileOpen(fullDir, dbDir.TimeStamp, true);

                        if (zr == ZipReturn.ZipGood)
                        {
                            dbDir.ZipStatus = checkZ.ZipStatus;

                            // to be Scanning a ZIP file means it is either new or has changed.
                            // as the code below only calls back here if that is true.
                            //
                            // Level1: Only use header CRC's
                            // Just get the CRC for the ZIP headers.
                            //
                            // Level2: Fully checksum changed only files
                            // We know this file has been changed to do a full checksum scan.
                            //
                            // Level3: Fully checksum everything
                            // So do a full checksum scan.
                            if (EScanLevel == eScanLevel.Level2 || EScanLevel == eScanLevel.Level3)
                                checkZ.DeepScan();

                            // add all of the file information from the zip file into scanDir
                            for (int i = 0; i < checkZ.LocalFilesCount(); i++)
                            {
                                RvFile tFile = new RvFile(DBTypeGet.FileFromDir(ft))
                                                   {
                                                       Name = checkZ.Filename(i),
                                                       ZipFileIndex = i,
                                                       ZipFileHeaderPosition = checkZ.LocalHeader(i),
                                                       Size = checkZ.UncompressedSize(i),
                                                       CRC = checkZ.CRC32(i)
                                                   };
                                // all 3 levels read the CRC from the ZIP header
                                tFile.SetStatus(chechingDatStatus, GotStatus.Got);
                                tFile.FileStatusSet(FileStatus.SizeFromHeader | FileStatus.CRCFromHeader);

                                // if we are in level 2 or level 3 then do a full CheckSum Scan.
                                if (EScanLevel == eScanLevel.Level2 || EScanLevel == eScanLevel.Level3)
                                {
                                    // DeepScan will return ZipReturn.ZipCRCDecodeError if the headers CRC and 
                                    // the actual CRC do not match.
                                    // So we just need to set the MD5 and SHA1 from the ZIP file.
                                    zr = checkZ.FileStatus(i);
                                    if (zr == ZipReturn.ZipUntested)
                                    {
                                        _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir + " : " + checkZ.Filename(i)));
                                    }
                                    else if (zr != ZipReturn.ZipGood)
                                    {
                                        _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir + " : " + checkZ.Filename(i)));
                                        tFile.GotStatus = GotStatus.Corrupt;
                                    }
                                    else
                                    {
                                        tFile.MD5 = checkZ.MD5(i);
                                        tFile.SHA1 = checkZ.SHA1(i);
                                        tFile.FileStatusSet(FileStatus.SizeVerified | FileStatus.CRCVerified | FileStatus.SHA1Verified | FileStatus.MD5Verified);
                                    }
                                }

                                fileDir.ChildAdd(tFile);
                            }
                        }
                        else if (zr == ZipReturn.ZipFileLocked)
                        {
                            _bgw.ReportProgress(0, new bgwShowError(fullDir, "Zip File Locked"));
                            dbDir.TimeStamp = 0;
                            dbDir.GotStatus = GotStatus.FileLocked;
                        }
                        else
                        {
                            _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir));
                            dbDir.GotStatus = GotStatus.Corrupt;
                        }
                        checkZ.ZipFileClose();
                    }
                    break;

                case FileType.Dir:
                    {
                        fileDir = new RvDir(FileType.Dir);


                        DirectoryInfo oDir = new DirectoryInfo(fullDir);
                        DirectoryInfo[] oDirs = oDir.GetDirectories();
                        FileInfo[] oFiles = oDir.GetFiles();

                        // add all the subdirectories into scanDir 
                        foreach (DirectoryInfo dir in oDirs)
                        {
                            RvBase tDir = new RvDir(FileType.Dir)
                                              {
                                                  Name = dir.Name,
                                                  TimeStamp = dir.LastWriteTime,
                                              };
                            tDir.SetStatus(chechingDatStatus, GotStatus.Got);
                            fileDir.ChildAdd(tDir);
                        }

                        // add all the files into scanDir
                        foreach (FileInfo oFile in oFiles)
                        {
                            // if we find any zip files add them as zip files.
                            string fExt = Path.GetExtension(oFile.Name);
                            switch (fExt.ToLower())
                            {
                                case ".zip":
                                    {
                                        RvDir tGame = new RvDir(FileType.Zip)
                                                          {
                                                              Name = Path.GetFileNameWithoutExtension(oFile.Name),
                                                              TimeStamp = oFile.LastWriteTime,
                                                          };
                                        tGame.SetStatus(chechingDatStatus, GotStatus.Got);
                                        fileDir.ChildAdd(tGame);
                                    }
                                    break;
                                default:
                                    {
                                        string fName = oFile.Name;
                                        if (fName == "__RomVault.tmp")
                                        {
                                            File.Delete(oFile.FullName);
                                            continue;
                                        }

                                        // Scanning a file
                                        //
                                        // Level1 & 2 : (are the same for files) Fully checksum changed only files
                                        // Here we are just getting the TimeStamp of the File, and later
                                        // if the TimeStamp was not matched we will have to read the files CRC, MD5 & SHA1
                                        //
                                        // Level3: Fully checksum everything
                                        // Get everything about the file right here so
                                        // read CRC, MD5 & SHA1


                                        // add all the files in the sub-directory to scanDir
                                        RvFile tFile = new RvFile(FileType.File)
                                                           {
                                                               Name = fName,
                                                               Size = (ulong)oFile.Length,
                                                               TimeStamp = oFile.LastWriteTime
                                                           };

                                        tFile.FileStatusSet(FileStatus.SizeVerified);

                                        int errorCode = CHD.CheckFile(oFile, out tFile.SHA1CHD, out tFile.MD5CHD, out tFile.CHDVersion);

                                        if (errorCode == 0)
                                        {
                                            if (tFile.SHA1CHD != null) tFile.FileStatusSet(FileStatus.SHA1CHDFromHeader);
                                            if (tFile.MD5CHD != null) tFile.FileStatusSet(FileStatus.MD5CHDFromHeader);

                                            tFile.SetStatus(chechingDatStatus, GotStatus.Got);

                                            // if we are scanning at Level3 then we get all the info here
                                            if (EScanLevel == eScanLevel.Level3)
                                            {
                                                DeepScanFile(fullDir, tFile);
                                                ChdManCheck(fullDir, tFile);
                                            }
                                        }
                                        else if (errorCode == 32)
                                        {
                                            tFile.GotStatus = GotStatus.FileLocked;
                                            _bgw.ReportProgress(0, new bgwShowError(fullDir, "File Locked"));
                                        }
                                        else
                                        {
                                            string filename = Path.Combine(fullDir, tFile.Name);
                                            ReportError.Show("File: " + filename + " Error: " + new Win32Exception(errorCode).Message + ". Scan Aborted.");
                                            _fileErrorAbort = true;
                                            return;
                                        }
                                        fileDir.ChildAdd(tFile);
                                    }
                                    break;
                            }
                        }
                    }
                    break;
                default:
                    ReportError.SendAndShow("Un supported file type in CheckADir " + ft);
                    break;
            }
            #endregion

            if (fileDir == null)
            {
                ReportError.SendAndShow("Unknown Reading File Type in Dir Scanner");
                return;
            }

            if (report)
            {
                _bgw.ReportProgress(0, new bgwSetRange2(fileDir.ChildCount - 1));

                _bgw.ReportProgress(0, new bgwRange2Visible(true));
            }

            if (!DBTypeGet.isCompressedDir(ft) && _bgw.CancellationPending) return;

            Compare(dbDir, fileDir, report, true);
        }