1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 // RomInfo.cpp : implementation file
20 //
21
22 #include "stdafx.h"
23 #include "vba.h"
24 #include "RomInfo.h"
25 #include "WinResUtil.h"
26
27 #ifdef _DEBUG
28 #define new DEBUG_NEW
29 #undef THIS_FILE
30 static char THIS_FILE[] = __FILE__;
31 #endif
32
33 extern int gbRomSize;
34
35 struct WinGBACompanyName {
36 LPCTSTR code;
37 LPCTSTR name;
38 };
39
40 static WinGBACompanyName winGBARomInfoCompanies[] = {
41 { "01", "Nintendo" },
42 { "02", "Rocket Games" },
43 { "08", "Capcom" },
44 { "09", "Hot B Co." },
45 { "0A", "Jaleco" },
46 { "0B", "Coconuts Japan" },
47 { "0C", "Coconuts Japan/G.X.Media" },
48 { "0H", "Starfish" },
49 { "0L", "Warashi Inc." },
50 { "0N", "Nowpro" },
51 { "0P", "Game Village" },
52 { "13", "Electronic Arts Japan" },
53 { "18", "Hudson Soft Japan" },
54 { "19", "S.C.P." },
55 { "1A", "Yonoman" },
56 { "1G", "SMDE" },
57 { "1P", "Creatures Inc." },
58 { "1Q", "TDK Deep Impresion" },
59 { "20", "Destination Software" },
60 { "22", "VR 1 Japan" },
61 { "25", "San-X" },
62 { "28", "Kemco Japan" },
63 { "29", "Seta" },
64 { "2H", "Ubisoft Japan" },
65 { "2K", "NEC InterChannel" },
66 { "2L", "Tam" },
67 { "2M", "Jordan" },
68 { "2N", "Smilesoft" },
69 { "2Q", "Mediakite" },
70 { "36", "Codemasters" },
71 { "37", "GAGA Communications" },
72 { "38", "Laguna" },
73 { "39", "Telstar Fun and Games" },
74 { "41", "Ubi Soft Entertainment" },
75 { "42", "Sunsoft" },
76 { "47", "Spectrum Holobyte" },
77 { "49", "IREM" },
78 { "4D", "Malibu Games" },
79 { "4F", "Eidos/U.S. Gold" },
80 { "4J", "Fox Interactive" },
81 { "4K", "Time Warner Interactive" },
82 { "4Q", "Disney" },
83 { "4S", "Black Pearl" },
84 { "4X", "GT Interactive" },
85 { "4Y", "RARE" },
86 { "4Z", "Crave Entertainment" },
87 { "50", "Absolute Entertainment" },
88 { "51", "Acclaim" },
89 { "52", "Activision" },
90 { "53", "American Sammy Corp." },
91 { "54", "Take 2 Interactive" },
92 { "55", "Hi Tech" },
93 { "56", "LJN LTD." },
94 { "58", "Mattel" },
95 { "5A", "Mindscape/Red Orb Ent." },
96 { "5C", "Taxan" },
97 { "5D", "Midway" },
98 { "5F", "American Softworks" },
99 { "5G", "Majesco Sales Inc" },
100 { "5H", "3DO" },
101 { "5K", "Hasbro" },
102 { "5L", "NewKidCo" },
103 { "5M", "Telegames" },
104 { "5N", "Metro3D" },
105 { "5P", "Vatical Entertainment" },
106 { "5Q", "LEGO Media" },
107 { "5S", "Xicat Interactive" },
108 { "5T", "Cryo Interactive" },
109 { "5W", "Red Storm Ent./BKN Ent." },
110 { "5X", "Microids" },
111 { "5Z", "Conspiracy Entertainment Corp." },
112 { "60", "Titus Interactive Studios" },
113 { "61", "Virgin Interactive" },
114 { "62", "Maxis" },
115 { "64", "LucasArts Entertainment" },
116 { "67", "Ocean" },
117 { "69", "Electronic Arts" },
118 { "6E", "Elite Systems Ltd." },
119 { "6F", "Electro Brain" },
120 { "6G", "The Learning Company" },
121 { "6H", "BBC" },
122 { "6J", "Software 2000" },
123 { "6L", "BAM! Entertainment" },
124 { "6M", "Studio 3" },
125 { "6Q", "Classified Games" },
126 { "6S", "TDK Mediactive" },
127 { "6U", "DreamCatcher" },
128 { "6V", "JoWood Productions" },
129 { "6W", "SEGA" },
130 { "6X", "Wannado Edition" },
131 { "6Y", "LSP" },
132 { "6Z", "ITE Media" },
133 { "70", "Infogrames" },
134 { "71", "Interplay" },
135 { "72", "JVC Musical Industries Inc" },
136 { "73", "Parker Brothers" },
137 { "75", "SCI" },
138 { "78", "THQ" },
139 { "79", "Accolade" },
140 { "7A", "Triffix Ent. Inc." },
141 { "7C", "Microprose Software" },
142 { "7D", "Universal Interactive Studios" },
143 { "7F", "Kemco" },
144 { "7G", "Rage Software" },
145 { "7H", "Encore" },
146 { "7J", "Zoo" },
147 { "7K", "BVM" },
148 { "7L", "Simon & Schuster Interactive" },
149 { "7M", "Asmik Ace Entertainment Inc./AIA" },
150 { "7N", "Empire Interactive" },
151 { "7Q", "Jester Interactive" },
152 { "7T", "Scholastic" },
153 { "7U", "Ignition Entertainment" },
154 { "7W", "Stadlbauer" },
155 { "80", "Misawa" },
156 { "83", "LOZC" },
157 { "8B", "Bulletproof Software" },
158 { "8C", "Vic Tokai Inc." },
159 { "8J", "General Entertainment" },
160 { "8N", "Success" },
161 { "8P", "SEGA Japan" },
162 { "91", "Chun Soft" },
163 { "92", "Video System" },
164 { "93", "BEC" },
165 { "96", "Yonezawa/S'pal" },
166 { "97", "Kaneko" },
167 { "99", "Victor Interactive Software" },
168 { "9A", "Nichibutsu/Nihon Bussan" },
169 { "9B", "Tecmo" },
170 { "9C", "Imagineer" },
171 { "9F", "Nova" },
172 { "9H", "Bottom Up" },
173 { "9L", "Hasbro Japan" },
174 { "9N", "Marvelous Entertainment" },
175 { "9P", "Keynet Inc." },
176 { "9Q", "Hands-On Entertainment" },
177 { "A0", "Telenet" },
178 { "A1", "Hori" },
179 { "A4", "Konami" },
180 { "A6", "Kawada" },
181 { "A7", "Takara" },
182 { "A9", "Technos Japan Corp." },
183 { "AA", "JVC" },
184 { "AC", "Toei Animation" },
185 { "AD", "Toho" },
186 { "AF", "Namco" },
187 { "AG", "Media Rings Corporation" },
188 { "AH", "J-Wing" },
189 { "AK", "KID" },
190 { "AL", "MediaFactory" },
191 { "AP", "Infogrames Hudson" },
192 { "AQ", "Kiratto. Ludic Inc" },
193 { "B0", "Acclaim Japan" },
194 { "B1", "ASCII" },
195 { "B2", "Bandai" },
196 { "B4", "Enix" },
197 { "B6", "HAL Laboratory" },
198 { "B7", "SNK" },
199 { "B9", "Pony Canyon Hanbai" },
200 { "BA", "Culture Brain" },
201 { "BB", "Sunsoft" },
202 { "BD", "Sony Imagesoft" },
203 { "BF", "Sammy" },
204 { "BG", "Magical" },
205 { "BJ", "Compile" },
206 { "BL", "MTO Inc." },
207 { "BN", "Sunrise Interactive" },
208 { "BP", "Global A Entertainment" },
209 { "BQ", "Fuuki" },
210 { "C0", "Taito" },
211 { "C2", "Kemco" },
212 { "C3", "Square Soft" },
213 { "C5", "Data East" },
214 { "C6", "Tonkin House" },
215 { "C8", "Koei" },
216 { "CA", "Konami/Palcom/Ultra" },
217 { "CB", "Vapinc/NTVIC" },
218 { "CC", "Use Co.,Ltd." },
219 { "CD", "Meldac" },
220 { "CE", "FCI/Pony Canyon" },
221 { "CF", "Angel" },
222 { "CM", "Konami Computer Entertainment Osaka" },
223 { "CP", "Enterbrain" },
224 { "D1", "Sofel" },
225 { "D2", "Quest" },
226 { "D3", "Sigma Enterprises" },
227 { "D4", "Ask Kodansa" },
228 { "D6", "Naxat" },
229 { "D7", "Copya System" },
230 { "D9", "Banpresto" },
231 { "DA", "TOMY" },
232 { "DB", "LJN Japan" },
233 { "DD", "NCS" },
234 { "DF", "Altron Corporation" },
235 { "DH", "Gaps Inc." },
236 { "DN", "ELF" },
237 { "E2", "Yutaka" },
238 { "E3", "Varie" },
239 { "E5", "Epoch" },
240 { "E7", "Athena" },
241 { "E8", "Asmik Ace Entertainment Inc." },
242 { "E9", "Natsume" },
243 { "EA", "King Records" },
244 { "EB", "Atlus" },
245 { "EC", "Epic/Sony Records" },
246 { "EE", "IGS" },
247 { "EL", "Spike" },
248 { "EM", "Konami Computer Entertainment Tokyo" },
249 { "EN", "Alphadream Corporation" },
250 { "F0", "A Wave" },
251 { "G1", "PCCW" },
252 { "G4", "KiKi Co Ltd" },
253 { "G5", "Open Sesame Inc." },
254 { "G6", "Sims" },
255 { "G7", "Broccoli" },
256 { "G8", "Avex" },
257 { "G9", "D3 Publisher" },
258 { "GB", "Konami Computer Entertainment Japan" },
259 { "GD", "Square-Enix" },
260 { "HY", "Sachen" },
261 { NULL, NULL }
262 };
263
winGBARomInfoFindMakerCode(LPCTSTR code)264 static LPCTSTR winGBARomInfoFindMakerCode(LPCTSTR code)
265 {
266 int i = 0;
267 while(winGBARomInfoCompanies[i].code) {
268 if(!strcmp(winGBARomInfoCompanies[i].code, code))
269 return winGBARomInfoCompanies[i].name;
270 i++;
271 }
272 return (LPCTSTR)winResLoadString(IDS_UNKNOWN);
273 }
274
275
276 /////////////////////////////////////////////////////////////////////////////
277 // RomInfoGB dialog
278
279
RomInfoGB(u8 * rom,CWnd * pParent)280 RomInfoGB::RomInfoGB(u8 *rom, CWnd* pParent /*=NULL*/)
281 : CDialog(RomInfoGB::IDD, pParent)
282 {
283 //{{AFX_DATA_INIT(RomInfoGB)
284 // NOTE: the ClassWizard will add member initialization here
285 //}}AFX_DATA_INIT
286 this->rom = rom;
287 }
288
289
DoDataExchange(CDataExchange * pDX)290 void RomInfoGB::DoDataExchange(CDataExchange* pDX)
291 {
292 CDialog::DoDataExchange(pDX);
293 //{{AFX_DATA_MAP(RomInfoGB)
294 // NOTE: the ClassWizard will add DDX and DDV calls here
295 //}}AFX_DATA_MAP
296 }
297
298
BEGIN_MESSAGE_MAP(RomInfoGB,CDialog)299 BEGIN_MESSAGE_MAP(RomInfoGB, CDialog)
300 //{{AFX_MSG_MAP(RomInfoGB)
301 ON_BN_CLICKED(ID_OK, OnOk)
302 //}}AFX_MSG_MAP
303 END_MESSAGE_MAP()
304
305 /////////////////////////////////////////////////////////////////////////////
306 // RomInfoGB message handlers
307
308 void RomInfoGB::OnOk()
309 {
310 EndDialog(TRUE);
311 }
312
OnInitDialog()313 BOOL RomInfoGB::OnInitDialog()
314 {
315 CDialog::OnInitDialog();
316
317 char buffer[128];
318
319 strncpy(buffer, (const char *)&rom[0x134], 15);
320 buffer[15] = 0;
321 GetDlgItem(IDC_ROM_TITLE)->SetWindowText(buffer);
322
323 sprintf(buffer, "%02x", rom[0x143]);
324 GetDlgItem(IDC_ROM_COLOR)->SetWindowText(buffer);
325
326 strncpy(buffer, (const char *)&rom[0x144],2);
327 buffer[2] = 0;
328 GetDlgItem(IDC_ROM_MAKER_CODE)->SetWindowText(buffer);
329
330 if(rom[0x14b] != 0x33) {
331 sprintf(buffer, "%02X", rom[0x14b]);
332 GetDlgItem(IDC_ROM_MAKER_CODE)->SetWindowText(buffer);
333 }
334 GetDlgItem(IDC_ROM_MAKER_NAME2)->SetWindowText(winGBARomInfoFindMakerCode(buffer));
335
336 sprintf(buffer, "%02x", rom[0x146]);
337 GetDlgItem(IDC_ROM_UNIT_CODE)->SetWindowText(buffer);
338
339 CString type = winResLoadString(IDS_UNKNOWN);
340 switch(rom[0x147]) {
341 case 0x00:
342 type = "ROM";
343 break;
344 case 0x01:
345 type = "ROM+MBC1";
346 break;
347 case 0x02:
348 type = "ROM+MBC1+RAM";
349 break;
350 case 0x03:
351 type = "ROM+MBC1+RAM+BATT";
352 break;
353 case 0x05:
354 type = "ROM+MBC2";
355 break;
356 case 0x06:
357 type = "ROM+MBC2+BATT";
358 break;
359 case 0x0f:
360 type = "ROM+MBC3+TIMER+BATT";
361 break;
362 case 0x10:
363 type = "ROM+MBC3+TIMER+RAM+BATT";
364 break;
365 case 0x11:
366 type = "ROM+MBC3";
367 break;
368 case 0x12:
369 type = "ROM+MBC3+RAM";
370 break;
371 case 0x13:
372 type = "ROM+MBC3+RAM+BATT";
373 break;
374 case 0x19:
375 type = "ROM+MBC5";
376 break;
377 case 0x1a:
378 type = "ROM+MBC5+RAM";
379 break;
380 case 0x1b:
381 type = "ROM+MBC5+RAM+BATT";
382 break;
383 case 0x1c:
384 type = "ROM+MBC5+RUMBLE";
385 break;
386 case 0x1d:
387 type = "ROM+MBC5+RUMBLE+RAM";
388 break;
389 case 0x1e:
390 type = "ROM+MBC5+RUMBLE+RAM+BATT";
391 break;
392 case 0x22:
393 type = "ROM+MBC7+BATT";
394 break;
395 case 0xfe:
396 type = "ROM+HuC-3";
397 break;
398 case 0xff:
399 type = "ROM+HuC-1";
400 break;
401 }
402 sprintf(buffer, "%02x (%s)", rom[0x147], (const char *)type);
403 GetDlgItem(IDC_ROM_DEVICE_TYPE)->SetWindowText(buffer);
404
405 type = winResLoadString(IDS_UNKNOWN);
406 switch(rom[0x148]) {
407 case 0:
408 type = "32K";
409 break;
410 case 1:
411 type = "64K";
412 break;
413 case 2:
414 type = "128K";
415 break;
416 case 3:
417 type = "256K";
418 break;
419 case 4:
420 type = "512K";
421 break;
422 case 5:
423 type = "1M";
424 break;
425 case 6:
426 type = "2M";
427 break;
428 case 7:
429 type = "4M";
430 break;
431 }
432
433 sprintf(buffer, "%02x (%s)", rom[0x148], (const char *)type);
434 GetDlgItem(IDC_ROM_SIZE)->SetWindowText(buffer);
435
436 type = winResLoadString(IDS_UNKNOWN);
437 switch(rom[0x149]) {
438 case 0:
439 type = winResLoadString(IDS_NONE);
440 break;
441 case 1:
442 type = "2K";
443 break;
444 case 2:
445 type = "8K";
446 break;
447 case 3:
448 type = "32K";
449 break;
450 case 4:
451 type = "128K";
452 break;
453 case 5:
454 type = "64K";
455 break;
456 }
457
458 sprintf(buffer, "%02x (%s)", rom[0x149], (const char *)type);
459 GetDlgItem(IDC_ROM_RAM_SIZE)->SetWindowText(buffer);
460
461 sprintf(buffer, "%02x", rom[0x14a]);
462 GetDlgItem(IDC_ROM_DEST_CODE)->SetWindowText(buffer);
463
464 sprintf(buffer, "%02x", rom[0x14b]);
465 GetDlgItem(IDC_ROM_LIC_CODE)->SetWindowText(buffer);
466
467 sprintf(buffer, "%02x", rom[0x14c]);
468 GetDlgItem(IDC_ROM_VERSION)->SetWindowText(buffer);
469
470 u8 crc = 25;
471 int i;
472 for(i = 0x134; i < 0x14d; i++) {
473 crc += rom[i];
474 }
475
476 crc = 256 - crc;
477
478 sprintf(buffer, "%02x (%02x)", crc, rom[0x14d]);
479 GetDlgItem(IDC_ROM_CRC)->SetWindowText(buffer);
480
481 u16 crc16 = 0;
482 for(i = 0; i < gbRomSize; i++) {
483 crc16 += rom[i];
484 }
485
486 crc16 -= rom[0x14e];
487 crc16 -= rom[0x14f];
488 sprintf(buffer, "%04x (%04x)", crc16, (rom[0x14e]<<8)|rom[0x14f]);
489 GetDlgItem(IDC_ROM_CHECKSUM)->SetWindowText(buffer);
490
491 CenterWindow();
492
493 return TRUE; // return TRUE unless you set the focus to a control
494 // EXCEPTION: OCX Property Pages should return FALSE
495 }
496 /////////////////////////////////////////////////////////////////////////////
497 // RomInfoGBA dialog
498
499
RomInfoGBA(u8 * rom,CWnd * pParent)500 RomInfoGBA::RomInfoGBA(u8 *rom, CWnd* pParent /*=NULL*/)
501 : CDialog(RomInfoGBA::IDD, pParent)
502 {
503 //{{AFX_DATA_INIT(RomInfoGBA)
504 // NOTE: the ClassWizard will add member initialization here
505 //}}AFX_DATA_INIT
506 this->rom = rom;
507 }
508
509
DoDataExchange(CDataExchange * pDX)510 void RomInfoGBA::DoDataExchange(CDataExchange* pDX)
511 {
512 CDialog::DoDataExchange(pDX);
513 //{{AFX_DATA_MAP(RomInfoGBA)
514 // NOTE: the ClassWizard will add DDX and DDV calls here
515 //}}AFX_DATA_MAP
516 }
517
518
BEGIN_MESSAGE_MAP(RomInfoGBA,CDialog)519 BEGIN_MESSAGE_MAP(RomInfoGBA, CDialog)
520 //{{AFX_MSG_MAP(RomInfoGBA)
521 ON_BN_CLICKED(ID_OK, OnOk)
522 //}}AFX_MSG_MAP
523 END_MESSAGE_MAP()
524
525 /////////////////////////////////////////////////////////////////////////////
526 // RomInfoGBA message handlers
527
528 void RomInfoGBA::OnOk()
529 {
530 EndDialog(TRUE);
531 }
532
OnInitDialog()533 BOOL RomInfoGBA::OnInitDialog()
534 {
535 CDialog::OnInitDialog();
536
537 char buffer[13];
538
539 strncpy(buffer, (const char *)&rom[0xa0], 12);
540 buffer[12] = 0;
541 GetDlgItem(IDC_ROM_TITLE)->SetWindowText(buffer);
542
543 strncpy(buffer, (const char *)&rom[0xac], 4);
544 buffer[4] = 0;
545 GetDlgItem(IDC_ROM_GAME_CODE)->SetWindowText(buffer);
546
547 strncpy(buffer, (const char *)&rom[0xb0],2);
548 buffer[2] = 0;
549 GetDlgItem(IDC_ROM_MAKER_CODE)->SetWindowText(buffer);
550
551 GetDlgItem(IDC_ROM_MAKER_NAME)->SetWindowText(winGBARomInfoFindMakerCode(buffer));
552
553 sprintf(buffer, "%02x", rom[0xb3]);
554 GetDlgItem(IDC_ROM_UNIT_CODE)->SetWindowText(buffer);
555
556 sprintf(buffer, "%02x", rom[0xb4]);
557 GetDlgItem(IDC_ROM_DEVICE_TYPE)->SetWindowText(buffer);
558
559 sprintf(buffer, "%02x", rom[0xbc]);
560 GetDlgItem(IDC_ROM_VERSION)->SetWindowText(buffer);
561
562 u8 crc = 0x19;
563 for(int i = 0xa0; i < 0xbd; i++) {
564 crc += rom[i];
565 }
566
567 crc = (-crc) & 255;
568
569 sprintf(buffer, "%02x (%02x)", crc, rom[0xbd]);
570 GetDlgItem(IDC_ROM_CRC)->SetWindowText(buffer);
571 CenterWindow();
572
573 return TRUE; // return TRUE unless you set the focus to a control
574 // EXCEPTION: OCX Property Pages should return FALSE
575 }
576