view src/win32/MapView.cpp @ 1:f9f4f1b99eed

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