Mercurial > vba-clojure
comparison 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 |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // MapView.cpp : implementation file | |
2 // | |
3 | |
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" | |
11 | |
12 #include "../gba/GBAGlobals.h" | |
13 #include "../NLS.h" | |
14 #include "../common/Util.h" | |
15 | |
16 extern "C" { | |
17 #include <png.h> | |
18 } | |
19 | |
20 ///////////////////////////////////////////////////////////////////////////// | |
21 // MapView dialog | |
22 | |
23 MapView::MapView(CWnd*pParent /*=NULL*/) | |
24 : ResizeDlg(MapView::IDD, pParent) | |
25 { | |
26 //{{AFX_DATA_INIT(MapView) | |
27 //}}AFX_DATA_INIT | |
28 autoUpdate = false; | |
29 | |
30 memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader)); | |
31 | |
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); | |
39 | |
40 mapView.setData(data); | |
41 mapView.setBmpInfo(&bmpInfo); | |
42 | |
43 control = BG0CNT; | |
44 | |
45 bg = 0; | |
46 frame = 0; | |
47 } | |
48 | |
49 MapView::~MapView() | |
50 { | |
51 free(data); | |
52 data = NULL; | |
53 } | |
54 | |
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 } | |
72 | |
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() | |
90 | |
91 ///////////////////////////////////////////////////////////////////////////// | |
92 // MapView message handlers | |
93 | |
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; | |
100 | |
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 } | |
118 | |
119 w = sizeX; | |
120 h = sizeY; | |
121 | |
122 if (control & 0x80) | |
123 { | |
124 for (int y = 0; y < sizeY; y++) | |
125 { | |
126 int yy = y & 255; | |
127 | |
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); | |
135 | |
136 for (int x = 0; x < sizeX; x++) | |
137 { | |
138 u16 data = *screenSource; | |
139 | |
140 int tile = data & 0x3FF; | |
141 int tileX = (x & 7); | |
142 int tileY = y & 7; | |
143 | |
144 if (data & 0x0400) | |
145 tileX = 7 - tileX; | |
146 if (data & 0x0800) | |
147 tileY = 7 - tileY; | |
148 | |
149 u8 c = charBase[tile * 64 + tileY * 8 + tileX]; | |
150 | |
151 u16 color = palette[c]; | |
152 | |
153 *bmp++ = ((color >> 10) & 0x1f) << 3; | |
154 *bmp++ = ((color >> 5) & 0x1f) << 3; | |
155 *bmp++ = (color & 0x1f) << 3; | |
156 | |
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; | |
176 | |
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); | |
184 | |
185 for (int x = 0; x < sizeX; x++) | |
186 { | |
187 u16 data = *screenSource; | |
188 | |
189 int tile = data & 0x3FF; | |
190 int tileX = (x & 7); | |
191 int tileY = y & 7; | |
192 | |
193 if (data & 0x0400) | |
194 tileX = 7 - tileX; | |
195 if (data & 0x0800) | |
196 tileY = 7 - tileY; | |
197 | |
198 u8 color = charBase[tile * 32 + tileY * 4 + (tileX>>1)]; | |
199 | |
200 if (tileX & 1) | |
201 { | |
202 color = (color >> 4); | |
203 } | |
204 else | |
205 { | |
206 color &= 0x0F; | |
207 } | |
208 | |
209 int pal = (*screenSource>>8) & 0xF0; | |
210 u16 color2 = palette[pal + color]; | |
211 | |
212 *bmp++ = ((color2 >> 10) & 0x1f) << 3; | |
213 *bmp++ = ((color2 >> 5) & 0x1f) << 3; | |
214 *bmp++ = (color2 & 0x1f) << 3; | |
215 | |
216 if (data & 0x0400) | |
217 { | |
218 if (tileX == 0) | |
219 screenSource++; | |
220 } | |
221 else if (tileX == 7) | |
222 screenSource++; | |
223 | |
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 } | |
268 | |
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; | |
275 | |
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 } | |
292 | |
293 w = sizeX; | |
294 h = sizeY; | |
295 | |
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)]; | |
303 | |
304 int tileX = (x & 7); | |
305 int tileY = y & 7; | |
306 | |
307 u8 color = charBase[tile * 64 + tileY * 8 + tileX]; | |
308 u16 color2 = palette[color]; | |
309 | |
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)]; | |
323 | |
324 int tileX = (x & 7); | |
325 int tileY = y & 7; | |
326 | |
327 u8 color = charBase[tile * 64 + tileY * 8 + tileX]; | |
328 u16 color2 = palette[color]; | |
329 | |
330 *bmp++ = ((color2 >> 10) & 0x1f) << 3; | |
331 *bmp++ = ((color2 >> 5) & 0x1f) << 3; | |
332 *bmp++ = (color2 & 0x1f) << 3; | |
333 } | |
334 } | |
335 } | |
336 | |
337 u32 xx; | |
338 u32 yy; | |
339 | |
340 switch (bg) | |
341 { | |
342 case 2: | |
343 xx = BG2X_L | BG2X_H << 16; | |
344 yy = BG2Y_L | BG2Y_H << 16; | |
345 | |
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 } | |
369 | |
370 void MapView::renderMode0() | |
371 { | |
372 renderTextScreen(control); | |
373 } | |
374 | |
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 } | |
393 | |
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 } | |
409 | |
410 void MapView::renderMode3() | |
411 { | |
412 u8 * bmp = data; | |
413 u16 *src = (u16 *)&vram[0]; | |
414 | |
415 w = 240; | |
416 h = 160; | |
417 | |
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 } | |
430 | |
431 void MapView::renderMode4() | |
432 { | |
433 u8 * bmp = data; | |
434 u8 * src = frame ? &vram[0xa000] : &vram[0]; | |
435 u16 *pal = (u16 *)&paletteRAM[0]; | |
436 | |
437 w = 240; | |
438 h = 160; | |
439 | |
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 } | |
453 | |
454 void MapView::renderMode5() | |
455 { | |
456 u8 * bmp = data; | |
457 u16 *src = (u16 *)(frame ? &vram[0xa000] : &vram[0]); | |
458 | |
459 w = 160; | |
460 h = 128; | |
461 | |
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 } | |
474 | |
475 void MapView::OnRefresh() | |
476 { | |
477 paint(); | |
478 } | |
479 | |
480 void MapView::paint() | |
481 { | |
482 if (vram == NULL) | |
483 return; | |
484 int mode = DISPCNT & 7; | |
485 | |
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 } | |
502 | |
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; | |
526 | |
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 } | |
540 | |
541 mapView.refresh(); | |
542 | |
543 CString buffer; | |
544 | |
545 u32 charBase = ((control >> 2) & 0x03) * 0x4000 + 0x6000000; | |
546 u32 screenBase = ((control >> 8) & 0x1f) * 0x800 + 0x6000000; | |
547 | |
548 buffer.Format("%d", mode); | |
549 m_mode.SetWindowText(buffer); | |
550 | |
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); | |
560 | |
561 buffer.Format("0x%08X", charBase); | |
562 m_charbase.SetWindowText(buffer); | |
563 } | |
564 | |
565 buffer.Format("%dx%d", w, h); | |
566 m_dim.SetWindowText(buffer); | |
567 | |
568 m_numcolors.SetWindowText(control & 0x80 ? "256" : "16"); | |
569 | |
570 buffer.Format("%d", control & 3); | |
571 m_priority.SetWindowText(buffer); | |
572 | |
573 m_mosaic.SetWindowText(control & 0x40 ? "1" : "0"); | |
574 | |
575 m_overflow.SetWindowText(bg <= 1 ? "" : | |
576 control & 0x2000 ? "1" : "0"); | |
577 } | |
578 | |
579 BOOL MapView::OnInitDialog() | |
580 { | |
581 CDialog::OnInitDialog(); | |
582 | |
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); | |
598 | |
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(); | |
608 | |
609 return TRUE; // return TRUE unless you set the focus to a control | |
610 // EXCEPTION: OCX Property Pages should return FALSE | |
611 } | |
612 | |
613 void MapView::PostNcDestroy() | |
614 { | |
615 delete this; | |
616 } | |
617 | |
618 void MapView::enableButtons(int mode) | |
619 { | |
620 bool enable[6] = { true, true, true, true, true, true }; | |
621 | |
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 } | |
685 | |
686 void MapView::OnFrame0() | |
687 { | |
688 frame = 0; | |
689 paint(); | |
690 } | |
691 | |
692 void MapView::OnFrame1() | |
693 { | |
694 frame = 1; | |
695 paint(); | |
696 } | |
697 | |
698 void MapView::OnBg0() | |
699 { | |
700 bg = 0; | |
701 control = BG0CNT; | |
702 paint(); | |
703 } | |
704 | |
705 void MapView::OnBg1() | |
706 { | |
707 bg = 1; | |
708 control = BG1CNT; | |
709 paint(); | |
710 } | |
711 | |
712 void MapView::OnBg2() | |
713 { | |
714 bg = 2; | |
715 control = BG2CNT; | |
716 paint(); | |
717 } | |
718 | |
719 void MapView::OnBg3() | |
720 { | |
721 bg = 3; | |
722 control = BG3CNT; | |
723 paint(); | |
724 } | |
725 | |
726 void MapView::OnStretch() | |
727 { | |
728 mapView.setStretch(!mapView.getStretch()); | |
729 paint(); | |
730 regSetDwordValue("mapViewStretch", mapView.getStretch()); | |
731 } | |
732 | |
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 } | |
745 | |
746 void MapView::update() | |
747 { | |
748 paint(); | |
749 } | |
750 | |
751 void MapView::OnClose() | |
752 { | |
753 theApp.winRemoveUpdateListener(this); | |
754 | |
755 DestroyWindow(); | |
756 } | |
757 | |
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); | |
771 | |
772 return base; | |
773 } | |
774 | |
775 u32 MapView::GetClickAddress(int x, int y) | |
776 { | |
777 int mode = DISPCNT & 7; | |
778 | |
779 u32 base = ((control >> 8) & 0x1f) * 0x800 + 0x6000000; | |
780 | |
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 } | |
799 | |
800 LRESULT MapView::OnMapInfo(WPARAM wParam, LPARAM lParam) | |
801 { | |
802 u8 *colors = (u8 *)lParam; | |
803 mapViewZoom.setColors(colors); | |
804 | |
805 int x = wParam & 0xffff; | |
806 int y = (wParam >> 16); | |
807 | |
808 CString buffer; | |
809 buffer.Format("(%d,%d)", x, y); | |
810 GetDlgItem(IDC_XY)->SetWindowText(buffer); | |
811 | |
812 u32 address = GetClickAddress(x, y); | |
813 buffer.Format("0x%08X", address); | |
814 GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer); | |
815 | |
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]); | |
828 | |
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); | |
836 | |
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 } | |
852 | |
853 return TRUE; | |
854 } | |
855 | |
856 LRESULT MapView::OnColInfo(WPARAM wParam, LPARAM lParam) | |
857 { | |
858 u16 c = (u16)wParam; | |
859 | |
860 color.setColor(c); | |
861 | |
862 int r = (c & 0x1f); | |
863 int g = (c & 0x3e0) >> 5; | |
864 int b = (c & 0x7c00) >> 10; | |
865 | |
866 CString buffer; | |
867 buffer.Format("R: %d", r); | |
868 GetDlgItem(IDC_R)->SetWindowText(buffer); | |
869 | |
870 buffer.Format("G: %d", g); | |
871 GetDlgItem(IDC_G)->SetWindowText(buffer); | |
872 | |
873 buffer.Format("B: %d", b); | |
874 GetDlgItem(IDC_B)->SetWindowText(buffer); | |
875 | |
876 return TRUE; | |
877 } | |
878 | |
879 void MapView::saveBMP(const char *name) | |
880 { | |
881 u8 writeBuffer[1024 * 3]; | |
882 | |
883 FILE *fp = fopen(name, "wb"); | |
884 | |
885 if (!fp) | |
886 { | |
887 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); | |
888 return; | |
889 } | |
890 | |
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)); | |
911 | |
912 bmpheader.ident[0] = 'B'; | |
913 bmpheader.ident[1] = 'M'; | |
914 | |
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); | |
924 | |
925 fwrite(&bmpheader, 1, sizeof(bmpheader), fp); | |
926 | |
927 u8 *b = writeBuffer; | |
928 | |
929 int sizeX = w; | |
930 int sizeY = h; | |
931 | |
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); | |
943 | |
944 b = writeBuffer; | |
945 } | |
946 | |
947 fclose(fp); | |
948 } | |
949 | |
950 void MapView::savePNG(const char *name) | |
951 { | |
952 u8 writeBuffer[1024 * 3]; | |
953 | |
954 FILE *fp = fopen(name, "wb"); | |
955 | |
956 if (!fp) | |
957 { | |
958 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); | |
959 return; | |
960 } | |
961 | |
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 } | |
971 | |
972 png_infop info_ptr = png_create_info_struct(png_ptr); | |
973 | |
974 if (!info_ptr) | |
975 { | |
976 png_destroy_write_struct(&png_ptr, NULL); | |
977 fclose(fp); | |
978 return; | |
979 } | |
980 | |
981 if (setjmp(png_ptr->jmpbuf)) | |
982 { | |
983 png_destroy_write_struct(&png_ptr, NULL); | |
984 fclose(fp); | |
985 return; | |
986 } | |
987 | |
988 png_init_io(png_ptr, fp); | |
989 | |
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); | |
999 | |
1000 png_write_info(png_ptr, info_ptr); | |
1001 | |
1002 u8 *b = writeBuffer; | |
1003 | |
1004 int sizeX = w; | |
1005 int sizeY = h; | |
1006 | |
1007 u8 *pixU8 = (u8 *)data; | |
1008 for (int y = 0; y < sizeY; y++) | |
1009 { | |
1010 for (int x = 0; x < sizeX; x++) | |
1011 { | |
1012 int blue = *pixU8++; | |
1013 int green = *pixU8++; | |
1014 int red = *pixU8++; | |
1015 | |
1016 *b++ = red; | |
1017 *b++ = green; | |
1018 *b++ = blue; | |
1019 } | |
1020 png_write_row(png_ptr, writeBuffer); | |
1021 | |
1022 b = writeBuffer; | |
1023 } | |
1024 | |
1025 png_write_end(png_ptr, info_ptr); | |
1026 | |
1027 png_destroy_write_struct(&png_ptr, &info_ptr); | |
1028 | |
1029 fclose(fp); | |
1030 } | |
1031 | |
1032 void MapView::OnSave() | |
1033 { | |
1034 CString filename; | |
1035 | |
1036 if (theApp.captureFormat == 0) | |
1037 filename = "map.png"; | |
1038 else | |
1039 filename = "map.bmp"; | |
1040 | |
1041 LPCTSTR exts[] = {".png", ".bmp", NULL }; | |
1042 | |
1043 CString filter = winResLoadFilter(IDS_FILTER_PNG); | |
1044 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); | |
1045 | |
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); | |
1055 | |
1056 if (dlg.DoModal() == IDCANCEL) | |
1057 { | |
1058 return; | |
1059 } | |
1060 | |
1061 if (dlg.getFilterIndex() == 2) | |
1062 saveBMP(dlg.GetPathName()); | |
1063 else | |
1064 savePNG(dlg.GetPathName()); | |
1065 } | |
1066 |