Mercurial > vba-linux
comparison src/win32/OamView.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 // OamView.cpp : implementation file | |
2 // | |
3 | |
4 #include "stdafx.h" | |
5 #include "resource.h" | |
6 #include "OamView.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 // OamView dialog | |
22 | |
23 OamView::OamView(CWnd*pParent /*=NULL*/) | |
24 : ResizeDlg(OamView::IDD, pParent) | |
25 { | |
26 //{{AFX_DATA_INIT(OamView) | |
27 m_stretch = FALSE; | |
28 //}}AFX_DATA_INIT | |
29 autoUpdate = false; | |
30 | |
31 memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader)); | |
32 | |
33 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader); | |
34 bmpInfo.bmiHeader.biWidth = 32; | |
35 bmpInfo.bmiHeader.biHeight = 32; | |
36 bmpInfo.bmiHeader.biPlanes = 1; | |
37 bmpInfo.bmiHeader.biBitCount = 24; | |
38 bmpInfo.bmiHeader.biCompression = BI_RGB; | |
39 data = (u8 *)calloc(1, 3 * 64 * 64); | |
40 | |
41 oamView.setData(data); | |
42 oamView.setBmpInfo(&bmpInfo); | |
43 | |
44 number = 0; | |
45 } | |
46 | |
47 void OamView::DoDataExchange(CDataExchange*pDX) | |
48 { | |
49 CDialog::DoDataExchange(pDX); | |
50 //{{AFX_DATA_MAP(OamView) | |
51 DDX_Control(pDX, IDC_SPRITE, m_sprite); | |
52 DDX_Check(pDX, IDC_STRETCH, m_stretch); | |
53 //}}AFX_DATA_MAP | |
54 DDX_Control(pDX, IDC_COLOR, color); | |
55 DDX_Control(pDX, IDC_OAM_VIEW, oamView); | |
56 DDX_Control(pDX, IDC_OAM_VIEW_ZOOM, oamZoom); | |
57 } | |
58 | |
59 BEGIN_MESSAGE_MAP(OamView, CDialog) | |
60 //{{AFX_MSG_MAP(OamView) | |
61 ON_BN_CLICKED(IDC_SAVE, OnSave) | |
62 ON_BN_CLICKED(IDC_STRETCH, OnStretch) | |
63 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate) | |
64 ON_EN_CHANGE(IDC_SPRITE, OnChangeSprite) | |
65 ON_BN_CLICKED(IDC_CLOSE, OnClose) | |
66 ON_WM_HSCROLL() | |
67 //}}AFX_MSG_MAP | |
68 ON_MESSAGE(WM_MAPINFO, OnMapInfo) | |
69 ON_MESSAGE(WM_COLINFO, OnColInfo) | |
70 END_MESSAGE_MAP() | |
71 | |
72 ///////////////////////////////////////////////////////////////////////////// | |
73 // OamView message handlers | |
74 | |
75 OamView::~OamView() | |
76 { | |
77 free(data); | |
78 data = NULL; | |
79 } | |
80 | |
81 void OamView::paint() | |
82 { | |
83 if (oam == NULL || paletteRAM == NULL || vram == NULL) | |
84 return; | |
85 | |
86 render(); | |
87 oamView.setSize(w, h); | |
88 oamView.refresh(); | |
89 } | |
90 | |
91 void OamView::update() | |
92 { | |
93 paint(); | |
94 } | |
95 | |
96 void OamView::setAttributes(u16 a0, u16 a1, u16 a2) | |
97 { | |
98 CString buffer; | |
99 | |
100 int y = a0 & 255; | |
101 int rot = a0 & 512; | |
102 int mode = (a0 >> 10) & 3; | |
103 int mosaic = a0 & 4096; | |
104 int color = a0 & 8192; | |
105 int duple = a0 & 1024; | |
106 int shape = (a0 >> 14) & 3; | |
107 int x = a1 & 511; | |
108 int rotParam = (a1 >> 9) & 31; | |
109 int flipH = a1 & 4096; | |
110 int flipV = a1 & 8192; | |
111 int size = (a1 >> 14) & 3; | |
112 int tile = a2 & 1023; | |
113 int prio = (a2 >> 10) & 3; | |
114 int pal = (a2 >> 12) & 15; | |
115 | |
116 buffer.Format("%d,%d", x, y); | |
117 GetDlgItem(IDC_POS)->SetWindowText(buffer); | |
118 | |
119 buffer.Format("%d", mode); | |
120 GetDlgItem(IDC_MODE)->SetWindowText(buffer); | |
121 | |
122 GetDlgItem(IDC_COLORS)->SetWindowText(color ? "256" : "16"); | |
123 | |
124 buffer.Format("%d", pal); | |
125 GetDlgItem(IDC_PALETTE)->SetWindowText(buffer); | |
126 | |
127 buffer.Format("%d", tile); | |
128 GetDlgItem(IDC_TILE)->SetWindowText(buffer); | |
129 | |
130 buffer.Format("%d", prio); | |
131 GetDlgItem(IDC_PRIO)->SetWindowText(buffer); | |
132 | |
133 buffer.Format("%d,%d", w, h); | |
134 GetDlgItem(IDC_SIZE2)->SetWindowText(buffer); | |
135 | |
136 if (rot) | |
137 { | |
138 buffer.Format("%d", rotParam); | |
139 } | |
140 else | |
141 buffer.Empty(); | |
142 GetDlgItem(IDC_ROT)->SetWindowText(buffer); | |
143 | |
144 buffer.Empty(); | |
145 | |
146 if (rot) | |
147 buffer += 'R'; | |
148 else | |
149 buffer += ' '; | |
150 if (!rot) | |
151 { | |
152 if (flipH) | |
153 buffer += 'H'; | |
154 else | |
155 buffer += ' '; | |
156 if (flipV) | |
157 buffer += 'V'; | |
158 else | |
159 buffer += ' '; | |
160 } | |
161 else | |
162 { | |
163 buffer += ' '; | |
164 buffer += ' '; | |
165 } | |
166 if (mosaic) | |
167 buffer += 'M'; | |
168 else | |
169 buffer += ' '; | |
170 if (duple) | |
171 buffer += 'D'; | |
172 else | |
173 buffer += ' '; | |
174 | |
175 GetDlgItem(IDC_FLAGS)->SetWindowText(buffer); | |
176 } | |
177 | |
178 void OamView::render() | |
179 { | |
180 int m = 0; | |
181 if (oam == NULL || paletteRAM == NULL || vram == NULL) | |
182 return; | |
183 | |
184 u16 *sprites = &((u16 *)oam)[4*number]; | |
185 u16 *spritePalette = &((u16 *)paletteRAM)[0x100]; | |
186 u8 * bmp = data; | |
187 | |
188 u16 a0 = *sprites++; | |
189 u16 a1 = *sprites++; | |
190 u16 a2 = *sprites++; | |
191 | |
192 int sizeY = 8; | |
193 int sizeX = 8; | |
194 | |
195 switch (((a0 >>12) & 0x0c)|(a1>>14)) | |
196 { | |
197 case 0: | |
198 break; | |
199 case 1: | |
200 sizeX = sizeY = 16; | |
201 break; | |
202 case 2: | |
203 sizeX = sizeY = 32; | |
204 break; | |
205 case 3: | |
206 sizeX = sizeY = 64; | |
207 break; | |
208 case 4: | |
209 sizeX = 16; | |
210 break; | |
211 case 5: | |
212 sizeX = 32; | |
213 break; | |
214 case 6: | |
215 sizeX = 32; | |
216 sizeY = 16; | |
217 break; | |
218 case 7: | |
219 sizeX = 64; | |
220 sizeY = 32; | |
221 break; | |
222 case 8: | |
223 sizeY = 16; | |
224 break; | |
225 case 9: | |
226 sizeY = 32; | |
227 break; | |
228 case 10: | |
229 sizeX = 16; | |
230 sizeY = 32; | |
231 break; | |
232 case 11: | |
233 sizeX = 32; | |
234 sizeY = 64; | |
235 break; | |
236 default: | |
237 return; | |
238 } | |
239 | |
240 w = sizeX; | |
241 h = sizeY; | |
242 | |
243 setAttributes(a0, a1, a2); | |
244 | |
245 int sy = (a0 & 255); | |
246 | |
247 if (a0 & 0x2000) | |
248 { | |
249 int c = (a2 & 0x3FF); | |
250 // if((DISPCNT & 7) > 2 && (c < 512)) | |
251 // return; | |
252 int inc = 32; | |
253 if (DISPCNT & 0x40) | |
254 inc = sizeX >> 2; | |
255 else | |
256 c &= 0x3FE; | |
257 | |
258 for (int y = 0; y < sizeY; y++) | |
259 { | |
260 for (int x = 0; x < sizeX; x++) | |
261 { | |
262 u32 color = vram[0x10000 + (((c + (y>>3) * inc)* | |
263 32 + (y & 7) * 8 + (x >> 3) * 64 + | |
264 (x & 7))&0x7FFF)]; | |
265 color = spritePalette[color]; | |
266 *bmp++ = ((color >> 10) & 0x1f) << 3; | |
267 *bmp++ = ((color >> 5) & 0x1f) << 3; | |
268 *bmp++ = (color & 0x1f) << 3; | |
269 } | |
270 } | |
271 } | |
272 else | |
273 { | |
274 int c = (a2 & 0x3FF); | |
275 // if((DISPCNT & 7) > 2 && (c < 512)) | |
276 // continue; | |
277 | |
278 int inc = 32; | |
279 if (DISPCNT & 0x40) | |
280 inc = sizeX >> 3; | |
281 int palette = (a2 >> 8) & 0xF0; | |
282 for (int y = 0; y < sizeY; y++) | |
283 { | |
284 for (int x = 0; x < sizeX; x++) | |
285 { | |
286 u32 color = vram[0x10000 + (((c + (y>>3) * inc)* | |
287 32 + (y & 7) * 4 + (x >> 3) * 32 + | |
288 ((x & 7)>>1))&0x7FFF)]; | |
289 if (x & 1) | |
290 color >>= 4; | |
291 else | |
292 color &= 0x0F; | |
293 | |
294 color = spritePalette[palette+color]; | |
295 *bmp++ = ((color >> 10) & 0x1f) << 3; | |
296 *bmp++ = ((color >> 5) & 0x1f) << 3; | |
297 *bmp++ = (color & 0x1f) << 3; | |
298 } | |
299 } | |
300 } | |
301 } | |
302 | |
303 void OamView::saveBMP(const char *name) | |
304 { | |
305 u8 writeBuffer[1024 * 3]; | |
306 | |
307 FILE *fp = fopen(name, "wb"); | |
308 | |
309 if (!fp) | |
310 { | |
311 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); | |
312 return; | |
313 } | |
314 | |
315 struct | |
316 { | |
317 u8 ident[2]; | |
318 u8 filesize[4]; | |
319 u8 reserved[4]; | |
320 u8 dataoffset[4]; | |
321 u8 headersize[4]; | |
322 u8 width[4]; | |
323 u8 height[4]; | |
324 u8 planes[2]; | |
325 u8 bitsperpixel[2]; | |
326 u8 compression[4]; | |
327 u8 datasize[4]; | |
328 u8 hres[4]; | |
329 u8 vres[4]; | |
330 u8 colors[4]; | |
331 u8 importantcolors[4]; | |
332 u8 pad[2]; | |
333 } bmpheader; | |
334 memset(&bmpheader, 0, sizeof(bmpheader)); | |
335 | |
336 bmpheader.ident[0] = 'B'; | |
337 bmpheader.ident[1] = 'M'; | |
338 | |
339 u32 fsz = sizeof(bmpheader) + w*h*3; | |
340 utilPutDword(bmpheader.filesize, fsz); | |
341 utilPutDword(bmpheader.dataoffset, 0x38); | |
342 utilPutDword(bmpheader.headersize, 0x28); | |
343 utilPutDword(bmpheader.width, w); | |
344 utilPutDword(bmpheader.height, h); | |
345 utilPutDword(bmpheader.planes, 1); | |
346 utilPutDword(bmpheader.bitsperpixel, 24); | |
347 utilPutDword(bmpheader.datasize, 3*w*h); | |
348 | |
349 fwrite(&bmpheader, 1, sizeof(bmpheader), fp); | |
350 | |
351 u8 *b = writeBuffer; | |
352 | |
353 int sizeX = w; | |
354 int sizeY = h; | |
355 | |
356 u8 *pixU8 = (u8 *)data+3*w*(h-1); | |
357 for (int y = 0; y < sizeY; y++) | |
358 { | |
359 for (int x = 0; x < sizeX; x++) | |
360 { | |
361 *b++ = *pixU8++; // B | |
362 *b++ = *pixU8++; // G | |
363 *b++ = *pixU8++; // R | |
364 } | |
365 pixU8 -= 2*3*w; | |
366 fwrite(writeBuffer, 1, 3*w, fp); | |
367 | |
368 b = writeBuffer; | |
369 } | |
370 | |
371 fclose(fp); | |
372 } | |
373 | |
374 void OamView::savePNG(const char *name) | |
375 { | |
376 u8 writeBuffer[1024 * 3]; | |
377 | |
378 FILE *fp = fopen(name, "wb"); | |
379 | |
380 if (!fp) | |
381 { | |
382 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); | |
383 return; | |
384 } | |
385 | |
386 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, | |
387 NULL, | |
388 NULL, | |
389 NULL); | |
390 if (!png_ptr) | |
391 { | |
392 fclose(fp); | |
393 return; | |
394 } | |
395 | |
396 png_infop info_ptr = png_create_info_struct(png_ptr); | |
397 | |
398 if (!info_ptr) | |
399 { | |
400 png_destroy_write_struct(&png_ptr, NULL); | |
401 fclose(fp); | |
402 return; | |
403 } | |
404 | |
405 if (setjmp(png_ptr->jmpbuf)) | |
406 { | |
407 png_destroy_write_struct(&png_ptr, NULL); | |
408 fclose(fp); | |
409 return; | |
410 } | |
411 | |
412 png_init_io(png_ptr, fp); | |
413 | |
414 png_set_IHDR(png_ptr, | |
415 info_ptr, | |
416 w, | |
417 h, | |
418 8, | |
419 PNG_COLOR_TYPE_RGB, | |
420 PNG_INTERLACE_NONE, | |
421 PNG_COMPRESSION_TYPE_DEFAULT, | |
422 PNG_FILTER_TYPE_DEFAULT); | |
423 | |
424 png_write_info(png_ptr, info_ptr); | |
425 | |
426 u8 *b = writeBuffer; | |
427 | |
428 int sizeX = w; | |
429 int sizeY = h; | |
430 | |
431 u8 *pixU8 = (u8 *)data; | |
432 for (int y = 0; y < sizeY; y++) | |
433 { | |
434 for (int x = 0; x < sizeX; x++) | |
435 { | |
436 int blue = *pixU8++; | |
437 int green = *pixU8++; | |
438 int red = *pixU8++; | |
439 | |
440 *b++ = red; | |
441 *b++ = green; | |
442 *b++ = blue; | |
443 } | |
444 png_write_row(png_ptr, writeBuffer); | |
445 | |
446 b = writeBuffer; | |
447 } | |
448 | |
449 png_write_end(png_ptr, info_ptr); | |
450 | |
451 png_destroy_write_struct(&png_ptr, &info_ptr); | |
452 | |
453 fclose(fp); | |
454 } | |
455 | |
456 void OamView::OnSave() | |
457 { | |
458 CString captureBuffer; | |
459 | |
460 if (theApp.captureFormat == 0) | |
461 captureBuffer = "oam.png"; | |
462 else | |
463 captureBuffer = "oam.bmp"; | |
464 | |
465 LPCTSTR exts[] = {".png", ".bmp", NULL }; | |
466 | |
467 CString filter = winResLoadFilter(IDS_FILTER_PNG); | |
468 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); | |
469 | |
470 FileDlg dlg(this, | |
471 captureBuffer, | |
472 filter, | |
473 theApp.captureFormat ? 2 : 1, | |
474 theApp.captureFormat ? "BMP" : "PNG", | |
475 exts, | |
476 "", | |
477 title, | |
478 true); | |
479 | |
480 if (dlg.DoModal() == IDCANCEL) | |
481 { | |
482 return; | |
483 } | |
484 captureBuffer = dlg.GetPathName(); | |
485 | |
486 if (dlg.getFilterIndex() == 2) | |
487 saveBMP(captureBuffer); | |
488 else | |
489 savePNG(captureBuffer); | |
490 } | |
491 | |
492 BOOL OamView::OnInitDialog() | |
493 { | |
494 CDialog::OnInitDialog(); | |
495 | |
496 DIALOG_SIZER_START(sz) | |
497 DIALOG_SIZER_ENTRY(IDC_OAM_VIEW, DS_SizeX | DS_SizeY) | |
498 DIALOG_SIZER_ENTRY(IDC_OAM_VIEW_ZOOM, DS_MoveX) | |
499 DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY) | |
500 DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY) | |
501 DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY) | |
502 DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY) | |
503 DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY) | |
504 DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY) | |
505 DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY) | |
506 DIALOG_SIZER_END() | |
507 SetData(sz, | |
508 TRUE, | |
509 HKEY_CURRENT_USER, | |
510 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\OamView", | |
511 NULL); | |
512 | |
513 m_sprite.SetWindowText("0"); | |
514 | |
515 updateScrollInfo(); | |
516 | |
517 m_stretch = regQueryDwordValue("oamViewStretch", 0); | |
518 if (m_stretch) | |
519 oamView.setStretch(true); | |
520 UpdateData(FALSE); | |
521 | |
522 paint(); | |
523 | |
524 return TRUE; // return TRUE unless you set the focus to a control | |
525 // EXCEPTION: OCX Property Pages should return FALSE | |
526 } | |
527 | |
528 void OamView::OnStretch() | |
529 { | |
530 oamView.setStretch(!oamView.getStretch()); | |
531 paint(); | |
532 regSetDwordValue("oamViewStretch", oamView.getStretch()); | |
533 } | |
534 | |
535 void OamView::OnAutoUpdate() | |
536 { | |
537 autoUpdate = !autoUpdate; | |
538 if (autoUpdate) | |
539 { | |
540 theApp.winAddUpdateListener(this); | |
541 } | |
542 else | |
543 { | |
544 theApp.winRemoveUpdateListener(this); | |
545 } | |
546 } | |
547 | |
548 void OamView::OnChangeSprite() | |
549 { | |
550 CString buffer; | |
551 m_sprite.GetWindowText(buffer); | |
552 int n = atoi(buffer); | |
553 if (n < 0 || n > 127) | |
554 { | |
555 buffer.Format("%d", number); | |
556 m_sprite.SetWindowText(buffer); | |
557 return; | |
558 } | |
559 number = n; | |
560 paint(); | |
561 updateScrollInfo(); | |
562 } | |
563 | |
564 void OamView::OnClose() | |
565 { | |
566 theApp.winRemoveUpdateListener(this); | |
567 | |
568 DestroyWindow(); | |
569 } | |
570 | |
571 LRESULT OamView::OnMapInfo(WPARAM wParam, LPARAM lParam) | |
572 { | |
573 u8 *colors = (u8 *)lParam; | |
574 oamZoom.setColors(colors); | |
575 | |
576 return TRUE; | |
577 } | |
578 | |
579 LRESULT OamView::OnColInfo(WPARAM wParam, LPARAM lParam) | |
580 { | |
581 u16 c = (u16)wParam; | |
582 | |
583 color.setColor(c); | |
584 | |
585 int r = (c & 0x1f); | |
586 int g = (c & 0x3e0) >> 5; | |
587 int b = (c & 0x7c00) >> 10; | |
588 | |
589 CString buffer; | |
590 buffer.Format("R: %d", r); | |
591 GetDlgItem(IDC_R)->SetWindowText(buffer); | |
592 | |
593 buffer.Format("G: %d", g); | |
594 GetDlgItem(IDC_G)->SetWindowText(buffer); | |
595 | |
596 buffer.Format("B: %d", b); | |
597 GetDlgItem(IDC_B)->SetWindowText(buffer); | |
598 | |
599 return TRUE; | |
600 } | |
601 | |
602 void OamView::updateScrollInfo() | |
603 { | |
604 SCROLLINFO si; | |
605 ZeroMemory(&si, sizeof(si)); | |
606 si.cbSize = sizeof(si); | |
607 si.fMask = SIF_PAGE | SIF_RANGE | SIF_DISABLENOSCROLL | SIF_POS; | |
608 si.nMin = 0; | |
609 si.nMax = 127; | |
610 si.nPage = 1; | |
611 si.nPos = number; | |
612 GetDlgItem(IDC_SCROLLBAR)->SetScrollInfo(SB_CTL, | |
613 &si, | |
614 TRUE); | |
615 } | |
616 | |
617 void OamView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar) | |
618 { | |
619 switch (nSBCode) | |
620 { | |
621 case SB_BOTTOM: | |
622 number = 127; | |
623 break; | |
624 case SB_LINEDOWN: | |
625 number++; | |
626 if (number > 127) | |
627 number = 127; | |
628 break; | |
629 case SB_LINEUP: | |
630 number--; | |
631 if (number < 0) | |
632 number = 0; | |
633 break; | |
634 case SB_PAGEDOWN: | |
635 number += 16; | |
636 if (number > 127) | |
637 number = 127; | |
638 break; | |
639 case SB_PAGEUP: | |
640 number -= 16; | |
641 if (number < 0) | |
642 number = 0; | |
643 break; | |
644 case SB_TOP: | |
645 number = 0; | |
646 break; | |
647 case SB_THUMBTRACK: | |
648 number = nPos; | |
649 if (number < 0) | |
650 number = 0; | |
651 if (number > 127) | |
652 number = 127; | |
653 break; | |
654 } | |
655 | |
656 updateScrollInfo(); | |
657 | |
658 CString buffer; | |
659 buffer.Format("%d", number); | |
660 m_sprite.SetWindowText(buffer); | |
661 paint(); | |
662 } | |
663 | |
664 void OamView::PostNcDestroy() | |
665 { | |
666 delete this; | |
667 } | |
668 |