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