1 // Driver Selector module
2 // TreeView Version by HyperYagami
3 #include "burner.h"
4 #include <process.h>
5 
6 // reduce the total number of sets by this number - (isgsm, neogeo, nmk004, pgm, skns, ym2608, coleco, msx_msx, spectrum, spec128, decocass, midssio, cchip, fdsbios, ngp, bubsys, channelf, namcoc69, namcoc70, namcoc75)
7 // don't reduce for these as we display them in the list (neogeo, neocdz)
8 #define REDUCE_TOTAL_SETS_BIOS      20
9 
10 UINT_PTR nTimer					= 0;
11 UINT_PTR nInitPreviewTimer		= 0;
12 int nDialogSelect				= -1;										// The driver which this dialog selected
13 int nOldDlgSelected				= -1;
14 bool bDialogCancel				= false;
15 
16 bool bDrvSelected				= false;
17 
18 static int nShowMVSCartsOnly	= 0;
19 
20 HBITMAP hPrevBmp				= NULL;
21 HBITMAP hTitleBmp				= NULL;
22 
23 HWND hSelDlg					= NULL;
24 static HWND hSelList			= NULL;
25 static HWND hParent				= NULL;
26 static HWND hInfoLabel[6]		= { NULL, NULL, NULL, NULL, NULL };			// 4 things in our Info-box
27 static HWND hInfoText[6]		= { NULL, NULL, NULL, NULL, NULL };			// 4 things in our Info-box
28 
29 TCHAR szSearchString[256]       = { _T("") };                               // Stores the search text between game loads
30 bool bSearchStringInit          = false;                                    // Used (internally) while dialog is initting
31 
32 static HBRUSH hWhiteBGBrush;
33 static HICON hExpand, hCollapse;
34 static HICON hNotWorking, hNotFoundEss, hNotFoundNonEss;
35 
36 static HICON hDrvIconMiss;
37 
38 static char TreeBuilding		= 0;										// if 1, ignore TVN_SELCHANGED messages
39 
40 static int bImageOrientation;
41 static int UpdatePreview(bool bReset, TCHAR *szPath, int HorCtrl, int VerCrtl);
42 
43 int	nIconsSize					= ICON_16x16;
44 int	nIconsSizeXY				= 16;
45 bool bEnableIcons				= 0;
46 bool bIconsLoaded				= 0;
47 bool bIconsOnlyParents          = 1;
48 int nIconsXDiff;
49 int nIconsYDiff;
50 static HICON hDrvIcon[19999];
51 bool bGameInfoOpen				= false;
52 
53 // Dialog Sizing
54 int nSelDlgWidth = 750;
55 int nSelDlgHeight = 588;
56 static int nDlgInitialWidth;
57 static int nDlgInitialHeight;
58 static int nDlgOptionsGrpInitialPos[4];
59 static int nDlgAvailableChbInitialPos[4];
60 static int nDlgUnavailableChbInitialPos[4];
61 static int nDlgAlwaysClonesChbInitialPos[4];
62 static int nDlgZipnamesChbInitialPos[4];
63 static int nDlgLatinTextChbInitialPos[4];
64 static int nDlgRomDirsBtnInitialPos[4];
65 static int nDlgScanRomsBtnInitialPos[4];
66 static int nDlgFilterGrpInitialPos[4];
67 static int nDlgFilterTreeInitialPos[4];
68 static int nDlgIpsGrpInitialPos[4];
69 static int nDlgApplyIpsChbInitialPos[4];
70 static int nDlgIpsManBtnInitialPos[4];
71 static int nDlgSearchGrpInitialPos[4];
72 static int nDlgSearchTxtInitialPos[4];
73 static int nDlgCancelBtnInitialPos[4];
74 static int nDlgPlayBtnInitialPos[4];
75 static int nDlgTitleGrpInitialPos[4];
76 static int nDlgTitleImgHInitialPos[4];
77 static int nDlgTitleImgVInitialPos[4];
78 static int nDlgPreviewGrpInitialPos[4];
79 static int nDlgPreviewImgHInitialPos[4];
80 static int nDlgPreviewImgVInitialPos[4];
81 static int nDlgWhiteBoxInitialPos[4];
82 static int nDlgGameInfoLblInitialPos[4];
83 static int nDlgRomNameLblInitialPos[4];
84 static int nDlgRomInfoLblInitialPos[4];
85 static int nDlgReleasedByLblInitialPos[4];
86 static int nDlgGenreLblInitialPos[4];
87 static int nDlgNotesLblInitialPos[4];
88 static int nDlgGameInfoTxtInitialPos[4];
89 static int nDlgRomNameTxtInitialPos[4];
90 static int nDlgRomInfoTxtInitialPos[4];
91 static int nDlgReleasedByTxtInitialPos[4];
92 static int nDlgGenreTxtInitialPos[4];
93 static int nDlgNotesTxtInitialPos[4];
94 static int nDlgDrvCountTxtInitialPos[4];
95 static int nDlgDrvRomInfoBtnInitialPos[4];
96 static int nDlgSelectGameGrpInitialPos[4];
97 static int nDlgSelectGameLstInitialPos[4];
98 
99 // Filter TreeView
100 HWND hFilterList					= NULL;
101 HTREEITEM hFilterCapcomMisc			= NULL;
102 HTREEITEM hFilterCave				= NULL;
103 HTREEITEM hFilterCps1				= NULL;
104 HTREEITEM hFilterCps2				= NULL;
105 HTREEITEM hFilterCps3				= NULL;
106 HTREEITEM hFilterDataeast			= NULL;
107 HTREEITEM hFilterGalaxian			= NULL;
108 HTREEITEM hFilterIrem				= NULL;
109 HTREEITEM hFilterKaneko				= NULL;
110 HTREEITEM hFilterKonami				= NULL;
111 HTREEITEM hFilterNeogeo				= NULL;
112 HTREEITEM hFilterPacman				= NULL;
113 HTREEITEM hFilterPgm				= NULL;
114 HTREEITEM hFilterPsikyo				= NULL;
115 HTREEITEM hFilterSega				= NULL;
116 HTREEITEM hFilterSeta				= NULL;
117 HTREEITEM hFilterTaito				= NULL;
118 HTREEITEM hFilterTechnos			= NULL;
119 HTREEITEM hFilterToaplan			= NULL;
120 HTREEITEM hFilterMiscPre90s			= NULL;
121 HTREEITEM hFilterMiscPost90s		= NULL;
122 HTREEITEM hFilterMegadrive			= NULL;
123 HTREEITEM hFilterPce				= NULL;
124 HTREEITEM hFilterMsx				= NULL;
125 HTREEITEM hFilterNes				= NULL;
126 HTREEITEM hFilterFds				= NULL;
127 HTREEITEM hFilterNgp				= NULL;
128 HTREEITEM hFilterChannelF			= NULL;
129 HTREEITEM hFilterSms				= NULL;
130 HTREEITEM hFilterGg					= NULL;
131 HTREEITEM hFilterSg1000				= NULL;
132 HTREEITEM hFilterColeco				= NULL;
133 HTREEITEM hFilterSpectrum			= NULL;
134 HTREEITEM hFilterMidway				= NULL;
135 HTREEITEM hFilterBootleg			= NULL;
136 HTREEITEM hFilterDemo				= NULL;
137 HTREEITEM hFilterHack				= NULL;
138 HTREEITEM hFilterHomebrew			= NULL;
139 HTREEITEM hFilterPrototype			= NULL;
140 HTREEITEM hFilterGenuine			= NULL;
141 HTREEITEM hFilterHorshoot			= NULL;
142 HTREEITEM hFilterVershoot			= NULL;
143 HTREEITEM hFilterScrfight			= NULL;
144 HTREEITEM hFilterVsfight			= NULL;
145 HTREEITEM hFilterBios				= NULL;
146 HTREEITEM hFilterBreakout			= NULL;
147 HTREEITEM hFilterCasino				= NULL;
148 HTREEITEM hFilterBallpaddle			= NULL;
149 HTREEITEM hFilterMaze				= NULL;
150 HTREEITEM hFilterMinigames			= NULL;
151 HTREEITEM hFilterPinball			= NULL;
152 HTREEITEM hFilterPlatform			= NULL;
153 HTREEITEM hFilterPuzzle				= NULL;
154 HTREEITEM hFilterQuiz				= NULL;
155 HTREEITEM hFilterSportsmisc			= NULL;
156 HTREEITEM hFilterSportsfootball 	= NULL;
157 HTREEITEM hFilterMisc				= NULL;
158 HTREEITEM hFilterMahjong			= NULL;
159 HTREEITEM hFilterRacing				= NULL;
160 HTREEITEM hFilterShoot				= NULL;
161 HTREEITEM hFilterRungun 			= NULL;
162 HTREEITEM hFilterAction				= NULL;
163 HTREEITEM hFilterStrategy   		= NULL;
164 HTREEITEM hFilterRpg        		= NULL;
165 HTREEITEM hFilterSim        		= NULL;
166 HTREEITEM hFilterAdv        		= NULL;
167 HTREEITEM hFilterOtherFamily		= NULL;
168 HTREEITEM hFilterMslug				= NULL;
169 HTREEITEM hFilterSf					= NULL;
170 HTREEITEM hFilterKof				= NULL;
171 HTREEITEM hFilterDstlk				= NULL;
172 HTREEITEM hFilterFatfury			= NULL;
173 HTREEITEM hFilterSamsho				= NULL;
174 HTREEITEM hFilter19xx				= NULL;
175 HTREEITEM hFilterSonicwi			= NULL;
176 HTREEITEM hFilterPwrinst			= NULL;
177 HTREEITEM hFilterSonic				= NULL;
178 HTREEITEM hFilterDonpachi			= NULL;
179 HTREEITEM hFilterMahou				= NULL;
180 HTREEITEM hFilterCapcomGrp			= NULL;
181 HTREEITEM hFilterSegaGrp			= NULL;
182 
183 HTREEITEM hRoot						= NULL;
184 HTREEITEM hBoardType				= NULL;
185 HTREEITEM hFamily					= NULL;
186 HTREEITEM hGenre					= NULL;
187 HTREEITEM hFavorites				= NULL;
188 HTREEITEM hHardware					= NULL;
189 
190 // GCC doesn't seem to define these correctly.....
191 #define _TreeView_SetItemState(hwndTV, hti, data, _mask) \
192 { TVITEM _ms_TVi;\
193   _ms_TVi.mask = TVIF_STATE; \
194   _ms_TVi.hItem = hti; \
195   _ms_TVi.stateMask = _mask;\
196   _ms_TVi.state = data;\
197   SNDMSG((hwndTV), TVM_SETITEM, 0, (LPARAM)(TV_ITEM *)&_ms_TVi);\
198 }
199 
200 #define _TreeView_SetCheckState(hwndTV, hti, fCheck) \
201   _TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), TVIS_STATEIMAGEMASK)
202 
203 // -----------------------------------------------------------------------------------------------------------------
204 
205 #define DISABLE_NON_AVAILABLE_SELECT	0						// Disable selecting non-available sets
206 #define NON_WORKING_PROMPT_ON_LOAD		1						// Prompt user on loading non-working sets
207 
208 static UINT64 CapcomMiscValue		= HARDWARE_PREFIX_CAPCOM_MISC >> 24;
209 static UINT64 MASKCAPMISC			= 1 << CapcomMiscValue;
210 static UINT64 CaveValue				= HARDWARE_PREFIX_CAVE >> 24;
211 static UINT64 MASKCAVE				= 1 << CaveValue;
212 static UINT64 CpsValue				= HARDWARE_PREFIX_CAPCOM >> 24;
213 static UINT64 MASKCPS				= 1 << CpsValue;
214 static UINT64 Cps2Value				= HARDWARE_PREFIX_CPS2 >> 24;
215 static UINT64 MASKCPS2				= 1 << Cps2Value;
216 static UINT64 Cps3Value				= HARDWARE_PREFIX_CPS3 >> 24;
217 static UINT64 MASKCPS3				= 1 << Cps3Value;
218 static UINT64 DataeastValue			= HARDWARE_PREFIX_DATAEAST >> 24;
219 static UINT64 MASKDATAEAST			= 1 << DataeastValue;
220 static UINT64 GalaxianValue			= HARDWARE_PREFIX_GALAXIAN >> 24;
221 static UINT64 MASKGALAXIAN			= 1 << GalaxianValue;
222 static UINT64 IremValue				= HARDWARE_PREFIX_IREM >> 24;
223 static UINT64 MASKIREM				= 1 << IremValue;
224 static UINT64 KanekoValue			= HARDWARE_PREFIX_KANEKO >> 24;
225 static UINT64 MASKKANEKO			= 1 << KanekoValue;
226 static UINT64 KonamiValue			= HARDWARE_PREFIX_KONAMI >> 24;
227 static UINT64 MASKKONAMI			= 1 << KonamiValue;
228 static UINT64 NeogeoValue			= HARDWARE_PREFIX_SNK >> 24;
229 static UINT64 MASKNEOGEO			= 1 << NeogeoValue;
230 static UINT64 PacmanValue			= HARDWARE_PREFIX_PACMAN >> 24;
231 static UINT64 MASKPACMAN			= 1 << PacmanValue;
232 static UINT64 PgmValue				= HARDWARE_PREFIX_IGS_PGM >> 24;
233 static UINT64 MASKPGM				= 1 << PgmValue;
234 static UINT64 PsikyoValue			= HARDWARE_PREFIX_PSIKYO >> 24;
235 static UINT64 MASKPSIKYO			= 1 << PsikyoValue;
236 static UINT64 SegaValue				= HARDWARE_PREFIX_SEGA >> 24;
237 static UINT64 MASKSEGA				= 1 << SegaValue;
238 static UINT64 SetaValue				= HARDWARE_PREFIX_SETA >> 24;
239 static UINT64 MASKSETA				= 1 << SetaValue;
240 static UINT64 TaitoValue			= HARDWARE_PREFIX_TAITO >> 24;
241 static UINT64 MASKTAITO				= 1 << TaitoValue;
242 static UINT64 TechnosValue			= HARDWARE_PREFIX_TECHNOS >> 24;
243 static UINT64 MASKTECHNOS			= 1 << TechnosValue;
244 static UINT64 ToaplanValue			= HARDWARE_PREFIX_TOAPLAN >> 24;
245 static UINT64 MASKTOAPLAN			= 1 << ToaplanValue;
246 static UINT64 MiscPre90sValue		= HARDWARE_PREFIX_MISC_PRE90S >> 24;
247 static UINT64 MASKMISCPRE90S		= 1 << MiscPre90sValue;
248 static UINT64 MiscPost90sValue		= HARDWARE_PREFIX_MISC_POST90S >> 24;
249 static UINT64 MASKMISCPOST90S		= 1 << MiscPost90sValue;
250 static UINT64 MegadriveValue		= HARDWARE_PREFIX_SEGA_MEGADRIVE >> 24;
251 static UINT64 MASKMEGADRIVE			= 1 << MegadriveValue;
252 static UINT64 PCEngineValue			= HARDWARE_PREFIX_PCENGINE >> 24;
253 static UINT64 MASKPCENGINE			= 1 << PCEngineValue;
254 static UINT64 SmsValue				= HARDWARE_PREFIX_SEGA_MASTER_SYSTEM >> 24;
255 static UINT64 MASKSMS				= 1 << SmsValue;
256 static UINT64 GgValue				= HARDWARE_PREFIX_SEGA_GAME_GEAR >> 24;
257 static UINT64 MASKGG				= 1 << GgValue;
258 static UINT64 Sg1000Value			= HARDWARE_PREFIX_SEGA_SG1000 >> 24;
259 static UINT64 MASKSG1000			= 1 << Sg1000Value;
260 static UINT64 ColecoValue			= HARDWARE_PREFIX_COLECO >> 24;
261 static UINT64 MASKCOLECO			= 1 << ColecoValue;
262 static UINT64 MsxValue				= HARDWARE_PREFIX_MSX >> 24;
263 static UINT64 MASKMSX				= 1 << MsxValue;
264 static UINT64 SpecValue				= HARDWARE_PREFIX_SPECTRUM >> 24;
265 static UINT64 MASKSPECTRUM			= 1 << SpecValue;
266 static UINT64 MidwayValue			= HARDWARE_PREFIX_MIDWAY >> 24;
267 static UINT64 MASKMIDWAY			= 1 << MidwayValue;
268 static UINT64 NesValue				= HARDWARE_PREFIX_NES >> 24;
269 static UINT64 MASKNES				= 1 << NesValue;
270 
271 static UINT64 FdsValue				= (UINT64)HARDWARE_PREFIX_FDS >> 24;
272 static UINT64 MASKFDS				= (UINT64)1 << FdsValue;            // 1 << 0x1f - needs casting or.. bonkers!
273 
274 // this is where things start going above the 32bit-zone. *solved w/64bit UINT?*
275 static UINT64 NgpValue				= (UINT64)HARDWARE_PREFIX_NGP >> 24;
276 static UINT64 MASKNGP				= (UINT64)1 << NgpValue;
277 
278 static UINT64 ChannelFValue			= (UINT64)HARDWARE_PREFIX_CHANNELF >> 24;
279 static UINT64 MASKCHANNELF			= (UINT64)1 << ChannelFValue;
280 
281 static UINT64 MASKALL				= ((UINT64)MASKCAPMISC | MASKCAVE | MASKCPS | MASKCPS2 | MASKCPS3 | MASKDATAEAST | MASKGALAXIAN | MASKIREM | MASKKANEKO | MASKKONAMI | MASKNEOGEO | MASKPACMAN | MASKPGM | MASKPSIKYO | MASKSEGA | MASKSETA | MASKTAITO | MASKTECHNOS | MASKTOAPLAN | MASKMISCPRE90S | MASKMISCPOST90S | MASKMEGADRIVE | MASKPCENGINE | MASKSMS | MASKGG | MASKSG1000 | MASKCOLECO | MASKMSX | MASKSPECTRUM | MASKMIDWAY | MASKNES | MASKFDS | MASKNGP | MASKCHANNELF );
282 
283 #define UNAVAILABLE				(1 << 27)
284 #define AVAILABLE				(1 << 28)
285 #define AUTOEXPAND				(1 << 29)
286 #define SHOWSHORT				(1 << 30)
287 #define ASCIIONLY				(1 << 31)
288 
289 #define MASKBOARDTYPEGENUINE	(1)
290 #define MASKFAMILYOTHER			0x10000000
291 
292 #define MASKALLGENRE			(GBF_HORSHOOT | GBF_VERSHOOT | GBF_SCRFIGHT | GBF_VSFIGHT | GBF_BIOS | GBF_BREAKOUT | GBF_CASINO | GBF_BALLPADDLE | GBF_MAZE | GBF_MINIGAMES | GBF_PINBALL | GBF_PLATFORM | GBF_PUZZLE | GBF_QUIZ | GBF_SPORTSMISC | GBF_SPORTSFOOTBALL | GBF_MISC | GBF_MAHJONG | GBF_RACING | GBF_SHOOT | GBF_ACTION | GBF_RUNGUN | GBF_STRATEGY | GBF_RPG | GBF_SIM | GBF_ADV)
293 #define MASKALLFAMILY			(MASKFAMILYOTHER | FBF_MSLUG | FBF_SF | FBF_KOF | FBF_DSTLK | FBF_FATFURY | FBF_SAMSHO | FBF_19XX | FBF_SONICWI | FBF_PWRINST | FBF_SONIC | FBF_DONPACHI | FBF_MAHOU)
294 #define MASKALLBOARD			(MASKBOARDTYPEGENUINE | BDF_BOOTLEG | BDF_DEMO | BDF_HACK | BDF_HOMEBREW | BDF_PROTOTYPE)
295 
296 #define MASKCAPGRP				(MASKCAPMISC | MASKCPS | MASKCPS2 | MASKCPS3)
297 #define MASKSEGAGRP				(MASKSEGA | MASKSG1000 | MASKSMS | MASKMEGADRIVE | MASKGG)
298 
299 UINT64 nLoadMenuShowX			= 0; // hardware etc
300 int nLoadMenuShowY				= 0; // selector options
301 int nLoadMenuBoardTypeFilter	= 0;
302 int nLoadMenuGenreFilter		= 0;
303 int nLoadMenuFavoritesFilter	= 0;
304 int nLoadMenuFamilyFilter		= 0;
305 
306 // expanded/collapsed state of filter nodes. default: expand main (0x01) & hardware (0x10)
307 int nLoadMenuExpand             = 0x10 | 0x01;
308 
309 struct NODEINFO {
310 	int nBurnDrvNo;
311 	bool bIsParent;
312 	char* pszROMName;
313 	HTREEITEM hTreeHandle;
314 };
315 
316 static NODEINFO* nBurnDrv = NULL;
317 static NODEINFO* nBurnZipListDrv = NULL;
318 static unsigned int nTmpDrvCount;
319 
320 // prototype  -----------------------
321 static void RebuildEverything();
322 // ----------------------------------
323 
324 // Dialog sizing support functions and macros (everything working in client co-ords)
325 #define GetInititalControlPos(a, b)								\
326 	GetWindowRect(GetDlgItem(hSelDlg, a), &rect);				\
327 	memset(&point, 0, sizeof(POINT));							\
328 	point.x = rect.left;										\
329 	point.y = rect.top;											\
330 	ScreenToClient(hSelDlg, &point);							\
331 	b[0] = point.x;												\
332 	b[1] = point.y;												\
333 	GetClientRect(GetDlgItem(hSelDlg, a), &rect);				\
334 	b[2] = rect.right;											\
335 	b[3] = rect.bottom;
336 
337 #define SetControlPosAlignTopRight(a, b)						\
338 	SetWindowPos(GetDlgItem(hSelDlg, a), hSelDlg, b[0] - xDelta, b[1], 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOSENDCHANGING);
339 
340 #define SetControlPosAlignTopLeft(a, b)							\
341 	SetWindowPos(GetDlgItem(hSelDlg, a), hSelDlg, b[0], b[1], 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOSENDCHANGING);
342 
343 #define SetControlPosAlignBottomRight(a, b)						\
344 	SetWindowPos(GetDlgItem(hSelDlg, a), hSelDlg, b[0] - xDelta, b[1] - yDelta, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOSENDCHANGING);
345 
346 #define SetControlPosAlignBottomLeftResizeHor(a, b)				\
347 	SetWindowPos(GetDlgItem(hSelDlg, a), hSelDlg, b[0], b[1] - yDelta, b[2] - xDelta, b[3], SWP_NOZORDER | SWP_NOSENDCHANGING);
348 
349 #define SetControlPosAlignTopRightResizeVert(a, b)				\
350 	xScrollBarDelta = (a == IDC_TREE2) ? -18 : 0;				\
351 	SetWindowPos(GetDlgItem(hSelDlg, a), hSelDlg, b[0] - xDelta, b[1], b[2] - xScrollBarDelta, b[3] - yDelta, SWP_NOZORDER | SWP_NOSENDCHANGING);
352 
353 #define SetControlPosAlignTopLeftResizeHorVert(a, b)			\
354 	xScrollBarDelta = (a == IDC_TREE1) ? -18 : 0;				\
355 	SetWindowPos(GetDlgItem(hSelDlg, a), hSelDlg, b[0], b[1], b[2] - xDelta - xScrollBarDelta, b[3] - yDelta, SWP_NOZORDER | SWP_NOSENDCHANGING);
356 
357 #define SetControlPosAlignTopLeftResizeHorVertALT(a, b)			\
358 	SetWindowPos(GetDlgItem(hSelDlg, a), hSelDlg, b[0], b[1], b[2] - xDelta, b[3] - yDelta, SWP_NOZORDER | SWP_NOSENDCHANGING);
359 
GetInitialPositions()360 static void GetInitialPositions()
361 {
362 	RECT rect;
363 	POINT point;
364 
365 	GetClientRect(hSelDlg, &rect);
366 	nDlgInitialWidth = rect.right;
367 	nDlgInitialHeight = rect.bottom;
368 
369 	GetInititalControlPos(IDC_STATIC_OPT, nDlgOptionsGrpInitialPos);
370 	GetInititalControlPos(IDC_CHECKAVAILABLE, nDlgAvailableChbInitialPos);
371 	GetInititalControlPos(IDC_CHECKUNAVAILABLE, nDlgUnavailableChbInitialPos);
372 	GetInititalControlPos(IDC_CHECKAUTOEXPAND, nDlgAlwaysClonesChbInitialPos);
373 	GetInititalControlPos(IDC_SEL_SHORTNAME, nDlgZipnamesChbInitialPos);
374 	GetInititalControlPos(IDC_SEL_ASCIIONLY, nDlgLatinTextChbInitialPos);
375 	GetInititalControlPos(IDROM, nDlgRomDirsBtnInitialPos);
376 	GetInititalControlPos(IDRESCAN, nDlgScanRomsBtnInitialPos);
377 	GetInititalControlPos(IDC_STATIC_SYS, nDlgFilterGrpInitialPos);
378 	GetInititalControlPos(IDC_TREE2, nDlgFilterTreeInitialPos);
379 	GetInititalControlPos(IDC_SEL_IPSGROUP, nDlgIpsGrpInitialPos);
380 	GetInititalControlPos(IDC_SEL_APPLYIPS, nDlgApplyIpsChbInitialPos);
381 	GetInititalControlPos(IDC_SEL_IPSMANAGER, nDlgIpsManBtnInitialPos);
382 	GetInititalControlPos(IDC_SEL_SEARCHGROUP, nDlgSearchGrpInitialPos);
383 	GetInititalControlPos(IDC_SEL_SEARCH, nDlgSearchTxtInitialPos);
384 	GetInititalControlPos(IDCANCEL, nDlgCancelBtnInitialPos);
385 	GetInititalControlPos(IDOK, nDlgPlayBtnInitialPos);
386 	GetInititalControlPos(IDC_STATIC3, nDlgTitleGrpInitialPos);
387 	GetInititalControlPos(IDC_SCREENSHOT2_H, nDlgTitleImgHInitialPos);
388 	GetInititalControlPos(IDC_SCREENSHOT2_V, nDlgTitleImgVInitialPos);
389 	GetInititalControlPos(IDC_STATIC2, nDlgPreviewGrpInitialPos);
390 	GetInititalControlPos(IDC_SCREENSHOT_H, nDlgPreviewImgHInitialPos);
391 	GetInititalControlPos(IDC_SCREENSHOT_V, nDlgPreviewImgVInitialPos);
392 	GetInititalControlPos(IDC_STATIC_INFOBOX, nDlgWhiteBoxInitialPos);
393 	GetInititalControlPos(IDC_LABELCOMMENT, nDlgGameInfoLblInitialPos);
394 	GetInititalControlPos(IDC_LABELROMNAME, nDlgRomNameLblInitialPos);
395 	GetInititalControlPos(IDC_LABELROMINFO, nDlgRomInfoLblInitialPos);
396 	GetInititalControlPos(IDC_LABELSYSTEM, nDlgReleasedByLblInitialPos);
397 	GetInititalControlPos(IDC_LABELGENRE, nDlgGenreLblInitialPos);
398 	GetInititalControlPos(IDC_LABELNOTES, nDlgNotesLblInitialPos);
399 	GetInititalControlPos(IDC_TEXTCOMMENT, nDlgGameInfoTxtInitialPos);
400 	GetInititalControlPos(IDC_TEXTROMNAME, nDlgRomNameTxtInitialPos);
401 	GetInititalControlPos(IDC_TEXTROMINFO, nDlgRomInfoTxtInitialPos);
402 	GetInititalControlPos(IDC_TEXTSYSTEM, nDlgReleasedByTxtInitialPos);
403 	GetInititalControlPos(IDC_TEXTGENRE, nDlgGenreTxtInitialPos);
404 	GetInititalControlPos(IDC_TEXTNOTES, nDlgNotesTxtInitialPos);
405 	GetInititalControlPos(IDC_DRVCOUNT, nDlgDrvCountTxtInitialPos);
406 	GetInititalControlPos(IDGAMEINFO, nDlgDrvRomInfoBtnInitialPos);
407 	GetInititalControlPos(IDC_STATIC1, nDlgSelectGameGrpInitialPos);
408 	GetInititalControlPos(IDC_TREE1, nDlgSelectGameLstInitialPos);
409 
410 	// When the window is created with too few entries for TreeView to warrant the
411 	// use of a vertical scrollbar, the right side will be slightly askew. -dink
412 
413 	if (nDlgSelectGameGrpInitialPos[2] - nDlgSelectGameLstInitialPos[2] < 30 ) {
414 		nDlgSelectGameLstInitialPos[2] = nDlgSelectGameGrpInitialPos[2] - 34;
415 	}
416 
417 	if (nDlgFilterGrpInitialPos[2] - nDlgFilterTreeInitialPos[2] < 30 ) {
418 		nDlgFilterTreeInitialPos[2] = nDlgFilterGrpInitialPos[2] - 34;
419 	}
420 }
421 
422 // Check if a specified driver is working
CheckWorkingStatus(int nDriver)423 static bool CheckWorkingStatus(int nDriver)
424 {
425 	int nOldnBurnDrvActive = nBurnDrvActive;
426 	nBurnDrvActive = nDriver;
427 	bool bStatus = BurnDrvIsWorking();
428 	nBurnDrvActive = nOldnBurnDrvActive;
429 
430 	return bStatus;
431 }
432 
MangleGamename(const TCHAR * szOldName,bool)433 static TCHAR* MangleGamename(const TCHAR* szOldName, bool /*bRemoveArticle*/)
434 {
435 	static TCHAR szNewName[256] = _T("");
436 
437 #if 0
438 	TCHAR* pszName = szNewName;
439 
440 	if (_tcsnicmp(szOldName, _T("the "), 4) == 0) {
441 		int x = 0, y = 0;
442 		while (szOldName[x] && szOldName[x] != _T('(') && szOldName[x] != _T('-')) {
443 			x++;
444 		}
445 		y = x;
446 		while (y && szOldName[y - 1] == _T(' ')) {
447 			y--;
448 		}
449 		_tcsncpy(pszName, szOldName + 4, y - 4);
450 		pszName[y - 4] = _T('\0');
451 		pszName += y - 4;
452 
453 		if (!bRemoveArticle) {
454 			pszName += _stprintf(pszName, _T(", the"));
455 		}
456 		if (szOldName[x]) {
457 			_stprintf(pszName, _T(" %s"), szOldName + x);
458 		}
459 	} else {
460 		_tcscpy(pszName, szOldName);
461 	}
462 #endif
463 
464 #if 0
465 	static TCHAR szPrefix[256] = _T("");
466 	// dink's prefix-izer - it's useless...
467 	_tcscpy(szPrefix, BurnDrvGetText(DRV_NAME));
468 	int use_prefix = 0;
469 	int nn_len = 0;
470 	for (int i = 0; i < 6; i++) {
471 		if (szPrefix[i] == _T('_')) {
472 			szNewName[nn_len++] = _T(' ');
473 			use_prefix = 1;
474 			break;
475 		} else {
476 			szNewName[nn_len++] = towupper(szPrefix[i]);
477 		}
478 	}
479 	if (use_prefix == 0) nn_len = 0;
480 #endif
481 
482 #if 1
483 	_tcscpy(szNewName, szOldName);
484 #endif
485 
486 	return szNewName;
487 }
488 
RemoveSpace(const TCHAR * szOldName)489 static TCHAR* RemoveSpace(const TCHAR* szOldName)
490 {
491 	static TCHAR szNewName[256] = _T("");
492 	int j = 0;
493 	int i = 0;
494 
495 	for (i = 0; szOldName[i]; i++) {
496 		if (!iswspace(szOldName[i])) {
497 			szNewName[j++] = szOldName[i];
498 		}
499 	}
500 
501 	szNewName[j] = _T('\0');
502 
503 	return szNewName;
504 }
505 
DoExtraFilters()506 static int DoExtraFilters()
507 {
508 	if (nLoadMenuFavoritesFilter) {
509 		return (CheckFavorites(BurnDrvGetTextA(DRV_NAME)) != -1) ? 0 : 1;
510 	}
511 
512 	if (nShowMVSCartsOnly && ((BurnDrvGetHardwareCode() & HARDWARE_PREFIX_CARTRIDGE) != HARDWARE_PREFIX_CARTRIDGE)) return 1;
513 
514 	if ((nLoadMenuBoardTypeFilter & BDF_BOOTLEG)			&& (BurnDrvGetFlags() & BDF_BOOTLEG))				return 1;
515 	if ((nLoadMenuBoardTypeFilter & BDF_DEMO)				&& (BurnDrvGetFlags() & BDF_DEMO))					return 1;
516 	if ((nLoadMenuBoardTypeFilter & BDF_HACK)				&& (BurnDrvGetFlags() & BDF_HACK))					return 1;
517 	if ((nLoadMenuBoardTypeFilter & BDF_HOMEBREW)			&& (BurnDrvGetFlags() & BDF_HOMEBREW))				return 1;
518 	if ((nLoadMenuBoardTypeFilter & BDF_PROTOTYPE)			&& (BurnDrvGetFlags() & BDF_PROTOTYPE))				return 1;
519 
520 	if ((nLoadMenuBoardTypeFilter & MASKBOARDTYPEGENUINE)	&& (!(BurnDrvGetFlags() & BDF_BOOTLEG))
521 															&& (!(BurnDrvGetFlags() & BDF_DEMO))
522 															&& (!(BurnDrvGetFlags() & BDF_HACK))
523 															&& (!(BurnDrvGetFlags() & BDF_HOMEBREW))
524 															&& (!(BurnDrvGetFlags() & BDF_PROTOTYPE)))	return 1;
525 
526 	if ((nLoadMenuFamilyFilter & FBF_MSLUG)					&& (BurnDrvGetFamilyFlags() & FBF_MSLUG))			return 1;
527 	if ((nLoadMenuFamilyFilter & FBF_SF)					&& (BurnDrvGetFamilyFlags() & FBF_SF))				return 1;
528 	if ((nLoadMenuFamilyFilter & FBF_KOF)					&& (BurnDrvGetFamilyFlags() & FBF_KOF))				return 1;
529 	if ((nLoadMenuFamilyFilter & FBF_DSTLK)					&& (BurnDrvGetFamilyFlags() & FBF_DSTLK))			return 1;
530 	if ((nLoadMenuFamilyFilter & FBF_FATFURY)				&& (BurnDrvGetFamilyFlags() & FBF_FATFURY))			return 1;
531 	if ((nLoadMenuFamilyFilter & FBF_SAMSHO)				&& (BurnDrvGetFamilyFlags() & FBF_SAMSHO))			return 1;
532 	if ((nLoadMenuFamilyFilter & FBF_19XX)					&& (BurnDrvGetFamilyFlags() & FBF_19XX))			return 1;
533 	if ((nLoadMenuFamilyFilter & FBF_SONICWI)				&& (BurnDrvGetFamilyFlags() & FBF_SONICWI))			return 1;
534 	if ((nLoadMenuFamilyFilter & FBF_PWRINST)				&& (BurnDrvGetFamilyFlags() & FBF_PWRINST))			return 1;
535 	if ((nLoadMenuFamilyFilter & FBF_SONIC)					&& (BurnDrvGetFamilyFlags() & FBF_SONIC))			return 1;
536 	if ((nLoadMenuFamilyFilter & FBF_DONPACHI)				&& (BurnDrvGetFamilyFlags() & FBF_DONPACHI))		return 1;
537 	if ((nLoadMenuFamilyFilter & FBF_MAHOU)					&& (BurnDrvGetFamilyFlags() & FBF_MAHOU))			return 1;
538 
539 	if ((nLoadMenuFamilyFilter & MASKFAMILYOTHER)			&& (!(BurnDrvGetFamilyFlags() & FBF_MSLUG))
540 															&& (!(BurnDrvGetFamilyFlags() & FBF_SF))
541 															&& (!(BurnDrvGetFamilyFlags() & FBF_KOF))
542 															&& (!(BurnDrvGetFamilyFlags() & FBF_DSTLK))
543 															&& (!(BurnDrvGetFamilyFlags() & FBF_FATFURY))
544 															&& (!(BurnDrvGetFamilyFlags() & FBF_SAMSHO))
545 															&& (!(BurnDrvGetFamilyFlags() & FBF_19XX))
546 															&& (!(BurnDrvGetFamilyFlags() & FBF_SONICWI))
547 															&& (!(BurnDrvGetFamilyFlags() & FBF_PWRINST))
548 															&& (!(BurnDrvGetFamilyFlags() & FBF_SONIC))
549 															&& (!(BurnDrvGetFamilyFlags() & FBF_DONPACHI))
550 															&& (!(BurnDrvGetFamilyFlags() & FBF_MAHOU)) )		return 1;
551 
552 
553 	// This filter supports multiple genre's per game
554 	int bGenreOk = 0;
555 	if ((~nLoadMenuGenreFilter & GBF_HORSHOOT)				&& (BurnDrvGetGenreFlags() & GBF_HORSHOOT))			bGenreOk = 1;
556 	if ((~nLoadMenuGenreFilter & GBF_VERSHOOT)				&& (BurnDrvGetGenreFlags() & GBF_VERSHOOT))			bGenreOk = 1;
557 	if ((~nLoadMenuGenreFilter & GBF_SCRFIGHT)				&& (BurnDrvGetGenreFlags() & GBF_SCRFIGHT))			bGenreOk = 1;
558 	if ((~nLoadMenuGenreFilter & GBF_VSFIGHT)				&& (BurnDrvGetGenreFlags() & GBF_VSFIGHT))			bGenreOk = 1;
559 	if ((~nLoadMenuGenreFilter & GBF_BIOS)					&& (BurnDrvGetGenreFlags() & GBF_BIOS))				bGenreOk = 1;
560 	if ((~nLoadMenuGenreFilter & GBF_BREAKOUT)				&& (BurnDrvGetGenreFlags() & GBF_BREAKOUT))			bGenreOk = 1;
561 	if ((~nLoadMenuGenreFilter & GBF_CASINO)				&& (BurnDrvGetGenreFlags() & GBF_CASINO))			bGenreOk = 1;
562 	if ((~nLoadMenuGenreFilter & GBF_BALLPADDLE)			&& (BurnDrvGetGenreFlags() & GBF_BALLPADDLE))		bGenreOk = 1;
563 	if ((~nLoadMenuGenreFilter & GBF_MAZE)					&& (BurnDrvGetGenreFlags() & GBF_MAZE))				bGenreOk = 1;
564 	if ((~nLoadMenuGenreFilter & GBF_MINIGAMES)				&& (BurnDrvGetGenreFlags() & GBF_MINIGAMES))		bGenreOk = 1;
565 	if ((~nLoadMenuGenreFilter & GBF_PINBALL)				&& (BurnDrvGetGenreFlags() & GBF_PINBALL))			bGenreOk = 1;
566 	if ((~nLoadMenuGenreFilter & GBF_PLATFORM)				&& (BurnDrvGetGenreFlags() & GBF_PLATFORM))			bGenreOk = 1;
567 	if ((~nLoadMenuGenreFilter & GBF_PUZZLE)				&& (BurnDrvGetGenreFlags() & GBF_PUZZLE))			bGenreOk = 1;
568 	if ((~nLoadMenuGenreFilter & GBF_QUIZ)					&& (BurnDrvGetGenreFlags() & GBF_QUIZ))				bGenreOk = 1;
569 	if ((~nLoadMenuGenreFilter & GBF_SPORTSMISC)			&& (BurnDrvGetGenreFlags() & GBF_SPORTSMISC))		bGenreOk = 1;
570 	if ((~nLoadMenuGenreFilter & GBF_SPORTSFOOTBALL) 		&& (BurnDrvGetGenreFlags() & GBF_SPORTSFOOTBALL))	bGenreOk = 1;
571 	if ((~nLoadMenuGenreFilter & GBF_MISC)					&& (BurnDrvGetGenreFlags() & GBF_MISC))				bGenreOk = 1;
572 	if ((~nLoadMenuGenreFilter & GBF_MAHJONG)				&& (BurnDrvGetGenreFlags() & GBF_MAHJONG))			bGenreOk = 1;
573 	if ((~nLoadMenuGenreFilter & GBF_RACING)				&& (BurnDrvGetGenreFlags() & GBF_RACING))			bGenreOk = 1;
574 	if ((~nLoadMenuGenreFilter & GBF_SHOOT)					&& (BurnDrvGetGenreFlags() & GBF_SHOOT))			bGenreOk = 1;
575 	if ((~nLoadMenuGenreFilter & GBF_ACTION)				&& (BurnDrvGetGenreFlags() & GBF_ACTION))			bGenreOk = 1;
576 	if ((~nLoadMenuGenreFilter & GBF_RUNGUN)				&& (BurnDrvGetGenreFlags() & GBF_RUNGUN))			bGenreOk = 1;
577 	if ((~nLoadMenuGenreFilter & GBF_STRATEGY)				&& (BurnDrvGetGenreFlags() & GBF_STRATEGY))			bGenreOk = 1;
578 	if ((~nLoadMenuGenreFilter & GBF_RPG)					&& (BurnDrvGetGenreFlags() & GBF_RPG))				bGenreOk = 1;
579 	if ((~nLoadMenuGenreFilter & GBF_SIM)					&& (BurnDrvGetGenreFlags() & GBF_SIM))				bGenreOk = 1;
580 	if ((~nLoadMenuGenreFilter & GBF_ADV)					&& (BurnDrvGetGenreFlags() & GBF_ADV))				bGenreOk = 1;
581 	if (bGenreOk == 0) return 1;
582 
583 	return 0;
584 }
585 
ZipNames_qs_cmp_desc(const void * p0,const void * p1)586 static int ZipNames_qs_cmp_desc(const void *p0, const void *p1) {
587 	struct NODEINFO *ni0 = (struct NODEINFO*) p0;
588 	struct NODEINFO *ni1 = (struct NODEINFO*) p1;
589 
590 	return stricmp(ni1->pszROMName, ni0->pszROMName);
591 }
592 
593 // Make a tree-view control with all drivers
SelListMake()594 static int SelListMake()
595 {
596 	int i, j;
597 	unsigned int nMissingDrvCount = 0;
598 
599 	if (nBurnDrv) {
600 		free(nBurnDrv);
601 		nBurnDrv = NULL;
602 	}
603 	nBurnDrv = (NODEINFO*)malloc(nBurnDrvCount * sizeof(NODEINFO));
604 	memset(nBurnDrv, 0, nBurnDrvCount * sizeof(NODEINFO));
605 
606 	nTmpDrvCount = 0;
607 
608 	if (hSelList == NULL) {
609 		return 1;
610 	}
611 
612 	LoadFavorites();
613 
614 	// Get dialog search string
615 	j = GetDlgItemText(hSelDlg, IDC_SEL_SEARCH, szSearchString, sizeof(szSearchString));
616 	for (UINT32 k = 0; k < j; k++)
617 		szSearchString[k] = _totlower(szSearchString[k]);
618 
619 	// pre-sort the list if using zip names
620 	if (nLoadMenuShowY & SHOWSHORT)	{
621 		// make a list of everything
622 		if (nBurnZipListDrv) {
623 			free(nBurnZipListDrv);
624 			nBurnZipListDrv = NULL;
625 		}
626 		nBurnZipListDrv = (NODEINFO*)malloc(nBurnDrvCount * sizeof(NODEINFO));
627 		memset(nBurnZipListDrv, 0, nBurnDrvCount * sizeof(NODEINFO));
628 
629 		for (i = nBurnDrvCount-1; i >= 0; i--) {
630 			nBurnDrvActive = i;
631 			nBurnZipListDrv[i].pszROMName = BurnDrvGetTextA(DRV_NAME);
632 			nBurnZipListDrv[i].nBurnDrvNo = i;
633 		}
634 
635 		// sort it in descending order (we add in descending order)
636 		qsort(nBurnZipListDrv, nBurnDrvCount, sizeof(NODEINFO), ZipNames_qs_cmp_desc);
637 	}
638 
639 	// Add all the driver names to the list
640 	// 1st: parents
641 	for (i = nBurnDrvCount-1; i >= 0; i--) {
642 		TV_INSERTSTRUCT TvItem;
643 
644 		nBurnDrvActive = i;																// Switch to driver i
645 
646 		// if showing zip names get active entry from our sorted list
647 		if (nLoadMenuShowY & SHOWSHORT) nBurnDrvActive = nBurnZipListDrv[nBurnDrvCount - 1 - i].nBurnDrvNo;
648 
649 		if (BurnDrvGetFlags() & BDF_BOARDROM) {
650 			continue;
651 		}
652 
653 		if (BurnDrvGetText(DRV_PARENT) != NULL && (BurnDrvGetFlags() & BDF_CLONE)) {	// Skip clones
654 			continue;
655 		}
656 
657 		if(!gameAv[nBurnDrvActive]) nMissingDrvCount++;
658 
659 		UINT64 nHardware = (UINT64)1 << (BurnDrvGetHardwareCode() >> 24);
660 		if ((nHardware & MASKALL) && ((nHardware & nLoadMenuShowX) || (nHardware & MASKALL) == 0)) {
661 			continue;
662 		}
663 
664 		if (avOk && (!(nLoadMenuShowY & UNAVAILABLE)) && !gameAv[nBurnDrvActive]) {						// Skip non-available games if needed
665 			continue;
666 		}
667 
668 		if (avOk && (!(nLoadMenuShowY & AVAILABLE)) && gameAv[nBurnDrvActive]) {						// Skip available games if needed
669 			continue;
670 		}
671 
672 		if (DoExtraFilters()) continue;
673 
674 		if (szSearchString[0]) {
675 			TCHAR *StringFound = NULL;
676 			TCHAR *StringFound2 = NULL;
677 			TCHAR *StringFound3 = NULL;
678 			TCHAR szDriverName[256] = { _T("") };
679 			TCHAR szManufacturerName[256] = { _T("") };
680 			wcscpy(szDriverName, BurnDrvGetText(DRV_FULLNAME));
681 			swprintf(szManufacturerName, _T("%s %s"), BurnDrvGetText(DRV_MANUFACTURER), BurnDrvGetText(DRV_SYSTEM));
682 			for (int k = 0; k < 256; k++) {
683 				szDriverName[k] = _totlower(szDriverName[k]);
684 				szManufacturerName[k] = _totlower(szManufacturerName[k]);
685 			}
686 			StringFound = wcsstr(szDriverName, szSearchString);
687 			StringFound2 = wcsstr(BurnDrvGetText(DRV_NAME), szSearchString);
688 			StringFound3 = wcsstr(szManufacturerName, szSearchString);
689 
690 			if (!StringFound && !StringFound2 && !StringFound3) continue;
691 		}
692 
693 		memset(&TvItem, 0, sizeof(TvItem));
694 		TvItem.item.mask = TVIF_TEXT | TVIF_PARAM;
695 		TvItem.hInsertAfter = TVI_FIRST;
696 		TvItem.item.pszText = (nLoadMenuShowY & SHOWSHORT) ? BurnDrvGetText(DRV_NAME) : RemoveSpace(BurnDrvGetText(DRV_ASCIIONLY | DRV_FULLNAME));
697 		TvItem.item.lParam = (LPARAM)&nBurnDrv[nTmpDrvCount];
698 		nBurnDrv[nTmpDrvCount].hTreeHandle = (HTREEITEM)SendMessage(hSelList, TVM_INSERTITEM, 0, (LPARAM)&TvItem);
699 		nBurnDrv[nTmpDrvCount].nBurnDrvNo = nBurnDrvActive;
700 		nBurnDrv[nTmpDrvCount].pszROMName = BurnDrvGetTextA(DRV_NAME);
701 		nBurnDrv[nTmpDrvCount].bIsParent = true;
702 		nTmpDrvCount++;
703 	}
704 
705 	// 2nd: clones
706 	for (i = nBurnDrvCount-1; i >= 0; i--) {
707 		TV_INSERTSTRUCT TvItem;
708 
709 		nBurnDrvActive = i;																// Switch to driver i
710 
711 		// if showing zip names get active entry from our sorted list
712 		if (nLoadMenuShowY & SHOWSHORT) nBurnDrvActive = nBurnZipListDrv[nBurnDrvCount - 1 - i].nBurnDrvNo;
713 
714 		if (BurnDrvGetFlags() & BDF_BOARDROM) {
715 			continue;
716 		}
717 
718 		if (BurnDrvGetTextA(DRV_PARENT) == NULL || !(BurnDrvGetFlags() & BDF_CLONE)) {	// Skip parents
719 			continue;
720 		}
721 
722 		if(!gameAv[nBurnDrvActive]) nMissingDrvCount++;
723 
724 		UINT64 nHardware = (UINT64)1 << (BurnDrvGetHardwareCode() >> 24);
725 		if ((nHardware & MASKALL) && ((nHardware & nLoadMenuShowX) || ((nHardware & MASKALL) == 0))) {
726 			continue;
727 		}
728 
729 		if (avOk && (!(nLoadMenuShowY & UNAVAILABLE)) && !gameAv[nBurnDrvActive]) {						// Skip non-available games if needed
730 			continue;
731 		}
732 
733 		if (avOk && (!(nLoadMenuShowY & AVAILABLE)) && gameAv[nBurnDrvActive]) {						// Skip available games if needed
734 			continue;
735 		}
736 
737 		if (DoExtraFilters()) continue;
738 
739 		if (szSearchString[0]) {
740 			TCHAR *StringFound = NULL;
741 			TCHAR *StringFound2 = NULL;
742 			TCHAR *StringFound3 = NULL;
743 			TCHAR szDriverName[256] = { _T("") };
744 			TCHAR szManufacturerName[256] = { _T("") };
745 			wcscpy(szDriverName, BurnDrvGetText(DRV_FULLNAME));
746 			swprintf(szManufacturerName, _T("%s %s"), BurnDrvGetText(DRV_MANUFACTURER), BurnDrvGetText(DRV_SYSTEM));
747 			for (int k =0; k < 256; k++) {
748 				szDriverName[k] = _totlower(szDriverName[k]);
749 				szManufacturerName[k] = _totlower(szManufacturerName[k]);
750 			}
751 			StringFound = wcsstr(szDriverName, szSearchString);
752 			StringFound2 = wcsstr(BurnDrvGetText(DRV_NAME), szSearchString);
753 			StringFound3 = wcsstr(szManufacturerName, szSearchString);
754 
755 			if (!StringFound && !StringFound2 && !StringFound3) continue;
756 		}
757 
758 		memset(&TvItem, 0, sizeof(TvItem));
759 		TvItem.item.mask = TVIF_TEXT | TVIF_PARAM;
760 		TvItem.hInsertAfter = TVI_FIRST;
761 		TvItem.item.pszText = (nLoadMenuShowY & SHOWSHORT) ? BurnDrvGetText(DRV_NAME) : RemoveSpace(BurnDrvGetText(DRV_ASCIIONLY | DRV_FULLNAME));
762 
763 		// Find the parent's handle
764 		for (j = 0; j < nTmpDrvCount; j++) {
765 			if (nBurnDrv[j].bIsParent) {
766 				if (!strcmp(BurnDrvGetTextA(DRV_PARENT), nBurnDrv[j].pszROMName)) {
767 					TvItem.hParent = nBurnDrv[j].hTreeHandle;
768 					break;
769 				}
770 			}
771 		}
772 
773 		// Find the parent and add a branch to the tree
774 		if (!TvItem.hParent) {
775 			char szTempName[32];
776 			strcpy(szTempName, BurnDrvGetTextA(DRV_PARENT));
777 			int nTempBurnDrvSelect = nBurnDrvActive;
778 			for (j = 0; j < nBurnDrvCount; j++) {
779 				nBurnDrvActive = j;
780 				if (!strcmp(szTempName, BurnDrvGetTextA(DRV_NAME))) {
781 					TV_INSERTSTRUCT TempTvItem;
782 					memset(&TempTvItem, 0, sizeof(TempTvItem));
783 					TempTvItem.item.mask = TVIF_TEXT | TVIF_PARAM;
784 					//TempTvItem.hInsertAfter = TVI_FIRST;
785 					TempTvItem.hInsertAfter = TVI_SORT; // only use the horribly-slow TVI_SORT for missing parents!
786 					TempTvItem.item.pszText = (nLoadMenuShowY & SHOWSHORT) ? BurnDrvGetText(DRV_NAME) : RemoveSpace(BurnDrvGetText(DRV_ASCIIONLY | DRV_FULLNAME));
787 					TempTvItem.item.lParam = (LPARAM)&nBurnDrv[nTmpDrvCount];
788 					nBurnDrv[nTmpDrvCount].hTreeHandle = (HTREEITEM)SendMessage(hSelList, TVM_INSERTITEM, 0, (LPARAM)&TempTvItem);
789 					nBurnDrv[nTmpDrvCount].nBurnDrvNo = j;
790 					nBurnDrv[nTmpDrvCount].bIsParent = true;
791 					nBurnDrv[nTmpDrvCount].pszROMName = BurnDrvGetTextA(DRV_NAME);
792 					TvItem.item.lParam = (LPARAM)&nBurnDrv[nTmpDrvCount];
793 					TvItem.hParent = nBurnDrv[nTmpDrvCount].hTreeHandle;
794 					nTmpDrvCount++;
795 					break;
796 				}
797 			}
798 			nBurnDrvActive = nTempBurnDrvSelect;
799 		}
800 
801 		TvItem.item.lParam = (LPARAM)&nBurnDrv[nTmpDrvCount];
802 		nBurnDrv[nTmpDrvCount].hTreeHandle = (HTREEITEM)SendMessage(hSelList, TVM_INSERTITEM, 0, (LPARAM)&TvItem);
803 		nBurnDrv[nTmpDrvCount].pszROMName = BurnDrvGetTextA(DRV_NAME);
804 		nBurnDrv[nTmpDrvCount].nBurnDrvNo = nBurnDrvActive;
805 		nTmpDrvCount++;
806 	}
807 
808 	for (i = 0; i < nTmpDrvCount; i++) {
809 		// See if we need to expand the branch of an unavailable or non-working parent
810 		if (nBurnDrv[i].bIsParent && ((nLoadMenuShowY & AUTOEXPAND) || !gameAv[nBurnDrv[i].nBurnDrvNo] || !CheckWorkingStatus(nBurnDrv[i].nBurnDrvNo))) {
811 			for (j = 0; j < nTmpDrvCount; j++) {
812 
813 				// Expand the branch only if a working clone is available -or-
814 				// If ROM Scanning is disabled (bSkipStartupCheck==1) and expand clones is set. -dink March 22, 2020
815 				if ( gameAv[nBurnDrv[j].nBurnDrvNo] || (bSkipStartupCheck && (nLoadMenuShowY & AUTOEXPAND)) ) {
816 					nBurnDrvActive = nBurnDrv[j].nBurnDrvNo;
817 					if (BurnDrvGetTextA(DRV_PARENT)) {
818 						if (strcmp(nBurnDrv[i].pszROMName, BurnDrvGetTextA(DRV_PARENT)) == 0) {
819 							SendMessage(hSelList, TVM_EXPAND, TVE_EXPAND, (LPARAM)nBurnDrv[i].hTreeHandle);
820 							break;
821 						}
822 					}
823 				}
824 			}
825 		}
826 	}
827 
828 	// Update the status info
829 	TCHAR szRomsAvailableInfo[128] = _T("");
830 
831 	_stprintf(szRomsAvailableInfo, FBALoadStringEx(hAppInst, IDS_SEL_SETSTATUS, true), nTmpDrvCount, nBurnDrvCount - REDUCE_TOTAL_SETS_BIOS, nMissingDrvCount);
832 	SendDlgItemMessage(hSelDlg, IDC_DRVCOUNT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)szRomsAvailableInfo);
833 
834 	return 0;
835 }
836 
MyEndDialog()837 static void MyEndDialog()
838 {
839 	if (nTimer) {
840 		KillTimer(hSelDlg, nTimer);
841 		nTimer = 0;
842 	}
843 
844 	if (nInitPreviewTimer) {
845 		KillTimer(hSelDlg, nInitPreviewTimer);
846 		nInitPreviewTimer = 0;
847 	}
848 
849 	SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
850 	SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
851 
852 	SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT2_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
853 	SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT2_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
854 
855 	if (hPrevBmp) {
856 		DeleteObject((HGDIOBJ)hPrevBmp);
857 		hPrevBmp = NULL;
858 	}
859 	if(hTitleBmp) {
860 		DeleteObject((HGDIOBJ)hTitleBmp);
861 		hTitleBmp = NULL;
862 	}
863 
864 	if (hExpand) {
865 		DestroyIcon(hExpand);
866 		hExpand = NULL;
867 	}
868 	if (hCollapse) {
869 		DestroyIcon(hCollapse);
870 		hCollapse = NULL;
871 	}
872 	if (hNotWorking) {
873 		DestroyIcon(hNotWorking);
874 		hNotWorking = NULL;
875 	}
876 	if (hNotFoundEss) {
877 		DestroyIcon(hNotFoundEss);
878 		hNotFoundEss = NULL;
879 	}
880 	if (hNotFoundNonEss) {
881 		DestroyIcon(hNotFoundNonEss);
882 		hNotFoundNonEss = NULL;
883 	}
884 	if(hDrvIconMiss) {
885 		DestroyIcon(hDrvIconMiss);
886 		hDrvIconMiss = NULL;
887 	}
888 
889 	RECT rect;
890 
891 	GetClientRect(hSelDlg, &rect);
892 	nSelDlgWidth = rect.right;
893 	nSelDlgHeight = rect.bottom;
894 
895 	EndDialog(hSelDlg, 0);
896 }
897 
898 // User clicked ok for a driver in the list
SelOkay()899 static void SelOkay()
900 {
901 	TV_ITEM TvItem;
902 	unsigned int nSelect = 0;
903 	HTREEITEM hSelectHandle = (HTREEITEM)SendMessage(hSelList, TVM_GETNEXTITEM, TVGN_CARET, ~0U);
904 
905 	if (!hSelectHandle)	{			// Nothing is selected, return without closing the window
906 		return;
907 	}
908 
909 	TvItem.hItem = hSelectHandle;
910 	TvItem.mask = TVIF_PARAM;
911 	SendMessage(hSelList, TVM_GETITEM, 0, (LPARAM)&TvItem);
912 	nSelect = ((NODEINFO*)TvItem.lParam)->nBurnDrvNo;
913 
914 #if DISABLE_NON_AVAILABLE_SELECT
915 	if (!gameAv[nSelect]) {			// Game not available, return without closing the window
916 		return;
917 	}
918 #endif
919 
920 #if NON_WORKING_PROMPT_ON_LOAD
921 	if (!CheckWorkingStatus(nSelect)) {
922 		TCHAR szWarningText[1024];
923 		_stprintf(szWarningText, _T("%s"), FBALoadStringEx(hAppInst, IDS_ERR_WARNING, true));
924 		if (MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NON_WORKING, true), szWarningText, MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDNO) {
925 			return;
926 		}
927 	}
928 #endif
929 	nDialogSelect = nSelect;
930 
931 	bDialogCancel = false;
932 	MyEndDialog();
933 }
934 
RefreshPanel()935 static void RefreshPanel()
936 {
937 	// clear preview shot
938 	if (hPrevBmp) {
939 		DeleteObject((HGDIOBJ)hPrevBmp);
940 		hPrevBmp = NULL;
941 	}
942 	if (hTitleBmp) {
943 		DeleteObject((HGDIOBJ)hTitleBmp);
944 		hTitleBmp = NULL;
945 	}
946 	if (nTimer) {
947 		KillTimer(hSelDlg, nTimer);
948 		nTimer = 0;
949 	}
950 
951 
952 	hPrevBmp = PNGLoadBitmap(hSelDlg, NULL, 213, 160, 2);
953 	hTitleBmp = PNGLoadBitmap(hSelDlg, NULL, 213, 160, 2);
954 
955 	SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPrevBmp);
956 	SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
957 
958 	SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT2_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hTitleBmp);
959 	SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT2_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
960 
961 	// Clear the things in our Info-box
962 	for (int i = 0; i < 6; i++) {
963 		SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
964 		EnableWindow(hInfoLabel[i], FALSE);
965 	}
966 
967     CheckDlgButton(hSelDlg, IDC_CHECKAUTOEXPAND, (nLoadMenuShowY & AUTOEXPAND) ? BST_CHECKED : BST_UNCHECKED);
968 	CheckDlgButton(hSelDlg, IDC_CHECKAVAILABLE, (nLoadMenuShowY & AVAILABLE) ? BST_CHECKED : BST_UNCHECKED);
969 	CheckDlgButton(hSelDlg, IDC_CHECKUNAVAILABLE, (nLoadMenuShowY & UNAVAILABLE) ? BST_CHECKED : BST_UNCHECKED);
970 
971 	CheckDlgButton(hSelDlg, IDC_SEL_SHORTNAME, nLoadMenuShowY & SHOWSHORT ? BST_CHECKED : BST_UNCHECKED);
972 	CheckDlgButton(hSelDlg, IDC_SEL_ASCIIONLY, nLoadMenuShowY & ASCIIONLY ? BST_CHECKED : BST_UNCHECKED);
973 }
974 
OpenPreview(int nIndex,TCHAR * szPath)975 FILE* OpenPreview(int nIndex, TCHAR *szPath)
976 {
977 	static bool bTryParent;
978 
979 	TCHAR szBaseName[MAX_PATH];
980 	TCHAR szFileName[MAX_PATH];
981 
982 	FILE* fp = NULL;
983 
984 	// Try to load a .PNG preview image
985 	_sntprintf(szBaseName, sizeof(szBaseName), _T("%s%s"), szPath, BurnDrvGetText(DRV_NAME));
986 	if (nIndex <= 1) {
987 		_stprintf(szFileName, _T("%s.png"), szBaseName);
988 		fp = _tfopen(szFileName, _T("rb"));
989 	}
990 	if (!fp) {
991 		_stprintf(szFileName, _T("%s [%02i].png"), szBaseName, nIndex);
992 		fp = _tfopen(szFileName, _T("rb"));
993 	}
994 
995 	if (nIndex <= 1) {
996 		bTryParent = fp ? false : true;
997 	}
998 
999 	if (!fp && BurnDrvGetText(DRV_PARENT) && bTryParent) {						// Try the parent
1000 		_sntprintf(szBaseName, sizeof(szBaseName), _T("%s%s"), szPath, BurnDrvGetText(DRV_PARENT));
1001 		if (nIndex <= 1) {
1002 			_stprintf(szFileName, _T("%s.png"), szBaseName);
1003 			fp = _tfopen(szFileName, _T("rb"));
1004 		}
1005 		if (!fp) {
1006 			_stprintf(szFileName, _T("%s [%02i].png"), szBaseName, nIndex);
1007 			fp = _tfopen(szFileName, _T("rb"));
1008 		}
1009 	}
1010 
1011 	return fp;
1012 }
1013 
PreviewTimerProc(HWND,UINT,UINT_PTR,DWORD)1014 static VOID CALLBACK PreviewTimerProc(HWND, UINT, UINT_PTR, DWORD)
1015 {
1016 	UpdatePreview(false, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V);
1017 }
1018 
InitPreviewTimerProc(HWND,UINT,UINT_PTR,DWORD)1019 static VOID CALLBACK InitPreviewTimerProc(HWND, UINT, UINT_PTR, DWORD)
1020 {
1021 	UpdatePreview(true, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V);
1022 
1023 	if (GetIpsNumPatches()) {
1024 		if (!nShowMVSCartsOnly) EnableWindow(GetDlgItem(hSelDlg, IDC_SEL_IPSMANAGER), TRUE);
1025 	} else {
1026 		EnableWindow(GetDlgItem(hSelDlg, IDC_SEL_IPSMANAGER), FALSE);
1027 	}
1028 
1029 	LoadIpsActivePatches();
1030 	if (GetIpsNumActivePatches()) {
1031 		if (!nShowMVSCartsOnly) EnableWindow(GetDlgItem(hSelDlg, IDC_SEL_APPLYIPS), TRUE);
1032 	} else {
1033 		EnableWindow(GetDlgItem(hSelDlg, IDC_SEL_APPLYIPS), FALSE);
1034 	}
1035 
1036 	KillTimer(hSelDlg, nInitPreviewTimer);
1037 	nInitPreviewTimer = 0;
1038 }
1039 
UpdatePreview(bool bReset,TCHAR * szPath,int HorCtrl,int VerCtrl)1040 static int UpdatePreview(bool bReset, TCHAR *szPath, int HorCtrl, int VerCtrl)
1041 {
1042 	static int nIndex;
1043 	int nOldIndex = 0;
1044 
1045 	FILE* fp = NULL;
1046 	HBITMAP hNewImage = NULL;
1047 
1048 	if (HorCtrl == IDC_SCREENSHOT_H) {
1049 		nOldIndex = nIndex;
1050 		nIndex++;
1051 		if (bReset) {
1052 			nIndex = 1;
1053 			nOldIndex = -1;
1054 			if (nTimer) {
1055 				KillTimer(hSelDlg, 1);
1056 				nTimer = 0;
1057 			}
1058 		}
1059 	}
1060 
1061 	nBurnDrvActive = nDialogSelect;
1062 
1063 	if ((nIndex != nOldIndex) || (HorCtrl == IDC_SCREENSHOT2_H)) {
1064 		int x, y, ax, ay;
1065 
1066 		BurnDrvGetAspect(&ax, &ay);
1067 
1068 		// If a game uses pixel aspect ratio (aspect ratio == pixel size) default to 4:3
1069 		// for Titles and Previews (otherwise the pictures weirdly draw ontop of the UI)
1070 		if (!_tcsncmp(BurnDrvGetText(DRV_NAME), _T("wrally2"), 7) || ax > 100) {
1071 			ax = 4;
1072 			ay = 3;
1073 		}
1074 
1075 		//if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) {
1076 		if (ay > ax) {
1077 			bImageOrientation = TRUE;
1078 
1079 			y = 160;
1080 			x = y * ax / ay;
1081 		} else {
1082 			bImageOrientation = FALSE;
1083 
1084 			x = 213;
1085 			y = x * ay / ax;
1086 		}
1087 
1088 		if (HorCtrl == IDC_SCREENSHOT_H) {
1089 			fp = OpenPreview(nIndex, szPath);
1090 		} else {
1091 			fp = OpenPreview(0, szPath);
1092 		}
1093 		if (!fp && nIndex > 1 && HorCtrl == IDC_SCREENSHOT_H) {
1094 			if (nIndex == 2) {
1095 
1096 				// There's only a single preview image, stop timer
1097 
1098 				if (nTimer) {
1099 					KillTimer(hSelDlg, 1);
1100 					nTimer = 0;
1101 				}
1102 
1103 				return 0;
1104 			}
1105 
1106 			nIndex = 1;
1107 			fp = OpenPreview(nIndex, szPath);
1108 		}
1109 		if (fp) {
1110 			if (ax > 4) {
1111 				// Check if title/preview image is captured from 1 monitor on a
1112 				// multi-monitor game, then make the proper adjustments so it
1113 				// looks correct.
1114 				IMAGE img;
1115 				INT32 game_x, game_y;
1116 
1117 				PNGGetInfo(&img, fp);
1118 				rewind(fp);
1119 
1120 				BurnDrvGetFullSize(&game_x, &game_y);
1121 
1122 				if (img.width <= game_x / 2) {
1123 					ax = 4;
1124 					ay = 3;
1125 					x = 213;
1126 					y = x * ay / ax;
1127 				}
1128 			}
1129 			hNewImage = PNGLoadBitmap(hSelDlg, fp, x, y, 3);
1130 		}
1131 	}
1132 
1133 	if (fp) {
1134 		fclose(fp);
1135 
1136 		if (HorCtrl == IDC_SCREENSHOT_H) nTimer = SetTimer(hSelDlg, 1, 2500, PreviewTimerProc);
1137 	} else {
1138 
1139 		// We couldn't load a new image for this game, so kill the timer (it will be restarted when a new game is selected)
1140 
1141 		if (HorCtrl == IDC_SCREENSHOT_H) {
1142 			if (nTimer) {
1143 				KillTimer(hSelDlg, 1);
1144 				nTimer = 0;
1145 			}
1146 		}
1147 
1148 		bImageOrientation = FALSE;
1149 		hNewImage = PNGLoadBitmap(hSelDlg, NULL, 213, 160, 2);
1150 	}
1151 
1152 	if (hPrevBmp && (HorCtrl == IDC_SCREENSHOT_H || VerCtrl == IDC_SCREENSHOT_V)) {
1153 		DeleteObject((HGDIOBJ)hPrevBmp);
1154 		*&hPrevBmp = NULL;
1155 		hPrevBmp = hNewImage;
1156 	}
1157 
1158 	if (hTitleBmp && (HorCtrl == IDC_SCREENSHOT2_H || VerCtrl == IDC_SCREENSHOT2_V)) {
1159 		DeleteObject((HGDIOBJ)hTitleBmp);
1160 		*&hTitleBmp = NULL;
1161 		hTitleBmp = hNewImage;
1162 	}
1163 
1164 	if (bImageOrientation == 0) {
1165 		SendDlgItemMessage(hSelDlg, HorCtrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hNewImage);
1166 		SendDlgItemMessage(hSelDlg, VerCtrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
1167 		ShowWindow(GetDlgItem(hSelDlg, HorCtrl), SW_SHOW);
1168 		ShowWindow(GetDlgItem(hSelDlg, VerCtrl), SW_HIDE);
1169 	} else {
1170 		SendDlgItemMessage(hSelDlg, HorCtrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
1171 		SendDlgItemMessage(hSelDlg, VerCtrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hNewImage);
1172 		ShowWindow(GetDlgItem(hSelDlg, HorCtrl), SW_HIDE);
1173 		ShowWindow(GetDlgItem(hSelDlg, VerCtrl), SW_SHOW);
1174 	}
1175 
1176 	UpdateWindow(hSelDlg);
1177 
1178 	return 0;
1179 }
1180 
DoShellExThread(void * arg)1181 static unsigned __stdcall DoShellExThread(void *arg)
1182 {
1183 	ShellExecute(NULL, _T("open"), (TCHAR*)arg, NULL, NULL, SW_SHOWNORMAL);
1184 
1185 	return 0;
1186 }
1187 
ViewEmma()1188 static void ViewEmma()
1189 {
1190 	HANDLE hThread = NULL;
1191 	unsigned ThreadID = 0;
1192 	TCHAR szShellExURL[MAX_PATH];
1193 
1194 	_stprintf(szShellExURL, _T("http://adb.arcadeitalia.net/dettaglio_mame.php?game_name=%s"), BurnDrvGetText(DRV_NAME));
1195 
1196 	hThread = (HANDLE)_beginthreadex(NULL, 0, DoShellExThread, (void*)szShellExURL, 0, &ThreadID);
1197 	Sleep(150); // allow arguments to pass to ShellExecute() in new thread before they get disposed.
1198 }
1199 
RebuildEverything()1200 static void RebuildEverything()
1201 {
1202 	RefreshPanel();
1203 
1204 	bDrvSelected = false;
1205 
1206 	TreeBuilding = 1;
1207 	SendMessage(hSelList, WM_SETREDRAW, (WPARAM)FALSE,(LPARAM)TVI_ROOT);	// disable redraw
1208 	SendMessage(hSelList, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);				// Destory all nodes
1209 	SelListMake();
1210 	SendMessage(hSelList, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM)TVI_ROOT);	// enable redraw
1211 
1212 	// Clear the things in our Info-box
1213 	for (int i = 0; i < 6; i++) {
1214 		SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
1215 		EnableWindow(hInfoLabel[i], FALSE);
1216 	}
1217 
1218 	TreeBuilding = 0;
1219 }
1220 
TvhFilterToBitmask(HTREEITEM hHandle)1221 static int TvhFilterToBitmask(HTREEITEM hHandle)
1222 {
1223 	if (hHandle == hRoot)				return (1 << 0);
1224 	if (hHandle == hBoardType)			return (1 << 1);
1225 	if (hHandle == hFamily)				return (1 << 2);
1226 	if (hHandle == hGenre)				return (1 << 3);
1227 	if (hHandle == hHardware)			return (1 << 4);
1228 	if (hHandle == hFilterCapcomGrp)	return (1 << 5);
1229 	if (hHandle == hFilterSegaGrp)		return (1 << 6);
1230 
1231 	return 0;
1232 }
1233 
TvBitTohFilter(int nBit)1234 static HTREEITEM TvBitTohFilter(int nBit)
1235 {
1236 	switch (nBit) {
1237 		case (1 << 0): return hRoot;
1238 		case (1 << 1): return hBoardType;
1239 		case (1 << 2): return hFamily;
1240 		case (1 << 3): return hGenre;
1241 		case (1 << 4): return hHardware;
1242 		case (1 << 5): return hFilterCapcomGrp;
1243 		case (1 << 6): return hFilterSegaGrp;
1244 	}
1245 
1246 	return 0;
1247 }
1248 
1249 #define _TVCreateFiltersA(a, b, c, d)								\
1250 {																	\
1251 	TvItem.hParent = a;												\
1252 	TvItem.item.pszText = FBALoadStringEx(hAppInst, b, true);		\
1253 	c = TreeView_InsertItem(hFilterList, &TvItem);					\
1254 	_TreeView_SetCheckState(hFilterList, c, (d) ? FALSE : TRUE);	\
1255 }
1256 
1257 #define _TVCreateFiltersB(a, b, c)								\
1258 {																\
1259 	TvItem.hParent = a;												\
1260 	TvItem.item.pszText = FBALoadStringEx(hAppInst, b, true);		\
1261 	c = TreeView_InsertItem(hFilterList, &TvItem);					\
1262 }
1263 
1264 #define _TVCreateFiltersC(a, b, c, d)								\
1265 {																	\
1266 	TvItem.hParent = a;												\
1267 	TvItem.item.pszText = FBALoadStringEx(hAppInst, b, true);		\
1268 	c = TreeView_InsertItem(hFilterList, &TvItem);					\
1269 	_TreeView_SetCheckState(hFilterList, c, (d) ? FALSE : TRUE);	\
1270 }
1271 
1272 #define _TVCreateFiltersD(a, b, c, d)								\
1273 {																	\
1274 	TvItem.hParent = a;												\
1275 	TvItem.item.pszText = FBALoadStringEx(hAppInst, b, true);		\
1276 	c = TreeView_InsertItem(hFilterList, &TvItem);					\
1277 	_TreeView_SetCheckState(hFilterList, c, (d) ? FALSE : TRUE);	\
1278 }
1279 
CreateFilters()1280 static void CreateFilters()
1281 {
1282 	TV_INSERTSTRUCT TvItem;
1283 	memset(&TvItem, 0, sizeof(TvItem));
1284 
1285 	hFilterList			= GetDlgItem(hSelDlg, IDC_TREE2);
1286 
1287 	TvItem.item.mask	= TVIF_TEXT | TVIF_PARAM;
1288 	TvItem.hInsertAfter = TVI_LAST;
1289 
1290 	_TVCreateFiltersA(TVI_ROOT		, IDS_FAVORITES			, hFavorites            , !nLoadMenuFavoritesFilter                         );
1291 
1292 	_TVCreateFiltersB(TVI_ROOT		, IDS_SEL_FILTERS		, hRoot						);
1293 
1294 	_TVCreateFiltersC(hRoot			, IDS_SEL_BOARDTYPE		, hBoardType			, nLoadMenuBoardTypeFilter & MASKALLBOARD	);
1295 
1296 	_TVCreateFiltersA(hBoardType	, IDS_SEL_GENUINE		, hFilterGenuine		, nLoadMenuBoardTypeFilter & MASKBOARDTYPEGENUINE	);
1297 	_TVCreateFiltersA(hBoardType	, IDS_SEL_BOOTLEG		, hFilterBootleg		, nLoadMenuBoardTypeFilter & BDF_BOOTLEG			);
1298 	_TVCreateFiltersA(hBoardType	, IDS_SEL_DEMO			, hFilterDemo			, nLoadMenuBoardTypeFilter & BDF_DEMO				);
1299 	_TVCreateFiltersA(hBoardType	, IDS_SEL_HACK			, hFilterHack			, nLoadMenuBoardTypeFilter & BDF_HACK				);
1300 	_TVCreateFiltersA(hBoardType	, IDS_SEL_HOMEBREW		, hFilterHomebrew		, nLoadMenuBoardTypeFilter & BDF_HOMEBREW			);
1301 	_TVCreateFiltersA(hBoardType	, IDS_SEL_PROTOTYPE		, hFilterPrototype		, nLoadMenuBoardTypeFilter & BDF_PROTOTYPE			);
1302 
1303 	_TVCreateFiltersC(hRoot			, IDS_FAMILY			, hFamily				, nLoadMenuFamilyFilter & MASKALLFAMILY	);
1304 
1305 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_19XX		, hFilter19xx			, nLoadMenuFamilyFilter & FBF_19XX					);
1306 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_DONPACHI	, hFilterDonpachi		, nLoadMenuFamilyFilter & FBF_DONPACHI				);
1307 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_SONICWI	, hFilterSonicwi		, nLoadMenuFamilyFilter & FBF_SONICWI				);
1308 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_DSTLK		, hFilterDstlk			, nLoadMenuFamilyFilter & FBF_DSTLK					);
1309 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_FATFURY	, hFilterFatfury		, nLoadMenuFamilyFilter & FBF_FATFURY				);
1310 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_KOF		, hFilterKof			, nLoadMenuFamilyFilter & FBF_KOF					);
1311 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_MSLUG		, hFilterMslug			, nLoadMenuFamilyFilter & FBF_MSLUG					);
1312 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_MAHOU		, hFilterMahou			, nLoadMenuFamilyFilter & FBF_MAHOU					);
1313 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_PWRINST	, hFilterPwrinst		, nLoadMenuFamilyFilter & FBF_PWRINST				);
1314 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_SAMSHO		, hFilterSamsho			, nLoadMenuFamilyFilter & FBF_SAMSHO				);
1315 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_SONIC		, hFilterSonic			, nLoadMenuFamilyFilter & FBF_SONIC					);
1316 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_SF			, hFilterSf				, nLoadMenuFamilyFilter & FBF_SF					);
1317 	_TVCreateFiltersA(hFamily		, IDS_FAMILY_OTHER		, hFilterOtherFamily	, nLoadMenuFamilyFilter & MASKFAMILYOTHER			);
1318 
1319 	_TVCreateFiltersC(hRoot			, IDS_GENRE				, hGenre				, nLoadMenuGenreFilter & MASKALLGENRE	);
1320 
1321 	_TVCreateFiltersA(hGenre		, IDS_GENRE_ACTION		, hFilterAction			, nLoadMenuGenreFilter & GBF_ACTION					);
1322 	_TVCreateFiltersA(hGenre		, IDS_GENRE_BALLPADDLE	, hFilterBallpaddle		, nLoadMenuGenreFilter & GBF_BALLPADDLE				);
1323 	_TVCreateFiltersA(hGenre		, IDS_GENRE_BREAKOUT	, hFilterBreakout		, nLoadMenuGenreFilter & GBF_BREAKOUT				);
1324 	_TVCreateFiltersA(hGenre		, IDS_GENRE_CASINO		, hFilterCasino			, nLoadMenuGenreFilter & GBF_CASINO					);
1325 	_TVCreateFiltersA(hGenre		, IDS_GENRE_SCRFIGHT	, hFilterScrfight		, nLoadMenuGenreFilter & GBF_SCRFIGHT				);
1326 	_TVCreateFiltersA(hGenre		, IDS_GENRE_VSFIGHT		, hFilterVsfight		, nLoadMenuGenreFilter & GBF_VSFIGHT				);
1327 	_TVCreateFiltersA(hGenre		, IDS_GENRE_MAHJONG		, hFilterMahjong		, nLoadMenuGenreFilter & GBF_MAHJONG				);
1328 	_TVCreateFiltersA(hGenre		, IDS_GENRE_MAZE		, hFilterMaze			, nLoadMenuGenreFilter & GBF_MAZE					);
1329 	_TVCreateFiltersA(hGenre		, IDS_GENRE_MINIGAMES	, hFilterMinigames		, nLoadMenuGenreFilter & GBF_MINIGAMES				);
1330 	_TVCreateFiltersA(hGenre		, IDS_GENRE_MISC		, hFilterMisc			, nLoadMenuGenreFilter & GBF_MISC					);
1331 	_TVCreateFiltersA(hGenre		, IDS_GENRE_PINBALL		, hFilterPinball		, nLoadMenuGenreFilter & GBF_PINBALL				);
1332 	_TVCreateFiltersA(hGenre		, IDS_GENRE_PLATFORM	, hFilterPlatform		, nLoadMenuGenreFilter & GBF_PLATFORM				);
1333 	_TVCreateFiltersA(hGenre		, IDS_GENRE_PUZZLE		, hFilterPuzzle			, nLoadMenuGenreFilter & GBF_PUZZLE					);
1334 	_TVCreateFiltersA(hGenre		, IDS_GENRE_QUIZ		, hFilterQuiz			, nLoadMenuGenreFilter & GBF_QUIZ					);
1335 	_TVCreateFiltersA(hGenre		, IDS_GENRE_RACING		, hFilterRacing			, nLoadMenuGenreFilter & GBF_RACING					);
1336 	_TVCreateFiltersA(hGenre		, IDS_GENRE_RUNGUN		, hFilterRungun			, nLoadMenuGenreFilter & GBF_RUNGUN 				);
1337 	_TVCreateFiltersA(hGenre		, IDS_GENRE_SHOOT		, hFilterShoot			, nLoadMenuGenreFilter & GBF_SHOOT					);
1338 	_TVCreateFiltersA(hGenre		, IDS_GENRE_HORSHOOT	, hFilterHorshoot		, nLoadMenuGenreFilter & GBF_HORSHOOT				);
1339 	_TVCreateFiltersA(hGenre		, IDS_GENRE_VERSHOOT	, hFilterVershoot		, nLoadMenuGenreFilter & GBF_VERSHOOT				);
1340 	_TVCreateFiltersA(hGenre		, IDS_GENRE_SPORTSMISC	, hFilterSportsmisc		, nLoadMenuGenreFilter & GBF_SPORTSMISC				);
1341 	_TVCreateFiltersA(hGenre		, IDS_GENRE_SPORTSFOOTBALL, hFilterSportsfootball, nLoadMenuGenreFilter & GBF_SPORTSFOOTBALL		);
1342 	_TVCreateFiltersA(hGenre		, IDS_GENRE_STRATEGY	, hFilterStrategy   	, nLoadMenuGenreFilter & GBF_STRATEGY   			);
1343 	_TVCreateFiltersA(hGenre		, IDS_GENRE_RPG			, hFilterRpg   			, nLoadMenuGenreFilter & GBF_RPG   					);
1344 	_TVCreateFiltersA(hGenre		, IDS_GENRE_SIM			, hFilterSim   			, nLoadMenuGenreFilter & GBF_SIM   					);
1345 	_TVCreateFiltersA(hGenre		, IDS_GENRE_ADV			, hFilterAdv   			, nLoadMenuGenreFilter & GBF_ADV   					);
1346 	_TVCreateFiltersA(hGenre		, IDS_GENRE_BIOS		, hFilterBios			, nLoadMenuGenreFilter & GBF_BIOS					);
1347 
1348 	_TVCreateFiltersC(hRoot			, IDS_SEL_HARDWARE		, hHardware				, nLoadMenuShowX & MASKALL					);
1349 
1350 	_TVCreateFiltersD(hHardware		, IDS_SEL_CAPCOM_GRP	, hFilterCapcomGrp			, nLoadMenuShowX & MASKCAPGRP				);
1351 
1352 	_TVCreateFiltersA(hFilterCapcomGrp	, IDS_SEL_CPS1			, hFilterCps1			, nLoadMenuShowX & MASKCPS							);
1353 	_TVCreateFiltersA(hFilterCapcomGrp	, IDS_SEL_CPS2			, hFilterCps2			, nLoadMenuShowX & MASKCPS2							);
1354 	_TVCreateFiltersA(hFilterCapcomGrp	, IDS_SEL_CPS3			, hFilterCps3			, nLoadMenuShowX & MASKCPS3							);
1355 	_TVCreateFiltersA(hFilterCapcomGrp	, IDS_SEL_CAPCOM_MISC	, hFilterCapcomMisc		, nLoadMenuShowX & MASKCAPMISC						);
1356 
1357 	_TVCreateFiltersA(hHardware		, IDS_SEL_CAVE			, hFilterCave			, nLoadMenuShowX & MASKCAVE							);
1358 	_TVCreateFiltersA(hHardware		, IDS_SEL_DATAEAST		, hFilterDataeast		, nLoadMenuShowX & MASKDATAEAST						);
1359 	_TVCreateFiltersA(hHardware		, IDS_SEL_GALAXIAN		, hFilterGalaxian		, nLoadMenuShowX & MASKGALAXIAN						);
1360 	_TVCreateFiltersA(hHardware		, IDS_SEL_IREM			, hFilterIrem			, nLoadMenuShowX & MASKIREM							);
1361 	_TVCreateFiltersA(hHardware		, IDS_SEL_KANEKO		, hFilterKaneko			, nLoadMenuShowX & MASKKANEKO						);
1362 	_TVCreateFiltersA(hHardware		, IDS_SEL_KONAMI		, hFilterKonami			, nLoadMenuShowX & MASKKONAMI						);
1363 	_TVCreateFiltersA(hHardware		, IDS_SEL_MIDWAY		, hFilterMidway			, nLoadMenuShowX & MASKMIDWAY						);
1364 	_TVCreateFiltersA(hHardware		, IDS_SEL_NEOGEO		, hFilterNeogeo			, nLoadMenuShowX & MASKNEOGEO						);
1365 	_TVCreateFiltersA(hHardware		, IDS_SEL_PACMAN		, hFilterPacman			, nLoadMenuShowX & MASKPACMAN						);
1366 	_TVCreateFiltersA(hHardware		, IDS_SEL_PGM			, hFilterPgm			, nLoadMenuShowX & MASKPGM							);
1367 	_TVCreateFiltersA(hHardware		, IDS_SEL_PSIKYO		, hFilterPsikyo			, nLoadMenuShowX & MASKPSIKYO						);
1368 
1369 	_TVCreateFiltersD(hHardware		, IDS_SEL_SEGA_GRP		, hFilterSegaGrp				, nLoadMenuShowX & MASKSEGAGRP				);
1370 
1371 	_TVCreateFiltersA(hFilterSegaGrp	, IDS_SEL_SG1000		, hFilterSg1000			, nLoadMenuShowX & MASKSG1000						);
1372 	_TVCreateFiltersA(hFilterSegaGrp	, IDS_SEL_SMS			, hFilterSms			, nLoadMenuShowX & MASKSMS							);
1373 	_TVCreateFiltersA(hFilterSegaGrp	, IDS_SEL_MEGADRIVE		, hFilterMegadrive		, nLoadMenuShowX & MASKMEGADRIVE					);
1374 	_TVCreateFiltersA(hFilterSegaGrp	, IDS_SEL_GG			, hFilterGg				, nLoadMenuShowX & MASKGG							);
1375 	_TVCreateFiltersA(hFilterSegaGrp	, IDS_SEL_SEGA			, hFilterSega			, nLoadMenuShowX & MASKSEGA							);
1376 
1377 	_TVCreateFiltersA(hHardware		, IDS_SEL_SETA			, hFilterSeta			, nLoadMenuShowX & MASKSETA							);
1378 	_TVCreateFiltersA(hHardware		, IDS_SEL_TAITO			, hFilterTaito			, nLoadMenuShowX & MASKTAITO						);
1379 	_TVCreateFiltersA(hHardware		, IDS_SEL_TECHNOS		, hFilterTechnos		, nLoadMenuShowX & MASKTECHNOS						);
1380 	_TVCreateFiltersA(hHardware		, IDS_SEL_TOAPLAN		, hFilterToaplan		, nLoadMenuShowX & MASKTOAPLAN						);
1381 	_TVCreateFiltersA(hHardware		, IDS_SEL_PCE			, hFilterPce			, nLoadMenuShowX & MASKPCENGINE						);
1382 	_TVCreateFiltersA(hHardware		, IDS_SEL_COLECO		, hFilterColeco			, nLoadMenuShowX & MASKCOLECO						);
1383 	_TVCreateFiltersA(hHardware		, IDS_SEL_MSX			, hFilterMsx			, nLoadMenuShowX & MASKMSX							);
1384 	_TVCreateFiltersA(hHardware		, IDS_SEL_SPECTRUM		, hFilterSpectrum		, nLoadMenuShowX & MASKSPECTRUM						);
1385 	_TVCreateFiltersA(hHardware		, IDS_SEL_NES			, hFilterNes			, nLoadMenuShowX & MASKNES							);
1386 	_TVCreateFiltersA(hHardware		, IDS_SEL_FDS			, hFilterFds			, nLoadMenuShowX & MASKFDS							);
1387 	_TVCreateFiltersA(hHardware		, IDS_SEL_NGP			, hFilterNgp			, nLoadMenuShowX & MASKNGP							);
1388 	_TVCreateFiltersA(hHardware		, IDS_SEL_CHANNELF		, hFilterChannelF		, nLoadMenuShowX & MASKCHANNELF						);
1389 	_TVCreateFiltersA(hHardware		, IDS_SEL_MISCPRE90S	, hFilterMiscPre90s		, nLoadMenuShowX & MASKMISCPRE90S					);
1390 	_TVCreateFiltersA(hHardware		, IDS_SEL_MISCPOST90S	, hFilterMiscPost90s	, nLoadMenuShowX & MASKMISCPOST90S					);
1391 
1392 	// restore expanded filter nodes
1393 	for (INT32 i = 0; i < 16; i++)
1394 	{
1395 		if (nLoadMenuExpand & (1 << i))
1396 			SendMessage(hFilterList, TVM_EXPAND, TVE_EXPAND, (LPARAM)TvBitTohFilter(1 << i));
1397 	}
1398 	//SendMessage(hFilterList	, TVM_EXPAND,TVE_EXPAND, (LPARAM)hRoot);
1399 	//SendMessage(hFilterList	, TVM_EXPAND,TVE_EXPAND, (LPARAM)hHardware);
1400 	//SendMessage(hFilterList	, TVM_EXPAND,TVE_EXPAND, (LPARAM)hFavorites);
1401 	TreeView_SelectSetFirstVisible(hFilterList, hFavorites);
1402 }
1403 
1404 #define ICON_MAXCONSOLES 12
1405 
1406 enum {
1407 	ICON_MEGADRIVE = 0,
1408 	ICON_PCEFAM = 1,
1409 	ICON_SG1000 = 2,
1410 	ICON_COLECO = 3,
1411 	ICON_SMS = 4,
1412 	ICON_GG = 5,
1413 	ICON_MSX = 6,
1414 	ICON_SPECTRUM = 7,
1415 	ICON_NES = 8,
1416 	ICON_FDS = 9,
1417 	ICON_NGP = 10,
1418 	ICON_CHANNELF = 11
1419 };
1420 
1421 static HICON hConsDrvIcon[ICON_MAXCONSOLES];
1422 
LoadDrvIcons()1423 void LoadDrvIcons()
1424 {
1425 	TCHAR szIcon[MAX_PATH];
1426 
1427 	if(nIconsSize == ICON_16x16) {
1428 		nIconsSizeXY	= 16;
1429 		nIconsYDiff		= 4;
1430 	}
1431 	if(nIconsSize == ICON_24x24) {
1432 		nIconsSizeXY	= 24;
1433 		nIconsYDiff		= 8;
1434 	}
1435 	if(nIconsSize == ICON_32x32) {
1436 		nIconsSizeXY	= 32;
1437 		nIconsYDiff		= 12;
1438 	}
1439 
1440 	{ // load default console images
1441 		_stprintf(szIcon, _T("%smegadrive_icon.ico"), szAppIconsPath);
1442 		hConsDrvIcon[ICON_MEGADRIVE] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1443 
1444 		_stprintf(szIcon, _T("%spce_icon.ico"), szAppIconsPath);
1445 		hConsDrvIcon[ICON_PCEFAM] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1446 
1447 		_stprintf(szIcon, _T("%ssg1000_icon.ico"), szAppIconsPath);
1448 		hConsDrvIcon[ICON_SG1000] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1449 
1450 		_stprintf(szIcon, _T("%scolecovision_icon.ico"), szAppIconsPath);
1451 		hConsDrvIcon[ICON_COLECO] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1452 
1453 		_stprintf(szIcon, _T("%ssms_icon.ico"), szAppIconsPath);
1454 		hConsDrvIcon[ICON_SMS] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1455 
1456 		_stprintf(szIcon, _T("%sgamegear_icon.ico"), szAppIconsPath);
1457 		hConsDrvIcon[ICON_GG] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1458 
1459 		_stprintf(szIcon, _T("%smsx_icon.ico"), szAppIconsPath);
1460 		hConsDrvIcon[ICON_MSX] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1461 
1462 		_stprintf(szIcon, _T("%sspectrum_icon.ico"), szAppIconsPath);
1463 		hConsDrvIcon[ICON_SPECTRUM] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1464 
1465 		_stprintf(szIcon, _T("%snes_icon.ico"), szAppIconsPath);
1466 		hConsDrvIcon[ICON_NES] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1467 
1468 		_stprintf(szIcon, _T("%sfds_icon.ico"), szAppIconsPath);
1469 		hConsDrvIcon[ICON_FDS] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1470 
1471 		_stprintf(szIcon, _T("%sngp_icon.ico"), szAppIconsPath);
1472 		hConsDrvIcon[ICON_NGP] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1473 
1474 		_stprintf(szIcon, _T("%schannelf_icon.ico"), szAppIconsPath);
1475 		hConsDrvIcon[ICON_CHANNELF] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1476 	}
1477 
1478 	unsigned int nOldDrvSel = nBurnDrvActive;
1479 
1480 	for(unsigned int nDrvIndex = 0; nDrvIndex < nBurnDrvCount; nDrvIndex++)
1481 	{
1482 		nBurnDrvActive = nDrvIndex;
1483 #if 0
1484 		if ((((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE)
1485 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_PCENGINE)
1486 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_TG16)
1487 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_SGX)
1488 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SG1000)
1489 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_COLECO)
1490 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MASTER_SYSTEM)
1491 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_GAME_GEAR)
1492 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_MSX)
1493 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SPECTRUM)
1494 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_NES)
1495 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_FDS)
1496 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NGP)
1497 			 || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_CHANNELF)
1498 			)) {
1499 			continue; // Skip everything but arcade
1500 		}
1501 #endif
1502 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE) {
1503 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_MEGADRIVE];
1504 			continue;
1505 		}
1506 
1507 		if (((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_PCENGINE) ||
1508 			((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_TG16) ||
1509 			((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_PCENGINE_SGX)) {
1510 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_PCEFAM];
1511 			continue;
1512 		}
1513 
1514 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SG1000) {
1515 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_SG1000];
1516 			continue;
1517 		}
1518 
1519 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_COLECO) {
1520 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_COLECO];
1521 			continue;
1522 		}
1523 
1524 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MASTER_SYSTEM) {
1525 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_SMS];
1526 			continue;
1527 		}
1528 
1529 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_GAME_GEAR) {
1530 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_GG];
1531 			continue;
1532 		}
1533 
1534 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_MSX) {
1535 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_MSX];
1536 			continue;
1537 		}
1538 
1539 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SPECTRUM) {
1540 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_SPECTRUM];
1541 			continue;
1542 		}
1543 
1544 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_NES) {
1545 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_NES];
1546 			continue;
1547 		}
1548 
1549 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_FDS) {
1550 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_FDS];
1551 			continue;
1552 		}
1553 
1554 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NGP) {
1555 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_NGP];
1556 			continue;
1557 		}
1558 
1559 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_CHANNELF) {
1560 			hDrvIcon[nDrvIndex] = hConsDrvIcon[ICON_CHANNELF];
1561 			continue;
1562 		}
1563 
1564 		if (bIconsOnlyParents && BurnDrvGetText(DRV_PARENT) != NULL && (BurnDrvGetFlags() & BDF_CLONE)) {	// Skip clones
1565 			continue;
1566 		}
1567 
1568 		_stprintf(szIcon, _T("%s%s.ico"), szAppIconsPath, BurnDrvGetText(DRV_NAME));
1569 		hDrvIcon[nDrvIndex] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1570 
1571 		if(!hDrvIcon[nDrvIndex] && BurnDrvGetText(DRV_PARENT)) {
1572 			_stprintf(szIcon, _T("%s%s.ico"), szAppIconsPath, BurnDrvGetText(DRV_PARENT));
1573 			hDrvIcon[nDrvIndex] = (HICON)LoadImage(hAppInst, szIcon, IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_LOADFROMFILE);
1574 		}
1575 	}
1576 
1577 	nBurnDrvActive = nOldDrvSel;
1578 }
1579 
UnloadDrvIcons()1580 void UnloadDrvIcons() {
1581 
1582 	nIconsSizeXY	= 16;
1583 	nIconsYDiff		= 4;
1584 
1585 	for(unsigned int nDrvIndex = 0; nDrvIndex < nBurnDrvCount; nDrvIndex++)
1586 	{
1587 		DestroyIcon(hDrvIcon[nDrvIndex]);
1588 		hDrvIcon[nDrvIndex] = NULL;
1589 	}
1590 }
1591 
1592 #define UM_CHECKSTATECHANGE (WM_USER + 100)
1593 #define UM_CLOSE			(WM_USER + 101)
1594 
1595 #define _ToggleGameListing(nShowX, nMASK)													\
1596 {																							\
1597 	nShowX ^= nMASK;																		\
1598 	_TreeView_SetCheckState(hFilterList, hItemChanged, (nShowX & nMASK) ? FALSE : TRUE);	\
1599 }
1600 
DialogProc(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM lParam)1601 static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
1602 {
1603 	if (Msg == WM_INITDIALOG) {
1604 
1605 		InitCommonControls();
1606 
1607 		hSelDlg = hDlg;
1608 
1609 		// add WS_MAXIMIZEBOX button;
1610 		SetWindowLongPtr(hSelDlg, GWL_STYLE, GetWindowLongPtr(hSelDlg, GWL_STYLE) | WS_MAXIMIZEBOX);
1611 
1612 		SendDlgItemMessage(hDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
1613 		SendDlgItemMessage(hDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
1614 
1615 		SendDlgItemMessage(hDlg, IDC_SCREENSHOT2_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
1616 		SendDlgItemMessage(hDlg, IDC_SCREENSHOT2_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
1617 
1618 		hWhiteBGBrush	= CreateSolidBrush(RGB(0xFF,0xFF,0xFF));
1619 
1620 		hExpand			= (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_PLUS),			IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1621 		hCollapse		= (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_MINUS),			IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1622 
1623 		hNotWorking		= (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_NOTWORKING),	IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_DEFAULTCOLOR);
1624 		hNotFoundEss	= (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_NOTFOUND_ESS),	IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_DEFAULTCOLOR);
1625 		hNotFoundNonEss = (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_NOTFOUND_NON),	IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_DEFAULTCOLOR);
1626 
1627 		hDrvIconMiss	= (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_APP),	IMAGE_ICON, nIconsSizeXY, nIconsSizeXY, LR_DEFAULTCOLOR);
1628 
1629 		TCHAR szOldTitle[1024] = _T(""), szNewTitle[1024] = _T("");
1630 		GetWindowText(hSelDlg, szOldTitle, 1024);
1631 		_sntprintf(szNewTitle, 1024, _T(APP_TITLE) _T(SEPERATOR_1) _T("%s"), szOldTitle);
1632 		SetWindowText(hSelDlg, szNewTitle);
1633 
1634 		hSelList		= GetDlgItem(hSelDlg, IDC_TREE1);
1635 
1636 		hInfoLabel[0]	= GetDlgItem(hSelDlg, IDC_LABELROMNAME);
1637 		hInfoLabel[1]	= GetDlgItem(hSelDlg, IDC_LABELROMINFO);
1638 		hInfoLabel[2]	= GetDlgItem(hSelDlg, IDC_LABELSYSTEM);
1639 		hInfoLabel[3]	= GetDlgItem(hSelDlg, IDC_LABELCOMMENT);
1640 		hInfoLabel[4]	= GetDlgItem(hSelDlg, IDC_LABELNOTES);
1641 		hInfoLabel[5]	= GetDlgItem(hSelDlg, IDC_LABELGENRE);
1642 		hInfoText[0]	= GetDlgItem(hSelDlg, IDC_TEXTROMNAME);
1643 		hInfoText[1]	= GetDlgItem(hSelDlg, IDC_TEXTROMINFO);
1644 		hInfoText[2]	= GetDlgItem(hSelDlg, IDC_TEXTSYSTEM);
1645 		hInfoText[3]	= GetDlgItem(hSelDlg, IDC_TEXTCOMMENT);
1646 		hInfoText[4]	= GetDlgItem(hSelDlg, IDC_TEXTNOTES);
1647 		hInfoText[5]	= GetDlgItem(hSelDlg, IDC_TEXTGENRE);
1648 
1649 #if !defined _UNICODE
1650 		EnableWindow(GetDlgItem(hDlg, IDC_SEL_ASCIIONLY), FALSE);
1651 #endif
1652 
1653 		bSearchStringInit = true; // so we don't set off the search timer during init w/SetDlgItemText() below
1654 		SetDlgItemText(hSelDlg, IDC_SEL_SEARCH, szSearchString); // Re-populate the search text
1655 
1656 		bool bFoundROMs = false;
1657 		for (unsigned int i = 0; i < nBurnDrvCount; i++) {
1658 			if (gameAv[i]) {
1659 				bFoundROMs = true;
1660 				break;
1661 			}
1662 		}
1663 		if (!bFoundROMs && bSkipStartupCheck == false) {
1664 			RomsDirCreate(hSelDlg);
1665 		}
1666 
1667 		// Icons size related -----------------------------------------
1668 		SHORT cyItem = nIconsSizeXY + 4;								// height (in pixels) of each item on the TreeView list
1669 		TreeView_SetItemHeight(hSelList, cyItem);
1670 
1671 		SetFocus(hSelList);
1672 
1673 		RebuildEverything();
1674 
1675 		TreeView_SetItemHeight(hSelList, cyItem);
1676 
1677 		if (nDialogSelect == -1) nDialogSelect = nOldDlgSelected;
1678 		if (nDialogSelect > -1) {
1679 			for (unsigned int i = 0; i < nTmpDrvCount; i++) {
1680 				if (nBurnDrv[i].nBurnDrvNo == nDialogSelect) {
1681 					nBurnDrvActive	= nBurnDrv[i].nBurnDrvNo;
1682 					TreeView_EnsureVisible(hSelList, nBurnDrv[i].hTreeHandle);
1683 					TreeView_Select(hSelList, nBurnDrv[i].hTreeHandle, TVGN_CARET);
1684 					TreeView_SelectSetFirstVisible(hSelList, nBurnDrv[i].hTreeHandle);
1685 					break;
1686 				}
1687 			}
1688 
1689 			// hack to load the preview image after a delay
1690 			nInitPreviewTimer = SetTimer(hSelDlg, 1, 20, InitPreviewTimerProc);
1691 		}
1692 
1693 		LONG_PTR Style;
1694 		Style = GetWindowLongPtr (GetDlgItem(hSelDlg, IDC_TREE2), GWL_STYLE);
1695 		Style |= TVS_CHECKBOXES;
1696 		SetWindowLongPtr (GetDlgItem(hSelDlg, IDC_TREE2), GWL_STYLE, Style);
1697 
1698 		CreateFilters();
1699 
1700 		EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), FALSE);
1701 		EnableWindow(GetDlgItem(hDlg, IDC_SEL_IPSMANAGER), FALSE);
1702 		bDoIpsPatch = FALSE;
1703 		IpsPatchExit();
1704 
1705 		WndInMid(hDlg, hParent);
1706 
1707 		HICON hIcon = LoadIcon(hAppInst, MAKEINTRESOURCE(IDI_APP));
1708 		SendMessage(hSelDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);		// Set the Game Selection dialog icon.
1709 
1710 		GetInitialPositions();
1711 
1712 		SetWindowPos(hDlg, NULL, 0, 0, nSelDlgWidth, nSelDlgHeight, SWP_NOZORDER);
1713 
1714 		WndInMid(hDlg, hParent);
1715 
1716 		return TRUE;
1717 	}
1718 
1719 	if(Msg == UM_CHECKSTATECHANGE) {
1720 
1721 		HTREEITEM   hItemChanged = (HTREEITEM)lParam;
1722 
1723 		if (hItemChanged == hHardware) {
1724 			if ((nLoadMenuShowX & MASKALL) == 0) {
1725 				_TreeView_SetCheckState(hFilterList, hItemChanged, FALSE);
1726 
1727 				_TreeView_SetCheckState(hFilterList, hFilterSegaGrp, FALSE);
1728 				_TreeView_SetCheckState(hFilterList, hFilterCapcomGrp, FALSE);
1729 				_TreeView_SetCheckState(hFilterList, hFilterCapcomMisc, FALSE);
1730 				_TreeView_SetCheckState(hFilterList, hFilterCave, FALSE);
1731 				_TreeView_SetCheckState(hFilterList, hFilterCps1, FALSE);
1732 				_TreeView_SetCheckState(hFilterList, hFilterCps2, FALSE);
1733 				_TreeView_SetCheckState(hFilterList, hFilterCps3, FALSE);
1734 				_TreeView_SetCheckState(hFilterList, hFilterDataeast, FALSE);
1735 				_TreeView_SetCheckState(hFilterList, hFilterGalaxian, FALSE);
1736 				_TreeView_SetCheckState(hFilterList, hFilterIrem, FALSE);
1737 				_TreeView_SetCheckState(hFilterList, hFilterKaneko, FALSE);
1738 				_TreeView_SetCheckState(hFilterList, hFilterKonami, FALSE);
1739 				_TreeView_SetCheckState(hFilterList, hFilterNeogeo, FALSE);
1740 				_TreeView_SetCheckState(hFilterList, hFilterPacman, FALSE);
1741 				_TreeView_SetCheckState(hFilterList, hFilterPgm, FALSE);
1742 				_TreeView_SetCheckState(hFilterList, hFilterPsikyo, FALSE);
1743 				_TreeView_SetCheckState(hFilterList, hFilterSega, FALSE);
1744 				_TreeView_SetCheckState(hFilterList, hFilterSeta, FALSE);
1745 				_TreeView_SetCheckState(hFilterList, hFilterTaito, FALSE);
1746 				_TreeView_SetCheckState(hFilterList, hFilterTechnos, FALSE);
1747 				_TreeView_SetCheckState(hFilterList, hFilterToaplan, FALSE);
1748 				_TreeView_SetCheckState(hFilterList, hFilterMiscPre90s, FALSE);
1749 				_TreeView_SetCheckState(hFilterList, hFilterMiscPost90s, FALSE);
1750 				_TreeView_SetCheckState(hFilterList, hFilterMegadrive, FALSE);
1751 				_TreeView_SetCheckState(hFilterList, hFilterPce, FALSE);
1752 				_TreeView_SetCheckState(hFilterList, hFilterSms, FALSE);
1753 				_TreeView_SetCheckState(hFilterList, hFilterGg, FALSE);
1754 				_TreeView_SetCheckState(hFilterList, hFilterSg1000, FALSE);
1755 				_TreeView_SetCheckState(hFilterList, hFilterColeco, FALSE);
1756 				_TreeView_SetCheckState(hFilterList, hFilterMsx, FALSE);
1757 				_TreeView_SetCheckState(hFilterList, hFilterSpectrum, FALSE);
1758 				_TreeView_SetCheckState(hFilterList, hFilterNes, FALSE);
1759 				_TreeView_SetCheckState(hFilterList, hFilterFds, FALSE);
1760 				_TreeView_SetCheckState(hFilterList, hFilterNgp, FALSE);
1761 				_TreeView_SetCheckState(hFilterList, hFilterChannelF, FALSE);
1762 				_TreeView_SetCheckState(hFilterList, hFilterMidway, FALSE);
1763 
1764 				nLoadMenuShowX |= MASKALL;
1765 			} else {
1766 				_TreeView_SetCheckState(hFilterList, hItemChanged, TRUE);
1767 
1768 				_TreeView_SetCheckState(hFilterList, hFilterSegaGrp, TRUE);
1769 				_TreeView_SetCheckState(hFilterList, hFilterCapcomGrp, TRUE);
1770 				_TreeView_SetCheckState(hFilterList, hFilterCapcomMisc, TRUE);
1771 				_TreeView_SetCheckState(hFilterList, hFilterCave, TRUE);
1772 				_TreeView_SetCheckState(hFilterList, hFilterCps1, TRUE);
1773 				_TreeView_SetCheckState(hFilterList, hFilterCps2, TRUE);
1774 				_TreeView_SetCheckState(hFilterList, hFilterCps3, TRUE);
1775 				_TreeView_SetCheckState(hFilterList, hFilterDataeast, TRUE);
1776 				_TreeView_SetCheckState(hFilterList, hFilterGalaxian, TRUE);
1777 				_TreeView_SetCheckState(hFilterList, hFilterIrem, TRUE);
1778 				_TreeView_SetCheckState(hFilterList, hFilterKaneko, TRUE);
1779 				_TreeView_SetCheckState(hFilterList, hFilterKonami, TRUE);
1780 				_TreeView_SetCheckState(hFilterList, hFilterNeogeo, TRUE);
1781 				_TreeView_SetCheckState(hFilterList, hFilterPacman, TRUE);
1782 				_TreeView_SetCheckState(hFilterList, hFilterPgm, TRUE);
1783 				_TreeView_SetCheckState(hFilterList, hFilterPsikyo, TRUE);
1784 				_TreeView_SetCheckState(hFilterList, hFilterSega, TRUE);
1785 				_TreeView_SetCheckState(hFilterList, hFilterSeta, TRUE);
1786 				_TreeView_SetCheckState(hFilterList, hFilterTaito, TRUE);
1787 				_TreeView_SetCheckState(hFilterList, hFilterTechnos, TRUE);
1788 				_TreeView_SetCheckState(hFilterList, hFilterToaplan, TRUE);
1789 				_TreeView_SetCheckState(hFilterList, hFilterMiscPre90s, TRUE);
1790 				_TreeView_SetCheckState(hFilterList, hFilterMiscPost90s, TRUE);
1791 				_TreeView_SetCheckState(hFilterList, hFilterMegadrive, TRUE);
1792 				_TreeView_SetCheckState(hFilterList, hFilterPce, TRUE);
1793 				_TreeView_SetCheckState(hFilterList, hFilterSms, TRUE);
1794 				_TreeView_SetCheckState(hFilterList, hFilterGg, TRUE);
1795 				_TreeView_SetCheckState(hFilterList, hFilterSg1000, TRUE);
1796 				_TreeView_SetCheckState(hFilterList, hFilterColeco, TRUE);
1797 				_TreeView_SetCheckState(hFilterList, hFilterMsx, TRUE);
1798 				_TreeView_SetCheckState(hFilterList, hFilterSpectrum, TRUE);
1799 				_TreeView_SetCheckState(hFilterList, hFilterNes, TRUE);
1800 				_TreeView_SetCheckState(hFilterList, hFilterFds, TRUE);
1801 				_TreeView_SetCheckState(hFilterList, hFilterNgp, TRUE);
1802 				_TreeView_SetCheckState(hFilterList, hFilterChannelF, TRUE);
1803 				_TreeView_SetCheckState(hFilterList, hFilterMidway, TRUE);
1804 
1805 				nLoadMenuShowX &= ~MASKALL; //0xf8000000; make this dynamic for future hardware additions -dink
1806 			}
1807 		}
1808 
1809 		if (hItemChanged == hBoardType) {
1810 			if ((nLoadMenuBoardTypeFilter & MASKALLBOARD) == 0) {
1811 				_TreeView_SetCheckState(hFilterList, hItemChanged, FALSE);
1812 
1813 				_TreeView_SetCheckState(hFilterList, hFilterBootleg, FALSE);
1814 				_TreeView_SetCheckState(hFilterList, hFilterDemo, FALSE);
1815 				_TreeView_SetCheckState(hFilterList, hFilterHack, FALSE);
1816 				_TreeView_SetCheckState(hFilterList, hFilterHomebrew, FALSE);
1817 				_TreeView_SetCheckState(hFilterList, hFilterPrototype, FALSE);
1818 				_TreeView_SetCheckState(hFilterList, hFilterGenuine, FALSE);
1819 
1820 				nLoadMenuBoardTypeFilter = MASKALLBOARD;
1821 			} else {
1822 				_TreeView_SetCheckState(hFilterList, hItemChanged, TRUE);
1823 
1824 				_TreeView_SetCheckState(hFilterList, hFilterBootleg, TRUE);
1825 				_TreeView_SetCheckState(hFilterList, hFilterDemo, TRUE);
1826 				_TreeView_SetCheckState(hFilterList, hFilterHack, TRUE);
1827 				_TreeView_SetCheckState(hFilterList, hFilterHomebrew, TRUE);
1828 				_TreeView_SetCheckState(hFilterList, hFilterPrototype, TRUE);
1829 				_TreeView_SetCheckState(hFilterList, hFilterGenuine, TRUE);
1830 
1831 				nLoadMenuBoardTypeFilter = 0;
1832 			}
1833 		}
1834 
1835 		if (hItemChanged == hFamily) {
1836 			if ((nLoadMenuFamilyFilter & MASKALLFAMILY) == 0) {
1837 				_TreeView_SetCheckState(hFilterList, hItemChanged, FALSE);
1838 
1839 				_TreeView_SetCheckState(hFilterList, hFilterOtherFamily, FALSE);
1840 				_TreeView_SetCheckState(hFilterList, hFilterMslug, FALSE);
1841 				_TreeView_SetCheckState(hFilterList, hFilterSf, FALSE);
1842 				_TreeView_SetCheckState(hFilterList, hFilterKof, FALSE);
1843 				_TreeView_SetCheckState(hFilterList, hFilterDstlk, FALSE);
1844 				_TreeView_SetCheckState(hFilterList, hFilterFatfury, FALSE);
1845 				_TreeView_SetCheckState(hFilterList, hFilterSamsho, FALSE);
1846 				_TreeView_SetCheckState(hFilterList, hFilter19xx, FALSE);
1847 				_TreeView_SetCheckState(hFilterList, hFilterSonicwi, FALSE);
1848 				_TreeView_SetCheckState(hFilterList, hFilterPwrinst, FALSE);
1849 				_TreeView_SetCheckState(hFilterList, hFilterSonic, FALSE);
1850 				_TreeView_SetCheckState(hFilterList, hFilterDonpachi, FALSE);
1851 				_TreeView_SetCheckState(hFilterList, hFilterMahou, FALSE);
1852 
1853 				nLoadMenuFamilyFilter = MASKALLFAMILY;
1854 			} else {
1855 				_TreeView_SetCheckState(hFilterList, hItemChanged, TRUE);
1856 
1857 				_TreeView_SetCheckState(hFilterList, hFilterOtherFamily, TRUE);
1858 				_TreeView_SetCheckState(hFilterList, hFilterMslug, TRUE);
1859 				_TreeView_SetCheckState(hFilterList, hFilterSf, TRUE);
1860 				_TreeView_SetCheckState(hFilterList, hFilterKof, TRUE);
1861 				_TreeView_SetCheckState(hFilterList, hFilterDstlk, TRUE);
1862 				_TreeView_SetCheckState(hFilterList, hFilterFatfury, TRUE);
1863 				_TreeView_SetCheckState(hFilterList, hFilterSamsho, TRUE);
1864 				_TreeView_SetCheckState(hFilterList, hFilter19xx, TRUE);
1865 				_TreeView_SetCheckState(hFilterList, hFilterSonicwi, TRUE);
1866 				_TreeView_SetCheckState(hFilterList, hFilterPwrinst, TRUE);
1867 				_TreeView_SetCheckState(hFilterList, hFilterSonic, TRUE);
1868 				_TreeView_SetCheckState(hFilterList, hFilterDonpachi, TRUE);
1869 				_TreeView_SetCheckState(hFilterList, hFilterMahou, TRUE);
1870 
1871 				nLoadMenuFamilyFilter = 0;
1872 			}
1873 		}
1874 
1875 		if (hItemChanged == hFavorites) {
1876 			if (nLoadMenuFavoritesFilter) {
1877 				_TreeView_SetCheckState(hFilterList, hItemChanged, FALSE);
1878 
1879 				nLoadMenuFavoritesFilter = 0;
1880 			} else {
1881 				_TreeView_SetCheckState(hFilterList, hItemChanged, TRUE);
1882 
1883 				nLoadMenuFavoritesFilter = 0xff;
1884 			}
1885 		}
1886 
1887 		if (hItemChanged == hFilterSegaGrp) {
1888 			if ((nLoadMenuShowX & MASKSEGAGRP) == 0) {
1889 				_TreeView_SetCheckState(hFilterList, hItemChanged, FALSE);
1890 
1891 				_TreeView_SetCheckState(hFilterList, hFilterSega, FALSE);
1892 				_TreeView_SetCheckState(hFilterList, hFilterSg1000, FALSE);
1893 				_TreeView_SetCheckState(hFilterList, hFilterSms, FALSE);
1894 				_TreeView_SetCheckState(hFilterList, hFilterMegadrive, FALSE);
1895 				_TreeView_SetCheckState(hFilterList, hFilterGg, FALSE);
1896 
1897 				nLoadMenuShowX &= ~MASKSEGAGRP;
1898 			} else {
1899 				_TreeView_SetCheckState(hFilterList, hItemChanged, TRUE);
1900 
1901 
1902 				_TreeView_SetCheckState(hFilterList, hFilterSega, TRUE);
1903 				_TreeView_SetCheckState(hFilterList, hFilterSg1000, TRUE);
1904 				_TreeView_SetCheckState(hFilterList, hFilterSms, TRUE);
1905 				_TreeView_SetCheckState(hFilterList, hFilterMegadrive, TRUE);
1906 				_TreeView_SetCheckState(hFilterList, hFilterGg, TRUE);
1907 
1908 				nLoadMenuShowX |= MASKSEGAGRP;
1909 			}
1910 		}
1911 
1912 		if (hItemChanged == hFilterCapcomGrp) {
1913 			if ((nLoadMenuShowX & MASKCAPGRP) == 0) {
1914 				_TreeView_SetCheckState(hFilterList, hItemChanged, FALSE);
1915 
1916 				_TreeView_SetCheckState(hFilterList, hFilterCapcomMisc, FALSE);
1917 				_TreeView_SetCheckState(hFilterList, hFilterCps1, FALSE);
1918 				_TreeView_SetCheckState(hFilterList, hFilterCps2, FALSE);
1919 				_TreeView_SetCheckState(hFilterList, hFilterCps3, FALSE);
1920 
1921 				nLoadMenuShowX &= ~MASKCAPGRP;
1922 			} else {
1923 				_TreeView_SetCheckState(hFilterList, hItemChanged, TRUE);
1924 
1925 				_TreeView_SetCheckState(hFilterList, hFilterCapcomMisc, TRUE);
1926 				_TreeView_SetCheckState(hFilterList, hFilterCps1, TRUE);
1927 				_TreeView_SetCheckState(hFilterList, hFilterCps2, TRUE);
1928 				_TreeView_SetCheckState(hFilterList, hFilterCps3, TRUE);
1929 
1930 				nLoadMenuShowX |= MASKCAPGRP;
1931 			}
1932 		}
1933 
1934 		if (hItemChanged == hGenre) {
1935 			if ((nLoadMenuGenreFilter & MASKALLGENRE) == 0) {
1936 				_TreeView_SetCheckState(hFilterList, hItemChanged, FALSE);
1937 
1938 				_TreeView_SetCheckState(hFilterList, hFilterHorshoot, FALSE);
1939 				_TreeView_SetCheckState(hFilterList, hFilterVershoot, FALSE);
1940 				_TreeView_SetCheckState(hFilterList, hFilterScrfight, FALSE);
1941 				_TreeView_SetCheckState(hFilterList, hFilterVsfight, FALSE);
1942 				_TreeView_SetCheckState(hFilterList, hFilterBios, FALSE);
1943 				_TreeView_SetCheckState(hFilterList, hFilterBreakout, FALSE);
1944 				_TreeView_SetCheckState(hFilterList, hFilterCasino, FALSE);
1945 				_TreeView_SetCheckState(hFilterList, hFilterBallpaddle, FALSE);
1946 				_TreeView_SetCheckState(hFilterList, hFilterMaze, FALSE);
1947 				_TreeView_SetCheckState(hFilterList, hFilterMinigames, FALSE);
1948 				_TreeView_SetCheckState(hFilterList, hFilterPinball, FALSE);
1949 				_TreeView_SetCheckState(hFilterList, hFilterPlatform, FALSE);
1950 				_TreeView_SetCheckState(hFilterList, hFilterPuzzle, FALSE);
1951 				_TreeView_SetCheckState(hFilterList, hFilterQuiz, FALSE);
1952 				_TreeView_SetCheckState(hFilterList, hFilterSportsmisc, FALSE);
1953 				_TreeView_SetCheckState(hFilterList, hFilterSportsfootball, FALSE);
1954 				_TreeView_SetCheckState(hFilterList, hFilterMisc, FALSE);
1955 				_TreeView_SetCheckState(hFilterList, hFilterMahjong, FALSE);
1956 				_TreeView_SetCheckState(hFilterList, hFilterRacing, FALSE);
1957 				_TreeView_SetCheckState(hFilterList, hFilterShoot, FALSE);
1958 				_TreeView_SetCheckState(hFilterList, hFilterAction, FALSE);
1959 				_TreeView_SetCheckState(hFilterList, hFilterRungun, FALSE);
1960 				_TreeView_SetCheckState(hFilterList, hFilterStrategy, FALSE);
1961 				_TreeView_SetCheckState(hFilterList, hFilterRpg, FALSE);
1962 				_TreeView_SetCheckState(hFilterList, hFilterSim, FALSE);
1963 				_TreeView_SetCheckState(hFilterList, hFilterAdv, FALSE);
1964 
1965 				nLoadMenuGenreFilter = MASKALLGENRE;
1966 			} else {
1967 				_TreeView_SetCheckState(hFilterList, hItemChanged, TRUE);
1968 
1969 				_TreeView_SetCheckState(hFilterList, hFilterHorshoot, TRUE);
1970 				_TreeView_SetCheckState(hFilterList, hFilterVershoot, TRUE);
1971 				_TreeView_SetCheckState(hFilterList, hFilterScrfight, TRUE);
1972 				_TreeView_SetCheckState(hFilterList, hFilterVsfight, TRUE);
1973 				_TreeView_SetCheckState(hFilterList, hFilterBios, TRUE);
1974 				_TreeView_SetCheckState(hFilterList, hFilterBreakout, TRUE);
1975 				_TreeView_SetCheckState(hFilterList, hFilterCasino, TRUE);
1976 				_TreeView_SetCheckState(hFilterList, hFilterBallpaddle, TRUE);
1977 				_TreeView_SetCheckState(hFilterList, hFilterMaze, TRUE);
1978 				_TreeView_SetCheckState(hFilterList, hFilterMinigames, TRUE);
1979 				_TreeView_SetCheckState(hFilterList, hFilterPinball, TRUE);
1980 				_TreeView_SetCheckState(hFilterList, hFilterPlatform, TRUE);
1981 				_TreeView_SetCheckState(hFilterList, hFilterPuzzle, TRUE);
1982 				_TreeView_SetCheckState(hFilterList, hFilterQuiz, TRUE);
1983 				_TreeView_SetCheckState(hFilterList, hFilterSportsmisc, TRUE);
1984 				_TreeView_SetCheckState(hFilterList, hFilterSportsfootball, TRUE);
1985 				_TreeView_SetCheckState(hFilterList, hFilterMisc, TRUE);
1986 				_TreeView_SetCheckState(hFilterList, hFilterMahjong, TRUE);
1987 				_TreeView_SetCheckState(hFilterList, hFilterRacing, TRUE);
1988 				_TreeView_SetCheckState(hFilterList, hFilterShoot, TRUE);
1989 				_TreeView_SetCheckState(hFilterList, hFilterAction, TRUE);
1990 				_TreeView_SetCheckState(hFilterList, hFilterRungun, TRUE);
1991 				_TreeView_SetCheckState(hFilterList, hFilterStrategy, TRUE);
1992 				_TreeView_SetCheckState(hFilterList, hFilterRpg, TRUE);
1993 				_TreeView_SetCheckState(hFilterList, hFilterSim, TRUE);
1994 				_TreeView_SetCheckState(hFilterList, hFilterAdv, TRUE);
1995 
1996 				nLoadMenuGenreFilter = 0;
1997 			}
1998 		}
1999 
2000 		if (hItemChanged == hFilterCapcomGrp)		_ToggleGameListing(nLoadMenuShowX, MASKCAPMISC);
2001 		if (hItemChanged == hFilterCapcomGrp)		_ToggleGameListing(nLoadMenuShowX, MASKCPS);
2002 		if (hItemChanged == hFilterCapcomGrp)		_ToggleGameListing(nLoadMenuShowX, MASKCPS2);
2003 		if (hItemChanged == hFilterCapcomGrp)		_ToggleGameListing(nLoadMenuShowX, MASKCPS3);
2004 
2005 		if (hItemChanged == hFilterSegaGrp)			_ToggleGameListing(nLoadMenuShowX, MASKSG1000);
2006 		if (hItemChanged == hFilterSegaGrp)			_ToggleGameListing(nLoadMenuShowX, MASKSMS);
2007 		if (hItemChanged == hFilterSegaGrp)			_ToggleGameListing(nLoadMenuShowX, MASKMEGADRIVE);
2008 		if (hItemChanged == hFilterSegaGrp)			_ToggleGameListing(nLoadMenuShowX, MASKGG);
2009 		if (hItemChanged == hFilterSegaGrp)			_ToggleGameListing(nLoadMenuShowX, MASKSEGA);
2010 
2011 		if (hItemChanged == hFilterCapcomMisc)		_ToggleGameListing(nLoadMenuShowX, MASKCAPMISC);
2012 		if (hItemChanged == hFilterCave)			_ToggleGameListing(nLoadMenuShowX, MASKCAVE);
2013 		if (hItemChanged == hFilterCps1)			_ToggleGameListing(nLoadMenuShowX, MASKCPS);
2014 		if (hItemChanged == hFilterCps2)			_ToggleGameListing(nLoadMenuShowX, MASKCPS2);
2015 		if (hItemChanged == hFilterCps3)			_ToggleGameListing(nLoadMenuShowX, MASKCPS3);
2016 		if (hItemChanged == hFilterDataeast)		_ToggleGameListing(nLoadMenuShowX, MASKDATAEAST);
2017 		if (hItemChanged == hFilterGalaxian)		_ToggleGameListing(nLoadMenuShowX, MASKGALAXIAN);
2018 		if (hItemChanged == hFilterIrem)			_ToggleGameListing(nLoadMenuShowX, MASKIREM);
2019 		if (hItemChanged == hFilterKaneko)			_ToggleGameListing(nLoadMenuShowX, MASKKANEKO);
2020 		if (hItemChanged == hFilterKonami)			_ToggleGameListing(nLoadMenuShowX, MASKKONAMI);
2021 		if (hItemChanged == hFilterNeogeo)			_ToggleGameListing(nLoadMenuShowX, MASKNEOGEO);
2022 		if (hItemChanged == hFilterPacman)			_ToggleGameListing(nLoadMenuShowX, MASKPACMAN);
2023 		if (hItemChanged == hFilterPgm)				_ToggleGameListing(nLoadMenuShowX, MASKPGM);
2024 		if (hItemChanged == hFilterPsikyo)			_ToggleGameListing(nLoadMenuShowX, MASKPSIKYO);
2025 		if (hItemChanged == hFilterSega)			_ToggleGameListing(nLoadMenuShowX, MASKSEGA);
2026 		if (hItemChanged == hFilterSeta)			_ToggleGameListing(nLoadMenuShowX, MASKSETA);
2027 		if (hItemChanged == hFilterTaito)			_ToggleGameListing(nLoadMenuShowX, MASKTAITO);
2028 		if (hItemChanged == hFilterTechnos)			_ToggleGameListing(nLoadMenuShowX, MASKTECHNOS);
2029 		if (hItemChanged == hFilterToaplan)			_ToggleGameListing(nLoadMenuShowX, MASKTOAPLAN);
2030 		if (hItemChanged == hFilterMiscPre90s)		_ToggleGameListing(nLoadMenuShowX, MASKMISCPRE90S);
2031 		if (hItemChanged == hFilterMiscPost90s)		_ToggleGameListing(nLoadMenuShowX, MASKMISCPOST90S);
2032 		if (hItemChanged == hFilterMegadrive)		_ToggleGameListing(nLoadMenuShowX, MASKMEGADRIVE);
2033 		if (hItemChanged == hFilterPce)				_ToggleGameListing(nLoadMenuShowX, MASKPCENGINE);
2034 		if (hItemChanged == hFilterSms)				_ToggleGameListing(nLoadMenuShowX, MASKSMS);
2035 		if (hItemChanged == hFilterGg)				_ToggleGameListing(nLoadMenuShowX, MASKGG);
2036 		if (hItemChanged == hFilterSg1000)			_ToggleGameListing(nLoadMenuShowX, MASKSG1000);
2037 		if (hItemChanged == hFilterColeco)			_ToggleGameListing(nLoadMenuShowX, MASKCOLECO);
2038 		if (hItemChanged == hFilterMsx)				_ToggleGameListing(nLoadMenuShowX, MASKMSX);
2039 		if (hItemChanged == hFilterSpectrum)		_ToggleGameListing(nLoadMenuShowX, MASKSPECTRUM);
2040 		if (hItemChanged == hFilterNes)				_ToggleGameListing(nLoadMenuShowX, MASKNES);
2041 		if (hItemChanged == hFilterFds)				_ToggleGameListing(nLoadMenuShowX, MASKFDS);
2042 		if (hItemChanged == hFilterNgp)				_ToggleGameListing(nLoadMenuShowX, MASKNGP);
2043 		if (hItemChanged == hFilterChannelF)		_ToggleGameListing(nLoadMenuShowX, MASKCHANNELF);
2044 		if (hItemChanged == hFilterMidway)			_ToggleGameListing(nLoadMenuShowX, MASKMIDWAY);
2045 
2046 		if (hItemChanged == hFilterBootleg)			_ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_BOOTLEG);
2047 		if (hItemChanged == hFilterDemo)			_ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_DEMO);
2048 		if (hItemChanged == hFilterHack)			_ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_HACK);
2049 		if (hItemChanged == hFilterHomebrew)		_ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_HOMEBREW);
2050 		if (hItemChanged == hFilterPrototype)		_ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_PROTOTYPE);
2051 		if (hItemChanged == hFilterGenuine)			_ToggleGameListing(nLoadMenuBoardTypeFilter, MASKBOARDTYPEGENUINE);
2052 
2053 		if (hItemChanged == hFilterOtherFamily)		_ToggleGameListing(nLoadMenuFamilyFilter, MASKFAMILYOTHER);
2054 		if (hItemChanged == hFilterMahou)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_MAHOU);
2055 		if (hItemChanged == hFilterDonpachi)		_ToggleGameListing(nLoadMenuFamilyFilter, FBF_DONPACHI);
2056 		if (hItemChanged == hFilterMslug)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_MSLUG);
2057 		if (hItemChanged == hFilterSf)				_ToggleGameListing(nLoadMenuFamilyFilter, FBF_SF);
2058 		if (hItemChanged == hFilterKof)				_ToggleGameListing(nLoadMenuFamilyFilter, FBF_KOF);
2059 		if (hItemChanged == hFilterDstlk)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_DSTLK);
2060 		if (hItemChanged == hFilterFatfury)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_FATFURY);
2061 		if (hItemChanged == hFilterSamsho)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_SAMSHO);
2062 		if (hItemChanged == hFilter19xx)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_19XX);
2063 		if (hItemChanged == hFilterSonicwi)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_SONICWI);
2064 		if (hItemChanged == hFilterPwrinst)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_PWRINST);
2065 		if (hItemChanged == hFilterSonic)			_ToggleGameListing(nLoadMenuFamilyFilter, FBF_SONIC);
2066 
2067 		if (hItemChanged == hFilterHorshoot)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_HORSHOOT);
2068 		if (hItemChanged == hFilterVershoot)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_VERSHOOT);
2069 		if (hItemChanged == hFilterScrfight)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_SCRFIGHT);
2070 		if (hItemChanged == hFilterVsfight)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_VSFIGHT);
2071 		if (hItemChanged == hFilterBios)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_BIOS);
2072 		if (hItemChanged == hFilterBreakout)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_BREAKOUT);
2073 		if (hItemChanged == hFilterCasino)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_CASINO);
2074 		if (hItemChanged == hFilterBallpaddle)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_BALLPADDLE);
2075 		if (hItemChanged == hFilterMaze)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_MAZE);
2076 		if (hItemChanged == hFilterMinigames)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_MINIGAMES);
2077 		if (hItemChanged == hFilterPinball)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_PINBALL);
2078 		if (hItemChanged == hFilterPlatform)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_PLATFORM);
2079 		if (hItemChanged == hFilterPuzzle)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_PUZZLE);
2080 		if (hItemChanged == hFilterQuiz)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_QUIZ);
2081 		if (hItemChanged == hFilterSportsmisc)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_SPORTSMISC);
2082 		if (hItemChanged == hFilterSportsfootball)	_ToggleGameListing(nLoadMenuGenreFilter, GBF_SPORTSFOOTBALL);
2083 		if (hItemChanged == hFilterMisc)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_MISC);
2084 		if (hItemChanged == hFilterMahjong)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_MAHJONG);
2085 		if (hItemChanged == hFilterRacing)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_RACING);
2086 		if (hItemChanged == hFilterShoot)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_SHOOT);
2087 		if (hItemChanged == hFilterAction)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_ACTION);
2088 		if (hItemChanged == hFilterRungun)			_ToggleGameListing(nLoadMenuGenreFilter, GBF_RUNGUN);
2089 		if (hItemChanged == hFilterStrategy)		_ToggleGameListing(nLoadMenuGenreFilter, GBF_STRATEGY);
2090 		if (hItemChanged == hFilterRpg)				_ToggleGameListing(nLoadMenuGenreFilter, GBF_RPG);
2091 		if (hItemChanged == hFilterSim)				_ToggleGameListing(nLoadMenuGenreFilter, GBF_SIM);
2092 		if (hItemChanged == hFilterAdv)				_ToggleGameListing(nLoadMenuGenreFilter, GBF_ADV);
2093 
2094 		RebuildEverything();
2095 	}
2096 
2097 	if (Msg == WM_COMMAND) {
2098 		if (HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == IDC_SEL_SEARCH) {
2099 			if (bSearchStringInit) {
2100 				bSearchStringInit = false;
2101 				return 0;
2102 			}
2103 
2104 			KillTimer(hDlg, IDC_SEL_SEARCHTIMER);
2105 			SetTimer(hDlg, IDC_SEL_SEARCHTIMER, 500, (TIMERPROC)NULL);
2106 		}
2107 
2108 		if (HIWORD(wParam) == BN_CLICKED) {
2109 			int wID = LOWORD(wParam);
2110 			switch (wID) {
2111 				case IDOK:
2112 					SelOkay();
2113 					break;
2114 				case IDROM:
2115 					RomsDirCreate(hSelDlg);
2116 					RebuildEverything();
2117 					break;
2118 				case IDRESCAN:
2119 					bRescanRoms = true;
2120 					CreateROMInfo(hSelDlg);
2121 					RebuildEverything();
2122 					break;
2123 				case IDCANCEL:
2124 					bDialogCancel = true;
2125 					SendMessage(hDlg, WM_CLOSE, 0, 0);
2126 					return 0;
2127 				case IDC_CHECKAVAILABLE:
2128 					nLoadMenuShowY ^= AVAILABLE;
2129 					RebuildEverything();
2130 					break;
2131 				case IDC_CHECKUNAVAILABLE:
2132 					nLoadMenuShowY ^= UNAVAILABLE;
2133 					RebuildEverything();
2134 					break;
2135 				case IDC_CHECKAUTOEXPAND:
2136 					nLoadMenuShowY ^= AUTOEXPAND;
2137 					RebuildEverything();
2138 					break;
2139 				case IDC_SEL_SHORTNAME:
2140 					nLoadMenuShowY ^= SHOWSHORT;
2141 					RebuildEverything();
2142 					break;
2143 				case IDC_SEL_ASCIIONLY:
2144 					nLoadMenuShowY ^= ASCIIONLY;
2145 					RebuildEverything();
2146 					break;
2147 				case IDGAMEINFO:
2148 					if (bDrvSelected) {
2149 						GameInfoDialogCreate(hSelDlg, nBurnDrvActive);
2150 						SetFocus(hSelList); // Update list for Rescan Romset button
2151 					} else {
2152 						MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NO_DRIVER_SELECTED, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK);
2153 					}
2154 					break;
2155 				case IDC_SEL_IPSMANAGER:
2156                     if (bDrvSelected) {
2157                         int nOldnBurnDrvActive = nBurnDrvActive;
2158 						IpsManagerCreate(hSelDlg);
2159                         nBurnDrvActive = nOldnBurnDrvActive; // due to some weird bug in sel.cpp, nBurnDrvActive can sometimes change when clicking in new dialogs.
2160 						LoadIpsActivePatches();
2161 						if (GetIpsNumActivePatches()) {
2162 							EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), TRUE);
2163 						} else {
2164 							EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), FALSE);
2165 						}
2166                         SetFocus(hSelList);
2167 					} else {
2168 						MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NO_DRIVER_SELECTED, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK);
2169 					}
2170 					break;
2171 				case IDC_SEL_APPLYIPS:
2172 					bDoIpsPatch = !bDoIpsPatch;
2173 					break;
2174 			}
2175 		}
2176 
2177 		int id = LOWORD(wParam);
2178 
2179 		switch (id) {
2180 			case GAMESEL_MENU_PLAY: {
2181 				SelOkay();
2182 				break;
2183 			}
2184 
2185 			case GAMESEL_MENU_GAMEINFO: {
2186 				/*UpdatePreview(true, hSelDlg, szAppPreviewsPath);
2187 				if (nTimer) {
2188 					KillTimer(hSelDlg, nTimer);
2189 					nTimer = 0;
2190 				}
2191 				GameInfoDialogCreate(hSelDlg, nBurnDrvSelect);*/
2192 				if (bDrvSelected) {
2193 					GameInfoDialogCreate(hSelDlg, nBurnDrvActive);
2194 					SetFocus(hSelList); // Update list for Rescan Romset button
2195 				} else {
2196 					MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NO_DRIVER_SELECTED, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK);
2197 				}
2198 				break;
2199 			}
2200 
2201 			case GAMESEL_MENU_VIEWEMMA: {
2202 				if (!nVidFullscreen) {
2203 					ViewEmma();
2204 				}
2205 				break;
2206 			}
2207 
2208 			case GAMESEL_MENU_FAVORITE: { // toggle favorite status.
2209 				if (bDrvSelected) {
2210 					AddFavorite_Ext((CheckFavorites(BurnDrvGetTextA(DRV_NAME)) == -1) ? 1 : 0);
2211 				} else {
2212 					MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NO_DRIVER_SELECTED, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK);
2213 				}
2214 
2215 				break;
2216 			}
2217 		}
2218 	}
2219 
2220 	if (Msg == WM_TIMER) {
2221 		switch (wParam) {
2222 			case IDC_SEL_SEARCHTIMER:
2223 				KillTimer(hDlg, IDC_SEL_SEARCHTIMER);
2224 				RebuildEverything();
2225 				break;
2226 		}
2227 	}
2228 
2229 	if (Msg == UM_CLOSE) {
2230 		nDialogSelect = nOldDlgSelected;
2231 		MyEndDialog();
2232 		DeleteObject(hWhiteBGBrush);
2233 		return 0;
2234 	}
2235 
2236 	if (Msg == WM_CLOSE) {
2237 		bDialogCancel = true;
2238 		nDialogSelect = nOldDlgSelected;
2239 		MyEndDialog();
2240 		DeleteObject(hWhiteBGBrush);
2241 		return 0;
2242 	}
2243 
2244 	if (Msg == WM_GETMINMAXINFO) {
2245 		MINMAXINFO *info = (MINMAXINFO*)lParam;
2246 
2247 		info->ptMinTrackSize.x = nDlgInitialWidth;
2248 		info->ptMinTrackSize.y = nDlgInitialHeight;
2249 
2250 		return 0;
2251 	}
2252 
2253 	if (Msg == WM_WINDOWPOSCHANGED) {
2254 		RECT rc;
2255 		int xDelta;
2256 		int yDelta;
2257 		int xScrollBarDelta;
2258 
2259 		if (nDlgInitialWidth == 0 || nDlgInitialHeight == 0) return 0;
2260 
2261 		GetClientRect(hDlg, &rc);
2262 
2263 		xDelta = nDlgInitialWidth - rc.right;
2264 		yDelta = nDlgInitialHeight - rc.bottom;
2265 
2266 		if (xDelta == 0 && yDelta == 0) return 0;
2267 
2268 		SetControlPosAlignTopRight(IDC_STATIC_OPT, nDlgOptionsGrpInitialPos);
2269 		SetControlPosAlignTopRight(IDC_CHECKAVAILABLE, nDlgAvailableChbInitialPos);
2270 		SetControlPosAlignTopRight(IDC_CHECKUNAVAILABLE, nDlgUnavailableChbInitialPos);
2271 		SetControlPosAlignTopRight(IDC_CHECKAUTOEXPAND, nDlgAlwaysClonesChbInitialPos);
2272 		SetControlPosAlignTopRight(IDC_SEL_SHORTNAME, nDlgZipnamesChbInitialPos);
2273 		SetControlPosAlignTopRight(IDC_SEL_ASCIIONLY, nDlgLatinTextChbInitialPos);
2274 		SetControlPosAlignTopRight(IDROM, nDlgRomDirsBtnInitialPos);
2275 		SetControlPosAlignTopRight(IDRESCAN, nDlgScanRomsBtnInitialPos);
2276 
2277 		SetControlPosAlignTopRightResizeVert(IDC_STATIC_SYS, nDlgFilterGrpInitialPos);
2278 		SetControlPosAlignTopRightResizeVert(IDC_TREE2, nDlgFilterTreeInitialPos);
2279 
2280 		SetControlPosAlignBottomRight(IDC_SEL_IPSGROUP, nDlgIpsGrpInitialPos);
2281 		SetControlPosAlignBottomRight(IDC_SEL_APPLYIPS, nDlgApplyIpsChbInitialPos);
2282 		SetControlPosAlignBottomRight(IDC_SEL_IPSMANAGER, nDlgIpsManBtnInitialPos);
2283 		SetControlPosAlignBottomRight(IDC_SEL_SEARCHGROUP, nDlgSearchGrpInitialPos);
2284 		SetControlPosAlignBottomRight(IDC_SEL_SEARCH, nDlgSearchTxtInitialPos);
2285 		SetControlPosAlignBottomRight(IDCANCEL, nDlgCancelBtnInitialPos);
2286 		SetControlPosAlignBottomRight(IDOK, nDlgPlayBtnInitialPos);
2287 
2288 		SetControlPosAlignTopLeft(IDC_STATIC3, nDlgTitleGrpInitialPos);
2289 		SetControlPosAlignTopLeft(IDC_SCREENSHOT2_H, nDlgTitleImgHInitialPos);
2290 		SetControlPosAlignTopLeft(IDC_SCREENSHOT2_V, nDlgTitleImgVInitialPos);
2291 		SetControlPosAlignTopLeft(IDC_STATIC2, nDlgPreviewGrpInitialPos);
2292 		SetControlPosAlignTopLeft(IDC_SCREENSHOT_H, nDlgPreviewImgHInitialPos);
2293 		SetControlPosAlignTopLeft(IDC_SCREENSHOT_V, nDlgPreviewImgVInitialPos);
2294 
2295 		SetControlPosAlignBottomLeftResizeHor(IDC_STATIC_INFOBOX, nDlgWhiteBoxInitialPos);
2296 		SetControlPosAlignBottomLeftResizeHor(IDC_LABELCOMMENT, nDlgGameInfoLblInitialPos);
2297 		SetControlPosAlignBottomLeftResizeHor(IDC_LABELROMNAME, nDlgRomNameLblInitialPos);
2298 		SetControlPosAlignBottomLeftResizeHor(IDC_LABELROMINFO, nDlgRomInfoLblInitialPos);
2299 		SetControlPosAlignBottomLeftResizeHor(IDC_LABELSYSTEM, nDlgReleasedByLblInitialPos);
2300 		SetControlPosAlignBottomLeftResizeHor(IDC_LABELGENRE, nDlgGenreLblInitialPos);
2301 		SetControlPosAlignBottomLeftResizeHor(IDC_LABELNOTES, nDlgNotesLblInitialPos);
2302 		SetControlPosAlignBottomLeftResizeHor(IDC_TEXTCOMMENT, nDlgGameInfoTxtInitialPos);
2303 		SetControlPosAlignBottomLeftResizeHor(IDC_TEXTROMNAME, nDlgRomNameTxtInitialPos);
2304 		SetControlPosAlignBottomLeftResizeHor(IDC_TEXTROMINFO, nDlgRomInfoTxtInitialPos);
2305 		SetControlPosAlignBottomLeftResizeHor(IDC_TEXTSYSTEM, nDlgReleasedByTxtInitialPos);
2306 		SetControlPosAlignBottomLeftResizeHor(IDC_TEXTGENRE, nDlgGenreTxtInitialPos);
2307 		SetControlPosAlignBottomLeftResizeHor(IDC_TEXTNOTES, nDlgNotesTxtInitialPos);
2308 		SetControlPosAlignBottomLeftResizeHor(IDC_DRVCOUNT, nDlgDrvCountTxtInitialPos);
2309 		SetControlPosAlignBottomRight(IDGAMEINFO, nDlgDrvRomInfoBtnInitialPos);
2310 
2311 		SetControlPosAlignTopLeftResizeHorVert(IDC_STATIC1, nDlgSelectGameGrpInitialPos);
2312 
2313 		if (bIsWindowsXP && nTmpDrvCount < 12) { // Fix an issue on WinXP where the scrollbar overwrites past the tree size when less then 12 items are in the list
2314 			SetControlPosAlignTopLeftResizeHorVertALT(IDC_TREE1, nDlgSelectGameLstInitialPos);
2315 		} else {
2316 			SetControlPosAlignTopLeftResizeHorVert(IDC_TREE1, nDlgSelectGameLstInitialPos);
2317 		}
2318 
2319 		InvalidateRect(hSelDlg, NULL, true);
2320 		UpdateWindow(hSelDlg);
2321 
2322 		return 0;
2323 	}
2324 
2325 //	if (Msg == WM_TIMER) {
2326 //		UpdatePreview(false, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V);
2327 //		return 0;
2328 //	}
2329 
2330 	if (Msg == WM_CTLCOLORSTATIC) {
2331 		for (int i = 0; i < 6; i++) {
2332 			if ((HWND)lParam == hInfoLabel[i])	{ return (INT_PTR)hWhiteBGBrush; }
2333 			if ((HWND)lParam == hInfoText[i])	{ return (INT_PTR)hWhiteBGBrush; }
2334 		}
2335 	}
2336 
2337 	NMHDR* pNmHdr = (NMHDR*)lParam;
2338 	if (Msg == WM_NOTIFY)
2339 	{
2340 		if ((pNmHdr->code == TVN_ITEMEXPANDED) && (pNmHdr->idFrom == IDC_TREE2))
2341 		{
2342 			// save the expanded state of the filter nodes
2343 			NM_TREEVIEW *pnmtv = (NM_TREEVIEW *)lParam;
2344 			TV_ITEM curItem = pnmtv->itemNew;
2345 
2346 			if (pnmtv->action == TVE_COLLAPSE)
2347 			{
2348 				nLoadMenuExpand &= ~TvhFilterToBitmask(curItem.hItem);
2349 			}
2350             else if (pnmtv->action == TVE_EXPAND)
2351             {
2352 				nLoadMenuExpand |= TvhFilterToBitmask(curItem.hItem);
2353 			}
2354 		}
2355 
2356 		if ((pNmHdr->code == NM_CLICK) && (pNmHdr->idFrom == IDC_TREE2))
2357 		{
2358 			TVHITTESTINFO thi;
2359 			DWORD dwpos = GetMessagePos();
2360 			thi.pt.x	= GET_X_LPARAM(dwpos);
2361 			thi.pt.y	= GET_Y_LPARAM(dwpos);
2362 			MapWindowPoints(HWND_DESKTOP, pNmHdr->hwndFrom, &thi.pt, 1);
2363 			TreeView_HitTest(pNmHdr->hwndFrom, &thi);
2364 
2365 			if(TVHT_ONITEMSTATEICON & thi.flags) {
2366 				PostMessage(hSelDlg, UM_CHECKSTATECHANGE, 0, (LPARAM)thi.hItem);
2367 			}
2368 
2369 			return 1;
2370 		}
2371 
2372 		NMTREEVIEW* pnmtv = (NMTREEVIEW*)lParam;
2373 
2374 		if (!TreeBuilding && pnmtv->hdr.code == NM_DBLCLK && pnmtv->hdr.idFrom == IDC_TREE1)
2375 		{
2376 			DWORD dwpos = GetMessagePos();
2377 
2378 			TVHITTESTINFO thi;
2379 			thi.pt.x	= GET_X_LPARAM(dwpos);
2380 			thi.pt.y	= GET_Y_LPARAM(dwpos);
2381 
2382 			MapWindowPoints(HWND_DESKTOP, pNmHdr->hwndFrom, &thi.pt, 1);
2383 
2384 			TreeView_HitTest(pNmHdr->hwndFrom, &thi);
2385 
2386 			HTREEITEM hSelectHandle = thi.hItem;
2387          		if(hSelectHandle == NULL) return 1;
2388 
2389 			TreeView_SelectItem(hSelList, hSelectHandle);
2390 
2391 			// Search through nBurnDrv[] for the nBurnDrvNo according to the returned hSelectHandle
2392 			for (unsigned int i = 0; i < nTmpDrvCount; i++) {
2393 				if (hSelectHandle == nBurnDrv[i].hTreeHandle) {
2394 					nBurnDrvActive = nBurnDrv[i].nBurnDrvNo;
2395 					break;
2396 				}
2397 			}
2398 
2399 			nDialogSelect	= nBurnDrvActive;
2400 			bDrvSelected	= true;
2401 
2402 			SelOkay();
2403 
2404 			// disable double-click node-expand
2405 			SetWindowLongPtr(hSelDlg, DWLP_MSGRESULT, 1);
2406 
2407 			return 1;
2408 		}
2409 
2410 		if (pNmHdr->code == NM_CUSTOMDRAW && LOWORD(wParam) == IDC_TREE1) {
2411 			LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
2412 			int nGetTextFlags = nLoadMenuShowY & ASCIIONLY ? DRV_ASCIIONLY : 0;
2413 			HTREEITEM hSelectHandle;
2414 
2415 			switch (lplvcd->nmcd.dwDrawStage) {
2416 				case CDDS_PREPAINT: {
2417 					SetWindowLongPtr(hSelDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
2418 					return 1;
2419 				}
2420 
2421 				case CDDS_ITEMPREPAINT:	{
2422 					hSelectHandle = (HTREEITEM)(lplvcd->nmcd.dwItemSpec);
2423 					HBRUSH hBackBrush;
2424 					RECT rect;
2425 
2426 					// TVITEM (msdn.microsoft.com) This structure is identical to the TV_ITEM structure, but it has been renamed to
2427 					// follow current naming conventions. New applications should use this structure.
2428 
2429 					//TV_ITEM TvItem;
2430 					TVITEM TvItem;
2431 					TvItem.hItem = hSelectHandle;
2432 					TvItem.mask = TVIF_PARAM | TVIF_STATE | TVIF_CHILDREN;
2433 					SendMessage(hSelList, TVM_GETITEM, 0, (LPARAM)&TvItem);
2434 
2435 //					dprintf(_T("  - Item (%i�%i) - (%i�%i) %hs\n"), lplvcd->nmcd.rc.left, lplvcd->nmcd.rc.top, lplvcd->nmcd.rc.right, lplvcd->nmcd.rc.bottom, ((NODEINFO*)TvItem.lParam)->pszROMName);
2436 
2437 					// Set the foreground and background colours unless the item is highlighted
2438 					if (!(TvItem.state & (TVIS_SELECTED | TVIS_DROPHILITED))) {
2439 
2440 						// Set less contrasting colours for clones
2441 						if (!((NODEINFO*)TvItem.lParam)->bIsParent) {
2442 							lplvcd->clrTextBk = RGB(0xD7, 0xD7, 0xD7);
2443 							lplvcd->clrText = RGB(0x3F, 0x3F, 0x3F);
2444 						}
2445 
2446 						// For parents, change the colour of the background, for clones, change only the text colour
2447 						if (!CheckWorkingStatus(((NODEINFO*)TvItem.lParam)->nBurnDrvNo)) {
2448 							lplvcd->clrText = RGB(0x7F, 0x7F, 0x7F);
2449 						}
2450 					}
2451 
2452 					rect.left	= lplvcd->nmcd.rc.left;
2453 					rect.right	= lplvcd->nmcd.rc.right;
2454 					rect.top	= lplvcd->nmcd.rc.top;
2455 					rect.bottom = lplvcd->nmcd.rc.bottom;
2456 
2457 					hBackBrush = CreateSolidBrush(lplvcd->clrTextBk);
2458 
2459 					nBurnDrvActive = ((NODEINFO*)TvItem.lParam)->nBurnDrvNo;
2460 
2461 					{
2462 						// Fill background
2463 						FillRect(lplvcd->nmcd.hdc, &lplvcd->nmcd.rc, hBackBrush);
2464 					}
2465 
2466 					{
2467 						// Draw plus and minus buttons
2468 						if (((NODEINFO*)TvItem.lParam)->bIsParent) {
2469 							if (TvItem.state & TVIS_EXPANDED) {
2470 								DrawIconEx(lplvcd->nmcd.hdc, rect.left + 4, rect.top + nIconsYDiff, hCollapse, 16, 16, 0, NULL, DI_NORMAL);
2471 							} else {
2472 								if (TvItem.cChildren) {
2473 									DrawIconEx(lplvcd->nmcd.hdc, rect.left + 4, rect.top + nIconsYDiff, hExpand, 16, 16, 0, NULL, DI_NORMAL);
2474 								}
2475 							}
2476 						}
2477 						rect.left += 16 + 8;
2478 					}
2479 
2480 					rect.top += 2;
2481 
2482 					{
2483 						// Draw text
2484 
2485 						TCHAR szText[1024];
2486 						TCHAR* pszPosition = szText;
2487 						TCHAR* pszName;
2488 						SIZE size = { 0, 0 };
2489 
2490 						SetTextColor(lplvcd->nmcd.hdc, lplvcd->clrText);
2491 						SetBkMode(lplvcd->nmcd.hdc, TRANSPARENT);
2492 
2493 						// Display the short name if needed
2494 						if (nLoadMenuShowY & SHOWSHORT) {
2495 							DrawText(lplvcd->nmcd.hdc, BurnDrvGetText(DRV_NAME), -1, &rect, DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER);
2496 							rect.left += 16 + 40 + 20 + 20;
2497 						}
2498 
2499 						{
2500 							// Draw icons if needed
2501 							if (!CheckWorkingStatus(((NODEINFO*)TvItem.lParam)->nBurnDrvNo)) {
2502 								DrawIconEx(lplvcd->nmcd.hdc, rect.left, rect.top, hNotWorking, nIconsSizeXY, nIconsSizeXY, 0, NULL, DI_NORMAL);
2503 								rect.left += nIconsSizeXY + 4;
2504 							} else {
2505 								if (!(gameAv[((NODEINFO*)TvItem.lParam)->nBurnDrvNo]) && !bSkipStartupCheck) {
2506 									DrawIconEx(lplvcd->nmcd.hdc, rect.left, rect.top, hNotFoundEss, nIconsSizeXY, nIconsSizeXY, 0, NULL, DI_NORMAL);
2507 									rect.left += nIconsSizeXY + 4;
2508 								} else {
2509 									if (!(nLoadMenuShowY & AVAILABLE) && !(gameAv[((NODEINFO*)TvItem.lParam)->nBurnDrvNo] & 2)) {
2510 										DrawIconEx(lplvcd->nmcd.hdc, rect.left, rect.top, hNotFoundNonEss, nIconsSizeXY, nIconsSizeXY, 0, NULL, DI_NORMAL);
2511 										rect.left += nIconsSizeXY + 4;
2512 									}
2513 								}
2514 							}
2515 						}
2516 
2517 						// Driver Icon drawing code...
2518 						if(bEnableIcons && bIconsLoaded) {
2519 							if(hDrvIcon[nBurnDrvActive]) {
2520 								DrawIconEx(lplvcd->nmcd.hdc, rect.left, rect.top, hDrvIcon[nBurnDrvActive], nIconsSizeXY, nIconsSizeXY, 0, NULL, DI_NORMAL);
2521 							}
2522 
2523 							if(!hDrvIcon[nBurnDrvActive]) {
2524 								DrawIconEx(lplvcd->nmcd.hdc, rect.left, rect.top, hDrvIconMiss, nIconsSizeXY, nIconsSizeXY, 0, NULL, DI_NORMAL);
2525 							}
2526 							rect.left += nIconsSizeXY + 4;
2527 						}
2528 
2529 						_tcsncpy(szText, MangleGamename(BurnDrvGetText(nGetTextFlags | DRV_FULLNAME), false), 1024);
2530 						szText[1023] = _T('\0');
2531 
2532 						GetTextExtentPoint32(lplvcd->nmcd.hdc, szText, _tcslen(szText), &size);
2533 
2534 						DrawText(lplvcd->nmcd.hdc, szText, -1, &rect, DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER);
2535 
2536 						// Display extra info if needed
2537 						szText[0] = _T('\0');
2538 
2539 						pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME);
2540 						while ((pszName = BurnDrvGetText(nGetTextFlags | DRV_NEXTNAME | DRV_FULLNAME)) != NULL) {
2541 							if (pszPosition + _tcslen(pszName) - 1024 > szText) {
2542 								break;
2543 							}
2544 							pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName);
2545 						}
2546 						if (szText[0]) {
2547 							szText[255] = _T('\0');
2548 
2549 							unsigned int r = ((lplvcd->clrText >> 16 & 255) * 2 + (lplvcd->clrTextBk >> 16 & 255)) / 3;
2550 							unsigned int g = ((lplvcd->clrText >>  8 & 255) * 2 + (lplvcd->clrTextBk >>  8 & 255)) / 3;
2551 							unsigned int b = ((lplvcd->clrText >>  0 & 255) * 2 + (lplvcd->clrTextBk >>  0 & 255)) / 3;
2552 
2553 							rect.left += size.cx;
2554 							SetTextColor(lplvcd->nmcd.hdc, (r << 16) | (g <<  8) | (b <<  0));
2555 							DrawText(lplvcd->nmcd.hdc, szText, -1, &rect, DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER);
2556 						}
2557 					}
2558 
2559 					DeleteObject(hBackBrush);
2560 
2561 					SetWindowLongPtr(hSelDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT);
2562 					return 1;
2563 				}
2564 
2565 				default: {
2566 					SetWindowLongPtr(hSelDlg, DWLP_MSGRESULT, CDRF_DODEFAULT);
2567 					return 1;
2568 				}
2569 			}
2570 		}
2571 
2572 		if (pNmHdr->code == TVN_ITEMEXPANDING && !TreeBuilding && LOWORD(wParam) == IDC_TREE1) {
2573 			SendMessage(hSelList, TVM_SELECTITEM, TVGN_CARET, (LPARAM)((LPNMTREEVIEW)lParam)->itemNew.hItem);
2574 			return FALSE;
2575 		}
2576 
2577 		if (pNmHdr->code == TVN_SELCHANGED && !TreeBuilding && LOWORD(wParam) == IDC_TREE1) {
2578 			HTREEITEM hSelectHandle = (HTREEITEM)SendMessage(hSelList, TVM_GETNEXTITEM, TVGN_CARET, ~0U);
2579 
2580 			// Search through nBurnDrv[] for the nBurnDrvNo according to the returned hSelectHandle
2581 			for (unsigned int i = 0; i < nTmpDrvCount; i++) {
2582 				if (hSelectHandle == nBurnDrv[i].hTreeHandle)
2583 				{
2584 					nBurnDrvActive	= nBurnDrv[i].nBurnDrvNo;
2585 					nDialogSelect	= nBurnDrvActive;
2586 					bDrvSelected	= true;
2587 					UpdatePreview(true, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V);
2588 					UpdatePreview(false, szAppTitlesPath, IDC_SCREENSHOT2_H, IDC_SCREENSHOT2_V);
2589 					break;
2590 				}
2591 			}
2592 
2593             CheckDlgButton(hDlg, IDC_SEL_APPLYIPS, BST_UNCHECKED);
2594 
2595             if (GetIpsNumPatches()) {
2596 				if (!nShowMVSCartsOnly) EnableWindow(GetDlgItem(hDlg, IDC_SEL_IPSMANAGER), TRUE);
2597 			} else {
2598 				EnableWindow(GetDlgItem(hDlg, IDC_SEL_IPSMANAGER), FALSE);
2599 			}
2600 
2601 			LoadIpsActivePatches();
2602 			if (GetIpsNumActivePatches()) {
2603 				if (!nShowMVSCartsOnly) EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), TRUE);
2604 			} else {
2605 				EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), FALSE);
2606 			}
2607 
2608 			// Get the text from the drivers via BurnDrvGetText()
2609 			for (int i = 0; i < 6; i++) {
2610 				int nGetTextFlags = nLoadMenuShowY & ASCIIONLY ? DRV_ASCIIONLY : 0;
2611 				TCHAR szItemText[256];
2612 				szItemText[0] = _T('\0');
2613 
2614 				switch (i) {
2615 					case 0: {
2616 						bool bBracket = false;
2617 
2618 						_stprintf(szItemText, _T("%s"), BurnDrvGetText(DRV_NAME));
2619 						if ((BurnDrvGetFlags() & BDF_CLONE) && BurnDrvGetTextA(DRV_PARENT)) {
2620 							int nOldDrvSelect = nBurnDrvActive;
2621 							TCHAR* pszName = BurnDrvGetText(DRV_PARENT);
2622 
2623 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_CLONE_OF, true), BurnDrvGetText(DRV_PARENT));
2624 
2625 							for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) {
2626 								if (!_tcsicmp(pszName, BurnDrvGetText(DRV_NAME))) {
2627 									break;
2628 								}
2629 							}
2630 							if (nBurnDrvActive < nBurnDrvCount) {
2631 								if (BurnDrvGetText(DRV_PARENT)) {
2632 									_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_ROMS_FROM_1, true), BurnDrvGetText(DRV_PARENT));
2633 								}
2634 							}
2635 							nBurnDrvActive = nOldDrvSelect;
2636 							bBracket = true;
2637 						} else {
2638 							if (BurnDrvGetTextA(DRV_PARENT)) {
2639 								_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_ROMS_FROM_2, true), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_PARENT));
2640 								bBracket = true;
2641 							}
2642 						}
2643 						if (BurnDrvGetTextA(DRV_SAMPLENAME)) {
2644 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SAMPLES_FROM, true), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_SAMPLENAME));
2645 							bBracket = true;
2646 						}
2647 						if (bBracket) {
2648 							_stprintf(szItemText + _tcslen(szItemText), _T(")"));
2649 						}
2650 						SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
2651 						EnableWindow(hInfoLabel[i], TRUE);
2652 						break;
2653 					}
2654 					case 1: {
2655 						bool bUseInfo = false;
2656 
2657 						if (BurnDrvGetFlags() & BDF_PROTOTYPE) {
2658 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_PROTOTYPE, true));
2659 							bUseInfo = true;
2660 						}
2661 						if (BurnDrvGetFlags() & BDF_BOOTLEG) {
2662 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_BOOTLEG, true), bUseInfo ? _T(", ") : _T(""));
2663 							bUseInfo = true;
2664 						}
2665 						if (BurnDrvGetFlags() & BDF_HACK) {
2666 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_HACK, true), bUseInfo ? _T(", ") : _T(""));
2667 							bUseInfo = true;
2668 						}
2669 						if (BurnDrvGetFlags() & BDF_HOMEBREW) {
2670 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_HOMEBREW, true), bUseInfo ? _T(", ") : _T(""));
2671 							bUseInfo = true;
2672 						}
2673 						if (BurnDrvGetFlags() & BDF_DEMO) {
2674 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_DEMO, true), bUseInfo ? _T(", ") : _T(""));
2675 							bUseInfo = true;
2676 						}
2677 						TCHAR szPlayersMax[100];
2678 						_stprintf(szPlayersMax, FBALoadStringEx(hAppInst, IDS_NUM_PLAYERS_MAX, true));
2679 						_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_NUM_PLAYERS, true), bUseInfo ? _T(", ") : _T(""), BurnDrvGetMaxPlayers(), (BurnDrvGetMaxPlayers() != 1) ? szPlayersMax : _T(""));
2680 						bUseInfo = true;
2681 						if (BurnDrvGetText(DRV_BOARDROM)) {
2682 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_BOARD_ROMS_FROM, true), bUseInfo ? _T(", ") : _T(""), BurnDrvGetText(DRV_BOARDROM));
2683 							SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
2684 							EnableWindow(hInfoLabel[i], TRUE);
2685 							bUseInfo = true;
2686 						}
2687 						SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
2688 						EnableWindow(hInfoLabel[i], bUseInfo);
2689 						break;
2690 					}
2691 					case 2: {
2692 						TCHAR szUnknown[100];
2693 						TCHAR szCartridge[100];
2694 						_stprintf(szUnknown, FBALoadStringEx(hAppInst, IDS_ERR_UNKNOWN, true));
2695 						_stprintf(szCartridge, FBALoadStringEx(hAppInst, IDS_MVS_CARTRIDGE, true));
2696 						_stprintf(szItemText, FBALoadStringEx(hAppInst, IDS_HARDWARE_DESC, true), BurnDrvGetTextA(DRV_MANUFACTURER) ? BurnDrvGetText(nGetTextFlags | DRV_MANUFACTURER) : szUnknown, BurnDrvGetText(DRV_DATE), (((BurnDrvGetHardwareCode() & HARDWARE_SNK_MVS) == HARDWARE_SNK_MVS) && ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK)) == HARDWARE_SNK_NEOGEO)? szCartridge : BurnDrvGetText(nGetTextFlags | DRV_SYSTEM));
2697 						SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
2698 						EnableWindow(hInfoLabel[i], TRUE);
2699 						break;
2700 					}
2701 					case 3: {
2702 						TCHAR szText[1024] = _T("");
2703 						TCHAR* pszPosition = szText;
2704 						TCHAR* pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME);
2705 
2706 						pszPosition += _sntprintf(szText, 1024, pszName);
2707 
2708 						pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME);
2709 						while ((pszName = BurnDrvGetText(nGetTextFlags | DRV_NEXTNAME | DRV_FULLNAME)) != NULL) {
2710 							if (pszPosition + _tcslen(pszName) - 1024 > szText) {
2711 								break;
2712 							}
2713 							pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName);
2714 						}
2715 						SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szText);
2716 						if (szText[0]) {
2717 							EnableWindow(hInfoLabel[i], TRUE);
2718 						} else {
2719 							EnableWindow(hInfoLabel[i], FALSE);
2720 						}
2721 						break;
2722 					}
2723 					case 4: {
2724 						_stprintf(szItemText, _T("%s"), BurnDrvGetTextA(DRV_COMMENT) ? BurnDrvGetText(nGetTextFlags | DRV_COMMENT) : _T(""));
2725 						if (BurnDrvGetFlags() & BDF_HISCORE_SUPPORTED) {
2726 							_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_HISCORES_SUPPORTED, true), _tcslen(szItemText) ? _T(", ") : _T(""));
2727 						}
2728 						SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
2729 						EnableWindow(hInfoLabel[i], TRUE);
2730 						break;
2731 					}
2732 
2733 					case 5: {
2734 						_stprintf(szItemText, _T("%s"), DecorateGenreInfo());
2735 						SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
2736 						EnableWindow(hInfoLabel[i], TRUE);
2737 						break;
2738 					}
2739 				}
2740 			}
2741 		}
2742 
2743 		if(!TreeBuilding && pnmtv->hdr.code == NM_RCLICK && pnmtv->hdr.idFrom == IDC_TREE1)
2744 		{
2745 			DWORD dwpos = GetMessagePos();
2746 
2747 			TVHITTESTINFO thi;
2748 			thi.pt.x	= GET_X_LPARAM(dwpos);
2749 			thi.pt.y	= GET_Y_LPARAM(dwpos);
2750 
2751 			MapWindowPoints(HWND_DESKTOP, pNmHdr->hwndFrom, &thi.pt, 1);
2752 
2753 			TreeView_HitTest(pNmHdr->hwndFrom, &thi);
2754 
2755 			HTREEITEM hSelectHandle = thi.hItem;
2756          	if(hSelectHandle == NULL) return 1;
2757 
2758 			TreeView_SelectItem(hSelList, hSelectHandle);
2759 
2760 			// Search through nBurnDrv[] for the nBurnDrvNo according to the returned hSelectHandle
2761 			for (unsigned int i = 0; i < nTmpDrvCount; i++) {
2762 				if (hSelectHandle == nBurnDrv[i].hTreeHandle) {
2763 					nBurnDrvSelect[0] = nBurnDrv[i].nBurnDrvNo;
2764 					break;
2765 				}
2766 			}
2767 
2768 			nDialogSelect	= nBurnDrvSelect[0];
2769 			bDrvSelected	= true;
2770 			UpdatePreview(true, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V);
2771 			UpdatePreview(false, szAppTitlesPath, IDC_SCREENSHOT2_H, IDC_SCREENSHOT2_V);
2772 
2773 			// Menu
2774 			POINT oPoint;
2775 			GetCursorPos(&oPoint);
2776 
2777 			HMENU hMenuLoad = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_GAMESEL));
2778 			HMENU hMenuX = GetSubMenu(hMenuLoad, 0);
2779 
2780 			CheckMenuItem(hMenuX, GAMESEL_MENU_FAVORITE, (CheckFavorites(BurnDrvGetTextA(DRV_NAME)) != -1) ? MF_CHECKED : MF_UNCHECKED);
2781 
2782 			TrackPopupMenu(hMenuX, TPM_LEFTALIGN | TPM_RIGHTBUTTON, oPoint.x, oPoint.y, 0, hSelDlg, NULL);
2783 			DestroyMenu(hMenuLoad);
2784 
2785 			return 1;
2786 		}
2787 	}
2788 	return 0;
2789 }
2790 
SelDialog(int nMVSCartsOnly,HWND hParentWND)2791 int SelDialog(int nMVSCartsOnly, HWND hParentWND)
2792 {
2793 	int nOldSelect = nBurnDrvActive;
2794 
2795 	if(bDrvOkay) {
2796 		nOldDlgSelected = nBurnDrvActive;
2797 	}
2798 
2799 	hParent = hParentWND;
2800 	nShowMVSCartsOnly = nMVSCartsOnly;
2801 
2802 	InitCommonControls();
2803 
2804 	FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SELNEW), hParent, (DLGPROC)DialogProc);
2805 
2806 	hSelDlg = NULL;
2807 	hSelList = NULL;
2808 
2809 	if (nBurnDrv) {
2810 		free(nBurnDrv);
2811 		nBurnDrv = NULL;
2812 	}
2813 
2814 	nBurnDrvActive = nOldSelect;
2815 
2816 	return nDialogSelect;
2817 }
2818 
2819 // -----------------------------------------------------------------------------
2820 
2821 static HBITMAP hMVSpreview[6];
2822 static unsigned int nPrevDrvSelect[6];
2823 
UpdateInfoROMInfo()2824 static void UpdateInfoROMInfo()
2825 {
2826 //	int nGetTextFlags = nLoadMenuShowY & ASCIIONLY ? DRV_ASCIIONLY : 0;
2827 	TCHAR szItemText[256] = _T("");
2828 	bool bBracket = false;
2829 
2830 	_stprintf(szItemText, _T("%s"), BurnDrvGetText(DRV_NAME));
2831 	if ((BurnDrvGetFlags() & BDF_CLONE) && BurnDrvGetTextA(DRV_PARENT)) {
2832 		int nOldDrvSelect = nBurnDrvActive;
2833 		TCHAR* pszName = BurnDrvGetText(DRV_PARENT);
2834 
2835 		_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_CLONE_OF, true), BurnDrvGetText(DRV_PARENT));
2836 
2837 		for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) {
2838 			if (!_tcsicmp(pszName, BurnDrvGetText(DRV_NAME))) {
2839 				break;
2840 			}
2841 		}
2842 		if (nBurnDrvActive < nBurnDrvCount) {
2843 			if (BurnDrvGetText(DRV_PARENT)) {
2844 				_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_ROMS_FROM_1, true), BurnDrvGetText(DRV_PARENT));
2845 			}
2846 		}
2847 		nBurnDrvActive = nOldDrvSelect;
2848 		bBracket = true;
2849 	} else {
2850 		if (BurnDrvGetTextA(DRV_PARENT)) {
2851 			_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_ROMS_FROM_2, true), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_PARENT));
2852 			bBracket = true;
2853 		}
2854 	}
2855 	if (BurnDrvGetText(DRV_BOARDROM)) {
2856 		_stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_BOARD_ROMS_FROM, true), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_BOARDROM));
2857 		bBracket = true;
2858 	}
2859 	if (bBracket) {
2860 		_stprintf(szItemText + _tcslen(szItemText), _T(")"));
2861 	}
2862 
2863 	if (hInfoText[0]) {
2864 		SendMessage(hInfoText[0], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
2865 	}
2866 	if (hInfoLabel[0]) {
2867 		EnableWindow(hInfoLabel[0], TRUE);
2868 	}
2869 
2870 	return;
2871 }
2872 
UpdateInfoRelease()2873 static void UpdateInfoRelease()
2874 {
2875 	int nGetTextFlags = nLoadMenuShowY & ASCIIONLY ? DRV_ASCIIONLY : 0;
2876 	TCHAR szItemText[256] = _T("");
2877 
2878 	TCHAR szUnknown[100];
2879 	TCHAR szCartridge[100];
2880 	TCHAR szHardware[100];
2881 	_stprintf(szUnknown, FBALoadStringEx(hAppInst, IDS_ERR_UNKNOWN, true));
2882 	_stprintf(szCartridge, FBALoadStringEx(hAppInst, IDS_CARTRIDGE, true));
2883 	_stprintf(szHardware, FBALoadStringEx(hAppInst, IDS_HARDWARE, true));
2884 	_stprintf(szItemText, _T("%s (%s, %s %s)"), BurnDrvGetTextA(DRV_MANUFACTURER) ? BurnDrvGetText(nGetTextFlags | DRV_MANUFACTURER) : szUnknown, BurnDrvGetText(DRV_DATE),
2885 		BurnDrvGetText(nGetTextFlags | DRV_SYSTEM), (BurnDrvGetHardwareCode() & HARDWARE_PREFIX_CARTRIDGE) ? szCartridge : szHardware);
2886 
2887 	if (hInfoText[2]) {
2888 		SendMessage(hInfoText[2], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
2889 	}
2890 	if (hInfoLabel[2]) {
2891 		EnableWindow(hInfoLabel[2], TRUE);
2892 	}
2893 
2894 	return;
2895 }
2896 
UpdateInfoGameInfo()2897 static void UpdateInfoGameInfo()
2898 {
2899 	int nGetTextFlags = nLoadMenuShowY & ASCIIONLY ? DRV_ASCIIONLY : 0;
2900 	TCHAR szText[1024] = _T("");
2901 	TCHAR* pszPosition = szText;
2902 	TCHAR* pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME);
2903 
2904 	pszPosition += _sntprintf(szText, 1024, pszName);
2905 
2906 	pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME);
2907 	while ((pszName = BurnDrvGetText(nGetTextFlags | DRV_NEXTNAME | DRV_FULLNAME)) != NULL) {
2908 		if (pszPosition + _tcslen(pszName) - 1024 > szText) {
2909 			break;
2910 		}
2911 		pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName);
2912 	}
2913 	if (BurnDrvGetText(nGetTextFlags | DRV_COMMENT)) {
2914 		pszPosition += _sntprintf(pszPosition, szText + 1024 - pszPosition, _T(SEPERATOR_1) _T("%s"), BurnDrvGetText(nGetTextFlags | DRV_COMMENT));
2915 	}
2916 
2917 	if (hInfoText[3]) {
2918 		SendMessage(hInfoText[3], WM_SETTEXT, (WPARAM)0, (LPARAM)szText);
2919 	}
2920 	if (hInfoLabel[3]) {
2921 		if (szText[0]) {
2922 			EnableWindow(hInfoLabel[3], TRUE);
2923 		} else {
2924 			EnableWindow(hInfoLabel[3], FALSE);
2925 		}
2926 	}
2927 
2928 	return;
2929 }
2930 
MVSpreviewUpdateSlot(int nSlot,HWND hDlg)2931 static int MVSpreviewUpdateSlot(int nSlot, HWND hDlg)
2932 {
2933 	int nOldSelect = nBurnDrvActive;
2934 
2935 	if (nSlot >= 0 && nSlot < 6) {
2936 		hInfoLabel[0] = 0; hInfoLabel[1] = 0; hInfoLabel[2] = 0; hInfoLabel[3] = 0;
2937 		hInfoText[0] = GetDlgItem(hDlg, IDC_MVS_TEXTROMNAME1 + nSlot);
2938 		hInfoText[1] = 0;
2939 		hInfoText[2] = GetDlgItem(hDlg, IDC_MVS_TEXTSYSTEM1 + nSlot);
2940 		hInfoText[3] = GetDlgItem(hDlg, IDC_MVS_TEXTCOMMENT1 + nSlot);
2941 
2942 		for (int j = 0; j < 4; j++) {
2943 			if (hInfoText[j]) {
2944 				SendMessage(hInfoText[j], WM_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
2945 			}
2946 			if (hInfoLabel[j]) {
2947 				EnableWindow(hInfoLabel[j], FALSE);
2948 			}
2949 		}
2950 
2951 		nBurnDrvActive = nBurnDrvSelect[nSlot];
2952 		if (nBurnDrvActive < nBurnDrvCount) {
2953 
2954 			FILE* fp = OpenPreview(0, szAppTitlesPath);
2955 			if (fp) {
2956 				hMVSpreview[nSlot] = PNGLoadBitmap(hDlg, fp, 72, 54, 5);
2957 				fclose(fp);
2958 			} else {
2959 				hMVSpreview[nSlot] = PNGLoadBitmap(hDlg, NULL, 72, 54, 4);
2960 			}
2961 
2962 			UpdateInfoROMInfo();
2963 			UpdateInfoRelease();
2964 			UpdateInfoGameInfo();
2965 			nPrevDrvSelect[nSlot] = nBurnDrvActive;
2966 
2967 		} else {
2968 			hMVSpreview[nSlot] = PNGLoadBitmap(hDlg, NULL, 72, 54, 4);
2969 			SendMessage(hInfoText[0], WM_SETTEXT, (WPARAM)0, (LPARAM)FBALoadStringEx(hAppInst, IDS_EMPTY, true));
2970 		}
2971 
2972 		SendDlgItemMessage(hDlg, IDC_MVS_CART1 + nSlot, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hMVSpreview[nSlot]);
2973 	}
2974 
2975 	nBurnDrvActive = nOldSelect;
2976 
2977 	return 0;
2978 }
2979 
MVSpreviewEndDialog()2980 static int MVSpreviewEndDialog()
2981 {
2982 	for (int i = 0; i < 6; i++) {
2983 		DeleteObject((HGDIOBJ)hMVSpreview[i]);
2984 		hMVSpreview[i] = NULL;
2985 	}
2986 
2987 	return 0;
2988 }
2989 
MVSpreviewProc(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM)2990 static INT_PTR CALLBACK MVSpreviewProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM)
2991 {
2992 	switch (Msg) {
2993 		case WM_INITDIALOG: {
2994 
2995 			nDialogSelect = ~0U;
2996 
2997 			for (int i = 0; i < 6; i++) {
2998 				nPrevDrvSelect[i] = nBurnDrvSelect[i];
2999 				MVSpreviewUpdateSlot(i, hDlg);
3000 			}
3001 
3002 			WndInMid(hDlg, hScrnWnd);
3003 
3004 			return TRUE;
3005 		}
3006 		case WM_COMMAND:
3007 			if (LOWORD(wParam) == ID_VALUE_CLOSE) {
3008 				SendMessage(hDlg, WM_CLOSE, 0, 0);
3009 				break;
3010 			}
3011 			if (HIWORD(wParam) == BN_CLICKED) {
3012 				if (LOWORD(wParam) == IDOK) {
3013 					if (nPrevDrvSelect[0] == ~0U) {
3014 						MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NO_DRIVER_SEL_SLOT1, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK);
3015 						break;
3016 					}
3017 					MVSpreviewEndDialog();
3018 					for (int i = 0; i < 6; i++) {
3019 						nBurnDrvSelect[i] = nPrevDrvSelect[i];
3020 					}
3021 					EndDialog(hDlg, 0);
3022 					break;
3023 				}
3024 				if (LOWORD(wParam) == IDCANCEL) {
3025 					SendMessage(hDlg, WM_CLOSE, 0, 0);
3026 					break;
3027 				}
3028 
3029 				if (LOWORD(wParam) >= IDC_MVS_CLEAR1 && LOWORD(wParam) <= IDC_MVS_CLEAR6) {
3030 					int nSlot = LOWORD(wParam) - IDC_MVS_CLEAR1;
3031 
3032 					nBurnDrvSelect[nSlot] = ~0U;
3033 					nPrevDrvSelect[nSlot] = ~0U;
3034 					MVSpreviewUpdateSlot(nSlot, hDlg);
3035 					break;
3036 				}
3037 
3038 				if (LOWORD(wParam) >= IDC_MVS_SELECT1 && LOWORD(wParam) <= IDC_MVS_SELECT6) {
3039 					int nSlot = LOWORD(wParam) - IDC_MVS_SELECT1;
3040 
3041 					nBurnDrvSelect[nSlot] = SelDialog(HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, hDlg);
3042 					MVSpreviewUpdateSlot(nSlot, hDlg);
3043 					break;
3044 				}
3045 			}
3046 			break;
3047 
3048 		case WM_CLOSE: {
3049 			MVSpreviewEndDialog();
3050 			for (int i = 0; i < 6; i++) {
3051 				nBurnDrvSelect[i] = nPrevDrvSelect[i];
3052 			}
3053 			EndDialog(hDlg, 1);
3054 			break;
3055 		}
3056 	}
3057 
3058 	return 0;
3059 }
3060 
SelMVSDialog()3061 int SelMVSDialog()
3062 {
3063 	return FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_MVS_SELECT_CARTS), hScrnWnd, (DLGPROC)MVSpreviewProc);
3064 }
3065