Mercurial > vba-linux
comparison src/win32/GBTileView.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 // GBTileView.cpp : implementation file | |
2 // | |
3 | |
4 #include "stdafx.h" | |
5 #include "resource.h" | |
6 #include "GBTileView.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 // GBTileView dialog | |
23 | |
24 GBTileView::GBTileView(CWnd*pParent /*=NULL*/) | |
25 : ResizeDlg(GBTileView::IDD, pParent) | |
26 { | |
27 //{{AFX_DATA_INIT(GBTileView) | |
28 m_charBase = -1; | |
29 m_bank = -1; | |
30 m_stretch = FALSE; | |
31 //}}AFX_DATA_INIT | |
32 autoUpdate = false; | |
33 | |
34 memset(&bmpInfo, 0, sizeof(bmpInfo)); | |
35 | |
36 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader); | |
37 bmpInfo.bmiHeader.biWidth = 32*8; | |
38 bmpInfo.bmiHeader.biHeight = 32*8; | |
39 bmpInfo.bmiHeader.biPlanes = 1; | |
40 bmpInfo.bmiHeader.biBitCount = 24; | |
41 bmpInfo.bmiHeader.biCompression = BI_RGB; | |
42 data = (u8 *)calloc(1, 3 * 32*32 * 64); | |
43 | |
44 tileView.setData(data); | |
45 tileView.setBmpInfo(&bmpInfo); | |
46 | |
47 charBase = 0; | |
48 palette = 0; | |
49 bank = 0; | |
50 w = h = 0; | |
51 } | |
52 | |
53 GBTileView::~GBTileView() | |
54 { | |
55 free(data); | |
56 data = NULL; | |
57 } | |
58 | |
59 void GBTileView::DoDataExchange(CDataExchange*pDX) | |
60 { | |
61 CDialog::DoDataExchange(pDX); | |
62 //{{AFX_DATA_MAP(GBTileView) | |
63 DDX_Control(pDX, IDC_PALETTE_SLIDER, m_slider); | |
64 DDX_Radio(pDX, IDC_CHARBASE_0, m_charBase); | |
65 DDX_Radio(pDX, IDC_BANK_0, m_bank); | |
66 DDX_Check(pDX, IDC_STRETCH, m_stretch); | |
67 //}}AFX_DATA_MAP | |
68 DDX_Control(pDX, IDC_TILE_VIEW, tileView); | |
69 DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, zoom); | |
70 DDX_Control(pDX, IDC_COLOR, color); | |
71 } | |
72 | |
73 BEGIN_MESSAGE_MAP(GBTileView, CDialog) | |
74 //{{AFX_MSG_MAP(GBTileView) | |
75 ON_BN_CLICKED(IDC_SAVE, OnSave) | |
76 ON_BN_CLICKED(IDC_CLOSE, OnClose) | |
77 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate) | |
78 ON_BN_CLICKED(IDC_CHARBASE_0, OnCharbase0) | |
79 ON_BN_CLICKED(IDC_CHARBASE_1, OnCharbase1) | |
80 ON_BN_CLICKED(IDC_BANK_0, OnBank0) | |
81 ON_BN_CLICKED(IDC_BANK_1, OnBank1) | |
82 ON_BN_CLICKED(IDC_STRETCH, OnStretch) | |
83 ON_WM_HSCROLL() | |
84 //}}AFX_MSG_MAP | |
85 ON_MESSAGE(WM_MAPINFO, OnMapInfo) | |
86 ON_MESSAGE(WM_COLINFO, OnColInfo) | |
87 END_MESSAGE_MAP() | |
88 | |
89 ///////////////////////////////////////////////////////////////////////////// | |
90 // GBTileView message handlers | |
91 | |
92 void GBTileView::saveBMP(const char *name) | |
93 { | |
94 u8 writeBuffer[1024 * 3]; | |
95 | |
96 FILE *fp = fopen(name, "wb"); | |
97 | |
98 if (!fp) | |
99 { | |
100 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); | |
101 return; | |
102 } | |
103 | |
104 struct | |
105 { | |
106 u8 ident[2]; | |
107 u8 filesize[4]; | |
108 u8 reserved[4]; | |
109 u8 dataoffset[4]; | |
110 u8 headersize[4]; | |
111 u8 width[4]; | |
112 u8 height[4]; | |
113 u8 planes[2]; | |
114 u8 bitsperpixel[2]; | |
115 u8 compression[4]; | |
116 u8 datasize[4]; | |
117 u8 hres[4]; | |
118 u8 vres[4]; | |
119 u8 colors[4]; | |
120 u8 importantcolors[4]; | |
121 u8 pad[2]; | |
122 } bmpheader; | |
123 memset(&bmpheader, 0, sizeof(bmpheader)); | |
124 | |
125 bmpheader.ident[0] = 'B'; | |
126 bmpheader.ident[1] = 'M'; | |
127 | |
128 u32 fsz = sizeof(bmpheader) + w*h*3; | |
129 utilPutDword(bmpheader.filesize, fsz); | |
130 utilPutDword(bmpheader.dataoffset, 0x38); | |
131 utilPutDword(bmpheader.headersize, 0x28); | |
132 utilPutDword(bmpheader.width, w); | |
133 utilPutDword(bmpheader.height, h); | |
134 utilPutDword(bmpheader.planes, 1); | |
135 utilPutDword(bmpheader.bitsperpixel, 24); | |
136 utilPutDword(bmpheader.datasize, 3*w*h); | |
137 | |
138 fwrite(&bmpheader, 1, sizeof(bmpheader), fp); | |
139 | |
140 u8 *b = writeBuffer; | |
141 | |
142 int sizeX = w; | |
143 int sizeY = h; | |
144 | |
145 u8 *pixU8 = (u8 *)data+3*w*(h-1); | |
146 for (int y = 0; y < sizeY; y++) | |
147 { | |
148 for (int x = 0; x < sizeX; x++) | |
149 { | |
150 *b++ = *pixU8++; // B | |
151 *b++ = *pixU8++; // G | |
152 *b++ = *pixU8++; // R | |
153 } | |
154 pixU8 -= 2*3*w; | |
155 fwrite(writeBuffer, 1, 3*w, fp); | |
156 | |
157 b = writeBuffer; | |
158 } | |
159 | |
160 fclose(fp); | |
161 } | |
162 | |
163 void GBTileView::savePNG(const char *name) | |
164 { | |
165 u8 writeBuffer[1024 * 3]; | |
166 | |
167 FILE *fp = fopen(name, "wb"); | |
168 | |
169 if (!fp) | |
170 { | |
171 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); | |
172 return; | |
173 } | |
174 | |
175 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, | |
176 NULL, | |
177 NULL, | |
178 NULL); | |
179 if (!png_ptr) | |
180 { | |
181 fclose(fp); | |
182 return; | |
183 } | |
184 | |
185 png_infop info_ptr = png_create_info_struct(png_ptr); | |
186 | |
187 if (!info_ptr) | |
188 { | |
189 png_destroy_write_struct(&png_ptr, NULL); | |
190 fclose(fp); | |
191 return; | |
192 } | |
193 | |
194 if (setjmp(png_ptr->jmpbuf)) | |
195 { | |
196 png_destroy_write_struct(&png_ptr, NULL); | |
197 fclose(fp); | |
198 return; | |
199 } | |
200 | |
201 png_init_io(png_ptr, fp); | |
202 | |
203 png_set_IHDR(png_ptr, | |
204 info_ptr, | |
205 w, | |
206 h, | |
207 8, | |
208 PNG_COLOR_TYPE_RGB, | |
209 PNG_INTERLACE_NONE, | |
210 PNG_COMPRESSION_TYPE_DEFAULT, | |
211 PNG_FILTER_TYPE_DEFAULT); | |
212 | |
213 png_write_info(png_ptr, info_ptr); | |
214 | |
215 u8 *b = writeBuffer; | |
216 | |
217 int sizeX = w; | |
218 int sizeY = h; | |
219 | |
220 u8 *pixU8 = (u8 *)data; | |
221 for (int y = 0; y < sizeY; y++) | |
222 { | |
223 for (int x = 0; x < sizeX; x++) | |
224 { | |
225 int blue = *pixU8++; | |
226 int green = *pixU8++; | |
227 int red = *pixU8++; | |
228 | |
229 *b++ = red; | |
230 *b++ = green; | |
231 *b++ = blue; | |
232 } | |
233 png_write_row(png_ptr, writeBuffer); | |
234 | |
235 b = writeBuffer; | |
236 } | |
237 | |
238 png_write_end(png_ptr, info_ptr); | |
239 | |
240 png_destroy_write_struct(&png_ptr, &info_ptr); | |
241 | |
242 fclose(fp); | |
243 } | |
244 | |
245 void GBTileView::OnSave() | |
246 { | |
247 CString captureBuffer; | |
248 | |
249 if (theApp.captureFormat == 0) | |
250 captureBuffer = "tiles.png"; | |
251 else | |
252 captureBuffer = "tiles.bmp"; | |
253 | |
254 LPCTSTR exts[] = {".png", ".bmp", NULL }; | |
255 | |
256 CString filter = winResLoadFilter(IDS_FILTER_PNG); | |
257 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); | |
258 | |
259 FileDlg dlg(this, | |
260 captureBuffer, | |
261 filter, | |
262 theApp.captureFormat ? 2 : 1, | |
263 theApp.captureFormat ? "BMP" : "PNG", | |
264 exts, | |
265 "", | |
266 title, | |
267 true); | |
268 | |
269 if (dlg.DoModal() == IDCANCEL) | |
270 { | |
271 return; | |
272 } | |
273 | |
274 captureBuffer = dlg.GetPathName(); | |
275 | |
276 if (theApp.captureFormat) | |
277 saveBMP(captureBuffer); | |
278 else | |
279 savePNG(captureBuffer); | |
280 } | |
281 | |
282 void GBTileView::renderTile(int tile, int x, int y, u8 *charBase) | |
283 { | |
284 u8 *bmp = &data[24*x + 8*16*24*y]; | |
285 | |
286 for (int j = 0; j < 8; j++) | |
287 { | |
288 u8 mask = 0x80; | |
289 u8 tile_a = charBase[tile*16+j*2]; | |
290 u8 tile_b = charBase[tile*16+j*2+1]; | |
291 | |
292 for (int i = 0; i < 8; i++) | |
293 { | |
294 u8 c = (tile_a & mask) ? 1 : 0; | |
295 c += ((tile_b & mask) ? 2 : 0); | |
296 | |
297 if (gbCgbMode) | |
298 { | |
299 c = c + palette*4; | |
300 } | |
301 else | |
302 { | |
303 c = gbBgp[c]; | |
304 } | |
305 | |
306 u16 color = gbPalette[c]; | |
307 | |
308 *bmp++ = ((color >> 10) & 0x1f) << 3; | |
309 *bmp++ = ((color >> 5) & 0x1f) << 3; | |
310 *bmp++ = (color & 0x1f) << 3; | |
311 | |
312 mask >>= 1; | |
313 } | |
314 bmp += 15*24; // advance line | |
315 } | |
316 } | |
317 | |
318 void GBTileView::render() | |
319 { | |
320 int tiles = 0x0000; | |
321 if (charBase) | |
322 tiles = 0x0800; | |
323 u8 *charBase = (gbVram != NULL) ? | |
324 (bank ? &gbVram[0x2000+tiles] : &gbVram[tiles]) : | |
325 &gbMemory[0x8000+tiles]; | |
326 | |
327 int tile = 0; | |
328 for (int y = 0; y < 16; y++) | |
329 { | |
330 for (int x = 0; x < 16; x++) | |
331 { | |
332 renderTile(tile, x, y, charBase); | |
333 tile++; | |
334 } | |
335 } | |
336 tileView.setSize(16*8, 16*8); | |
337 w = 16*8; | |
338 h = 16*8; | |
339 SIZE s; | |
340 s.cx = s.cy = 16*8; | |
341 if (tileView.getStretch()) | |
342 { | |
343 s.cx = s.cy = 1; | |
344 } | |
345 tileView.SetScrollSizes(MM_TEXT, s); | |
346 } | |
347 | |
348 void GBTileView::update() | |
349 { | |
350 paint(); | |
351 } | |
352 | |
353 BOOL GBTileView::OnInitDialog() | |
354 { | |
355 CDialog::OnInitDialog(); | |
356 | |
357 DIALOG_SIZER_START(sz) | |
358 DIALOG_SIZER_ENTRY(IDC_TILE_VIEW, DS_SizeX | DS_SizeY) | |
359 DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY) | |
360 DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY) | |
361 DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY) | |
362 DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY) | |
363 DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY) | |
364 DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY) | |
365 DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY) | |
366 DIALOG_SIZER_END() | |
367 SetData(sz, | |
368 TRUE, | |
369 HKEY_CURRENT_USER, | |
370 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\GBTileView", | |
371 NULL); | |
372 | |
373 m_charBase = charBase; | |
374 m_bank = bank; | |
375 | |
376 m_slider.SetRange(0, 7); | |
377 m_slider.SetPageSize(2); | |
378 m_slider.SetTicFreq(1); | |
379 paint(); | |
380 | |
381 m_stretch = regQueryDwordValue("tileViewStretch", 0); | |
382 if (m_stretch) | |
383 tileView.setStretch(true); | |
384 UpdateData(FALSE); | |
385 | |
386 return TRUE; // return TRUE unless you set the focus to a control | |
387 // EXCEPTION: OCX Property Pages should return FALSE | |
388 } | |
389 | |
390 void GBTileView::OnClose() | |
391 { | |
392 theApp.winRemoveUpdateListener(this); | |
393 | |
394 DestroyWindow(); | |
395 } | |
396 | |
397 void GBTileView::OnAutoUpdate() | |
398 { | |
399 autoUpdate = !autoUpdate; | |
400 if (autoUpdate) | |
401 { | |
402 theApp.winAddUpdateListener(this); | |
403 } | |
404 else | |
405 { | |
406 theApp.winRemoveUpdateListener(this); | |
407 } | |
408 } | |
409 | |
410 void GBTileView::paint() | |
411 { | |
412 if (gbRom != NULL) | |
413 { | |
414 render(); | |
415 tileView.refresh(); | |
416 } | |
417 } | |
418 | |
419 void GBTileView::OnCharbase0() | |
420 { | |
421 charBase = 0; | |
422 paint(); | |
423 } | |
424 | |
425 void GBTileView::OnCharbase1() | |
426 { | |
427 charBase = 1; | |
428 paint(); | |
429 } | |
430 | |
431 void GBTileView::OnBank0() | |
432 { | |
433 bank = 0; | |
434 paint(); | |
435 } | |
436 | |
437 void GBTileView::OnBank1() | |
438 { | |
439 bank = 1; | |
440 paint(); | |
441 } | |
442 | |
443 void GBTileView::OnStretch() | |
444 { | |
445 tileView.setStretch(!tileView.getStretch()); | |
446 paint(); | |
447 regSetDwordValue("tileViewStretch", tileView.getStretch()); | |
448 } | |
449 | |
450 LRESULT GBTileView::OnMapInfo(WPARAM wParam, LPARAM lParam) | |
451 { | |
452 u8 *colors = (u8 *)lParam; | |
453 zoom.setColors(colors); | |
454 | |
455 int x = (wParam & 0xFFFF)/8; | |
456 int y = ((wParam >> 16) & 0xFFFF)/8; | |
457 | |
458 int tiles = 0x0000; | |
459 if (charBase) | |
460 tiles = 0x0800; | |
461 u32 address = 0x8000 + tiles; | |
462 int tile = 16 * y + x; | |
463 | |
464 address += 16 * tile; | |
465 | |
466 CString buffer; | |
467 buffer.Format("%d", tile); | |
468 GetDlgItem(IDC_TILE_NUMBER)->SetWindowText(buffer); | |
469 | |
470 buffer.Format("%04x", address); | |
471 GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer); | |
472 | |
473 return TRUE; | |
474 } | |
475 | |
476 LRESULT GBTileView::OnColInfo(WPARAM wParam, LPARAM) | |
477 { | |
478 u16 c = (u16)wParam; | |
479 | |
480 color.setColor(c); | |
481 | |
482 int r = (c & 0x1f); | |
483 int g = (c & 0x3e0) >> 5; | |
484 int b = (c & 0x7c00) >> 10; | |
485 | |
486 CString buffer; | |
487 buffer.Format("R: %d", r); | |
488 GetDlgItem(IDC_R)->SetWindowText(buffer); | |
489 | |
490 buffer.Format("G: %d", g); | |
491 GetDlgItem(IDC_G)->SetWindowText(buffer); | |
492 | |
493 buffer.Format("B: %d", b); | |
494 GetDlgItem(IDC_B)->SetWindowText(buffer); | |
495 | |
496 return TRUE; | |
497 } | |
498 | |
499 void GBTileView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar) | |
500 { | |
501 switch (nSBCode) | |
502 { | |
503 case TB_THUMBPOSITION: | |
504 palette = nPos; | |
505 break; | |
506 default: | |
507 palette = m_slider.GetPos(); | |
508 break; | |
509 } | |
510 paint(); | |
511 } | |
512 | |
513 void GBTileView::PostNcDestroy() | |
514 { | |
515 delete this; | |
516 } | |
517 |