/***************************************************************************

   M.A.M.E.32  -  Multiple Arcade Machine Emulator for Win32
   Win32 Portions Copyright (C) 1997-98 Michael Soderstrom and Chris Kirmse

   This file is part of MAME32, and may only be used, modified and
   distributed under the terms of the MAME license, in "readme.txt".
   By continuing to use, modify or distribute this file you indicate
   that you have read the license and understand and accept it fully.

***************************************************************************/

/***************************************************************************

  TreeView.c

  TreeView support routines - MSH 11/19/1998

***************************************************************************/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <shellapi.h>
#include <stdio.h>  /* for sprintf */
#include <stdlib.h> /* For malloc and free */
#include <commctrl.h>
#include <htmlhelp.h>
#ifdef EXTRA_FOLDER
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef _MSC_VER
#include <direct.h>
#endif
#include <io.h>
#endif

#include "win32.h"
#include "misc.h"
#include "driver.h"
#include "config.h"
#include "tsv.h"
#include "resource.h"
#include "help.h"

#include "M32Util.h"
#include "TreeView.h"
#include "Screenshot.h"
#include "Properties.h"

#ifndef MAME32HELP
#define MAME32HELP "mame32jp.chm"
#endif


#define FILTERTEXT_LEN 256

#ifdef EXTRA_FOLDER
#define MAX_EXTRA_FOLDERS 256
#endif

/***************************************************************************
    public structures
 ***************************************************************************/

enum {
    ICON_FOLDER_OPEN = 0,
    ICON_FOLDER,
    ICON_FOLDER_AVAILABLE,
    ICON_FOLDER_CUSTOM,
    ICON_FOLDER_MANUFACTURER,
    ICON_FOLDER_UNAVAILABLE,
    ICON_FOLDER_YEAR,
    ICON_MANUFACTURER,
    ICON_WORKING,
    ICON_NONWORKING,
    ICON_YEAR,
    ICON_STEREO,
    ICON_NEOGEO,
    ICON_CPS
};

/* Name used for user-defined custom icons */
/* external *.ico file to look for. */
static char treeIconNames[][15] = {
    "foldopen",
    "folder",
    "foldavail",
    "custom",
    "foldmanu",
    "foldunav",
    "foldyear",
    "manufact",
    "working",
    "nonwork",
    "year",
    "sound",
    "neo-geo",
    "cps",
    "system"
};

typedef struct {
    LPSTR       m_lpTitle;      /* Folder Title */
    FOLDERTYPE  m_nFolderType;  /* Folder Type */
    UINT        m_nFolderId;    /* ID */
    UINT        m_nParent;      /* Parent Folder ID */
    DWORD       m_dwFlags;      /* Flags - Customizable and Filters */
    UINT        m_nIconId;      /* Icon index into the ImageList */
} FOLDERDATA, *LPFOLDERDATA;

#ifdef JAPANESE
FOLDERDATA folderData[] =
{
    {"全てのゲーム",       IS_ROOT,  FOLDER_ALLGAMES,    FOLDER_NONE,  0,        ICON_FOLDER},
    {"所有しているゲーム", IS_ROOT,  FOLDER_AVAILABLE,   FOLDER_NONE,  0,        ICON_FOLDER_AVAILABLE},

    {"未所有のゲーム",     IS_ROOT,  FOLDER_UNAVAILABLE, FOLDER_NONE,  0,        ICON_FOLDER_UNAVAILABLE},

#if !defined(NEOFREE)
    {"SNKネオジオ",        IS_ROOT,  FOLDER_NEOGEO,      FOLDER_NONE,  0,        ICON_NEOGEO},
#endif
    {"カプコンCPS1&3",     IS_ROOT,  FOLDER_CPS1,        FOLDER_NONE,  0,        ICON_CPS},
    {"カプコンCPS2",       IS_ROOT,  FOLDER_CPS2,        FOLDER_NONE,  0,        ICON_CPS},
    {"ナムコS1&S2他",      IS_ROOT,  FOLDER_NAMCOS2,     FOLDER_NONE,  0,        ICON_FOLDER},
    {"タイトーF2&3他",     IS_ROOT,  FOLDER_TAITOF3,     FOLDER_NONE,  0,        ICON_FOLDER},
    {"コナミGX&OLDs",      IS_ROOT,  FOLDER_KONAMIGX,    FOLDER_NONE,  0,        ICON_FOLDER},
    {"セガS16_S32他",      IS_ROOT,  FOLDER_SEGAS16,     FOLDER_NONE,  0,        ICON_FOLDER},
    {"東亜&CAVE&BP他",     IS_ROOT,  FOLDER_TOACAVE,     FOLDER_NONE,  0,        ICON_FOLDER},
    {"その他OLDs抜粋",     IS_ROOT,  FOLDER_OTHERS,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"80年代黎明期他",     IS_ROOT,  FOLDER_OTHERS2,     FOLDER_NONE,  0,        ICON_FOLDER},
    {"洋物作品抜粋",       IS_ROOT,  FOLDER_OTHERS3,     FOLDER_NONE,  0,        ICON_FOLDER},
    {"麻雀/パズル他",      IS_ROOT,  FOLDER_OTHERS4,     FOLDER_NONE,  0,        ICON_FOLDER},
    {"次世代基板",      IS_ROOT,  FOLDER_OTHERS5,     FOLDER_NONE,  0,        ICON_FOLDER},
    {"製造元",             IS_ROOT,  FOLDER_MANUFACTURER,FOLDER_NONE,  0,        ICON_FOLDER_MANUFACTURER},
    {"製造年度",           IS_ROOT,  FOLDER_YEAR,        FOLDER_NONE,  0,        ICON_FOLDER_YEAR},
    {"CPU",                IS_ROOT,  FOLDER_CPU,         FOLDER_NONE,  0,        ICON_FOLDER},
    {"サウンド",           IS_ROOT,  FOLDER_SND,         FOLDER_NONE,  0,        ICON_FOLDER},
    {"\x83\x5cース",       IS_ROOT,  FOLDER_SOURCE,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"動作可",             IS_ROOT,  FOLDER_WORKING,     FOLDER_NONE,  0,        ICON_WORKING},
    {"動作不可",           IS_ROOT,  FOLDER_NONWORKING,  FOLDER_NONE,  0,        ICON_NONWORKING},
    {"カスタム",           IS_ROOT,  FOLDER_CUSTOM,      FOLDER_NONE,  F_CUSTOM, ICON_FOLDER_CUSTOM},
    {"プレイ済み",         IS_FOLDER,FOLDER_PLAYED,      FOLDER_CUSTOM,F_CUSTOM, ICON_FOLDER_CUSTOM},
    {"お気に入り",         IS_FOLDER,FOLDER_FAVORITE,    FOLDER_CUSTOM,F_CUSTOM, ICON_FOLDER_CUSTOM},
    {"オリジナル",         IS_ROOT,  FOLDER_ORIGINAL,    FOLDER_NONE,  0,        ICON_FOLDER},
    {"クローン",           IS_ROOT,  FOLDER_CLONES,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"ラスタグラフィック", IS_ROOT,  FOLDER_RASTER,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"ベクタグラフィック", IS_ROOT,  FOLDER_VECTOR,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"トラックボール",     IS_ROOT,  FOLDER_TRACKBALL,   FOLDER_NONE,  0,        ICON_FOLDER},
    {"ステレオ",           IS_ROOT,  FOLDER_STEREO,      FOLDER_NONE,  0,        ICON_STEREO}
};
#else
FOLDERDATA folderData[] =
{
    {"All Games",   IS_ROOT,  FOLDER_ALLGAMES,    FOLDER_NONE,  0,        ICON_FOLDER},
    {"Available",   IS_ROOT,  FOLDER_AVAILABLE,   FOLDER_NONE,  0,        ICON_FOLDER_AVAILABLE},

    {"Unavailable", IS_ROOT,  FOLDER_UNAVAILABLE, FOLDER_NONE,  0,        ICON_FOLDER_UNAVAILABLE},

#if !defined(NEOFREE)
    {"SNK Neo-Geo",     IS_ROOT,  FOLDER_NEOGEO,      FOLDER_NONE,  0,        ICON_NEOGEO},
#endif
    {"CAOCOM CPS1&3",        IS_ROOT,  FOLDER_CPS1,        FOLDER_NONE,  0,        ICON_CPS},
    {"CAOCOM CPS2",        IS_ROOT,  FOLDER_CPS2,        FOLDER_NONE,  0,        ICON_CPS},
    {"NAMCOS1&2&86",        IS_ROOT,  FOLDER_NAMCOS2,        FOLDER_NONE,  0,        ICON_FOLDER},
    {"TAITOF2&3etc",        IS_ROOT,  FOLDER_TAITOF3,        FOLDER_NONE,  0,        ICON_FOLDER},
    {"KONAMIGX&OLDs",   IS_ROOT,  FOLDER_KONAMIGX,       FOLDER_NONE,  0,        ICON_FOLDER},
    {"SEGAS16to32",     IS_ROOT,  FOLDER_SEGAS16,        FOLDER_NONE,  0,        ICON_FOLDER},
    {"TOA&CAVE&BPetc",      IS_ROOT,  FOLDER_TOACAVE,        FOLDER_NONE,  0,        ICON_FOLDER},
    {"OTHERS_OLDs",      IS_ROOT,  FOLDER_OTHERS,        FOLDER_NONE,  0,        ICON_FOLDER},
    {"OTHERS_OLDers",      IS_ROOT,  FOLDER_OTHERS2,        FOLDER_NONE,  0,        ICON_FOLDER},
    {"OTHERS_Oversea",      IS_ROOT,  FOLDER_OTHERS3,        FOLDER_NONE,  0,        ICON_FOLDER},
    {"OTHERS_Puzzle",      IS_ROOT,  FOLDER_OTHERS4,        FOLDER_NONE,  0,        ICON_FOLDER},
    {"Newer Arcade Board",      IS_ROOT,  FOLDER_OTHERS5,     FOLDER_NONE,  0,        ICON_FOLDER},

    {"Manufacturer",IS_ROOT,  FOLDER_MANUFACTURER,FOLDER_NONE,  0,        ICON_FOLDER_MANUFACTURER},
    {"Year",        IS_ROOT,  FOLDER_YEAR,        FOLDER_NONE,  0,        ICON_FOLDER_YEAR},
    {"Cpu",         IS_ROOT,  FOLDER_CPU,         FOLDER_NONE,  0,        ICON_FOLDER},
    {"Snd",         IS_ROOT,  FOLDER_SND,         FOLDER_NONE,  0,        ICON_FOLDER},
    {"Src",         IS_ROOT,  FOLDER_SOURCE,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"Working",     IS_ROOT,  FOLDER_WORKING,     FOLDER_NONE,  0,        ICON_WORKING},
    {"Non-Working", IS_ROOT,  FOLDER_NONWORKING,  FOLDER_NONE,  0,        ICON_NONWORKING},
    {"Custom",      IS_ROOT,  FOLDER_CUSTOM,      FOLDER_NONE,  F_CUSTOM, ICON_FOLDER_CUSTOM},
    {"Played",      IS_FOLDER,FOLDER_PLAYED,      FOLDER_CUSTOM,F_CUSTOM, ICON_FOLDER_CUSTOM},
    {"Favorites",   IS_FOLDER,FOLDER_FAVORITE,    FOLDER_CUSTOM,F_CUSTOM, ICON_FOLDER_CUSTOM},
    {"Originals",   IS_ROOT,  FOLDER_ORIGINAL,    FOLDER_NONE,  0,        ICON_FOLDER},
    {"Clones",      IS_ROOT,  FOLDER_CLONES,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"Raster",      IS_ROOT,  FOLDER_RASTER,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"Vector",      IS_ROOT,  FOLDER_VECTOR,      FOLDER_NONE,  0,        ICON_FOLDER},
    {"Trackball",   IS_ROOT,  FOLDER_TRACKBALL,   FOLDER_NONE,  0,        ICON_FOLDER},
    {"Stereo",      IS_ROOT,  FOLDER_STEREO,      FOLDER_NONE,  0,        ICON_STEREO}
};
#endif

#define NUM_FOLDERS (sizeof(folderData) / sizeof(FOLDERDATA))

#ifdef EXTRA_FOLDER
typedef struct {
    char        m_szTitle[64];  /* Folder Title */
    FOLDERTYPE  m_nFolderType;  /* Folder Type */
    UINT        m_nFolderId;    /* ID */
    UINT        m_nParent;      /* Parent Folder ID */
    DWORD       m_dwFlags;      /* Flags - Customizable and Filters */
    UINT        m_nIconId;      /* Icon index into the ImageList */
    UINT        m_nSubIconId;   /* Sub folder's Icon index into the ImageList */
} EXFOLDERDATA, *LPEXFOLDERDATA;
#endif

/***************************************************************************
    private variables
 ***************************************************************************/

static TREEFOLDER    **treeFolders = NULL;
static UINT          numFolders = 0;         /* Number of folder in the folder array */
static UINT          folderArrayLength = 0;  /* Size of the folder array */
static LPTREEFOLDER  lpCurrentFolder = 0;    /* Currently selected folder */
static UINT          nCurrentFolder = 0;     /* Current folder ID */
static WNDPROC       g_lpTreeWndProc = 0;    /* for subclassing the TreeView */
static HIMAGELIST    hTreeSmall = 0;         /* TreeView Image list of icons */
static char          g_FilterText[FILTERTEXT_LEN];
#ifdef EXTRA_FOLDER
static LPEXFOLDERDATA ExtraFolderData[MAX_EXTRA_FOLDERS];
static int            numExtraFolders = 0;
static int            numExtraIcons = 0;
static char           *ExtraFolderIcons[MAX_EXTRA_FOLDERS];
#endif

/***************************************************************************
    private function prototypes
 ***************************************************************************/

static BOOL         CreateTreeIcons(HWND hWnd);
static char *       FixString(char *s);
static char *       LicenseManufacturer(char *s);
static BOOL         AddFolder(LPTREEFOLDER lpFolder);
static BOOL         RemoveFolder(LPTREEFOLDER lpFolder);
static LPTREEFOLDER NewFolder(LPSTR lpTitle, FOLDERTYPE nFolderType,
                              UINT nFolderId, int nParent, UINT nIconId,
                              DWORD dwFlags, UINT nBits);
static void         DeleteFolder(LPTREEFOLDER lpFolder);
static void         BuildTreeFolders(HWND hWnd);

static LRESULT CALLBACK TreeWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

#ifdef EXTRA_FOLDER
static int InitExtraFolders(void);
static void FreeExtraFolder(void);
static void SetExtraIcons(char *name, int *id);
INLINE int GetIndexByName(const char *name);
#endif

/***************************************************************************
    public functions
 ***************************************************************************/

static char *GetBaseName(const char *path)
{
    char *p, *basename, *ext;
    static char temp[256];

    basename = ext = NULL;

    strcpy(temp, path);
    p = temp;

    while (p)
    {
        if (*p == '\\' || *p == '/')
            basename = p + 1;

        if (*p == '.')
            ext = p;

        p++;
    }

    if (ext != NULL)
        *ext = '\0';

    return basename;
}

/* De-allocate all folder memory */
void FreeFolders(void)
{
    int i = 0;

    if (treeFolders != 0)
    {
#ifdef EXTRA_FOLDER
        if (numExtraFolders)
        {
            FreeExtraFolder();
            numFolders -= numExtraFolders;
        }
#endif

        for (i = numFolders - 1; i >= 0; i--)
        {
            DeleteFolder(treeFolders[i]);
            treeFolders[i] = 0;
            numFolders--;
        }
        free(treeFolders);
        treeFolders = 0;
    }
    numFolders = 0;
}

/* Reset folder filters */
void ResetFilters(void)
{
    int i = 0;

    if (treeFolders != 0)
    {
        for (i = 0; i < (int)numFolders; i++)
        {
            treeFolders[i]->m_dwFlags &= ~F_MASK;
            SetFolderFlags(treeFolders[i]->m_lpTitle, 0);
        }
    }
}

/* Can be called to re-initialize the array of treeFolders */
BOOL InitFolders(UINT nGames)
{
    int             i = 0;
    DWORD           dwFolderFlags;
    LPFOLDERDATA    fData = 0;

    memset(g_FilterText, 0, FILTERTEXT_LEN * sizeof(char));

    if (treeFolders != 0)
    {
        for (i = numFolders - 1; i >= 0; i--)
        {
            DeleteFolder(treeFolders[i]);
            treeFolders[i] = 0;
            numFolders--;
        }
    }
    numFolders = 0;
    if (folderArrayLength == 0)
    {
        folderArrayLength = 200;
        treeFolders = (TREEFOLDER **)malloc(sizeof(TREEFOLDER **) * folderArrayLength);
        if (!treeFolders)
        {
            folderArrayLength = 0;
            return 0;
        }
        else
        {
            memset(treeFolders,'\0', sizeof(TREEFOLDER **) * folderArrayLength);
        }
    }
    for (i = 0; i < NUM_FOLDERS; i++)
    {
        fData = &folderData[i];

        /* OR in the saved folder flags */
        dwFolderFlags = fData->m_dwFlags | GetFolderFlags(fData->m_lpTitle);
        /* create the folder */
        treeFolders[numFolders] = NewFolder(fData->m_lpTitle, fData->m_nFolderType,
                                            fData->m_nFolderId, fData->m_nParent,
                                            fData->m_nIconId, dwFolderFlags, nGames);
        if (treeFolders[numFolders])
            numFolders++;
    }
#ifdef EXTRA_FOLDER
    numExtraFolders = InitExtraFolders();
    for (i = 0; i < numExtraFolders; i++)
    {
        LPEXFOLDERDATA  fExData = ExtraFolderData[i];

        /* OR in the saved folder flags */
        dwFolderFlags = fExData->m_dwFlags | GetFolderFlags(fExData->m_szTitle);
        /* create the folder */
        treeFolders[numFolders] = NewFolder(fExData->m_szTitle, fExData->m_nFolderType,
                                            fExData->m_nFolderId, fExData->m_nParent,
                                            fExData->m_nIconId, dwFolderFlags, nGames);
        if (treeFolders[numFolders])
            numFolders++;
    }
#endif

    /* insure we have a current folder */
    SetCurrentFolder(treeFolders[0]);

    InitGames(nGames);

    return TRUE;
}

void InitTree(HWND hWnd, UINT nGames)
{
    if (numFolders == 0)
        InitFolders(nGames);

    CreateTreeIcons(hWnd);
    BuildTreeFolders(hWnd);
}

void SetCurrentFolder(LPTREEFOLDER lpFolder)
{
    lpCurrentFolder = (lpFolder == 0) ? treeFolders[0] : lpFolder;
    nCurrentFolder = (lpCurrentFolder) ? lpCurrentFolder->m_nFolderId : 0;
}

LPTREEFOLDER GetCurrentFolder(void)
{
    return lpCurrentFolder;
}

UINT GetCurrentFolderID(void)
{
    return nCurrentFolder;
}

LPTREEFOLDER GetFolder(UINT nFolder)
{
    return (nFolder < numFolders) ? treeFolders[nFolder] : (LPTREEFOLDER)0;
}

LPTREEFOLDER GetFolderByID(UINT nID)
{
    UINT i;

    for (i = 0; i < numFolders; i++)
    {
        if (treeFolders[i]->m_nFolderId == nID)
        {
            return treeFolders[i];
        }
    }

    return (LPTREEFOLDER)0;
}

void AddGame(LPTREEFOLDER lpFolder, UINT nGame)
{
    SetBit(lpFolder->m_lpGameBits, nGame);
}

void RemoveGame(LPTREEFOLDER lpFolder, UINT nGame)
{
    ClearBit(lpFolder->m_lpGameBits, nGame);
}

int FindGame(LPTREEFOLDER lpFolder, int nGame)
{
    return FindBit(lpFolder->m_lpGameBits, nGame, TRUE);
}

/* Called to re-associate games with folders */
void InitGames(UINT nGames)
{
    static BOOL firstTime = TRUE;
    UINT    i, jj;
    UINT    tmpNumFolders;
    char    done[5100]; // = NULL;
    game_data_type * gameData = GetGameData();
    UINT    nFolderId = FOLDER_END;

#ifdef EXTRA_FOLDER
    if (numExtraFolders)
        nFolderId += numExtraFolders;
#endif

    if (!numFolders)
        return;

    tmpNumFolders = numFolders;

    for (i = 0; i < tmpNumFolders; i++)
    {
        LPTREEFOLDER lpFolder = treeFolders[i];
        switch(lpFolder->m_nFolderId)
        {
        case FOLDER_ALLGAMES:
            // Clear the bitmask
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
            if (strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_AVAILABLE:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (GetHasRoms(jj) == TRUE && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_UNAVAILABLE:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (GetHasRoms(jj) == FALSE && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;

#ifndef NEOFREE
        case FOLDER_NEOGEO:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (gameData[jj].neogeo && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;
#endif

        case FOLDER_CPS1:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/cps1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/cps3.c"))
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_CPS2:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/cps2.c") && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;
 
        case FOLDER_NAMCOS2:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namcos1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namcos2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namcos86.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/baraduke.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/galaga.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/digdug.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gaplus.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/mappy.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/xevious.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/toypop.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/skykid.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/pacland.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/phozon.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/grobda.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namcona1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namconb1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namcond1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namcos21.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/tceptor.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/bosco.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/polepos.c"))
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_TAITOF3:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/taito_f2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/taito_f3.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/taito_z.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/taito_b.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/taito_l.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/taito_h.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/warriorb.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ninjaw.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/darius.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/bublbobl.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rainbow.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/tnzs.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/asuka.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rastan.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/flstory.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/chaknpop.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/lkage.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ashnojoe.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/slapshot.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/topspeed.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/opwolf.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/othunder.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/mexico86.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/volfied.c"))
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_KONAMIGX:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/konamigx.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/mystwarr.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/xexex.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/tmnt.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/twin16.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/nemesis.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gradius3.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/thunderx.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ajax.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/flkatck.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/contra.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/parodius.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/hcastle.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/battlnts.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/combatsc.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/labyrunr.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/moo.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/vendetta.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/yiear.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gbusters.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/xmen.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/chqflag.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/blockhl.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gberet.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gijoe.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/scotrsht.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/simpsons.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ironhors.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rockrage.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/mainevt.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/aliens.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/wecleman.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/jackal.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/crimfght.c"))
                    AddGame(lpFolder, jj);
           }
            break; 

        case FOLDER_SEGAS16:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/system1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/system16.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/aburner.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/outrun.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/sharrier.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/system18.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/system24.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/system32.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/multi32.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/segac2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/model1.c"))
                    AddGame(lpFolder, jj);
            }
            break; 

        case FOLDER_TOACAVE:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/toaplan1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/toaplan2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/twincobr.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/slapfght.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/snowbros.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/cave.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/macrossp.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/psikyo.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/psikyo4.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/seta.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/seta2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ssv.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/srmp2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/raiden.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/suprnova.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/kaneko16.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/taito_x.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/inufuku.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/dcon.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/mjsister.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ms32.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/fuukifg3.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/aerofgt.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rabbit.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/powerins.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/shadfrce.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/psikyosh.c") && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/tetrisp2.c") && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break; 

        case FOLDER_OTHERS:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/airbustr.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/snk.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/hal21.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/1942.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/1943.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/bionicc.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/blktiger.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/tigeroad.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/lwings.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gng.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/sonson.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/exedexes.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/commando.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gunsmoke.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/sidearms.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/srumbler.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/bwing.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/dec8.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/kalnov.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/vaportra.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/darkseal.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rohga.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/cninja.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/actfancr.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gaiden.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/megasys1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/psychic5.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ginganin.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/terracre.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/armedf.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/galivan.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/argus.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/tecmo.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/bombjack.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/senjyo.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/omegaf.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ninjakid.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ninjakd2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/m72.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/m92.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/equites.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/vigilant.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/nmk16.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/dassault.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/fcombat.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/vball.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/dec0.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/boogwing.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/brkthru.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/sf1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/karnov.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/dynduke.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/alpha68k.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ddragon.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ddragon3.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/battlera.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/hyprduel.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/deadang.c"))
                    AddGame(lpFolder, jj);
            }
            break; 

        case FOLDER_OTHERS2:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/8080bw.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/n8080.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/galaxian.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/warpwarp.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/cclimber.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/geebee.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rallyx.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/missile.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/nyny.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/phoenix.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/pacman.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/dkong.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/mrdo.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/docastle.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/scramble.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/spacefb.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/vicdual.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rockola.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/crbaloon.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/naughtyb.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/taitosj.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/frogger.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/pooyan.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/timeplt.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/scobra.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/trackfld.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/hyperspt.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rocnrope.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/pengo.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/segar.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/zaxxon.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/astrocde.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ladybug.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/superpac.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/mario.c"))
                    AddGame(lpFolder, jj);
            }
            break; 

        case FOLDER_OTHERS3:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gauntlet.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/atarisy1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/atarisy2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/artmagic.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/blockout.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gaelco2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/harddriv.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/pgm.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/atarigx2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/rampart.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/midvunit.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/midwunit.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/midtunit.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/midyunit.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/skullxbo.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/afega.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/atarig1.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/klax.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/nmg5.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/1945kiii.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/dooyong.c"))
                    AddGame(lpFolder, jj);
            }
            break; 

        case FOLDER_OTHERS4:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/fromanc2.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/fromance.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/homedata.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/metro.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/mitchell.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/nbmj8688.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/nbmj8891.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/nbmj8991.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/nbmj9195.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/niyanpai.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/hanaroku.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/deniam.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/galpanic.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/gomoku.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ojankohs.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/shangha3.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/shanghai.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/shisen.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/pipedrm.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/ddenlovr.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/funkyjet.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/realbrk.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/crospang.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/funybubl.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/st0016.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/paradise.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/m62.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/momoko.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/solomon.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/dynax.c"))
                    AddGame(lpFolder, jj);
            }
            break; 

        case FOLDER_OTHERS5:
            SetAllBits( lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namcos21.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/namcos22.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/zn.c"))
                    AddGame(lpFolder, jj);
                if (!strcmp(drivers[jj]->source_file, "src/drivers/stv.c"))
                    AddGame(lpFolder, jj);

            }
            break;


        case FOLDER_YEAR:
            if (!firstTime)
                break;

            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            memset(done, 0, nGames);
            for (jj = 0; jj < nGames; jj++)
            {
                LPTREEFOLDER lpTemp = 0;
                UINT j;
                DWORD dwFolderFlags;
                char cTmp[40];

                if (done[jj])
                    continue;

                strcpy(cTmp,FixString((char *)drivers[jj]->year));
                if (cTmp[4] == '?')
                    cTmp[4] = '\0';
                dwFolderFlags = GetFolderFlags(cTmp);
                lpTemp = NewFolder(cTmp, IS_FOLDER, nFolderId++,
                                   FOLDER_YEAR, ICON_YEAR, 0, nGames);
                if (strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0) AddFolder(lpTemp);
                done[jj] = 1;

                for (j = 0; j < nGames; j++)
                {
                    if (strncmp(cTmp, FixString((char *)drivers[j]->year), 4) == 0 && strncmp("XXXX", FixString((char *)drivers[j]->year), 4) != 0)
                    {
                        done[j] = 1;
                        AddGame(lpTemp, j);
                    }
                }
            }
            break;

        case FOLDER_CPU:
            if (!firstTime)
            {
                break;
            }

            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 1; jj < CPU_COUNT; jj++)
            {
                LPTREEFOLDER lpTemp = 0;
                UINT j;
                DWORD dwFolderFlags;
                char cTmp[40];
                int n;

                if (jj > 1 && !strcmp(cputype_name(jj),cputype_name(jj-1))) continue;
                strcpy(cTmp,cputype_name(jj));
                dwFolderFlags = GetFolderFlags(cTmp);
                lpTemp = NewFolder(cTmp, IS_FOLDER, nFolderId++,
                                   FOLDER_CPU, ICON_YEAR, dwFolderFlags, nGames);
                AddFolder(lpTemp);

                for (j = 0; j < nGames; j++)
                {
                    struct InternalMachineDriver drv;
                              expand_machine_driver(drivers[j]->drv,&drv);

                    for (n = 0; n < MAX_CPU; n++)
                        if (strcmp(cTmp,cputype_name(drv.cpu[n].cpu_type)) == 0 && strncmp("XXXX", FixString((char *)drivers[j]->year), 4) != 0)
                            AddGame(lpTemp, j);
                }
            }
            break;

        case FOLDER_SND:
            if (!firstTime)
            {
                break;
            }

            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 1; jj < SOUND_COUNT; jj++)
            {
                // Defined in sndintrf.c
                struct snd_interface
                {
                    unsigned sound_num;                                     /* ID */
                    const char *name;                                       /* description */
                    int (*chips_num)(const struct MachineSound *msound);    /* returns number of chips if applicable */
                    int (*chips_clock)(const struct MachineSound *msound);  /* returns chips clock if applicable */
                    int (*start)(const struct MachineSound *msound);        /* starts sound emulation */
                    void (*stop)(void);                                     /* stops sound emulation */
                    void (*update)(void);                                   /* updates emulation once per frame if necessary */
                    void (*reset)(void);                                    /* resets sound emulation */
                };
                extern struct snd_interface sndintf[];

                LPTREEFOLDER lpTemp = 0;
                UINT j;
                DWORD dwFolderFlags;
                char cTmp[40];
                int n;

                strcpy(cTmp,sndintf[jj].name);
                dwFolderFlags = GetFolderFlags(cTmp);
                lpTemp = NewFolder(cTmp, IS_FOLDER, nFolderId++,
                                   FOLDER_SND, ICON_STEREO, dwFolderFlags, nGames);
                AddFolder(lpTemp);

                for (j = 0; j < nGames; j++)
                {
                    struct InternalMachineDriver drv;
                           expand_machine_driver(drivers[j]->drv,&drv);

                    for (n = 0; n < MAX_SOUND; n++)
                        if (strcmp(cTmp,sound_name(&drv.sound[n])) == 0 && strncmp("XXXX", FixString((char *)drivers[j]->year), 4) != 0)
                            AddGame(lpTemp, j);
                }

            }
            break;

        case FOLDER_SOURCE:
            if (!firstTime)
            {
                break;
            }

            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            memset(done, 0, nGames);
            for (jj = 0; jj < nGames; jj++)

            {
                LPTREEFOLDER lpTemp = 0;
                UINT j;
                DWORD dwFolderFlags;
                char cTmp[40];

                if (done[jj])
                    continue;

                strcpy(cTmp,GetDriverFilename(jj));
                            
                if (cTmp[0] == '\0')
                    continue;

                dwFolderFlags = GetFolderFlags(cTmp);

                lpTemp = NewFolder( cTmp, IS_FOLDER, nFolderId++, 
                                    FOLDER_SOURCE, ICON_YEAR, 0, nGames );
                AddFolder(lpTemp);
                done[jj] = TRUE;
                
                for (j = 0; j < nGames; j++)
                {
                    if (strcmp(cTmp, GetDriverFilename(j)) == 0)
                    {
                        done[j] = TRUE;
                        if (strncmp("XXXX", FixString((char *)drivers[j]->year), 4) != 0) AddGame(lpTemp, j);
                    }
                }
            }
            break;

        case FOLDER_MANUFACTURER:
            if (!firstTime)
                break;

            SetAllBits(lpFolder->m_lpGameBits, FALSE);

            memset(done, 0, nGames);

            for (jj = 0; jj < nGames; jj++)
            {
                LPTREEFOLDER lpTemp = 0;
                DWORD dwFolderFlags;
                int j;
                char cTmp[128];

                if (done[jj])
                    continue;

                memset(cTmp, 0, 128);

                if (jj == nGames)
                    strcpy(cTmp, "Romstar");
                else
                    strcpy(cTmp, FixString((char *)drivers[jj]->manufacturer));

                if (cTmp[0] == '\0')
                    continue;

//                strcpy(cTmp, FixString((char *)drivers[jj]->manufacturer));
                dwFolderFlags = GetFolderFlags(cTmp);
                lpTemp = NewFolder(cTmp, IS_FOLDER, nFolderId++,
                                   FOLDER_MANUFACTURER, ICON_MANUFACTURER, 0, nGames);
                if (strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0) {
                AddFolder(lpTemp);
                done[jj] = 1;
                }

                for (j = 0; j < nGames; j++)
                {
                    char *tmp = LicenseManufacturer((char *)drivers[j]->manufacturer);

                    if (tmp != NULL && strncmp(cTmp, tmp, 5) == 0){
                        if (strncmp("XXXX", FixString((char *)drivers[j]->year), 4) != 0) AddGame(lpTemp, j);
                        }
                    if (strncmp(cTmp, FixString((char *)drivers[j]->manufacturer), 5) == 0)
                    {
                        done[j] = 1;
                        if (strncmp("XXXX", FixString((char *)drivers[j]->year), 4) != 0) AddGame(lpTemp, j);
                    }
                }
            }
            break;

        case FOLDER_WORKING:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!(drivers[jj]->flags & GAME_BROKEN) && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_NONWORKING:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                /* Mark wrong colors as non-working */
                if (drivers[jj]->flags & GAME_BROKEN && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_ORIGINAL:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (drivers[jj]->clone_of->flags & NOT_A_DRIVER && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_CLONES:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (!(drivers[jj]->clone_of->flags & NOT_A_DRIVER) && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_RASTER:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
				struct InternalMachineDriver drv;
				expand_machine_driver(drivers[jj]->drv, &drv);
                if ((drv.video_attributes & VIDEO_TYPE_VECTOR) == 0 && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_VECTOR:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
				struct InternalMachineDriver drv;
				expand_machine_driver(drivers[jj]->drv, &drv);
                if (drv.video_attributes & VIDEO_TYPE_VECTOR)
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_TRACKBALL:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (GameUsesTrackball(jj))
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_PLAYED:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (GetPlayCount(jj))
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_FAVORITE:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
                if (GetIsFavorite(jj))
                    AddGame(lpFolder, jj);
            }
            break;

        case FOLDER_STEREO:
            SetAllBits(lpFolder->m_lpGameBits, FALSE);
            for (jj = 0; jj < nGames; jj++)
            {
				struct InternalMachineDriver drv;
				expand_machine_driver(drivers[jj]->drv, &drv);
                if (drv.sound_attributes & SOUND_SUPPORTS_STEREO && strncmp("XXXX", FixString((char *)drivers[jj]->year), 4) != 0)
                    AddGame(lpFolder, jj);
            }
            break;

#ifdef EXTRA_FOLDER
        default:
            if (!firstTime)
                break;

            if (lpFolder->m_nFolderId > FOLDER_END
            &&  lpFolder->m_nFolderId <= FOLDER_END + numExtraFolders)
            {
                FILE *fp;
                char fname[MAX_PATH];
                char readbuf[256];
                char *p;
                char *name;
                int  index, id, current_id;
                LPTREEFOLDER lpTemp = 0;

                current_id = lpFolder->m_nFolderId;
                id = lpFolder->m_nFolderId - FOLDER_END - 1;
                sprintf(fname, "%s/%s.ini", GetFolderDir(), ExtraFolderData[id]->m_szTitle);

                fp = fopen(fname, "r");
                if (fp == NULL)
                {
                    lpFolder->m_nFolderId = FOLDER_END;
                    break;
                }

                SetAllBits(lpFolder->m_lpGameBits, FALSE);
                memset(done, 0, nGames);

                while (fgets(readbuf, 256, fp))
                {
                    if (readbuf[0] == '[')
                    {
                        p = strchr(readbuf, ']');
                        if (p == NULL)
                            continue;

                        *p = '\0';
                        name = &readbuf[1];

                        if (!strcmp(name, "FOLDER_SETTINGS"))
                        {
                            current_id = -1;
                            continue;
                        }
                        else
                        {
                            DWORD dwFolderFlags;

                            dwFolderFlags = GetFolderFlags(name);
                            if (!strcmp(name, "ROOT_FOLDER"))
                            {
                                current_id = lpFolder->m_nFolderId;
                                lpTemp = lpFolder;
                            }
                            else
                            {
                                current_id = nFolderId++;
                                lpTemp = NewFolder(name, IS_FOLDER, nFolderId++,
                                                   lpFolder->m_nFolderId, ExtraFolderData[id]->m_nSubIconId,
                                                   0, nGames);
                                AddFolder(lpTemp);
                            }
                        }
                    }
                    else if (current_id != -1)
                    {
                        name = strtok(readbuf, " \t\r\n");
                        if (name == NULL)
                        {
                            current_id = -1;
                            continue;
                        }

                        index = GetIndexByName(name);

                        if (index != -1 && !done[index])
                            AddGame(lpTemp, index);
                    }
                }
                fclose(fp);
            }
            break;
#endif
        }
    }
    firstTime = FALSE;
}

/* Subclass the Treeview Header */
void Tree_Initialize(HWND hWnd)
{
    /* this will subclass the listview (where WM_DRAWITEM gets sent for
       the header control) */
    g_lpTreeWndProc = (WNDPROC)(LRESULT)GetWindowLong(hWnd, GWL_WNDPROC);
    SetWindowLong(hWnd, GWL_WNDPROC, (LONG)TreeWndProc);
}


/* Used to build the GameList */
BOOL GameFiltered(int nGame, DWORD dwMask)
{
    BOOL vector;
    game_data_type *gameData = GetGameData();
	struct InternalMachineDriver drv;
	expand_machine_driver(drivers[nGame]->drv, &drv);

    /* Filter games */
    if (g_FilterText[0] != '\0')
    {
        if (!MyStrStrI(GetDescriptionByIndex(nGame), g_FilterText))
            return TRUE;
    }

    /* Are there filters set on this folder? */
    if ((dwMask & F_MASK) == 0)
        return FALSE;

    /* Filter out clones? */
    if (dwMask & F_CLONES
    &&  !(drivers[nGame]->clone_of->flags & NOT_A_DRIVER))
        return TRUE;

    /* Filter non working games */
    if (dwMask & F_NONWORKING
    && (drivers[nGame]->flags & GAME_BROKEN))
        return TRUE;

#ifndef NEOFREE
    /* Filter neo-geo games */
    if (dwMask & F_NEOGEO && gameData[nGame].neogeo)
        return TRUE;
#endif

    /* Filter CPS1 games */
    if (dwMask & F_CPS1 && !strcmp(drivers[nGame]->source_file, "src/drivers/cps1.c"))
        return TRUE;
    if (dwMask & F_CPS1 && !strcmp(drivers[nGame]->source_file, "src/drivers/cps3.c"))
        return TRUE;

    /* Filter CPS2 games */
    if (dwMask & F_CPS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/cps2.c"))
        return TRUE;

    /* Filter NAMCOS2 games */
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/namcos1.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/namcos1.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/namcos86.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/baraduke.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/galaga.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/digdug.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/gaplus.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/mappy.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/xevious.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/toypop.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/skykid.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/pacland.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/phozon.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/grobda.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/namcona1.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/namconb1.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/namcond1.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/namcos21.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/tceptor.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/bosco.c"))
        return TRUE;
    if (dwMask & F_NAMCOS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/polepos.c"))
        return TRUE;

    /* Filter TAITOF3 games */
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/taito_f2.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/taito_f3.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/taito_z.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/taito_b.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/taito_l.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/taito_h.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/warriorb.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/ninjaw.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/darius.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/bublbobl.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/rainbow.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/tnzs.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/asuka.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/rastan.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/flstory.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/chaknpop.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/lkage.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/ashnojoe.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/slapshot.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/topspeed.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/opwolf.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/othunder.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/mexico86.c"))
        return TRUE;
    if (dwMask & F_TAITOF3 && !strcmp(drivers[nGame]->source_file, "src/drivers/volfied.c"))
        return TRUE;

    /* Filter KONAMIGX games */
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/konamigx.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/mystwarr.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/xexex.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/tmnt.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/twin16.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/nemesis.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/gradius3.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/thunderx.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/ajax.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/flkatck.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/contra.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/parodius.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/hcastle.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/battlnts.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/combatsc.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/labyrunr.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/moo.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/vendetta.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/yiear.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/gbusters.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/xmen.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/chqflag.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/blockhl.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/gberet.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/gijoe.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/scotrsht.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/simpsons.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/ironhors.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/rockrage.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/mainevt.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/aliens.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/wecleman.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/jackal.c"))
        return TRUE;
    if (dwMask & F_KONAMIGX && !strcmp(drivers[nGame]->source_file, "src/drivers/crimfght.c"))
        return TRUE;

    /* Filter SEGAS16 games */
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/system1.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/system16.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/aburner.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/outrun.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/sharrier.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/system18.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/system24.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/system32.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/multi32.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/segac2.c"))
        return TRUE;
    if (dwMask & F_SEGAS16 && !strcmp(drivers[nGame]->source_file, "src/drivers/model1.c"))
        return TRUE;

    /* Filter TOACAVE games */
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/toaplan1.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/toaplan2.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/twincobr.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/slapfght.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/snowbros.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/cave.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/macrossp.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/psikyo.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/psikyo4.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/seta.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/seta2.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/ssv.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/srmp2.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/raiden.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/suprnova.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/kaneko16.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/taito_x.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/inufuku.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/dcon.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/mjsister.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/ms32.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/fuukifg3.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/aerofgt.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/rabbit.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/powerins.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/shadfrce.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/psikyosh.c"))
        return TRUE;
    if (dwMask & F_TOACAVE && !strcmp(drivers[nGame]->source_file, "src/drivers/tetrisp2.c"))
        return TRUE;

    /* Filter OTHERS games */
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/airbustr.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/hal21.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/snk.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/1942.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/1943.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/bionicc.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/blktiger.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/tigeroad.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/lwings.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/gng.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/sonson.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/exedexes.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/commando.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/gunsmoke.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/sidearms.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/srumbler.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/bwing.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/dec8.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/kalnov.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/vaportra.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/darkseal.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/rohga.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/cninja.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/actfancr.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/gaiden.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/megasys1.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/psychic5.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/ginganin.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/terracre.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/armedf.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/galivan.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/argus.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/tecmo.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/bombjack.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/senjyo.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/omegaf.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/ninjakid.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/ninjakd2.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/m72.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/m92.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/equites.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/vigilant.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/nmk16.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/dassault.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/fcombat.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/vball.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/dec0.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/boogwing.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/brkthru.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/sf1.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/karnov.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/dynduke.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/alpha68k.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/ddragon.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/ddragon3.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/battlera.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/hyprduel.c"))
        return TRUE;
    if (dwMask & F_OTHERS && !strcmp(drivers[nGame]->source_file, "src/drivers/deadang.c"))
        return TRUE;

    /* Filter OTHERS2 games */
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/8080bw.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/n8080.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/galaxian.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/warpwarp.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/cclimber.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/geebee.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/rallyx.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/missile.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/nyny.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/phoenix.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/pacman.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/dkong.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/mrdo.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/docastle.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/scramble.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/spacefb.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/vicdual.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/rockola.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/crbaloon.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/naughtyb.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/taitosj.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/frogger.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/pooyan.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/timeplt.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/scobra.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/trackfld.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/hyperspt.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/rocnrope.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/pengo.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/segar.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/zaxxon.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/astrocde.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/ladybug.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/superpac.c"))
        return TRUE;
    if (dwMask & F_OTHERS2 && !strcmp(drivers[nGame]->source_file, "src/drivers/mario.c"))
        return TRUE;

    /* Filter OTHERS3 games */
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/gauntlet.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/atarisy1.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/atarisy2.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/artmagic.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/blockout.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/gaelco2.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/harddriv.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/pgm.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/atarigx2.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/rampart.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/midvunit.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/midwunit.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/midtunit.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/midyunit.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/skullxbo.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/afega.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/atarig1.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/klax.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/nmg5.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/1945kiii.c"))
        return TRUE;
    if (dwMask & F_OTHERS3 && !strcmp(drivers[nGame]->source_file, "src/drivers/dooyong.c"))
        return TRUE;

    /* Filter OTHERS4 games */
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/fromanc2.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/fromance.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/homedata.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/metro.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/mitchell.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/nbmj8688.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/nbmj8891.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/nbmj8991.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/nbmj9195.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/niyanpai.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/hanaroku.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/deniam.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/galpanic.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/gomoku.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/ojankohs.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/shangha3.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/shanghai.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/shisen.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/ddenlovr.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/funkyjet.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/realbrk.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/crospang.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/funybubl.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/st0016.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/paradise.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/m62.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/momoko.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/solomon.c"))
        return TRUE;
    if (dwMask & F_OTHERS4 && !strcmp(drivers[nGame]->source_file, "src/drivers/dynax.c"))
        return TRUE;

    /* Filter unavailable games */
    if (dwMask & F_UNAVAILABLE && GetHasRoms(nGame) == FALSE)
        return TRUE;

    vector = drv.video_attributes & VIDEO_TYPE_VECTOR;

    /* Filter vector games */
    if (dwMask & F_VECTOR && vector)
        return TRUE;

    /* Filter Raster games */
    if (dwMask & F_RASTER && !vector)
        return TRUE;

    /* FIlter original games */
    if (dwMask & F_ORIGINALS
    &&  (drivers[nGame]->clone_of->flags & NOT_A_DRIVER))
        return TRUE;

    /* Filter working games */
    if (dwMask & F_WORKING && !(drivers[nGame]->flags & GAME_BROKEN))
        return TRUE;


    /* filter available games */
    if (dwMask & F_AVAILABLE && GetHasRoms(nGame) == TRUE)
        return TRUE;


    return FALSE;
}

INT_PTR CALLBACK ResetDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    BOOL resetFilters = FALSE;
    BOOL resetGames = FALSE;
    BOOL resetUI = FALSE;
    BOOL resetDefaults = FALSE;

    switch (Msg)
    {
    case WM_INITDIALOG:
        return TRUE;

    case WM_HELP:
        HtmlHelp(((LPHELPINFO)lParam)->hItemHandle, MAME32HELP, HH_TP_HELP_WM_HELP, GetHelpIDs());
        break;

    case WM_CONTEXTMENU:
        HtmlHelp(hDlg, MAME32HELP, HH_TP_HELP_CONTEXTMENU, GetHelpIDs());
        break;

    case WM_COMMAND :
        switch (GET_WM_COMMAND_ID(wParam, lParam))
        {
        case IDOK :
            resetFilters = Button_GetCheck(GetDlgItem(hDlg, IDC_RESET_FILTERS));
            resetGames = Button_GetCheck(GetDlgItem(hDlg, IDC_RESET_GAMES));
            resetDefaults = Button_GetCheck(GetDlgItem(hDlg, IDC_RESET_DEFAULT));
            resetUI = Button_GetCheck(GetDlgItem(hDlg, IDC_RESET_UI));
            if (resetFilters || resetGames || resetUI || resetDefaults)
            {
                char temp[200];
#ifdef JAPANESE
                strcpy(temp, MAME32NAME " は選択された項目をインストール時\n");
                strcat(temp, "の設定に戻して、終了します。\n");
                strcat(temp, "新しい設定は、次回の" MAME32NAME " 起動時に反映されます。\n\n");
                strcat(temp, "続けますか？");
                if (MessageBox(hDlg, temp, MAME32NAME " - 設定の初期化", IDOK) == IDOK)
#else
                strcpy(temp, MAME32NAME " will now reset the selected\n");
                strcat(temp, "items to the original, installation\n");
                strcat(temp, "settings then exit.\n\n");
                strcat(temp, "The new settings will take effect\n");
                strcat(temp, "the next time " MAME32NAME " is run.\n\n");
                strcat(temp, "Do you wish to continue?");
                if (MessageBox(hDlg, temp, "Restore Settings", IDOK) == IDOK)
#endif
                {
                    if (resetFilters)
                        ResetFilters();

                    if (resetUI)
                        ResetGUI();

                    if (resetDefaults)
                        ResetGameDefaults();

                    if (resetGames)
                        ResetAllGameOptions();

                    EndDialog(hDlg, 1);
                    return TRUE;
                }
            }
            /* Fall through if no options were selected
             * or the user hit cancel in the popup dialog.
             */
        case IDCANCEL :
            EndDialog(hDlg, 0);
            return TRUE;
        }
        break;
    }
    return 0;
}

INT_PTR CALLBACK StartupDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
    case WM_INITDIALOG:
        Button_SetCheck(GetDlgItem(hDlg, IDC_START_GAME_CHECK),     GetGameCheck());
        Button_SetCheck(GetDlgItem(hDlg, IDC_START_VERSION_WARN),   GetVersionCheck());
        Button_SetCheck(GetDlgItem(hDlg, IDC_START_MMX_CHECK),      GetMMXCheck());
#ifdef JOYGUI
        Button_SetCheck(GetDlgItem(hDlg, IDC_JOY_GUI),	GetJoyGUI());
#endif
#ifdef RANDAM_BACKGROUND
        Button_SetCheck(GetDlgItem(hDlg, IDC_RANDOM_BG),            GetRandomBg());
#endif /* RANDAM_BACKGROUND */
        return TRUE;

    case WM_HELP:
        HtmlHelp(((LPHELPINFO)lParam)->hItemHandle, MAME32HELP, HH_TP_HELP_WM_HELP, GetHelpIDs());
        break;

    case WM_CONTEXTMENU:
        HtmlHelp(hDlg, MAME32HELP, HH_TP_HELP_CONTEXTMENU, GetHelpIDs());
        break;

    case WM_COMMAND :
        switch (GET_WM_COMMAND_ID(wParam, lParam))
        {
        case IDOK :
            SetGameCheck(Button_GetCheck(GetDlgItem(hDlg, IDC_START_GAME_CHECK)));
            SetVersionCheck(Button_GetCheck(GetDlgItem(hDlg, IDC_START_VERSION_WARN)));
            SetMMXCheck(Button_GetCheck(GetDlgItem(hDlg, IDC_START_MMX_CHECK)));
#ifdef JOYGUI
            SetJoyGUI(Button_GetCheck(GetDlgItem(hDlg, IDC_JOY_GUI)));
#endif
#ifdef RANDAM_BACKGROUND
            SetRandomBg(Button_GetCheck(GetDlgItem(hDlg, IDC_RANDOM_BG)));
#endif /* RANDAM_BACKGROUND */

            /* Fall through */

        case IDCANCEL :
            EndDialog(hDlg, 0);
            return TRUE;
        }
        break;
    }
    return 0;
}

/***************************************************************************
    private functions
 ***************************************************************************/

/* Add a folder to the list.  Does not allocate */
static BOOL AddFolder(LPTREEFOLDER lpFolder)
{
    UINT i = 0;

    if (!lpFolder)
        return FALSE;

    if (numFolders + 1 >= folderArrayLength)
    {
        TREEFOLDER ** tmpFolders = treeFolders;

        i = folderArrayLength;

        folderArrayLength += 10;

        treeFolders = (TREEFOLDER **)malloc(sizeof(TREEFOLDER **) * folderArrayLength);
        if (!treeFolders)
        {
            folderArrayLength = i;
            treeFolders = tmpFolders;
            return FALSE;
        }
        for (i = 0; i < numFolders; i++)
        {
            treeFolders[i] = tmpFolders[i];
        }
        free(tmpFolders);
        for (i = numFolders; i < folderArrayLength; i++)
        {
            treeFolders[i] = 0;
        }
    }

    treeFolders[numFolders] = lpFolder;
    numFolders++;

    return TRUE;
}

/* Remove a folder from the list, but do NOT delete it */
static BOOL RemoveFolder(LPTREEFOLDER lpFolder)
{
    int     found = -1;
    UINT    i = 0;

    /* Find the folder */
    for (i = 0; i < numFolders && found == -1; i++)
    {
        if (lpFolder == treeFolders[i])
        {
            found = i;
        }
    }
    if (found != -1)
    {
        numFolders--;
        treeFolders[i] = 0; /* In case we removed the last folder */

        /* Move folders up in the array if needed */
        for (i = (UINT)found; (UINT)found < numFolders; i++)
            treeFolders[i] = treeFolders[i+1];
    }
    return (found != -1) ? TRUE : FALSE;
}

/* Allocate and initialize a NEW TREEFOLDER */
static LPTREEFOLDER NewFolder(LPSTR lpTitle, FOLDERTYPE nFolderType,
                       UINT nFolderId, int nParent, UINT nIconId,
                       DWORD dwFlags, UINT nBits)
{
    LPTREEFOLDER lpFolder = (LPTREEFOLDER)malloc(sizeof(TREEFOLDER));
    int numBits = (nBits < 8) ? 8 : nBits;

    if (lpFolder)
    {
        memset(lpFolder, '\0', sizeof (TREEFOLDER));
        lpFolder->m_lpTitle = (LPSTR)malloc(strlen(lpTitle) + 1);
        if (lpFolder->m_lpTitle)
        {
            strcpy((char *)lpFolder->m_lpTitle,lpTitle);
            lpFolder->m_lpGameBits = 0;
        }
        else
        {
            free(lpFolder);
            return (LPTREEFOLDER)0;
        }
        lpFolder->m_lpGameBits = NewBits(numBits);
        if (lpFolder->m_lpGameBits == NULL)
        {
            free(lpFolder->m_lpTitle);
            free(lpFolder);
            return (LPTREEFOLDER)0;
        }
        lpFolder->m_nFolderId = nFolderId;
        lpFolder->m_nFolderType = nFolderType;
        lpFolder->m_nParent = nParent;
        lpFolder->m_nIconId = nIconId;
        lpFolder->m_dwFlags = dwFlags;
    }
    return lpFolder;
}

/* Deallocate the passed in LPTREEFOLDER */
static void DeleteFolder(LPTREEFOLDER lpFolder)
{
    if (lpFolder)
    {
        if (lpFolder->m_lpGameBits)
        {
            DeleteBits(lpFolder->m_lpGameBits);
            lpFolder->m_lpGameBits = 0;
        }
        free(lpFolder->m_lpTitle);
        lpFolder->m_lpTitle = 0;
        free(lpFolder);
        lpFolder = 0;
    }
}

/* Can be called to reinitialize the tree control */
static void BuildTreeFolders(HWND hWnd)
{
    UINT            i;
    TVINSERTSTRUCT  tvs;
    TVITEM          tvi;

#ifdef MAME32JP
    tvs.hInsertAfter = TVI_LAST;
#else
    tvs.hInsertAfter = TVI_SORT;
#endif

    if (TreeView_GetCount(hWnd) > 0)
    {
        TreeView_DeleteAllItems(hWnd);
    }

    for (i = 0; i < numFolders; i++)
    {
        LPTREEFOLDER lpFolder = treeFolders[i];

        if (lpFolder->m_nFolderType == IS_ROOT)
        {
            HTREEITEM   hti;
            UINT        jj;

            tvi.mask           = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
            tvi.pszText        = lpFolder->m_lpTitle;
            tvi.lParam         = (LPARAM)lpFolder;
            tvi.iImage         = lpFolder->m_nIconId;
            tvi.iSelectedImage = 0;

            tvs.hParent        = TVI_ROOT;
            tvs.item           = tvi;

            /* Add root branch */
            hti = TreeView_InsertItem(hWnd, &tvs);

            if (i == 0 || lpFolder->m_nFolderId == GetSavedFolderID())
                TreeView_SelectItem(hWnd, hti);

#ifdef MAME32JP
            tvs.hInsertAfter = TVI_SORT;
#endif
            for (jj = 0; jj < numFolders; jj++)
            {
                LPTREEFOLDER tmp = treeFolders[jj];

                if (tmp->m_nParent != FOLDER_NONE
                &&  tmp->m_nParent == lpFolder->m_nFolderId)
                {
                    HTREEITEM shti;

                    tvi.mask           = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
                    tvi.iImage         = tmp->m_nIconId;
                    tvi.iSelectedImage = 0;
                    tvi.pszText        = tmp->m_lpTitle;
                    tvi.lParam         = (LPARAM)tmp;

                    tvs.hParent        = hti;
                    tvs.item           = tvi;

                    /* Add it to this tree branch */
                    shti = TreeView_InsertItem(hWnd, &tvs);
                    if (tmp->m_nFolderId == GetSavedFolderID())
                        TreeView_SelectItem(hWnd, shti);
                }
            }
#ifdef MAME32JP
            tvs.hInsertAfter = TVI_LAST;
#endif
        }
    }
}

#ifdef JAPANESE
#define ISSJIS1(c) ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfc))
#define ISSJIS2(c) ((c >= 0x40 && c <= 0xfc) && (c != 0x7f))
#endif

/* Make a reasonable name out of the one found in the driver array */
static char * FixString(char *s)
{
    static char tmp[40];
    char *      ptr;

    if (*s == '?' || *s == '<' || s[3] == '?')
#ifdef JAPANESE
        strcpy(tmp,"<不明>");
#else
        strcpy(tmp,"<unknown>");
#endif
    else
    {
        int i = 0;
#ifdef JAPANESE
        unsigned char c1, c2;
#endif

        ptr = s;
        while(*ptr)
        {
#ifdef JAPANESE
            c1 = *(unsigned char *)ptr;
            c2 = *(unsigned char *)(ptr + 1);

            if (ISSJIS1(c1) && ISSJIS2(c2))
            {
               tmp[i++] = *ptr++;
               tmp[i++] = *ptr++;
            }
            else
#endif
            if ((*ptr == ' ') &&
                ((ptr[1] == '(' || ptr[1] == '/') || (ptr[1] == '+')))
                break;

            if (*ptr == '[')
                ptr++;
            else if (*ptr == ']' || *ptr == '/')
                break;
            else
                tmp[i++] = *ptr++;

        }
        tmp[i] = '\0';
    }
    return tmp;
}

/* Make a reasonable name out of the one found in the driver array */
static char * LicenseManufacturer(char *s)
{
    static char tmp[40];
    char *      ptr, *t;

    t = tmp;

#ifdef JAPANESE
    ptr = (char *)strchr(s,'(');
    if (ptr != NULL
    &&  !ISSJIS1(*(unsigned char *)(ptr - 1))
    &&  !ISSJIS2(*(unsigned char *)(ptr)))
#else
    if ((ptr = (char *)strchr(s,'(')) != NULL)
#endif
    {
        ptr++;
        if (strncmp(ptr, "licensed from ", 14) == 0)
            ptr += 14;

        while (*ptr != ')')
        {
            if (*ptr == ' ' && strncmp(ptr, " license", 8) == 0)
                break;

            *t++ = *ptr++;
        }

        *t = '\0';
        return tmp;
    }
    return NULL;
}

#ifdef JAPANESE
#undef ISSJIS1
#undef ISSJIS2
#endif


/* create iconlist and Treeview control */
static BOOL CreateTreeIcons(HWND hWnd)
{
    HICON   hIcon;
    INT     i;
    HINSTANCE hInst = GetModuleHandle(0);
#ifdef EXTRA_FOLDER
    int numIcons = 12 + numExtraIcons;

    hTreeSmall = ImageList_Create (16, 16, ILC_COLORDDB | ILC_MASK, numIcons, numIcons);
#else
    hTreeSmall = ImageList_Create (16, 16, ILC_COLORDDB | ILC_MASK, 12, 12);
#endif

    for (i = IDI_FOLDER_OPEN; i <= IDI_CPS; i++)
    {
        if ((hIcon = LoadIconFromFile(treeIconNames[i - IDI_FOLDER_OPEN])) == 0)
            hIcon = LoadIcon (hInst, MAKEINTRESOURCE(i));

        if (ImageList_AddIcon (hTreeSmall, hIcon) == -1)
            return FALSE;
    }

#ifdef EXTRA_FOLDER
    for (i = 0; i < numExtraIcons; i++)
    {
        if ((hIcon = LoadIconFromFile(ExtraFolderIcons[i])) == 0)
            hIcon = LoadIcon (hInst, MAKEINTRESOURCE(IDI_FOLDER));

        if (ImageList_AddIcon (hTreeSmall, hIcon) == -1)
            return FALSE;
    }

    // Be sure that all the small icons were added.
    if (ImageList_GetImageCount (hTreeSmall) < numIcons)
        return FALSE;
#else
    // Be sure that all the small icons were added.
    if (ImageList_GetImageCount (hTreeSmall) < 12)
        return FALSE;
#endif

    // Associate the image lists with the list view control.
    TreeView_SetImageList (hWnd, hTreeSmall, LVSIL_NORMAL);
    return TRUE;
}

static BOOL TreeCtrlOnPaint(HWND hWnd, UINT uMsg,  WPARAM wParam,  LPARAM lParam)
{

    PAINTSTRUCT ps;
    HDC         hDC = GetDC(hWnd);
    RECT        rcClip, rcClient;
    HDC         memDC;
    HBITMAP     bitmap;
    HBITMAP     hOldBitmap;

    if (hBitmap == 0)
        return 1;

    BeginPaint(hWnd, &ps);

    GetClipBox(hDC, &rcClip);
    GetClientRect(hWnd, &rcClient);

    // Create a compatible memory DC
    memDC = CreateCompatibleDC(hDC);

    // Select a compatible bitmap into the memory DC
    bitmap = CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
    hOldBitmap = SelectObject(memDC, bitmap);

    // First let the control do its default drawing.
    CallWindowProc(g_lpTreeWndProc, hWnd, uMsg, (WPARAM)memDC, 0);
    // DefWindowProc(hWnd, WM_PAINT, (WPARAM)memDC, 0);

    // Draw bitmap in the background if one has been set
    if (hBitmap != NULL)
    {
        HPALETTE    hPAL;
        HDC maskDC;
        HBITMAP maskBitmap;
        HDC tempDC;
        HDC imageDC;
        HBITMAP bmpImage;
        HBITMAP hOldBmpBitmap;
        HBITMAP hOldMaskBitmap;
        HBITMAP hOldHBitmap;
        int i, j;
        RECT rcRoot;

        // Now create a mask
        maskDC = CreateCompatibleDC(hDC);

        // Create monochrome bitmap for the mask
        maskBitmap = CreateBitmap(rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
                        1, 1, NULL);
        hOldMaskBitmap = SelectObject(maskDC, maskBitmap);
        SetBkColor(memDC, GetSysColor(COLOR_WINDOW));

        // Create the mask from the memory DC
        BitBlt(maskDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, memDC,
                    rcClient.left, rcClient.top, SRCCOPY);


        tempDC = CreateCompatibleDC(hDC);
        hOldHBitmap = SelectObject(tempDC, hBitmap);

        imageDC = CreateCompatibleDC(hDC);
        bmpImage = CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left,
                        rcClient.bottom - rcClient.top);
        hOldBmpBitmap = SelectObject(imageDC, bmpImage);

        hPAL = (! hPALbg) ? CreateHalftonePalette(hDC) : hPALbg;

        if (GetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE && hPAL != NULL)
        {
            SelectPalette(hDC, hPAL, FALSE);
            RealizePalette(hDC);
            SelectPalette(imageDC, hPAL, FALSE);
        }

        // Get x and y offset
        TreeView_GetItemRect(hWnd, TreeView_GetRoot(hWnd), &rcRoot, FALSE);
        rcRoot.left = -GetScrollPos(hWnd, SB_HORZ);

        // Draw bitmap in tiled manner to imageDC
        for (i = rcRoot.left; i < rcClient.right; i += bmDesc.bmWidth)
            for (j = rcRoot.top; j < rcClient.bottom; j += bmDesc.bmHeight)
                BitBlt(imageDC,  i, j, bmDesc.bmWidth, bmDesc.bmHeight, tempDC,
                            0, 0, SRCCOPY);

        // Set the background in memDC to black. Using SRCPAINT with black and any other
        // color results in the other color, thus making black the transparent color
        SetBkColor(memDC, RGB(0,0,0));
        SetTextColor(memDC, RGB(255,255,255));
        BitBlt(memDC, rcClip.left, rcClip.top, rcClip.right - rcClip.left,
                rcClip.bottom - rcClip.top,
                maskDC, rcClip.left, rcClip.top, SRCAND);

        // Set the foreground to black. See comment above.
        SetBkColor(imageDC, RGB(255,255,255));
        SetTextColor(imageDC, RGB(0,0,0));
        BitBlt(imageDC, rcClip.left, rcClip.top, rcClip.right - rcClip.left,
                rcClip.bottom - rcClip.top, maskDC,
                rcClip.left, rcClip.top, SRCAND);

        // Combine the foreground with the background
        BitBlt(imageDC, rcClip.left, rcClip.top, rcClip.right - rcClip.left,
                rcClip.bottom - rcClip.top,
                memDC, rcClip.left, rcClip.top, SRCPAINT);
        // Draw the final image to the screen

        BitBlt(hDC, rcClip.left, rcClip.top, rcClip.right - rcClip.left,
                rcClip.bottom - rcClip.top,
                imageDC, rcClip.left, rcClip.top, SRCCOPY);

        SelectObject(maskDC,  hOldMaskBitmap);
        SelectObject(tempDC,  hOldHBitmap);
        SelectObject(imageDC, hOldBmpBitmap);

        DeleteDC(maskDC);
        DeleteDC(imageDC);
        DeleteDC(tempDC);
        DeleteObject(bmpImage);
        DeleteObject(maskBitmap);
    }
    else
    {
        BitBlt(hDC,  rcClip.left, rcClip.top, rcClip.right - rcClip.left,
                rcClip.bottom - rcClip.top,
                memDC, rcClip.left, rcClip.top, SRCCOPY);
    }
    SelectObject(memDC, hOldBitmap);
    DeleteObject(bitmap);
    DeleteDC(memDC);
    EndPaint(hWnd, &ps);
    ReleaseDC(hWnd, hDC);

    return 0;
}

/* Header code - Directional Arrows */
static LRESULT CALLBACK TreeWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_ERASEBKGND:
        if (hBitmap)
            return TRUE;
        break;

    case WM_PAINT:
        if (TreeCtrlOnPaint(hWnd, uMsg, wParam, lParam) == 0)
            return 0;
        break;
    }

    /* message not handled */
    return CallWindowProc(g_lpTreeWndProc, hWnd, uMsg, wParam, lParam);
}

/*
 * Filter code - should be moved to filter.c/filter.h
 * Added 01/09/99 - MSH <mhaaland@hypertech.com>
 */

/***************************************************************************
    private structures
 ***************************************************************************/

typedef struct {
    DWORD m_dwFolderID;     /* Folder ID */
    DWORD m_dwUnset;        /* Excluded filters */
    DWORD m_dwSet;          /* Implied filters */
} FILTER_RECORD, * LPFILTER_RECORD;

typedef struct {
    DWORD m_dwFilterType;   /* Filter value */
    DWORD m_dwCtrlID;       /* Control ID that represents it */
} FILTER_ITEM, *LPFILTER_ITEM;

/* List of folders with implied and excluded filters */
static FILTER_RECORD filterRecord[NUM_FOLDERS] = {
    {FOLDER_ALLGAMES,    0,             0               },
    {FOLDER_AVAILABLE,   F_AVAILABLE,   F_UNAVAILABLE   },
    {FOLDER_UNAVAILABLE, F_UNAVAILABLE, F_AVAILABLE     },
#if !defined(NEOFREE)
    {FOLDER_NEOGEO,      F_NEOGEO,      0               },
#endif
    {FOLDER_CPS1,        F_CPS1,        0               },
    {FOLDER_CPS2,        F_CPS2,        0               },
    {FOLDER_NAMCOS2,     F_NAMCOS2,     0               },
    {FOLDER_TAITOF3,     F_TAITOF3,     0               },
    {FOLDER_KONAMIGX,    F_KONAMIGX,    0               },
    {FOLDER_SEGAS16,     F_SEGAS16,     0               },
    {FOLDER_TOACAVE,     F_TOACAVE,     0               },
    {FOLDER_OTHERS,      F_OTHERS,      0               },
    {FOLDER_OTHERS2,     F_OTHERS2,     0               },
    {FOLDER_OTHERS3,     F_OTHERS3,     0               },
    {FOLDER_OTHERS4,     F_OTHERS4,     0               },
    {FOLDER_MANUFACTURER,0,             0               },
    {FOLDER_YEAR,        0,             0               },
    {FOLDER_WORKING,     F_WORKING,     F_NONWORKING    },
    {FOLDER_NONWORKING,  F_NONWORKING,  F_WORKING       },
    {FOLDER_CUSTOM,      0,             0               },
    {FOLDER_PLAYED,      0,             0               },
    {FOLDER_FAVORITE,    0,             0               },
    {FOLDER_ORIGINAL,    F_ORIGINALS,   F_CLONES        },
    {FOLDER_CLONES,      F_CLONES,      F_ORIGINALS     },
    {FOLDER_RASTER,      F_RASTER,      F_VECTOR        },
    {FOLDER_VECTOR,      F_VECTOR,      F_RASTER        },
    {FOLDER_TRACKBALL,   0,             0               },
    {FOLDER_STEREO,      0,             0               }
};

#define NUM_EXCLUSIONS  9

/* Pairs of filters that exclude each other */
DWORD filterExclusion[NUM_EXCLUSIONS] = {
    IDC_FILTER_CLONES,      IDC_FILTER_ORIGINALS,
    IDC_FILTER_NONWORKING,  IDC_FILTER_WORKING,
    IDC_FILTER_UNAVAILABLE, IDC_FILTER_AVAILABLE,
    IDC_FILTER_RASTER,      IDC_FILTER_VECTOR
};

/* list of filter/control Id pairs */
FILTER_ITEM filterList[F_NUM_FILTERS] = {
    {F_NEOGEO,       IDC_FILTER_NEOGEO},
    {F_CPS1,         IDC_FILTER_CPS1},
    {F_CPS2,         IDC_FILTER_CPS2},
    {F_NAMCOS2,      IDC_FILTER_NAMCOS2},
    {F_TAITOF3,      IDC_FILTER_TAITOF3},
    {F_KONAMIGX,     IDC_FILTER_KONAMIGX},
    {F_SEGAS16,      IDC_FILTER_SEGAS16},
    {F_TOACAVE,      IDC_FILTER_TOACAVE},
    {F_OTHERS,       IDC_FILTER_OTHERS},
    {F_OTHERS2,      IDC_FILTER_OTHERS2},
    {F_OTHERS3,      IDC_FILTER_OTHERS3},
    {F_OTHERS4,      IDC_FILTER_OTHERS4},
    {F_CLONES,       IDC_FILTER_CLONES},
    {F_NONWORKING,   IDC_FILTER_NONWORKING},
    {F_UNAVAILABLE,  IDC_FILTER_UNAVAILABLE},
    {F_RASTER,       IDC_FILTER_RASTER},
    {F_VECTOR,       IDC_FILTER_VECTOR},
    {F_ORIGINALS,    IDC_FILTER_ORIGINALS},
    {F_WORKING,      IDC_FILTER_WORKING},
    {F_AVAILABLE,    IDC_FILTER_AVAILABLE}
};

/***************************************************************************
    private functions prototypes
 ***************************************************************************/

static void             DisableFilters(HWND hWnd, LPFILTER_RECORD lpFilterRecord, LPFILTER_ITEM lpFilterItem, DWORD dwFlags);
static DWORD            ValidateFilters(LPFILTER_RECORD lpFilterRecord, DWORD dwFlags);
static void             EnableFilters(HWND hWnd, DWORD dwCtrlID);
static LPFILTER_RECORD  FindFilter(DWORD folderID);

/***************************************************************************
    public functions
 ***************************************************************************/

INT_PTR CALLBACK FilterDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    static DWORD            dwFilters;
    static LPFILTER_RECORD  lpFilterRecord;
    int                     i;

    switch (Msg)
    {
    case WM_INITDIALOG:
        dwFilters = 0;

        /* Use global lpCurrentFolder */
        if (lpCurrentFolder != NULL)
        {
            char tmp[80];

            Edit_SetText(GetDlgItem(hDlg, IDC_FILTER_EDIT), g_FilterText);
            Edit_SetSel(GetDlgItem(hDlg, IDC_FILTER_EDIT), 0, -1);

            /* Display current folder name in dialog titlebar */
#ifdef JAPANESE
            sprintf(tmp,"\"%s\"フォルダのフィルタ", lpCurrentFolder->m_lpTitle);
#else
            sprintf(tmp,"Filters for %s Folder", lpCurrentFolder->m_lpTitle);
#endif
            SetWindowText(hDlg, tmp);

            /* Mask out non filter flags */
            dwFilters = lpCurrentFolder->m_dwFlags & F_MASK;

            /* Find the matching filter record if it exists */
            lpFilterRecord = FindFilter(lpCurrentFolder->m_nFolderId);

            /* initialize and disable appropriate controls */
            for (i = 0; i < F_NUM_FILTERS; i++)
            {
                DisableFilters(hDlg, lpFilterRecord, &filterList[i], dwFilters);
            }
        }
        SetFocus(GetDlgItem(hDlg, IDC_FILTER_EDIT));
        return FALSE;

    case WM_HELP:
        HtmlHelp(((LPHELPINFO)lParam)->hItemHandle, MAME32HELP, HH_TP_HELP_WM_HELP, GetHelpIDs());
        break;

    case WM_CONTEXTMENU:
        HtmlHelp(hDlg, MAME32HELP, HH_TP_HELP_CONTEXTMENU, GetHelpIDs());
        break;

    case WM_COMMAND :
        {
            WORD wID         = GET_WM_COMMAND_ID(wParam, lParam);
            WORD wNotifyCode = GET_WM_COMMAND_CMD(wParam, lParam);

            switch (wID)
            {
            case IDOK :
                dwFilters = 0;

                Edit_GetText(GetDlgItem(hDlg, IDC_FILTER_EDIT), g_FilterText, FILTERTEXT_LEN);

                /* see which buttons are checked */
                for (i = 0; i < F_NUM_FILTERS; i++)
                {
                    if (Button_GetCheck(GetDlgItem(hDlg, filterList[i].m_dwCtrlID)))
                        dwFilters |= filterList[i].m_dwFilterType;
                }

                /* Mask out invalid filters */
                dwFilters = ValidateFilters(lpFilterRecord, dwFilters);

                /* Keep non filter flags */
                lpCurrentFolder->m_dwFlags &= ~F_MASK;

                /* or in the set filters */
                lpCurrentFolder->m_dwFlags |= dwFilters;

                /* Save the filters to the Registry */
                SetFolderFlags(lpCurrentFolder->m_lpTitle, dwFilters);
                EndDialog(hDlg, 1);
                return TRUE;

            case IDCANCEL :
                EndDialog(hDlg, 0);
                return TRUE;

            default:
                /* Handle unchecking mutually exclusive filters */
                if (wNotifyCode == BN_CLICKED)
                    EnableFilters(hDlg, wID);
            }
        }
        break;
    }
    return 0;
}

/***************************************************************************
    private functions
 ***************************************************************************/

/* Initialize controls */
static void DisableFilters(HWND hWnd, LPFILTER_RECORD lpFilterRecord, LPFILTER_ITEM lpFilterItem, DWORD dwFlags)
{
    HWND  hWndCtrl = GetDlgItem(hWnd, lpFilterItem->m_dwCtrlID);
    DWORD dwFilterType = lpFilterItem->m_dwFilterType;

    /* Check the appropriate control */
    if (dwFilterType & dwFlags)
        Button_SetCheck(hWndCtrl, MF_CHECKED);

    /* No special rules for this folder? */
    if (lpFilterRecord == (LPFILTER_RECORD)0)
        return;

    /* If this is an excluded filter */
    if (lpFilterRecord->m_dwUnset & dwFilterType)
    {
        /* uncheck it and disable the control */
        Button_SetCheck(hWndCtrl, MF_UNCHECKED);
        EnableWindow(hWndCtrl, FALSE);
    }

    /* If this is an implied filter, check it and disable the control */
    if (lpFilterRecord->m_dwSet & dwFilterType)
    {
        Button_SetCheck(hWndCtrl, MF_CHECKED);
        EnableWindow(hWndCtrl, FALSE);
    }
}

/* find a FILTER_RECORD by folderID */
static LPFILTER_RECORD FindFilter(DWORD folderID)
{
    int i;

    for (i = 0; i < NUM_FOLDERS; i++)
    {
        if (filterRecord[i].m_dwFolderID == folderID)
            return &filterRecord[i];
    }
    return (LPFILTER_RECORD)0;
}

/* Handle disabling mutually exclusive controls */
static void EnableFilters(HWND hWnd, DWORD dwCtrlID)
{
    int     i;
    DWORD   id;

    for (i = 0; i < NUM_EXCLUSIONS; i++)
    {
        /* is this control in the list? */
        if (filterExclusion[i] == dwCtrlID)
        {
            /* found the control id */
            break;
        }
    }

    /* if the control was found */
    if (i < NUM_EXCLUSIONS)
    {
        /* find the opposing control id */
        if (i % 2)
            id = filterExclusion[i - 1];
        else
            id = filterExclusion[i + 1];

        /* Uncheck the other control */
        Button_SetCheck(GetDlgItem(hWnd, id), MF_UNCHECKED);
    }
}

/* Validate filter setting, mask out inappropriate filters for this folder */
static DWORD ValidateFilters(LPFILTER_RECORD lpFilterRecord, DWORD dwFlags)
{
    DWORD dwFilters;

    if (lpFilterRecord != (LPFILTER_RECORD)0)
    {
        /* Mask out implied and excluded filters */
        dwFilters = lpFilterRecord->m_dwSet | lpFilterRecord->m_dwUnset;
        return dwFlags & ~dwFilters;
    }

    /* No special cases - all filters apply */
    return dwFlags;
}

/**************************************************************************/

#ifdef EXTRA_FOLDER
static int InitExtraFolders(void)
{
    struct stat stat_buffer;
    struct _finddata_t files;
    int i, count = 0;
    long hLong;
    char *ext;
    char buf[256];
    char curdir[MAX_PATH];
    const char *dir = GetFolderDir();

    memset(ExtraFolderData, 0, MAX_EXTRA_FOLDERS * sizeof(LPEXFOLDERDATA));

    if (stat(dir, &stat_buffer) != 0)
        _mkdir(dir);

    _getcwd(curdir, MAX_PATH);

    _chdir(dir);

    hLong = _findfirst("*", &files);

    for (i = 0; i < MAX_EXTRA_FOLDERS; i++)
        ExtraFolderIcons[i] = NULL;
    numExtraIcons = 0;

    while (!_findnext(hLong, &files))
    {
        if ((files.attrib & _A_SUBDIR) == 0)
        {
            FILE *fp;

            fp = fopen(files.name, "r");
            if (fp != NULL)
            {
                int icon[2] = { 0, 0 };
                char *p, *name;

                while (fgets(buf, 256, fp))
                {
                    if (buf[0] == '[')
                    {
                        p = strchr(buf, ']');
                        if (p == NULL)
                            continue;

                        *p = '\0';
                        name = &buf[1];
                        if (!strcmp(name, "FOLDER_SETTINGS"))
                        {
                            while (fgets(buf, 256, fp))
                            {
                                name = strtok(buf, " =\r\n");
                                if (name == NULL)
                                    break;

                                if (!strcmp(name, "RootFolderIcon"))
                                {
                                    name = strtok(NULL, " =\r\n");
                                    if (name != NULL)
                                        SetExtraIcons(name, &icon[0]);
                                }
                                if (!strcmp(name, "SubFolderIcon"))
                                {
                                    name = strtok(NULL, " =\r\n");
                                    if (name != NULL)
                                        SetExtraIcons(name, &icon[1]);
                                }
                            }
                            break;
                        }
                    }
                }
                fclose(fp);

                strcpy(buf, files.name);
                ext = strrchr(buf, '.');

                if (ext && *(ext + 1) && !stricmp(ext + 1, "ini"))
                {
                    ExtraFolderData[count] = malloc(sizeof(EXFOLDERDATA));
                    if (ExtraFolderData[count]) 
                    {
                        *ext = '\0';

                        memset(ExtraFolderData[count], 0, sizeof(EXFOLDERDATA));

                        strncpy(ExtraFolderData[count]->m_szTitle, buf, 63);
                        ExtraFolderData[count]->m_nFolderType = IS_ROOT;
                        ExtraFolderData[count]->m_nFolderId   = FOLDER_END + count + 1;
                        ExtraFolderData[count]->m_nParent     = FOLDER_NONE;
                        ExtraFolderData[count]->m_dwFlags     = 0;
                        ExtraFolderData[count]->m_nIconId     = icon[0] ? icon[0] : ICON_FOLDER;
                        ExtraFolderData[count]->m_nSubIconId  = icon[1] ? icon[1] : ICON_FOLDER;
                        count++;
                    }
                }
            }
        }
    }

    _chdir(curdir);

    return count;
}

void FreeExtraFolder(void)
{
    int i;

    for (i = 0; i < numExtraFolders; i++)
    {
        if (ExtraFolderData[i])
        {
            free(ExtraFolderData[i]);
            ExtraFolderData[i] = NULL;
        }
    }

    for (i = 0; i < numExtraIcons; i++)
        free(ExtraFolderIcons[i]);
    numExtraIcons = 0;
}


static void SetExtraIcons(char *name, int *id)
{
    char *p = strchr(name, '.');

    if (p != NULL)
        *p = '\0';

    ExtraFolderIcons[numExtraIcons] = malloc(strlen(name) + 1);
    if (ExtraFolderIcons[numExtraIcons])
    {
        *id = (ICON_CPS + 1) + numExtraIcons;
        strcpy(ExtraFolderIcons[numExtraIcons], name);
        numExtraIcons++;
    }
}


INLINE int GetIndexByName(const char *name)
{
    int i;

    for (i = 0; drivers[i]; i++)
    {
        if (strcmp(name, drivers[i]->name) == 0)
            return i;
    }
    return -1;
}
#endif

/* End of source file */
