1 // FBAlpha Game Info and Favorites handling
2 #include "burner.h"
3
4 static HWND hGameInfoDlg = NULL;
5 static HWND hParent = NULL;
6 static HWND hTabControl = NULL;
7 static HMODULE hRiched = NULL;
8 static HBITMAP hPreview = NULL;
9 HBITMAP hGiBmp = NULL;
10 static TCHAR szFullName[1024];
11 static int nGiDriverSelected;
12 static HBRUSH hWhiteBGBrush;
13
OpenPreview(TCHAR * szPath)14 static FILE* OpenPreview(TCHAR *szPath)
15 {
16 TCHAR szBaseName[MAX_PATH];
17 TCHAR szFileName[MAX_PATH];
18
19 FILE* fp = NULL;
20
21 // Try to load a .PNG preview image
22 _sntprintf(szBaseName, sizeof(szBaseName), _T("%s%s"), szPath, BurnDrvGetText(DRV_NAME));
23 _stprintf(szFileName, _T("%s.png"), szBaseName);
24 fp = _tfopen(szFileName, _T("rb"));
25
26 if (!fp && BurnDrvGetText(DRV_PARENT)) { // Try the parent
27 _sntprintf(szBaseName, sizeof(szBaseName), _T("%s%s"), szPath, BurnDrvGetText(DRV_PARENT));
28 _stprintf(szFileName, _T("%s.png"), szBaseName);
29 fp = _tfopen(szFileName, _T("rb"));
30 }
31
32 return fp;
33 }
34
35 #define IMG_MAX_HEIGHT 380
36 #define IMG_MAX_WIDTH 700
37 #define IMG_DEFAULT_WIDTH 506
38 #define IMG_DEFAULT_WIDTH_V 285
39 #define IMG_ASPECT_4_3 1
40 #define IMG_ASPECT_PRESERVE 2
41
SetPreview(TCHAR * szPreviewDir,int nAspectFlag)42 static void SetPreview(TCHAR* szPreviewDir, int nAspectFlag)
43 {
44 HWND hDlg = hGameInfoDlg;
45
46 HBITMAP hNewImage = NULL;
47
48 if (hGiBmp) {
49 DeleteObject((HGDIOBJ)hGiBmp);
50 hGiBmp = NULL;
51 }
52
53 // get image dimensions and work out what to resize to (default to 4:3)
54 IMAGE img = { 0, 0, 0, 0, NULL, NULL, 0};
55 int img_width = IMG_DEFAULT_WIDTH;
56 int img_height = IMG_MAX_HEIGHT;
57
58 FILE *fp = OpenPreview(szPreviewDir);
59 if (fp) {
60 PNGGetInfo(&img, fp);
61
62 // vertical 3:4
63 if (img.height > img.width) {
64 img_width = IMG_DEFAULT_WIDTH_V;
65 }
66
67 // preserve aspect support
68 if (nAspectFlag == IMG_ASPECT_PRESERVE) {
69 double nAspect = (double)img.width / img.height;
70 img_width = (int)((double)IMG_MAX_HEIGHT * nAspect);
71
72 if (img_width > IMG_MAX_WIDTH) {
73 img_width = IMG_MAX_WIDTH;
74 img_height = (int)((double)IMG_MAX_WIDTH / nAspect);
75 }
76 }
77
78 img_free(&img);
79 fclose(fp);
80 }
81
82 fp = OpenPreview(szPreviewDir);
83 if (fp) {
84 hNewImage = PNGLoadBitmap(hDlg, fp, img_width, img_height, 3);
85 fclose(fp);
86 }
87
88 if (hNewImage) {
89
90 if(hGiBmp) DeleteObject((HGDIOBJ)hGiBmp);
91
92 hGiBmp = hNewImage;
93
94 if (bPngImageOrientation == 0) {
95 SendDlgItemMessage(hDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hGiBmp);
96 SendDlgItemMessage(hDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
97 ShowWindow(GetDlgItem(hDlg, IDC_SCREENSHOT_V), SW_HIDE);
98 } else {
99 SendDlgItemMessage(hDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
100 ShowWindow(GetDlgItem(hDlg, IDC_SCREENSHOT_V), SW_SHOW);
101 SendDlgItemMessage(hDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hGiBmp);
102 }
103
104 } else {
105 SendDlgItemMessage(hDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)LoadBitmap(hAppInst, MAKEINTRESOURCE(BMP_SPLASH)));
106 SendDlgItemMessage(hDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
107 ShowWindow(GetDlgItem(hDlg, IDC_SCREENSHOT_V), SW_HIDE);
108 }
109 }
110
DisplayRomInfo()111 static int DisplayRomInfo()
112 {
113 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_SCREENSHOT_H), SW_HIDE);
114 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_MESSAGE_EDIT_ENG), SW_HIDE);
115 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST1), SW_SHOW);
116 UpdateWindow(hGameInfoDlg);
117
118 return 0;
119 }
120
DisplayHDDInfo()121 static int DisplayHDDInfo()
122 {
123 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_SCREENSHOT_H), SW_HIDE);
124 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_MESSAGE_EDIT_ENG), SW_HIDE);
125 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST3), SW_SHOW);
126 UpdateWindow(hGameInfoDlg);
127
128 return 0;
129 }
130
DisplaySampleInfo()131 static int DisplaySampleInfo()
132 {
133 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_SCREENSHOT_H), SW_HIDE);
134 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_MESSAGE_EDIT_ENG), SW_HIDE);
135 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST2), SW_SHOW);
136 UpdateWindow(hGameInfoDlg);
137
138 return 0;
139 }
140
DisplayHistory()141 static int DisplayHistory()
142 {
143 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_SCREENSHOT_H), SW_HIDE);
144 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST1), SW_HIDE);
145 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST2), SW_HIDE);
146 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST3), SW_HIDE);
147 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_MESSAGE_EDIT_ENG), SW_SHOW);
148 UpdateWindow(hGameInfoDlg);
149
150 return 0;
151 }
152
153 // make gcc 8.x happy about sprintf() usage below...
154 #if __GNUC__ == 8
155 #pragma GCC diagnostic push
156 #pragma GCC diagnostic ignored "-Wformat-overflow="
157 #endif
158
GameInfoInit()159 static int GameInfoInit()
160 {
161 // Get the games full name
162 TCHAR szText[1024] = _T("");
163 TCHAR* pszPosition = szText;
164 TCHAR* pszName = BurnDrvGetText(DRV_FULLNAME);
165
166 pszPosition += _sntprintf(szText, 1024, pszName);
167
168 pszName = BurnDrvGetText(DRV_FULLNAME);
169 while ((pszName = BurnDrvGetText(DRV_NEXTNAME | DRV_FULLNAME)) != NULL) {
170 if (pszPosition + _tcslen(pszName) - 1024 > szText) {
171 break;
172 }
173 pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName);
174 }
175
176 _tcscpy(szFullName, szText);
177
178 _stprintf(szText, _T("%s") _T(SEPERATOR_1) _T("%s"), FBALoadStringEx(hAppInst, IDS_GAMEINFO_DIALOGTITLE, true), szFullName);
179
180 // Set the window caption
181 SetWindowText(hGameInfoDlg, szText);
182
183 // Setup the tabs
184 hTabControl = GetDlgItem(hGameInfoDlg, IDC_TAB1);
185 TC_ITEM TCI;
186 TCI.mask = TCIF_TEXT;
187
188 UINT idsString[17] = { IDS_GAMEINFO_ROMINFO, IDS_GAMEINFO_HDD, IDS_GAMEINFO_SAMPLES, IDS_GAMEINFO_HISTORY, IDS_GAMEINFO_INGAME, IDS_GAMEINFO_TITLE, IDS_GAMEINFO_SELECT, IDS_GAMEINFO_VERSUS, IDS_GAMEINFO_HOWTO, IDS_GAMEINFO_SCORES, IDS_GAMEINFO_BOSSES, IDS_GAMEINFO_GAMEOVER, IDS_GAMEINFO_FLYER, IDS_GAMEINFO_CABINET, IDS_GAMEINFO_MARQUEE, IDS_GAMEINFO_CONTROLS, IDS_GAMEINFO_PCB };
189
190 for(int i = 0; i < 17; i++) {
191 TCI.pszText = FBALoadStringEx(hAppInst, idsString[i], true);
192 SendMessage(hTabControl, TCM_INSERTITEM, (WPARAM) i, (LPARAM) &TCI);
193 }
194
195 // Load the preview image
196 hPreview = LoadBitmap(hAppInst, MAKEINTRESOURCE(BMP_SPLASH));
197
198 // Display preview image
199 SendDlgItemMessage(hGameInfoDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
200 SendDlgItemMessage(hGameInfoDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
201
202 // Favorite game checkbox
203 CheckDlgButton(hGameInfoDlg,IDFAVORITESET,(CheckFavorites(BurnDrvGetTextA(DRV_NAME)) != -1) ? BST_CHECKED : BST_UNCHECKED);
204
205 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST1), SW_HIDE);
206 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST2), SW_HIDE);
207 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST3), SW_HIDE);
208 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_MESSAGE_EDIT_ENG), SW_HIDE);
209 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_SCREENSHOT_H), SW_SHOW);
210 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_SCREENSHOT_V), SW_SHOW);
211 UpdateWindow(hGameInfoDlg);
212
213 nBurnDrvActive = nGiDriverSelected;
214 DisplayRomInfo();
215
216 // Display the game title
217 TCHAR szItemText[1024];
218 HWND hInfoControl = GetDlgItem(hGameInfoDlg, IDC_TEXTCOMMENT);
219 SendMessage(hInfoControl, WM_SETTEXT, (WPARAM)0, (LPARAM)szFullName);
220
221 // Display the romname
222 bool bBracket = false;
223 hInfoControl = GetDlgItem(hGameInfoDlg, IDC_TEXTROMNAME);
224 _stprintf(szItemText, _T("%s"), BurnDrvGetText(DRV_NAME));
225 if ((BurnDrvGetFlags() & BDF_CLONE) && BurnDrvGetTextA(DRV_PARENT)) {
226 int nOldDrvSelect = nBurnDrvActive;
227 pszName = BurnDrvGetText(DRV_PARENT);
228
229 _stprintf(szItemText + _tcslen(szItemText), _T(" (clone of %s"), BurnDrvGetText(DRV_PARENT));
230
231 for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) {
232 if (!_tcsicmp(pszName, BurnDrvGetText(DRV_NAME))) {
233 break;
234 }
235 }
236 if (nBurnDrvActive < nBurnDrvCount) {
237 if (BurnDrvGetText(DRV_PARENT)) {
238 _stprintf(szItemText + _tcslen(szItemText), _T(", uses ROMs from %s"), BurnDrvGetText(DRV_PARENT));
239 }
240 }
241 nBurnDrvActive = nOldDrvSelect;
242 bBracket = true;
243 } else {
244 if (BurnDrvGetTextA(DRV_PARENT)) {
245 _stprintf(szItemText + _tcslen(szItemText), _T("%suses ROMs from %s"), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_PARENT));
246 bBracket = true;
247 }
248 }
249 if (BurnDrvGetTextA(DRV_SAMPLENAME)) {
250 _stprintf(szItemText + _tcslen(szItemText), _T("%suses samples from %s"), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_SAMPLENAME));
251 bBracket = true;
252 }
253 if (bBracket) {
254 _stprintf(szItemText + _tcslen(szItemText), _T(")"));
255 }
256 SendMessage(hInfoControl, WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
257
258 //Display the rom info
259 bool bUseInfo = false;
260 szItemText[0] = _T('\0');
261 hInfoControl = GetDlgItem(hGameInfoDlg, IDC_TEXTROMINFO);
262 if (BurnDrvGetFlags() & BDF_PROTOTYPE) {
263 _stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_PROTOTYPE, true));
264 bUseInfo = true;
265 }
266 if (BurnDrvGetFlags() & BDF_BOOTLEG) {
267 _stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_BOOTLEG, true), bUseInfo ? _T(", ") : _T(""));
268 bUseInfo = true;
269 }
270 if (BurnDrvGetFlags() & BDF_HACK) {
271 _stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_HACK, true), bUseInfo ? _T(", ") : _T(""));
272 bUseInfo = true;
273 }
274 if (BurnDrvGetFlags() & BDF_HOMEBREW) {
275 _stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_HOMEBREW, true), bUseInfo ? _T(", ") : _T(""));
276 bUseInfo = true;
277 }
278 if (BurnDrvGetFlags() & BDF_DEMO) {
279 _stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_SEL_DEMO, true), bUseInfo ? _T(", ") : _T(""));
280 bUseInfo = true;
281 }
282 TCHAR szPlayersMax[100];
283 _stprintf(szPlayersMax, FBALoadStringEx(hAppInst, IDS_NUM_PLAYERS_MAX, true));
284 _stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_NUM_PLAYERS, true), bUseInfo ? _T(", ") : _T(""), BurnDrvGetMaxPlayers(), (BurnDrvGetMaxPlayers() != 1) ? szPlayersMax : _T(""));
285 bUseInfo = true;
286 if (BurnDrvGetText(DRV_BOARDROM)) {
287 _stprintf(szItemText + _tcslen(szItemText), FBALoadStringEx(hAppInst, IDS_BOARD_ROMS_FROM, true), bUseInfo ? _T(", ") : _T(""), BurnDrvGetText(DRV_BOARDROM));
288 SendMessage(hInfoControl, WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
289 bUseInfo = true;
290 }
291 SendMessage(hInfoControl, WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
292
293 // Display the release info
294 szItemText[0] = _T('\0');
295 hInfoControl = GetDlgItem(hGameInfoDlg, IDC_TEXTSYSTEM);
296 TCHAR szUnknown[100];
297 TCHAR szCartridge[100];
298 _stprintf(szUnknown, FBALoadStringEx(hAppInst, IDS_ERR_UNKNOWN, true));
299 _stprintf(szCartridge, FBALoadStringEx(hAppInst, IDS_MVS_CARTRIDGE, true));
300 _stprintf(szItemText, FBALoadStringEx(hAppInst, IDS_HARDWARE_DESC, true), BurnDrvGetTextA(DRV_MANUFACTURER) ? BurnDrvGetText(DRV_MANUFACTURER) : szUnknown, BurnDrvGetText(DRV_DATE), (((BurnDrvGetHardwareCode() & HARDWARE_SNK_MVS) == HARDWARE_SNK_MVS) && ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK)) == HARDWARE_SNK_NEOGEO)? szCartridge : BurnDrvGetText(DRV_SYSTEM));
301 SendMessage(hInfoControl, WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
302
303 // Display any comments
304 szItemText[0] = _T('\0');
305 hInfoControl = GetDlgItem(hGameInfoDlg, IDC_TEXTNOTES);
306 _stprintf(szItemText, _T("%s"), BurnDrvGetTextA(DRV_COMMENT) ? BurnDrvGetText(DRV_COMMENT) : _T(""));
307 if (BurnDrvGetFlags() & BDF_HISCORE_SUPPORTED) {
308 _stprintf(szItemText + _tcslen(szItemText), _T("%shigh scores supported"), _tcslen(szItemText) ? _T(", ") : _T(""));
309 }
310 SendMessage(hInfoControl, WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
311
312 // Display the genre
313 szItemText[0] = _T('\0');
314 hInfoControl = GetDlgItem(hGameInfoDlg, IDC_TEXTGENRE);
315 _stprintf(szItemText, _T("%s"), DecorateGenreInfo());
316 SendMessage(hInfoControl, WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText);
317
318 // Set up the rom info list
319 HWND hList = GetDlgItem(hGameInfoDlg, IDC_LIST1);
320 LV_COLUMN LvCol;
321 LV_ITEM LvItem;
322
323 ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);
324
325 memset(&LvCol, 0, sizeof(LvCol));
326 LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
327 LvCol.cx = 200;
328 LvCol.pszText = _T("Name");
329 SendMessage(hList, LVM_INSERTCOLUMN , 0, (LPARAM)&LvCol);
330 LvCol.cx = 100;
331 LvCol.pszText = _T("Size (bytes)");
332 SendMessage(hList, LVM_INSERTCOLUMN , 1, (LPARAM)&LvCol);
333 LvCol.cx = 100;
334 LvCol.pszText = _T("CRC32");
335 SendMessage(hList, LVM_INSERTCOLUMN , 2, (LPARAM)&LvCol);
336 LvCol.cx = 200;
337 LvCol.pszText = _T("Type");
338 SendMessage(hList, LVM_INSERTCOLUMN , 3, (LPARAM)&LvCol);
339 LvCol.cx = 100;
340 LvCol.pszText = _T("Flags");
341 SendMessage(hList, LVM_INSERTCOLUMN , 4, (LPARAM)&LvCol);
342 LvCol.cx = 100;
343
344 memset(&LvItem, 0, sizeof(LvItem));
345 LvItem.mask= LVIF_TEXT;
346 LvItem.cchTextMax = 256;
347 int RomPos = 0;
348 for (int i = 0; i < 0x100; i++) { // assume max 0x100 roms per game
349 int nRet;
350 struct BurnRomInfo ri;
351 char nLen[10] = "";
352 char nCrc[10] = "";
353 char *szRomName = NULL;
354 char Type[100] = "";
355 char FormatType[100] = "";
356
357 memset(&ri, 0, sizeof(ri));
358
359 nRet = BurnDrvGetRomInfo(&ri, i);
360 nRet += BurnDrvGetRomName(&szRomName, i, 0);
361
362 if (ri.nLen == 0) continue;
363 if (ri.nType & BRF_BIOS) continue;
364
365 LvItem.iItem = RomPos;
366 LvItem.iSubItem = 0;
367 LvItem.pszText = ANSIToTCHAR(szRomName, NULL, 0);
368 SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem);
369
370 sprintf(nLen, "%d", ri.nLen);
371 LvItem.iSubItem = 1;
372 LvItem.pszText = ANSIToTCHAR(nLen, NULL, 0);
373 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
374
375 sprintf(nCrc, "%08X", ri.nCrc);
376 if (!(ri.nType & BRF_NODUMP)) {
377 LvItem.iSubItem = 2;
378 LvItem.pszText = ANSIToTCHAR(nCrc, NULL, 0);
379 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
380 }
381
382 if (ri.nType & BRF_ESS) sprintf(Type, "%s, Essential", Type);
383 if (ri.nType & BRF_OPT) sprintf(Type, "%s, Optional", Type);
384 if (ri.nType & BRF_PRG) sprintf(Type, "%s, Program", Type);
385 if (ri.nType & BRF_GRA) sprintf(Type, "%s, Graphics", Type);
386 if (ri.nType & BRF_SND) sprintf(Type, "%s, Sound", Type);
387 if (ri.nType & BRF_BIOS) sprintf(Type, "%s, BIOS", Type);
388
389 for (int j = 0; j < 98; j++) {
390 FormatType[j] = Type[j + 2];
391 }
392
393 LvItem.iSubItem = 3;
394 LvItem.pszText = ANSIToTCHAR(FormatType, NULL, 0);
395 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
396
397 LvItem.iSubItem = 4;
398 LvItem.pszText = _T("");
399 if (ri.nType & BRF_NODUMP) LvItem.pszText = _T("No Dump");
400 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
401
402 RomPos++;
403 }
404
405 // Check for board roms
406 if (BurnDrvGetTextA(DRV_BOARDROM)) {
407 char szBoardName[12] = "";
408 unsigned int nOldDrvSelect = nBurnDrvActive;
409 strcpy(szBoardName, BurnDrvGetTextA(DRV_BOARDROM));
410
411 for (unsigned int i = 0; i < nBurnDrvCount; i++) {
412 nBurnDrvActive = i;
413 if (!strcmp(szBoardName, BurnDrvGetTextA(DRV_NAME))) break;
414 }
415
416 for (int j = 0; j < 0x100; j++) {
417 int nRetBoard;
418 struct BurnRomInfo riBoard;
419 char nLenBoard[10] = "";
420 char nCrcBoard[10] = "";
421 char *szBoardRomName = NULL;
422 char BoardType[100] = "";
423 char BoardFormatType[100] = "";
424
425 memset(&riBoard, 0, sizeof(riBoard));
426
427 nRetBoard = BurnDrvGetRomInfo(&riBoard, j);
428 nRetBoard += BurnDrvGetRomName(&szBoardRomName, j, 0);
429
430 if (riBoard.nLen == 0) continue;
431
432 LvItem.iItem = RomPos;
433 LvItem.iSubItem = 0;
434 LvItem.pszText = ANSIToTCHAR(szBoardRomName, NULL, 0);
435 SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem);
436
437 sprintf(nLenBoard, "%d", riBoard.nLen);
438 LvItem.iSubItem = 1;
439 LvItem.pszText = ANSIToTCHAR(nLenBoard, NULL, 0);
440 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
441
442 sprintf(nCrcBoard, "%08X", riBoard.nCrc);
443 if (!(riBoard.nType & BRF_NODUMP)) {
444 LvItem.iSubItem = 2;
445 LvItem.pszText = ANSIToTCHAR(nCrcBoard, NULL, 0);
446 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
447 }
448
449 if (riBoard.nType & BRF_ESS) sprintf(BoardType, "%s, Essential", BoardType);
450 if (riBoard.nType & BRF_OPT) sprintf(BoardType, "%s, Optional", BoardType);
451 if (riBoard.nType & BRF_PRG) sprintf(BoardType, "%s, Program", BoardType);
452 if (riBoard.nType & BRF_GRA) sprintf(BoardType, "%s, Graphics", BoardType);
453 if (riBoard.nType & BRF_SND) sprintf(BoardType, "%s, Sound", BoardType);
454 if (riBoard.nType & BRF_BIOS) sprintf(BoardType, "%s, BIOS", BoardType);
455
456 for (int k = 0; k < 98; k++) {
457 BoardFormatType[k] = BoardType[k + 2];
458 }
459
460 LvItem.iSubItem = 3;
461 LvItem.pszText = ANSIToTCHAR(BoardFormatType, NULL, 0);
462 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
463
464 LvItem.iSubItem = 4;
465 LvItem.pszText = _T("");
466 if (riBoard.nType & BRF_NODUMP) LvItem.pszText = _T("No Dump");
467 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
468
469 RomPos++;
470 }
471
472 nBurnDrvActive = nOldDrvSelect;
473 }
474
475 // Set up the sample info list
476 hList = GetDlgItem(hGameInfoDlg, IDC_LIST2);
477
478 ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);
479
480 memset(&LvCol, 0, sizeof(LvCol));
481 LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
482 LvCol.cx = 200;
483 LvCol.pszText = _T("Name");
484 SendMessage(hList, LVM_INSERTCOLUMN , 0, (LPARAM)&LvCol);
485
486 memset(&LvItem, 0, sizeof(LvItem));
487 LvItem.mask= LVIF_TEXT;
488 LvItem.cchTextMax = 256;
489 int SamplePos = 0;
490 if (BurnDrvGetTextA(DRV_SAMPLENAME) != NULL) {
491 for (int i = 0; i < 0x100; i++) { // assume max 0x100 samples per game
492 int nRet;
493 struct BurnSampleInfo si;
494 char *szSampleName = NULL;
495
496 memset(&si, 0, sizeof(si));
497
498 nRet = BurnDrvGetSampleInfo(&si, i);
499 nRet += BurnDrvGetSampleName(&szSampleName, i, 0);
500
501 if (si.nFlags == 0) continue;
502
503 LvItem.iItem = SamplePos;
504 LvItem.iSubItem = 0;
505 LvItem.pszText = ANSIToTCHAR(szSampleName, NULL, 0);
506 SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem);
507
508 SamplePos++;
509 }
510 }
511
512 // Set up the hdd info list
513 hList = GetDlgItem(hGameInfoDlg, IDC_LIST3);
514
515 ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);
516
517 memset(&LvCol, 0, sizeof(LvCol));
518 LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
519 LvCol.cx = 200;
520 LvCol.pszText = _T("Name");
521 SendMessage(hList, LVM_INSERTCOLUMN , 0, (LPARAM)&LvCol);
522 LvCol.cx = 100;
523 LvCol.pszText = _T("Size (bytes)");
524 SendMessage(hList, LVM_INSERTCOLUMN , 1, (LPARAM)&LvCol);
525 LvCol.cx = 100;
526 LvCol.pszText = _T("CRC32");
527 SendMessage(hList, LVM_INSERTCOLUMN , 2, (LPARAM)&LvCol);
528 LvCol.cx = 100;
529
530 memset(&LvItem, 0, sizeof(LvItem));
531 LvItem.mask= LVIF_TEXT;
532 LvItem.cchTextMax = 256;
533 int HDDPos = 0;
534 for (int i = 0; i < 0x100; i++) { // assume max 0x100 hdds per game
535 int nRet;
536 struct BurnHDDInfo hddi;
537 char nLen[10] = "";
538 char nCrc[10] = "";
539 char *szHDDName = NULL;
540
541 memset(&hddi, 0, sizeof(hddi));
542
543 nRet = BurnDrvGetHDDInfo(&hddi, i);
544 nRet += BurnDrvGetHDDName(&szHDDName, i, 0);
545
546 if (hddi.nLen == 0) continue;
547
548 LvItem.iItem = HDDPos;
549 LvItem.iSubItem = 0;
550 LvItem.pszText = ANSIToTCHAR(szHDDName, NULL, 0);
551 SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem);
552
553 sprintf(nLen, "%d", hddi.nLen);
554 LvItem.iSubItem = 1;
555 LvItem.pszText = ANSIToTCHAR(nLen, NULL, 0);
556 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
557
558 sprintf(nCrc, "%08X", hddi.nCrc);
559 LvItem.iSubItem = 2;
560 LvItem.pszText = ANSIToTCHAR(nCrc, NULL, 0);
561 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
562
563 HDDPos++;
564 }
565
566 // Get the history info
567 CHAR szFileName[MAX_PATH] = "";
568 sprintf(szFileName, "%shistory.dat", TCHARToANSI(szAppHistoryPath, NULL, 0));
569
570 FILE *fp = fopen(szFileName, "rt");
571 char Temp[10000];
572 int inGame = 0;
573
574 #ifdef USE_SEGOE
575 TCHAR szBuffer[50000] = _T("{\\rtf1\\ansi{\\fonttbl(\\f0\\fnil\\fcharset0 Verdana;)}{\\colortbl;\\red220\\green0\\blue0;\\red0\\green0\\blue0;}");
576 #else
577 TCHAR szBuffer[50000] = _T("{\\rtf1\\ansi{\\fonttbl(\\f0\\fnil\\fcharset0 Segoe UI;)}{\\colortbl;\\red220\\green0\\blue0;\\red0\\green0\\blue0;}");
578 #endif
579
580 if (fp) {
581 while (!feof(fp)) {
582 char *Tokens;
583
584 fgets(Temp, 10000, fp);
585 if (!strncmp("$info=", Temp, 6)) {
586 Tokens = strtok(Temp, "=,");
587 while (Tokens != NULL) {
588 if (!strcmp(Tokens, BurnDrvGetTextA(DRV_NAME))) {
589 inGame = 1;
590 break;
591 }
592
593 Tokens = strtok(NULL, "=,");
594 }
595 }
596
597 if (inGame) {
598 int nTitleWrote = 0;
599 while (strncmp("$end", Temp, 4)) {
600 fgets(Temp, 10000, fp);
601
602 if (!strncmp("$", Temp, 1)) continue;
603
604 if (!nTitleWrote) {
605 _stprintf(szBuffer, _T("%s{\\b\\f0\\fs28\\cf1 %s}"), szBuffer, ANSIToTCHAR(Temp, NULL, 0));
606 } else {
607 _stprintf(szBuffer, _T("%s\\line"), szBuffer);
608 if (!strncmp("- ", Temp, 2)) {
609 _stprintf(szBuffer, _T("%s{\\b\\f0\\fs16\\cf1 %s}"), szBuffer, ANSIToTCHAR(Temp, NULL, 0));
610 } else {
611 _stprintf(szBuffer, _T("%s{\\f0\\fs16\\cf2 %s}"), szBuffer, ANSIToTCHAR(Temp, NULL, 0));
612 }
613 }
614
615 if (strcmp("\n", Temp)) nTitleWrote = 1;
616 }
617 break;
618 }
619 }
620 fclose(fp);
621 }
622
623 _stprintf(szBuffer, _T("%s}"), szBuffer);
624 SendMessage(GetDlgItem(hGameInfoDlg, IDC_MESSAGE_EDIT_ENG), WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer);
625
626 // Make a white brush
627 hWhiteBGBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF));
628
629 return 0;
630 }
631
632 #if __GNUC__ == 8
633 #pragma GCC diagnostic pop
634 #endif
635
636 // make gcc 8.x happy about strncpy() usage below...
637 #if __GNUC__ == 8
638 #pragma GCC diagnostic push
639 #pragma GCC diagnostic ignored "-Wstringop-truncation"
640 #endif
641
642 #define MAXFAVORITES 2000
643 char szFavorites[MAXFAVORITES][28];
644 INT32 nFavorites = 0;
645
LoadFavorites()646 void LoadFavorites()
647 {
648 char szTemp[255];
649 char szFileName[] = "config/favorites.dat";
650
651 nFavorites = 0;
652 memset(szFavorites, 0, sizeof(szFavorites));
653
654 FILE *fp = fopen(szFileName, "rb");
655
656 if (fp) {
657 while (!feof(fp)) {
658 memset(szTemp, 0, sizeof(szTemp));
659 fgets(szTemp, 255, fp);
660
661 // Get rid of the linefeed at the end
662 INT32 nLen = strlen(szTemp);
663 while (nLen > 0 && (szTemp[nLen - 1] == 0x0A || szTemp[nLen - 1] == 0x0D)) {
664 szTemp[nLen - 1] = 0;
665 nLen--;
666 }
667
668 if (strlen(szTemp) < 25 && strlen(szTemp) > 2) {
669 strncpy(szFavorites[nFavorites++], szTemp, 25);
670 //bprintf(0, _T("Loaded: %S.\n"), szFavorites[nFavorites-1]);
671 }
672 }
673 fclose(fp);
674 }
675 }
676
SaveFavorites()677 static void SaveFavorites()
678 {
679 char szFileName[] = "config/favorites.dat";
680 FILE *fp = fopen(szFileName, "wb");
681 INT32 nSaved = 0;
682
683 if (fp) {
684 for (INT32 i = 0; i < nFavorites; i++) {
685 if (strlen(szFavorites[i]) > 0) {
686 fprintf(fp, "%s\n", szFavorites[i]);
687 nSaved++;
688 }
689 }
690 //bprintf(0, _T("Saved %X favorites.\n"), nSaved);
691 fclose(fp);
692 }
693 }
694
CheckFavorites(char * name)695 INT32 CheckFavorites(char *name)
696 {
697 for (INT32 i = 0; i < nFavorites; i++) {
698 if (!strcmp(name, szFavorites[i])) {
699 return i;
700 }
701 }
702 return -1;
703 }
704
AddFavorite(UINT8 addf)705 static void AddFavorite(UINT8 addf)
706 {
707 UINT32 nOldDrvSelect = nBurnDrvActive;
708 char szBoardName[28] = "";
709
710 LoadFavorites();
711
712 nBurnDrvActive = nGiDriverSelected; // get driver name under cursor
713 strcpy(szBoardName, BurnDrvGetTextA(DRV_NAME));
714 nBurnDrvActive = nOldDrvSelect;
715
716 INT32 inthere = CheckFavorites(szBoardName);
717
718 if (addf && inthere == -1) { // add favorite
719 //bprintf(0, _T("[add %S]"), szBoardName);
720 strcpy(szFavorites[nFavorites++], szBoardName);
721 }
722
723 if (addf == 0 && inthere != -1) { // remove favorite
724 //bprintf(0, _T("[remove %S]"), szBoardName);
725 szFavorites[inthere][0] = '\0';
726 }
727
728 SaveFavorites();
729 }
730
AddFavorite_Ext(UINT8 addf)731 void AddFavorite_Ext(UINT8 addf)
732 { // For use outside of the gameinfo window.
733 nGiDriverSelected = nBurnDrvActive;
734 AddFavorite(addf);
735 }
736
737 #if __GNUC__ == 8
738 #pragma GCC diagnostic pop
739 #endif
740
MyEndDialog()741 static void MyEndDialog()
742 {
743 SendDlgItemMessage(hGameInfoDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
744 SendDlgItemMessage(hGameInfoDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
745
746 if (hGiBmp) {
747 DeleteObject((HGDIOBJ)hGiBmp);
748 hGiBmp = NULL;
749 }
750 if (hPreview) {
751 DeleteObject((HGDIOBJ)hPreview);
752 hPreview = NULL;
753 }
754
755 hTabControl = NULL;
756 memset(szFullName, 0, 1024 * sizeof(TCHAR));
757
758 EndDialog(hGameInfoDlg, 0);
759 }
760
DialogProc(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM lParam)761 static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
762 {
763 if (Msg == WM_INITDIALOG) {
764 hGameInfoDlg = hDlg;
765
766 if (bDrvOkay) {
767 if (!kNetGame && bAutoPause) bRunPause = 1;
768 AudSoundStop();
769 }
770
771 GameInfoInit();
772
773 WndInMid(hDlg, hParent);
774 SetFocus(hDlg); // Enable Esc=close
775
776 return TRUE;
777 }
778
779 if (Msg == WM_CLOSE) {
780 MyEndDialog();
781 DeleteObject(hWhiteBGBrush);
782
783 EnableWindow(hScrnWnd, TRUE);
784 DestroyWindow(hGameInfoDlg);
785
786 FreeLibrary(hRiched);
787 hRiched = NULL;
788
789 if (bDrvOkay) {
790 if(!bAltPause && bRunPause) bRunPause = 0;
791 AudSoundPlay();
792 }
793
794 return 0;
795 }
796
797 if (Msg == WM_COMMAND) {
798 int Id = LOWORD(wParam);
799 int Notify = HIWORD(wParam);
800
801 if (Id == IDCANCEL && Notify == BN_CLICKED) {
802 SendMessage(hGameInfoDlg, WM_CLOSE, 0, 0);
803 return 0;
804 }
805
806 if (Id == IDFAVORITESET && Notify == BN_CLICKED) {
807 INT32 nButtonState = SendDlgItemMessage(hGameInfoDlg, IDFAVORITESET, BM_GETSTATE, 0, 0);
808
809 AddFavorite((nButtonState & BST_CHECKED) ? 1 : 0);
810 return 0;
811 }
812
813 if (Id == IDRESCANSET && Notify == BN_CLICKED) {
814 nBurnDrvActive = nGiDriverSelected;
815 // use the nBurnDrvActive value from when the Rom Info button was clicked, because it can/will change
816 // even though the selection list [window below it] doesn't have focus. -dink
817 // for proof/symptoms - uncomment the line below and click the 'rescan' button after moving the window to different places on the screen.
818 //bprintf(0, _T("nBurnDrvActive %d nGiDriverSelected %d\n"), nBurnDrvActive, nGiDriverSelected);
819
820 switch (BzipOpen(1)) {
821 case 0: {
822 gameAv[nGiDriverSelected] = 3;
823 break;
824 }
825
826 case 2: {
827 gameAv[nGiDriverSelected] = 1;
828 break;
829 }
830
831 case 1: {
832 gameAv[nGiDriverSelected] = 0;
833 BzipClose();
834 BzipOpen(0); // this time, get the missing roms/error message.
835 {
836 HWND hScrnWndtmp = hScrnWnd; // Crash preventer: Make the gameinfo dialog (this one) the parent modal for the popup message
837 hScrnWnd = hGameInfoDlg;
838 FBAPopupDisplay(PUF_TYPE_ERROR);
839 hScrnWnd = hScrnWndtmp;
840 }
841 break;
842 }
843 }
844
845 if (gameAv[nGiDriverSelected] > 0) {
846 int TabPage = TabCtrl_GetCurSel(hTabControl);
847 if (TabPage != 0) {
848 MessageBox(hGameInfoDlg, FBALoadStringEx(hAppInst, IDS_ERR_LOAD_OK, true), FBALoadStringEx(hAppInst, IDS_ERR_INFORMATION, true), MB_OK);
849 }
850 if (TabPage == 0) {
851 // if the romset is OK, just say so in the rom info dialog (instead of popping up a window)
852 HWND hList = GetDlgItem(hGameInfoDlg, IDC_LIST1);
853 LV_ITEM LvItem;
854 memset(&LvItem, 0, sizeof(LvItem));
855 LvItem.mask= LVIF_TEXT;
856 LvItem.cchTextMax = 256;
857 LvItem.iSubItem = 4;
858 LvItem.pszText = _T("Romset OK!");
859 SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem);
860 UpdateWindow(hGameInfoDlg);
861 }
862 }
863 BzipClose();
864 WriteGameAvb();
865 return 0;
866 }
867 }
868
869 if (Msg == WM_NOTIFY) {
870 NMHDR* pNmHdr = (NMHDR*)lParam;
871
872 if (pNmHdr->code == TCN_SELCHANGE) {
873 int TabPage = TabCtrl_GetCurSel(hTabControl);
874
875 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST1), SW_HIDE);
876 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST2), SW_HIDE);
877 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_LIST3), SW_HIDE);
878 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_MESSAGE_EDIT_ENG), SW_HIDE);
879 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_SCREENSHOT_H), SW_SHOW);
880 ShowWindow(GetDlgItem(hGameInfoDlg, IDC_SCREENSHOT_V), SW_SHOW);
881 UpdateWindow(hGameInfoDlg);
882
883 nBurnDrvActive = nGiDriverSelected;
884
885 if (TabPage == 0) DisplayRomInfo();
886 if (TabPage == 1) DisplayHDDInfo();
887 if (TabPage == 2) DisplaySampleInfo();
888 if (TabPage == 3) DisplayHistory();
889 if (TabPage == 4) SetPreview(szAppPreviewsPath, IMG_ASPECT_4_3);
890 if (TabPage == 5) SetPreview(szAppTitlesPath, IMG_ASPECT_4_3);
891 if (TabPage == 6) SetPreview(szAppSelectPath, IMG_ASPECT_4_3);
892 if (TabPage == 7) SetPreview(szAppVersusPath, IMG_ASPECT_4_3);
893 if (TabPage == 8) SetPreview(szAppHowtoPath, IMG_ASPECT_4_3);
894 if (TabPage == 9) SetPreview(szAppScoresPath, IMG_ASPECT_4_3);
895 if (TabPage == 10) SetPreview(szAppBossesPath, IMG_ASPECT_4_3);
896 if (TabPage == 11) SetPreview(szAppGameoverPath, IMG_ASPECT_4_3);
897 if (TabPage == 12) SetPreview(szAppFlyersPath, IMG_ASPECT_PRESERVE);
898 if (TabPage == 13) SetPreview(szAppCabinetsPath, IMG_ASPECT_PRESERVE);
899 if (TabPage == 14) SetPreview(szAppMarqueesPath, IMG_ASPECT_PRESERVE);
900 if (TabPage == 15) SetPreview(szAppControlsPath, IMG_ASPECT_PRESERVE);
901 if (TabPage == 16) SetPreview(szAppPCBsPath, IMG_ASPECT_PRESERVE);
902
903 return FALSE;
904 }
905 }
906
907 if (Msg == WM_CTLCOLORSTATIC) {
908 if ((HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_LABELCOMMENT) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_LABELROMNAME) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_LABELROMINFO) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_LABELSYSTEM) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_LABELNOTES) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_LABELGENRE) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_TEXTCOMMENT) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_TEXTROMNAME) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_TEXTROMINFO) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_TEXTSYSTEM) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_TEXTNOTES) || (HWND)lParam == GetDlgItem(hGameInfoDlg, IDC_TEXTGENRE)) {
909 return (INT_PTR)hWhiteBGBrush;
910 }
911 }
912
913 return 0;
914 }
915
GameInfoDialogCreate(HWND hParentWND,int nDrvSel)916 int GameInfoDialogCreate(HWND hParentWND, int nDrvSel)
917 {
918 bGameInfoOpen = true;
919 nGiDriverSelected = nDrvSel;
920
921 #if defined (_UNICODE)
922 hRiched = LoadLibrary(L"RICHED20.DLL");
923 #else
924 hRiched = LoadLibrary("RICHED20.DLL");
925 #endif
926
927 if (hRiched) {
928 hParent = hParentWND;
929 FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_GAMEINFO), hParent, (DLGPROC)DialogProc);
930 }
931
932 bGameInfoOpen = false;
933 return 0;
934 }
935