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