1 #include "stdafx.h"
2 #include "vba.h"
3 #include "FileDlg.h"
4 #include "MapView.h"
5 #include "Reg.h"
6 #include "WinResUtil.h"
7
8 #include "../System.h"
9 #include "../gba/GBA.h"
10 #include "../gba/Globals.h"
11 #include "../NLS.h"
12 #include "../Util.h"
13
14 extern "C" {
15 #include <png.h>
16 }
17
18 #ifdef _DEBUG
19 #define new DEBUG_NEW
20 #undef THIS_FILE
21 static char THIS_FILE[] = __FILE__;
22 #endif
23
24 /////////////////////////////////////////////////////////////////////////////
25 // MapView dialog
26
27
MapView(CWnd * pParent)28 MapView::MapView(CWnd* pParent /*=NULL*/)
29 : ResizeDlg(MapView::IDD, pParent)
30 {
31 //{{AFX_DATA_INIT(MapView)
32 //}}AFX_DATA_INIT
33 autoUpdate = false;
34
35 memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader));
36
37 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
38 bmpInfo.bmiHeader.biWidth = 1024;
39 bmpInfo.bmiHeader.biHeight = -1024;
40 bmpInfo.bmiHeader.biPlanes = 1;
41 bmpInfo.bmiHeader.biBitCount = 24;
42 bmpInfo.bmiHeader.biCompression = BI_RGB;
43 data = (u8 *)calloc(1, 3 * 1024 * 1024);
44
45 mapView.setData(data);
46 mapView.setBmpInfo(&bmpInfo);
47
48 control = BG0CNT;
49
50 bg = 0;
51 frame = 0;
52 }
53
~MapView()54 MapView::~MapView()
55 {
56 free(data);
57 data = NULL;
58 }
59
DoDataExchange(CDataExchange * pDX)60 void MapView::DoDataExchange(CDataExchange* pDX)
61 {
62 CDialog::DoDataExchange(pDX);
63 //{{AFX_DATA_MAP(MapView)
64 DDX_Control(pDX, IDC_NUMCOLORS, m_numcolors);
65 DDX_Control(pDX, IDC_MODE, m_mode);
66 DDX_Control(pDX, IDC_OVERFLOW, m_overflow);
67 DDX_Control(pDX, IDC_MOSAIC, m_mosaic);
68 DDX_Control(pDX, IDC_PRIORITY, m_priority);
69 DDX_Control(pDX, IDC_DIM, m_dim);
70 DDX_Control(pDX, IDC_CHARBASE, m_charbase);
71 DDX_Control(pDX, IDC_MAPBASE, m_mapbase);
72 //}}AFX_DATA_MAP
73 DDX_Control(pDX, IDC_MAP_VIEW, mapView);
74 DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, mapViewZoom);
75 DDX_Control(pDX, IDC_COLOR, color);
76 }
77
78
BEGIN_MESSAGE_MAP(MapView,CDialog)79 BEGIN_MESSAGE_MAP(MapView, CDialog)
80 //{{AFX_MSG_MAP(MapView)
81 ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
82 ON_BN_CLICKED(IDC_FRAME_0, OnFrame0)
83 ON_BN_CLICKED(IDC_FRAME_1, OnFrame1)
84 ON_BN_CLICKED(IDC_BG0, OnBg0)
85 ON_BN_CLICKED(IDC_BG1, OnBg1)
86 ON_BN_CLICKED(IDC_BG2, OnBg2)
87 ON_BN_CLICKED(IDC_BG3, OnBg3)
88 ON_BN_CLICKED(IDC_STRETCH, OnStretch)
89 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)
90 ON_BN_CLICKED(IDC_CLOSE, OnClose)
91 ON_BN_CLICKED(IDC_SAVE, OnSave)
92 //}}AFX_MSG_MAP
93 ON_MESSAGE(WM_MAPINFO, OnMapInfo)
94 ON_MESSAGE(WM_COLINFO, OnColInfo)
95 END_MESSAGE_MAP()
96
97 /////////////////////////////////////////////////////////////////////////////
98 // MapView message handlers
99
100 void MapView::renderTextScreen(u16 control)
101 {
102 u16 *palette = (u16 *)paletteRAM;
103 u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
104 u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
105 u8 *bmp = data;
106
107 int sizeX = 256;
108 int sizeY = 256;
109 switch((control >> 14) & 3) {
110 case 0:
111 break;
112 case 1:
113 sizeX = 512;
114 break;
115 case 2:
116 sizeY = 512;
117 break;
118 case 3:
119 sizeX = 512;
120 sizeY = 512;
121 break;
122 }
123
124 w = sizeX;
125 h = sizeY;
126
127 if(control & 0x80) {
128 for(int y = 0; y < sizeY; y++) {
129 int yy = y & 255;
130
131 if(y == 256 && sizeY > 256) {
132 screenBase += 0x400;
133 if(sizeX > 256)
134 screenBase += 0x400;
135 }
136 u16 *screenSource = screenBase + ((yy>>3)*32);
137
138 for(int x = 0; x < sizeX; x++) {
139 u16 data = *screenSource;
140
141 int tile = data & 0x3FF;
142 int tileX = (x & 7);
143 int tileY = y & 7;
144
145 if(data & 0x0400)
146 tileX = 7 - tileX;
147 if(data & 0x0800)
148 tileY = 7 - tileY;
149
150 u8 c = charBase[tile * 64 + tileY * 8 + tileX];
151
152 u16 color = palette[c];
153
154 *bmp++ = ((color >> 10) & 0x1f) << 3;
155 *bmp++ = ((color >> 5) & 0x1f) << 3;
156 *bmp++ = (color & 0x1f) << 3;
157
158 if(data & 0x0400) {
159 if(tileX == 0)
160 screenSource++;
161 } else if(tileX == 7)
162 screenSource++;
163 if(x == 255 && sizeX > 256) {
164 screenSource = screenBase + 0x400 + ((yy>>3)*32);
165 }
166 }
167 }
168 } else {
169 for(int y = 0; y < sizeY; y++) {
170 int yy = y & 255;
171
172 if(y == 256 && sizeY > 256) {
173 screenBase += 0x400;
174 if(sizeX > 256)
175 screenBase += 0x400;
176 }
177 u16 *screenSource = screenBase + ((yy>>3)*32);
178
179 for(int x = 0; x < sizeX; x++) {
180 u16 data = *screenSource;
181
182 int tile = data & 0x3FF;
183 int tileX = (x & 7);
184 int tileY = y & 7;
185
186 if(data & 0x0400)
187 tileX = 7 - tileX;
188 if(data & 0x0800)
189 tileY = 7 - tileY;
190
191 u8 color = charBase[tile * 32 + tileY * 4 + (tileX>>1)];
192
193 if(tileX & 1) {
194 color = (color >> 4);
195 } else {
196 color &= 0x0F;
197 }
198
199 int pal = (*screenSource>>8) & 0xF0;
200 u16 color2 = palette[pal + color];
201
202 *bmp++ = ((color2 >> 10) & 0x1f) << 3;
203 *bmp++ = ((color2 >> 5) & 0x1f) << 3;
204 *bmp++ = (color2 & 0x1f) << 3;
205
206 if(data & 0x0400) {
207 if(tileX == 0)
208 screenSource++;
209 } else if(tileX == 7)
210 screenSource++;
211
212 if(x == 255 && sizeX > 256) {
213 screenSource = screenBase + 0x400 + ((yy>>3)*32);
214 }
215 }
216 }
217 }
218 /*
219 switch(bg) {
220 case 0:
221 renderView(BG0HOFS<<8, BG0VOFS<<8,
222 0x100, 0x000,
223 0x000, 0x100,
224 (sizeX -1) <<8,
225 (sizeY -1) << 8,
226 true);
227 break;
228 case 1:
229 renderView(BG1HOFS<<8, BG1VOFS<<8,
230 0x100, 0x000,
231 0x000, 0x100,
232 (sizeX -1) <<8,
233 (sizeY -1) << 8,
234 true);
235 break;
236 case 2:
237 renderView(BG2HOFS<<8, BG2VOFS<<8,
238 0x100, 0x000,
239 0x000, 0x100,
240 (sizeX -1) <<8,
241 (sizeY -1) << 8,
242 true);
243 break;
244 case 3:
245 renderView(BG3HOFS<<8, BG3VOFS<<8,
246 0x100, 0x000,
247 0x000, 0x100,
248 (sizeX -1) <<8,
249 (sizeY -1) << 8,
250 true);
251 break;
252 }
253 */
254 }
255
renderRotScreen(u16 control)256 void MapView::renderRotScreen(u16 control)
257 {
258 u16 *palette = (u16 *)paletteRAM;
259 u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
260 u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800];
261 u8 *bmp = data;
262
263 int sizeX = 128;
264 int sizeY = 128;
265 switch((control >> 14) & 3) {
266 case 0:
267 break;
268 case 1:
269 sizeX = sizeY = 256;
270 break;
271 case 2:
272 sizeX = sizeY = 512;
273 break;
274 case 3:
275 sizeX = sizeY = 1024;
276 break;
277 }
278
279 w = sizeX;
280 h = sizeY;
281
282 for(int y = 0; y < sizeY; y++) {
283 for(int x = 0; x < sizeX; x++) {
284 int tile = screenBase[(x>>3) + (y>>3)*(w>>3)];
285
286 int tileX = (x & 7);
287 int tileY = y & 7;
288
289 u8 color = charBase[tile * 64 + tileY * 8 + tileX];
290 u16 color2 = palette[color];
291
292 *bmp++ = ((color2 >> 10) & 0x1f) << 3;
293 *bmp++ = ((color2 >> 5) & 0x1f) << 3;
294 *bmp++ = (color2 & 0x1f) << 3;
295 }
296 }
297
298 u32 xx;
299 u32 yy;
300
301 switch(bg) {
302 case 2:
303 xx = BG2X_L | BG2X_H << 16;
304 yy = BG2Y_L | BG2Y_H << 16;
305
306 /*
307 renderView(xx, yy,
308 BG2PA, BG2PC,
309 BG2PB, BG2PD,
310 (sizeX -1) <<8,
311 (sizeY -1) << 8,
312 (control & 0x2000) != 0);
313 */
314 break;
315 case 3:
316 xx = BG3X_L | BG3X_H << 16;
317 yy = BG3Y_L | BG3Y_H << 16;
318 /*
319 renderView(xx, yy,
320 BG3PA, BG3PC,
321 BG3PB, BG3PD,
322 (sizeX -1) <<8,
323 (sizeY -1) << 8,
324 (control & 0x2000) != 0);
325 */
326 break;
327 }
328 }
329
renderMode0()330 void MapView::renderMode0()
331 {
332 renderTextScreen(control);
333 }
334
renderMode1()335 void MapView::renderMode1()
336 {
337 switch(bg) {
338 case 0:
339 case 1:
340 renderTextScreen(control);
341 break;
342 case 2:
343 renderRotScreen(control);
344 break;
345 default:
346 bg = 0;
347 control = BG0CNT;
348 renderTextScreen(control);
349 break;
350 }
351 }
352
renderMode2()353 void MapView::renderMode2()
354 {
355 switch(bg) {
356 case 2:
357 case 3:
358 renderRotScreen(control);
359 break;
360 default:
361 bg = 2;
362 control = BG2CNT;
363 renderRotScreen(control);
364 break;
365 }
366 }
367
renderMode3()368 void MapView::renderMode3()
369 {
370 u8 *bmp = data;
371 u16 *src = (u16 *)&vram[0];
372
373 w = 240;
374 h = 160;
375
376 for(int y = 0; y < 160; y++) {
377 for(int x = 0; x < 240; x++) {
378 u16 data = *src++;
379 *bmp++ = ((data >> 10) & 0x1f) << 3;
380 *bmp++ = ((data >> 5) & 0x1f) << 3;
381 *bmp++ = (data & 0x1f) << 3;
382 }
383 }
384 bg = 2;
385 }
386
387
renderMode4()388 void MapView::renderMode4()
389 {
390 u8 *bmp = data;
391 u8 *src = frame ? &vram[0xa000] : &vram[0];
392 u16 *pal = (u16 *)&paletteRAM[0];
393
394 w = 240;
395 h = 160;
396
397 for(int y = 0; y < 160; y++) {
398 for(int x = 0; x < 240; x++) {
399 u8 c = *src++;
400 u16 data = pal[c];
401 *bmp++ = ((data >> 10) & 0x1f) << 3;
402 *bmp++ = ((data >> 5) & 0x1f) << 3;
403 *bmp++ = (data & 0x1f) << 3;
404 }
405 }
406 bg = 2;
407 }
408
409
renderMode5()410 void MapView::renderMode5()
411 {
412 u8 *bmp = data;
413 u16 *src = (u16 *)(frame ? &vram[0xa000] : &vram[0]);
414
415 w = 160;
416 h = 128;
417
418 for(int y = 0; y < 128; y++) {
419 for(int x = 0; x < 160; x++) {
420 u16 data = *src++;
421 *bmp++ = ((data >> 10) & 0x1f) << 3;
422 *bmp++ = ((data >> 5) & 0x1f) << 3;
423 *bmp++ = (data & 0x1f) << 3;
424 }
425 }
426 bg = 2;
427 }
428
429
OnRefresh()430 void MapView::OnRefresh()
431 {
432 paint();
433 }
434
paint()435 void MapView::paint()
436 {
437 if(vram == NULL)
438 return;
439 int mode = DISPCNT & 7;
440
441 switch(bg) {
442 default:
443 case 0:
444 control = BG0CNT;
445 break;
446 case 1:
447 control = BG1CNT;
448 break;
449 case 2:
450 control = BG2CNT;
451 break;
452 case 3:
453 control = BG3CNT;
454 break;
455 }
456
457 switch(mode) {
458 case 0:
459 renderMode0();
460 break;
461 case 1:
462 renderMode1();
463 break;
464 case 2:
465 renderMode2();
466 break;
467 case 3:
468 renderMode3();
469 break;
470 case 4:
471 renderMode4();
472 break;
473 case 5:
474 renderMode5();
475 break;
476 case 6:
477 renderMode5();
478 break;
479 case 7:
480 renderMode5();
481 break;
482 }
483 enableButtons(mode);
484 SIZE s;
485
486 if(mapView.getStretch()) {
487 mapView.setSize(w, h);
488 s.cx = s.cy = 1;
489 mapView.SetScrollSizes(MM_TEXT, s);
490 } else {
491 mapView.setSize(w, h);
492 s.cx = w;
493 s.cy = h;
494 mapView.SetScrollSizes(MM_TEXT, s);
495 }
496
497 mapView.refresh();
498
499 CString buffer;
500
501 u32 charBase = ((control >> 2) & 0x03) * 0x4000 + 0x6000000;
502 u32 screenBase = ((control >> 8) & 0x1f) * 0x800 + 0x6000000;
503
504 buffer.Format("%d", mode);
505 m_mode.SetWindowText(buffer);
506
507 if(mode >= 3) {
508 m_mapbase.SetWindowText("");
509 m_charbase.SetWindowText("");
510 } else {
511 buffer.Format("0x%08X", screenBase);
512 m_mapbase.SetWindowText(buffer);
513
514 buffer.Format("0x%08X", charBase);
515 m_charbase.SetWindowText(buffer);
516 }
517
518 buffer.Format("%dx%d", w, h);
519 m_dim.SetWindowText(buffer);
520
521 m_numcolors.SetWindowText(control & 0x80 ? "256" : "16");
522
523 buffer.Format("%d", control & 3);
524 m_priority.SetWindowText(buffer);
525
526 m_mosaic.SetWindowText(control & 0x40 ? "1" : "0");
527
528 m_overflow.SetWindowText(bg <= 1 ? "" :
529 control & 0x2000 ? "1" : "0");
530 }
531
OnInitDialog()532 BOOL MapView::OnInitDialog()
533 {
534 CDialog::OnInitDialog();
535
536 DIALOG_SIZER_START( sz )
537 DIALOG_SIZER_ENTRY( IDC_MAP_VIEW, DS_SizeX | DS_SizeY )
538 DIALOG_SIZER_ENTRY( IDC_REFRESH, DS_MoveY)
539 DIALOG_SIZER_ENTRY( IDC_CLOSE, DS_MoveY)
540 DIALOG_SIZER_ENTRY( IDC_SAVE, DS_MoveY)
541 DIALOG_SIZER_ENTRY( IDC_COLOR, DS_MoveY)
542 DIALOG_SIZER_ENTRY( IDC_R, DS_MoveY)
543 DIALOG_SIZER_ENTRY( IDC_G, DS_MoveY)
544 DIALOG_SIZER_ENTRY( IDC_B, DS_MoveY)
545 DIALOG_SIZER_END()
546 SetData(sz,
547 TRUE,
548 HKEY_CURRENT_USER,
549 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\MapView",
550 NULL);
551 SIZE size;
552 size.cx = 1;
553 size.cy = 1;
554 mapView.SetScrollSizes(MM_TEXT,size);
555 int s = regQueryDwordValue("mapViewStretch", 0);
556 if(s)
557 mapView.setStretch(true);
558 ((CButton *)GetDlgItem(IDC_STRETCH))->SetCheck(s);
559 paint();
560
561 return TRUE; // return TRUE unless you set the focus to a control
562 // EXCEPTION: OCX Property Pages should return FALSE
563 }
564
PostNcDestroy()565 void MapView::PostNcDestroy()
566 {
567 delete this;
568 }
569
enableButtons(int mode)570 void MapView::enableButtons(int mode)
571 {
572 bool enable[6] = { true, true, true, true, true, true };
573
574 switch(mode) {
575 case 0:
576 enable[4] = false;
577 enable[5] = false;
578 break;
579 case 1:
580 enable[3] = false;
581 enable[4] = false;
582 enable[5] = false;
583 break;
584 case 2:
585 enable[0] = false;
586 enable[1] = false;
587 enable[4] = false;
588 enable[5] = false;
589 break;
590 case 3:
591 enable[0] = false;
592 enable[1] = false;
593 enable[2] = false;
594 enable[3] = false;
595 enable[4] = false;
596 enable[5] = false;
597 break;
598 case 4:
599 enable[0] = false;
600 enable[1] = false;
601 enable[2] = false;
602 enable[3] = false;
603 break;
604 case 5:
605 enable[0] = false;
606 enable[1] = false;
607 enable[2] = false;
608 enable[3] = false;
609 break;
610 }
611 GetDlgItem(IDC_BG0)->EnableWindow(enable[0]);
612 GetDlgItem(IDC_BG1)->EnableWindow(enable[1]);
613 GetDlgItem(IDC_BG2)->EnableWindow(enable[2]);
614 GetDlgItem(IDC_BG3)->EnableWindow(enable[3]);
615 GetDlgItem(IDC_FRAME_0)->EnableWindow(enable[4]);
616 GetDlgItem(IDC_FRAME_1)->EnableWindow(enable[5]);
617 int id = IDC_BG0;
618 switch(bg) {
619 case 1:
620 id = IDC_BG1;
621 break;
622 case 2:
623 id = IDC_BG2;
624 break;
625 case 3:
626 id = IDC_BG3;
627 break;
628 }
629 CheckRadioButton(IDC_BG0, IDC_BG3, id);
630 id = IDC_FRAME_0;
631 if(frame != 0)
632 id = IDC_FRAME_1;
633 CheckRadioButton(IDC_FRAME_0, IDC_FRAME_1, id);
634 }
635
OnFrame0()636 void MapView::OnFrame0()
637 {
638 frame = 0;
639 paint();
640 }
641
OnFrame1()642 void MapView::OnFrame1()
643 {
644 frame = 1;
645 paint();
646 }
647
OnBg0()648 void MapView::OnBg0()
649 {
650 bg = 0;
651 control = BG0CNT;
652 paint();
653 }
654
OnBg1()655 void MapView::OnBg1()
656 {
657 bg = 1;
658 control = BG1CNT;
659 paint();
660 }
661
OnBg2()662 void MapView::OnBg2()
663 {
664 bg = 2;
665 control = BG2CNT;
666 paint();
667 }
668
OnBg3()669 void MapView::OnBg3()
670 {
671 bg = 3;
672 control = BG3CNT;
673 paint();
674 }
675
OnStretch()676 void MapView::OnStretch()
677 {
678 mapView.setStretch(!mapView.getStretch());
679 paint();
680 regSetDwordValue("mapViewStretch", mapView.getStretch());
681 }
682
OnAutoUpdate()683 void MapView::OnAutoUpdate()
684 {
685 autoUpdate = !autoUpdate;
686 if(autoUpdate) {
687 theApp.winAddUpdateListener(this);
688 } else {
689 theApp.winRemoveUpdateListener(this);
690 }
691 (CButton*)GetDlgItem(IDC_REFRESH)->EnableWindow(autoUpdate ? FALSE : TRUE);
692 }
693
update()694 void MapView::update()
695 {
696 paint();
697 }
698
OnClose()699 void MapView::OnClose()
700 {
701 theApp.winRemoveUpdateListener(this);
702
703 DestroyWindow();
704 }
705
GetTextClickAddress(u32 base,int x,int y)706 u32 MapView::GetTextClickAddress(u32 base, int x, int y)
707 {
708 if(y > 255 && h > 256) {
709 base += 0x800;
710 if(w > 256)
711 base += 0x800;
712 }
713 if(x >= 256)
714 base += 0x800;
715 x &= 255;
716 y &= 255;
717 base += (x>>3)*2 + 64*(y>>3);
718
719 return base;
720 }
721
722
723
GetClickAddress(int x,int y)724 u32 MapView::GetClickAddress(int x, int y)
725 {
726 int mode = DISPCNT & 7;
727
728 u32 base = ((control >> 8) & 0x1f) * 0x800 + 0x6000000;
729
730 // all text bgs (16 bits)
731 if(mode == 0 ||(mode < 3 && bg < 2) || mode == 6 || mode == 7) {
732 return GetTextClickAddress(base, x, y);
733 }
734 // rot bgs (8 bits)
735 if(mode < 3) {
736 return base + (x>>3) + (w>>3)*(y>>3);
737 }
738 // mode 3/5 (16 bits)
739 if(mode != 4) {
740 return 0x6000000 + 0xa000*frame + 2*x + w*y*2;
741 }
742 // mode 4 (8 bits)
743 return 0x6000000 + 0xa000*frame + x + w*y;
744 }
745
OnMapInfo(WPARAM wParam,LPARAM lParam)746 LRESULT MapView::OnMapInfo(WPARAM wParam, LPARAM lParam)
747 {
748 u8 *colors = (u8 *)lParam;
749 mapViewZoom.setColors(colors);
750
751 int x = (int)(wParam & 0xffff);
752 int y = (int)(wParam >> 16);
753
754 CString buffer;
755 buffer.Format("(%d,%d)", x, y);
756 GetDlgItem(IDC_XY)->SetWindowText(buffer);
757
758 u32 address = GetClickAddress(x,y);
759 buffer.Format("0x%08X", address);
760 GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer);
761
762 int mode = DISPCNT & 7;
763 if(mode >= 3 && mode <=5) {
764 // bitmap modes
765 GetDlgItem(IDC_TILE_NUM)->SetWindowText("---");
766 GetDlgItem(IDC_FLIP)->SetWindowText("--");
767 GetDlgItem(IDC_PALETTE_NUM)->SetWindowText("---");
768 } else if(mode == 0 || bg < 2) {
769 // text bgs
770 u16 value = *((u16 *)&vram[address - 0x6000000]);
771
772 int tile = value & 1023;
773 buffer.Format("%d", tile);
774 GetDlgItem(IDC_TILE_NUM)->SetWindowText(buffer);
775 buffer.Empty();
776 buffer += value & 1024 ? 'H' : '-';
777 buffer += value & 2048 ? 'V' : '-';
778 GetDlgItem(IDC_FLIP)->SetWindowText(buffer);
779
780 if(!(control & 0x80)) {
781 buffer.Format("%d", (value >> 12) & 15);
782 } else
783 buffer = "---";
784 GetDlgItem(IDC_PALETTE_NUM)->SetWindowText(buffer);
785 } else {
786 // rot bgs
787 GetDlgItem(IDC_TILE_NUM)->SetWindowText("---");
788 GetDlgItem(IDC_FLIP)->SetWindowText("--");
789 GetDlgItem(IDC_PALETTE_NUM)->SetWindowText("---");
790 }
791
792 return TRUE;
793 }
794
OnColInfo(WPARAM wParam,LPARAM lParam)795 LRESULT MapView::OnColInfo(WPARAM wParam, LPARAM lParam)
796 {
797 u16 c = (u16)wParam;
798
799 color.setColor(c);
800
801 int r = (c & 0x1f);
802 int g = (c & 0x3e0) >> 5;
803 int b = (c & 0x7c00) >> 10;
804
805 CString buffer;
806 buffer.Format("R: %d", r);
807 GetDlgItem(IDC_R)->SetWindowText(buffer);
808
809 buffer.Format("G: %d", g);
810 GetDlgItem(IDC_G)->SetWindowText(buffer);
811
812 buffer.Format("B: %d", b);
813 GetDlgItem(IDC_B)->SetWindowText(buffer);
814
815 return TRUE;
816 }
817
saveBMP(const char * name)818 void MapView::saveBMP(const char *name)
819 {
820 u8 writeBuffer[1024 * 3];
821
822 FILE *fp = fopen(name,"wb");
823
824 if(!fp) {
825 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
826 return;
827 }
828
829 struct {
830 u8 ident[2];
831 u8 filesize[4];
832 u8 reserved[4];
833 u8 dataoffset[4];
834 u8 headersize[4];
835 u8 width[4];
836 u8 height[4];
837 u8 planes[2];
838 u8 bitsperpixel[2];
839 u8 compression[4];
840 u8 datasize[4];
841 u8 hres[4];
842 u8 vres[4];
843 u8 colors[4];
844 u8 importantcolors[4];
845 u8 pad[2];
846 } bmpheader;
847 memset(&bmpheader, 0, sizeof(bmpheader));
848
849 bmpheader.ident[0] = 'B';
850 bmpheader.ident[1] = 'M';
851
852 u32 fsz = sizeof(bmpheader) + w*h*3;
853 utilPutDword(bmpheader.filesize, fsz);
854 utilPutDword(bmpheader.dataoffset, 0x38);
855 utilPutDword(bmpheader.headersize, 0x28);
856 utilPutDword(bmpheader.width, w);
857 utilPutDword(bmpheader.height, h);
858 utilPutDword(bmpheader.planes, 1);
859 utilPutDword(bmpheader.bitsperpixel, 24);
860 utilPutDword(bmpheader.datasize, 3*w*h);
861
862 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
863
864 u8 *b = writeBuffer;
865
866 int sizeX = w;
867 int sizeY = h;
868
869 u8 *pixU8 = (u8 *)data+3*w*(h-1);
870 for(int y = 0; y < sizeY; y++) {
871 for(int x = 0; x < sizeX; x++) {
872 *b++ = *pixU8++; // B
873 *b++ = *pixU8++; // G
874 *b++ = *pixU8++; // R
875 }
876 pixU8 -= 2*3*w;
877 fwrite(writeBuffer, 1, 3*w, fp);
878
879 b = writeBuffer;
880 }
881
882 fclose(fp);
883 }
884
885
886
savePNG(const char * name)887 void MapView::savePNG(const char *name)
888 {
889 u8 writeBuffer[1024 * 3];
890
891 FILE *fp = fopen(name,"wb");
892
893 if(!fp) {
894 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
895 return;
896 }
897
898 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
899 NULL,
900 NULL,
901 NULL);
902 if(!png_ptr) {
903 fclose(fp);
904 return;
905 }
906
907 png_infop info_ptr = png_create_info_struct(png_ptr);
908
909 if(!info_ptr) {
910 png_destroy_write_struct(&png_ptr,NULL);
911 fclose(fp);
912 return;
913 }
914
915 if(setjmp(png_ptr->jmpbuf)) {
916 png_destroy_write_struct(&png_ptr,NULL);
917 fclose(fp);
918 return;
919 }
920
921 png_init_io(png_ptr,fp);
922
923 png_set_IHDR(png_ptr,
924 info_ptr,
925 w,
926 h,
927 8,
928 PNG_COLOR_TYPE_RGB,
929 PNG_INTERLACE_NONE,
930 PNG_COMPRESSION_TYPE_DEFAULT,
931 PNG_FILTER_TYPE_DEFAULT);
932
933 png_write_info(png_ptr,info_ptr);
934
935 u8 *b = writeBuffer;
936
937 int sizeX = w;
938 int sizeY = h;
939
940 u8 *pixU8 = (u8 *)data;
941 for(int y = 0; y < sizeY; y++) {
942 for(int x = 0; x < sizeX; x++) {
943 int blue = *pixU8++;
944 int green = *pixU8++;
945 int red = *pixU8++;
946
947 *b++ = red;
948 *b++ = green;
949 *b++ = blue;
950 }
951 png_write_row(png_ptr,writeBuffer);
952
953 b = writeBuffer;
954 }
955
956 png_write_end(png_ptr, info_ptr);
957
958 png_destroy_write_struct(&png_ptr, &info_ptr);
959
960 fclose(fp);
961 }
962
OnSave()963 void MapView::OnSave()
964 {
965 if(rom != NULL)
966 {
967 CString filename;
968
969 if(captureFormat == 0)
970 filename = "map.png";
971 else
972 filename = "map.bmp";
973
974 LPCTSTR exts[] = {".png", ".bmp" };
975
976 CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
977 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
978
979 FileDlg dlg(this,
980 filename,
981 filter,
982 captureFormat ? 2 : 1,
983 captureFormat ? "BMP" : "PNG",
984 exts,
985 "",
986 title,
987 true);
988
989 if(dlg.DoModal() == IDCANCEL) {
990 return;
991 }
992
993 if(dlg.getFilterIndex() == 2)
994 saveBMP(dlg.GetPathName());
995 else
996 savePNG(dlg.GetPathName());
997 }
998 }
999