Mercurial > vba-linux
diff src/win32/TileView.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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/TileView.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,582 @@ 1.4 +// TileView.cpp : implementation file 1.5 +// 1.6 + 1.7 +#include "stdafx.h" 1.8 +#include "resource.h" 1.9 +#include "FileDlg.h" 1.10 +#include "Reg.h" 1.11 +#include "TileView.h" 1.12 +#include "WinResUtil.h" 1.13 +#include "VBA.h" // for theApp 1.14 + 1.15 +#include "../gba/GBAGlobals.h" 1.16 +#include "../NLS.h" 1.17 +#include "../common/Util.h" 1.18 + 1.19 +extern "C" { 1.20 +#include <png.h> 1.21 +} 1.22 + 1.23 +///////////////////////////////////////////////////////////////////////////// 1.24 +// TileView dialog 1.25 + 1.26 +TileView::TileView(CWnd*pParent /*=NULL*/) 1.27 + : ResizeDlg(TileView::IDD, pParent) 1.28 +{ 1.29 + //{{AFX_DATA_INIT(TileView) 1.30 + m_colors = -1; 1.31 + m_charBase = -1; 1.32 + m_stretch = FALSE; 1.33 + //}}AFX_DATA_INIT 1.34 + autoUpdate = false; 1.35 + 1.36 + memset(&bmpInfo, 0, sizeof(bmpInfo)); 1.37 + 1.38 + bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader); 1.39 + bmpInfo.bmiHeader.biWidth = 32*8; 1.40 + bmpInfo.bmiHeader.biHeight = 32*8; 1.41 + bmpInfo.bmiHeader.biPlanes = 1; 1.42 + bmpInfo.bmiHeader.biBitCount = 24; 1.43 + bmpInfo.bmiHeader.biCompression = BI_RGB; 1.44 + data = (u8 *)calloc(1, 3 * 32*32 * 64); 1.45 + 1.46 + tileView.setData(data); 1.47 + tileView.setBmpInfo(&bmpInfo); 1.48 + 1.49 + charBase = 0; 1.50 + is256Colors = 0; 1.51 + palette = 0; 1.52 + w = h = 0; 1.53 +} 1.54 + 1.55 +TileView::~TileView() 1.56 +{ 1.57 + free(data); 1.58 + data = NULL; 1.59 +} 1.60 + 1.61 +void TileView::DoDataExchange(CDataExchange*pDX) 1.62 +{ 1.63 + CDialog::DoDataExchange(pDX); 1.64 + //{{AFX_DATA_MAP(TileView) 1.65 + DDX_Control(pDX, IDC_PALETTE_SLIDER, m_slider); 1.66 + DDX_Radio(pDX, IDC_16_COLORS, m_colors); 1.67 + DDX_Radio(pDX, IDC_CHARBASE_0, m_charBase); 1.68 + DDX_Check(pDX, IDC_STRETCH, m_stretch); 1.69 + //}}AFX_DATA_MAP 1.70 + DDX_Control(pDX, IDC_TILE_VIEW, tileView); 1.71 + DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, zoom); 1.72 + DDX_Control(pDX, IDC_COLOR, color); 1.73 +} 1.74 + 1.75 +BEGIN_MESSAGE_MAP(TileView, CDialog) 1.76 +//{{AFX_MSG_MAP(TileView) 1.77 +ON_BN_CLICKED(IDC_SAVE, OnSave) 1.78 +ON_BN_CLICKED(IDC_CLOSE, OnClose) 1.79 +ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate) 1.80 +ON_BN_CLICKED(IDC_16_COLORS, On16Colors) 1.81 +ON_BN_CLICKED(IDC_256_COLORS, On256Colors) 1.82 +ON_BN_CLICKED(IDC_CHARBASE_0, OnCharbase0) 1.83 +ON_BN_CLICKED(IDC_CHARBASE_1, OnCharbase1) 1.84 +ON_BN_CLICKED(IDC_CHARBASE_2, OnCharbase2) 1.85 +ON_BN_CLICKED(IDC_CHARBASE_3, OnCharbase3) 1.86 +ON_BN_CLICKED(IDC_CHARBASE_4, OnCharbase4) 1.87 +ON_BN_CLICKED(IDC_STRETCH, OnStretch) 1.88 +ON_WM_HSCROLL() 1.89 +//}}AFX_MSG_MAP 1.90 +ON_MESSAGE(WM_MAPINFO, OnMapInfo) 1.91 +ON_MESSAGE(WM_COLINFO, OnColInfo) 1.92 +END_MESSAGE_MAP() 1.93 + 1.94 +///////////////////////////////////////////////////////////////////////////// 1.95 +// TileView message handlers 1.96 + 1.97 +void TileView::saveBMP(const char *name) 1.98 +{ 1.99 + u8 writeBuffer[1024 * 3]; 1.100 + 1.101 + FILE *fp = fopen(name, "wb"); 1.102 + 1.103 + if (!fp) 1.104 + { 1.105 + systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); 1.106 + return; 1.107 + } 1.108 + 1.109 + struct 1.110 + { 1.111 + u8 ident[2]; 1.112 + u8 filesize[4]; 1.113 + u8 reserved[4]; 1.114 + u8 dataoffset[4]; 1.115 + u8 headersize[4]; 1.116 + u8 width[4]; 1.117 + u8 height[4]; 1.118 + u8 planes[2]; 1.119 + u8 bitsperpixel[2]; 1.120 + u8 compression[4]; 1.121 + u8 datasize[4]; 1.122 + u8 hres[4]; 1.123 + u8 vres[4]; 1.124 + u8 colors[4]; 1.125 + u8 importantcolors[4]; 1.126 + u8 pad[2]; 1.127 + } bmpheader; 1.128 + memset(&bmpheader, 0, sizeof(bmpheader)); 1.129 + 1.130 + bmpheader.ident[0] = 'B'; 1.131 + bmpheader.ident[1] = 'M'; 1.132 + 1.133 + u32 fsz = sizeof(bmpheader) + w*h*3; 1.134 + utilPutDword(bmpheader.filesize, fsz); 1.135 + utilPutDword(bmpheader.dataoffset, 0x38); 1.136 + utilPutDword(bmpheader.headersize, 0x28); 1.137 + utilPutDword(bmpheader.width, w); 1.138 + utilPutDword(bmpheader.height, h); 1.139 + utilPutDword(bmpheader.planes, 1); 1.140 + utilPutDword(bmpheader.bitsperpixel, 24); 1.141 + utilPutDword(bmpheader.datasize, 3*w*h); 1.142 + 1.143 + fwrite(&bmpheader, 1, sizeof(bmpheader), fp); 1.144 + 1.145 + u8 *b = writeBuffer; 1.146 + 1.147 + int sizeX = w; 1.148 + int sizeY = h; 1.149 + 1.150 + u8 *pixU8 = (u8 *)data+3*w*(h-1); 1.151 + for (int y = 0; y < sizeY; y++) 1.152 + { 1.153 + for (int x = 0; x < sizeX; x++) 1.154 + { 1.155 + *b++ = *pixU8++; // B 1.156 + *b++ = *pixU8++; // G 1.157 + *b++ = *pixU8++; // R 1.158 + } 1.159 + pixU8 -= 2*3*w; 1.160 + fwrite(writeBuffer, 1, 3*w, fp); 1.161 + 1.162 + b = writeBuffer; 1.163 + } 1.164 + 1.165 + fclose(fp); 1.166 +} 1.167 + 1.168 +void TileView::savePNG(const char *name) 1.169 +{ 1.170 + u8 writeBuffer[1024 * 3]; 1.171 + 1.172 + FILE *fp = fopen(name, "wb"); 1.173 + 1.174 + if (!fp) 1.175 + { 1.176 + systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); 1.177 + return; 1.178 + } 1.179 + 1.180 + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 1.181 + NULL, 1.182 + NULL, 1.183 + NULL); 1.184 + if (!png_ptr) 1.185 + { 1.186 + fclose(fp); 1.187 + return; 1.188 + } 1.189 + 1.190 + png_infop info_ptr = png_create_info_struct(png_ptr); 1.191 + 1.192 + if (!info_ptr) 1.193 + { 1.194 + png_destroy_write_struct(&png_ptr, NULL); 1.195 + fclose(fp); 1.196 + return; 1.197 + } 1.198 + 1.199 + if (setjmp(png_ptr->jmpbuf)) 1.200 + { 1.201 + png_destroy_write_struct(&png_ptr, NULL); 1.202 + fclose(fp); 1.203 + return; 1.204 + } 1.205 + 1.206 + png_init_io(png_ptr, fp); 1.207 + 1.208 + png_set_IHDR(png_ptr, 1.209 + info_ptr, 1.210 + w, 1.211 + h, 1.212 + 8, 1.213 + PNG_COLOR_TYPE_RGB, 1.214 + PNG_INTERLACE_NONE, 1.215 + PNG_COMPRESSION_TYPE_DEFAULT, 1.216 + PNG_FILTER_TYPE_DEFAULT); 1.217 + 1.218 + png_write_info(png_ptr, info_ptr); 1.219 + 1.220 + u8 *b = writeBuffer; 1.221 + 1.222 + int sizeX = w; 1.223 + int sizeY = h; 1.224 + 1.225 + u8 *pixU8 = (u8 *)data; 1.226 + for (int y = 0; y < sizeY; y++) 1.227 + { 1.228 + for (int x = 0; x < sizeX; x++) 1.229 + { 1.230 + int blue = *pixU8++; 1.231 + int green = *pixU8++; 1.232 + int red = *pixU8++; 1.233 + 1.234 + *b++ = red; 1.235 + *b++ = green; 1.236 + *b++ = blue; 1.237 + } 1.238 + png_write_row(png_ptr, writeBuffer); 1.239 + 1.240 + b = writeBuffer; 1.241 + } 1.242 + 1.243 + png_write_end(png_ptr, info_ptr); 1.244 + 1.245 + png_destroy_write_struct(&png_ptr, &info_ptr); 1.246 + 1.247 + fclose(fp); 1.248 +} 1.249 + 1.250 +void TileView::OnSave() 1.251 +{ 1.252 + CString captureBuffer; 1.253 + 1.254 + if (theApp.captureFormat == 0) 1.255 + captureBuffer = "tiles.png"; 1.256 + else 1.257 + captureBuffer = "tiles.bmp"; 1.258 + 1.259 + LPCTSTR exts[] = {".png", ".bmp", NULL }; 1.260 + 1.261 + CString filter = winResLoadFilter(IDS_FILTER_PNG); 1.262 + CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); 1.263 + 1.264 + FileDlg dlg(this, 1.265 + captureBuffer, 1.266 + filter, 1.267 + theApp.captureFormat ? 2 : 1, 1.268 + theApp.captureFormat ? "BMP" : "PNG", 1.269 + exts, 1.270 + "", 1.271 + title, 1.272 + true); 1.273 + 1.274 + if (dlg.DoModal() == IDCANCEL) 1.275 + { 1.276 + return; 1.277 + } 1.278 + 1.279 + captureBuffer = dlg.GetPathName(); 1.280 + 1.281 + if (dlg.getFilterIndex() == 2) 1.282 + saveBMP(captureBuffer); 1.283 + else 1.284 + savePNG(captureBuffer); 1.285 +} 1.286 + 1.287 +void TileView::renderTile256(int tile, int x, int y, u8 *charBase, u16 *palette) 1.288 +{ 1.289 + u8 *bmp = &data[24*x + 8*32*24*y]; 1.290 + 1.291 + for (int j = 0; j < 8; j++) 1.292 + { 1.293 + for (int i = 0; i < 8; i++) 1.294 + { 1.295 + u8 c = charBase[tile*64 + j * 8 + i]; 1.296 + 1.297 + u16 color = palette[c]; 1.298 + 1.299 + *bmp++ = ((color >> 10) & 0x1f) << 3; 1.300 + *bmp++ = ((color >> 5) & 0x1f) << 3; 1.301 + *bmp++ = (color & 0x1f) << 3; 1.302 + } 1.303 + bmp += 31*24; // advance line 1.304 + } 1.305 +} 1.306 + 1.307 +void TileView::renderTile16(int tile, int x, int y, u8 *charBase, u16 *palette) 1.308 +{ 1.309 + u8 *bmp = &data[24*x + 8*32*24*y]; 1.310 + 1.311 + int pal = this->palette; 1.312 + 1.313 + if (this->charBase == 4) 1.314 + pal += 16; 1.315 + 1.316 + for (int j = 0; j < 8; j++) 1.317 + { 1.318 + for (int i = 0; i < 8; i++) 1.319 + { 1.320 + u8 c = charBase[tile*32 + j * 4 + (i>>1)]; 1.321 + 1.322 + if (i & 1) 1.323 + c = c>>4; 1.324 + else 1.325 + c = c & 15; 1.326 + 1.327 + u16 color = palette[pal*16+c]; 1.328 + 1.329 + *bmp++ = ((color >> 10) & 0x1f) << 3; 1.330 + *bmp++ = ((color >> 5) & 0x1f) << 3; 1.331 + *bmp++ = (color & 0x1f) << 3; 1.332 + } 1.333 + bmp += 31*24; // advance line 1.334 + } 1.335 +} 1.336 + 1.337 +void TileView::render() 1.338 +{ 1.339 + u16 *palette = (u16 *)paletteRAM; 1.340 + u8 * charBase = &vram[this->charBase * 0x4000]; 1.341 + 1.342 + int maxY; 1.343 + 1.344 + if (is256Colors) 1.345 + { 1.346 + int tile = 0; 1.347 + maxY = 16; 1.348 + for (int y = 0; y < maxY; y++) 1.349 + { 1.350 + for (int x = 0; x < 32; x++) 1.351 + { 1.352 + if (this->charBase == 4) 1.353 + renderTile256(tile, x, y, charBase, &palette[256]); 1.354 + else 1.355 + renderTile256(tile, x, y, charBase, palette); 1.356 + tile++; 1.357 + } 1.358 + } 1.359 + tileView.setSize(32*8, maxY*8); 1.360 + w = 32*8; 1.361 + h = maxY*8; 1.362 + SIZE s; 1.363 + s.cx = 32*8; 1.364 + s.cy = maxY*8; 1.365 + if (tileView.getStretch()) 1.366 + { 1.367 + s.cx = s.cy = 1; 1.368 + } 1.369 + tileView.SetScrollSizes(MM_TEXT, s); 1.370 + } 1.371 + else 1.372 + { 1.373 + int tile = 0; 1.374 + maxY = 32; 1.375 + if (this->charBase == 3) 1.376 + maxY = 16; 1.377 + for (int y = 0; y < maxY; y++) 1.378 + { 1.379 + for (int x = 0; x < 32; x++) 1.380 + { 1.381 + renderTile16(tile, x, y, charBase, palette); 1.382 + tile++; 1.383 + } 1.384 + } 1.385 + tileView.setSize(32*8, maxY*8); 1.386 + w = 32*8; 1.387 + h = maxY*8; 1.388 + SIZE s; 1.389 + s.cx = 32*8; 1.390 + s.cy = maxY*8; 1.391 + if (tileView.getStretch()) 1.392 + { 1.393 + s.cx = s.cy = 1; 1.394 + } 1.395 + tileView.SetScrollSizes(MM_TEXT, s); 1.396 + } 1.397 +} 1.398 + 1.399 +void TileView::update() 1.400 +{ 1.401 + paint(); 1.402 +} 1.403 + 1.404 +BOOL TileView::OnInitDialog() 1.405 +{ 1.406 + CDialog::OnInitDialog(); 1.407 + 1.408 + DIALOG_SIZER_START(sz) 1.409 + DIALOG_SIZER_ENTRY(IDC_TILE_VIEW, DS_SizeX | DS_SizeY) 1.410 + DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY) 1.411 + DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY) 1.412 + DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY) 1.413 + DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY) 1.414 + DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY) 1.415 + DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY) 1.416 + DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY) 1.417 + DIALOG_SIZER_END() 1.418 + SetData(sz, 1.419 + TRUE, 1.420 + HKEY_CURRENT_USER, 1.421 + "Software\\Emulators\\VisualBoyAdvance\\Viewer\\TileView", 1.422 + NULL); 1.423 + 1.424 + m_colors = is256Colors; 1.425 + m_charBase = charBase; 1.426 + 1.427 + m_slider.SetRange(0, 15); 1.428 + m_slider.SetPageSize(4); 1.429 + m_slider.SetTicFreq(1); 1.430 + 1.431 + paint(); 1.432 + 1.433 + m_stretch = regQueryDwordValue("tileViewStretch", 0); 1.434 + if (m_stretch) 1.435 + tileView.setStretch(true); 1.436 + UpdateData(FALSE); 1.437 + 1.438 + return TRUE; // return TRUE unless you set the focus to a control 1.439 + // EXCEPTION: OCX Property Pages should return FALSE 1.440 +} 1.441 + 1.442 +void TileView::OnClose() 1.443 +{ 1.444 + theApp.winRemoveUpdateListener(this); 1.445 + 1.446 + DestroyWindow(); 1.447 +} 1.448 + 1.449 +void TileView::OnAutoUpdate() 1.450 +{ 1.451 + autoUpdate = !autoUpdate; 1.452 + if (autoUpdate) 1.453 + { 1.454 + theApp.winAddUpdateListener(this); 1.455 + } 1.456 + else 1.457 + { 1.458 + theApp.winRemoveUpdateListener(this); 1.459 + } 1.460 +} 1.461 + 1.462 +void TileView::paint() 1.463 +{ 1.464 + if (vram != NULL && paletteRAM != NULL) 1.465 + { 1.466 + render(); 1.467 + tileView.refresh(); 1.468 + } 1.469 +} 1.470 + 1.471 +void TileView::On16Colors() 1.472 +{ 1.473 + is256Colors = 0; 1.474 + paint(); 1.475 +} 1.476 + 1.477 +void TileView::On256Colors() 1.478 +{ 1.479 + is256Colors = 1; 1.480 + paint(); 1.481 +} 1.482 + 1.483 +void TileView::OnCharbase0() 1.484 +{ 1.485 + charBase = 0; 1.486 + paint(); 1.487 +} 1.488 + 1.489 +void TileView::OnCharbase1() 1.490 +{ 1.491 + charBase = 1; 1.492 + paint(); 1.493 +} 1.494 + 1.495 +void TileView::OnCharbase2() 1.496 +{ 1.497 + charBase = 2; 1.498 + paint(); 1.499 +} 1.500 + 1.501 +void TileView::OnCharbase3() 1.502 +{ 1.503 + charBase = 3; 1.504 + paint(); 1.505 +} 1.506 + 1.507 +void TileView::OnCharbase4() 1.508 +{ 1.509 + charBase = 4; 1.510 + paint(); 1.511 +} 1.512 + 1.513 +void TileView::OnStretch() 1.514 +{ 1.515 + tileView.setStretch(!tileView.getStretch()); 1.516 + paint(); 1.517 + regSetDwordValue("tileViewStretch", tileView.getStretch()); 1.518 +} 1.519 + 1.520 +LRESULT TileView::OnMapInfo(WPARAM wParam, LPARAM lParam) 1.521 +{ 1.522 + u8 *colors = (u8 *)lParam; 1.523 + zoom.setColors(colors); 1.524 + 1.525 + int x = (wParam & 0xFFFF)/8; 1.526 + int y = ((wParam >> 16) & 0xFFFF)/8; 1.527 + 1.528 + u32 address = 0x6000000 + 0x4000 * charBase; 1.529 + int tile = 32 * y + x; 1.530 + if (is256Colors) 1.531 + tile *= 2; 1.532 + address += 32 * tile; 1.533 + 1.534 + CString buffer; 1.535 + buffer.Format("%d", tile); 1.536 + GetDlgItem(IDC_TILE_NUMBER)->SetWindowText(buffer); 1.537 + 1.538 + buffer.Format("%08x", address); 1.539 + GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer); 1.540 + 1.541 + return TRUE; 1.542 +} 1.543 + 1.544 +LRESULT TileView::OnColInfo(WPARAM wParam, LPARAM) 1.545 +{ 1.546 + u16 c = (u16)wParam; 1.547 + 1.548 + color.setColor(c); 1.549 + 1.550 + int r = (c & 0x1f); 1.551 + int g = (c & 0x3e0) >> 5; 1.552 + int b = (c & 0x7c00) >> 10; 1.553 + 1.554 + CString buffer; 1.555 + buffer.Format("R: %d", r); 1.556 + GetDlgItem(IDC_R)->SetWindowText(buffer); 1.557 + 1.558 + buffer.Format("G: %d", g); 1.559 + GetDlgItem(IDC_G)->SetWindowText(buffer); 1.560 + 1.561 + buffer.Format("B: %d", b); 1.562 + GetDlgItem(IDC_B)->SetWindowText(buffer); 1.563 + 1.564 + return TRUE; 1.565 +} 1.566 + 1.567 +void TileView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar) 1.568 +{ 1.569 + switch (nSBCode) 1.570 + { 1.571 + case TB_THUMBPOSITION: 1.572 + palette = nPos; 1.573 + break; 1.574 + default: 1.575 + palette = m_slider.GetPos(); 1.576 + break; 1.577 + } 1.578 + paint(); 1.579 +} 1.580 + 1.581 +void TileView::PostNcDestroy() 1.582 +{ 1.583 + delete this; 1.584 +} 1.585 +