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