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