Mercurial > vba-linux
view src/win32/GBMapView.cpp @ 7:c0a590a394c3
ignore generated files
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:50:33 -0600 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 // GBMapView.cpp : implementation file2 //4 #include "stdafx.h"5 #include "resource.h"6 #include "GBMapView.h"7 #include "FileDlg.h"8 #include "Reg.h"9 #include "WinResUtil.h"10 #include "VBA.h"12 //#include "../common/System.h"13 #include "../gb/gbGlobals.h"14 #include "../NLS.h"15 #include "../common/Util.h"17 extern "C" {18 #include <png.h>19 }21 extern u8 gbInvertTab[256];23 /////////////////////////////////////////////////////////////////////////////24 // GBMapView dialog26 GBMapView::GBMapView(CWnd*pParent /*=NULL*/)27 : ResizeDlg(GBMapView::IDD, pParent)28 {29 //{{AFX_DATA_INIT(GBMapView)30 // NOTE: the ClassWizard will add member initialization here31 //}}AFX_DATA_INIT32 autoUpdate = false;34 memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader));36 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);37 bmpInfo.bmiHeader.biWidth = 1024;38 bmpInfo.bmiHeader.biHeight = -1024;39 bmpInfo.bmiHeader.biPlanes = 1;40 bmpInfo.bmiHeader.biBitCount = 24;41 bmpInfo.bmiHeader.biCompression = BI_RGB;42 data = (u8 *)calloc(1, 3 * 1024 * 1024);44 mapView.setData(data);45 mapView.setBmpInfo(&bmpInfo);47 bg = 0;48 bank = 0;49 }51 void GBMapView::DoDataExchange(CDataExchange*pDX)52 {53 CDialog::DoDataExchange(pDX);54 //{{AFX_DATA_MAP(GBMapView)55 // NOTE: the ClassWizard will add DDX and DDV calls here56 //}}AFX_DATA_MAP57 DDX_Control(pDX, IDC_MAP_VIEW, mapView);58 DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, mapViewZoom);59 DDX_Control(pDX, IDC_COLOR, color);60 }62 BEGIN_MESSAGE_MAP(GBMapView, CDialog)63 //{{AFX_MSG_MAP(GBMapView)64 ON_BN_CLICKED(IDC_SAVE, OnSave)65 ON_BN_CLICKED(IDC_REFRESH, OnRefresh)66 ON_BN_CLICKED(IDC_BG0, OnBg0)67 ON_BN_CLICKED(IDC_BG1, OnBg1)68 ON_BN_CLICKED(IDC_BANK_0, OnBank0)69 ON_BN_CLICKED(IDC_BANK_1, OnBank1)70 ON_BN_CLICKED(IDC_STRETCH, OnStretch)71 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)72 ON_BN_CLICKED(IDC_CLOSE, OnClose)73 //}}AFX_MSG_MAP74 ON_MESSAGE(WM_MAPINFO, OnMapInfo)75 ON_MESSAGE(WM_COLINFO, OnColInfo)76 END_MESSAGE_MAP()78 /////////////////////////////////////////////////////////////////////////////79 // GBMapView message handlers81 GBMapView::~GBMapView()82 {83 free(data);84 data = NULL;85 }87 void GBMapView::saveBMP(const char *name)88 {89 u8 writeBuffer[1024 * 3];91 FILE *fp = fopen(name, "wb");93 if (!fp)94 {95 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);96 return;97 }99 struct100 {101 u8 ident[2];102 u8 filesize[4];103 u8 reserved[4];104 u8 dataoffset[4];105 u8 headersize[4];106 u8 width[4];107 u8 height[4];108 u8 planes[2];109 u8 bitsperpixel[2];110 u8 compression[4];111 u8 datasize[4];112 u8 hres[4];113 u8 vres[4];114 u8 colors[4];115 u8 importantcolors[4];116 u8 pad[2];117 } bmpheader;118 memset(&bmpheader, 0, sizeof(bmpheader));120 bmpheader.ident[0] = 'B';121 bmpheader.ident[1] = 'M';123 u32 fsz = sizeof(bmpheader) + w*h*3;124 utilPutDword(bmpheader.filesize, fsz);125 utilPutDword(bmpheader.dataoffset, 0x38);126 utilPutDword(bmpheader.headersize, 0x28);127 utilPutDword(bmpheader.width, w);128 utilPutDword(bmpheader.height, h);129 utilPutDword(bmpheader.planes, 1);130 utilPutDword(bmpheader.bitsperpixel, 24);131 utilPutDword(bmpheader.datasize, 3*w*h);133 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);135 u8 *b = writeBuffer;137 int sizeX = w;138 int sizeY = h;140 u8 *pixU8 = (u8 *)data+3*w*(h-1);141 for (int y = 0; y < sizeY; y++)142 {143 for (int x = 0; x < sizeX; x++)144 {145 *b++ = *pixU8++; // B146 *b++ = *pixU8++; // G147 *b++ = *pixU8++; // R148 }149 pixU8 -= 2*3*w;150 fwrite(writeBuffer, 1, 3*w, fp);152 b = writeBuffer;153 }155 fclose(fp);156 }158 void GBMapView::savePNG(const char *name)159 {160 u8 writeBuffer[1024 * 3];162 FILE *fp = fopen(name, "wb");164 if (!fp)165 {166 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);167 return;168 }170 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,171 NULL,172 NULL,173 NULL);174 if (!png_ptr)175 {176 fclose(fp);177 return;178 }180 png_infop info_ptr = png_create_info_struct(png_ptr);182 if (!info_ptr)183 {184 png_destroy_write_struct(&png_ptr, NULL);185 fclose(fp);186 return;187 }189 if (setjmp(png_ptr->jmpbuf))190 {191 png_destroy_write_struct(&png_ptr, NULL);192 fclose(fp);193 return;194 }196 png_init_io(png_ptr, fp);198 png_set_IHDR(png_ptr,199 info_ptr,200 w,201 h,202 8,203 PNG_COLOR_TYPE_RGB,204 PNG_INTERLACE_NONE,205 PNG_COMPRESSION_TYPE_DEFAULT,206 PNG_FILTER_TYPE_DEFAULT);208 png_write_info(png_ptr, info_ptr);210 u8 *b = writeBuffer;212 int sizeX = w;213 int sizeY = h;215 u8 *pixU8 = (u8 *)data;216 for (int y = 0; y < sizeY; y++)217 {218 for (int x = 0; x < sizeX; x++)219 {220 int blue = *pixU8++;221 int green = *pixU8++;222 int red = *pixU8++;224 *b++ = red;225 *b++ = green;226 *b++ = blue;227 }228 png_write_row(png_ptr, writeBuffer);230 b = writeBuffer;231 }233 png_write_end(png_ptr, info_ptr);235 png_destroy_write_struct(&png_ptr, &info_ptr);237 fclose(fp);238 }240 void GBMapView::OnSave()241 {242 CString filename;244 if (theApp.captureFormat == 0)245 filename = "map.png";246 else247 filename = "map.bmp";249 LPCTSTR exts[] = {".png", ".bmp", NULL };250 CString filter = winResLoadFilter(IDS_FILTER_PNG);251 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);253 FileDlg dlg(this,254 filename,255 filter,256 theApp.captureFormat ? 2 : 1,257 theApp.captureFormat ? "BMP" : "PNG",258 exts,259 "",260 title,261 true);263 if (dlg.DoModal() == IDCANCEL)264 {265 return;266 }268 if (dlg.getFilterIndex() == 2)269 saveBMP(dlg.GetPathName());270 else271 savePNG(dlg.GetPathName());272 }274 void GBMapView::render()275 {276 u8 *bank0;277 u8 *bank1;278 if (gbCgbMode)279 {280 bank0 = &gbVram[0x0000];281 bank1 = &gbVram[0x2000];282 }283 else284 {285 bank0 = &gbMemory[0x8000];286 bank1 = NULL;287 }289 int tile_map_address = 0x1800;290 if (bg == 1)291 tile_map_address = 0x1c00;293 int tile_pattern = 0x0000;294 if (bank == 1)295 tile_pattern = 0x0800;297 w = 256;298 h = 256;300 int tile = 0;301 for (int y = 0; y < 32; y++)302 {303 for (int x = 0; x < 32; x++)304 {305 u8 *bmp = &data[y * 8 * 32 * 24 + x*24];306 u8 attrs = 0;307 if (bank1 != NULL)308 attrs = bank1[tile_map_address];309 u8 tile = bank0[tile_map_address];310 tile_map_address++;312 if (bank == 1)313 {314 if (tile < 128)315 tile += 128;316 else317 tile -= 128;318 }319 for (int j = 0; j < 8; j++)320 {321 int tile_pattern_address = attrs & 0x40 ?322 tile_pattern + tile*16 + (7-j)*2 :323 tile_pattern + tile*16+j*2;325 u8 tile_a = 0;326 u8 tile_b = 0;328 if (attrs & 0x08)329 {330 tile_a = bank1[tile_pattern_address++];331 tile_b = bank1[tile_pattern_address];332 }333 else334 {335 tile_a = bank0[tile_pattern_address++];336 tile_b = bank0[tile_pattern_address];337 }339 if (attrs & 0x20)340 {341 tile_a = gbInvertTab[tile_a];342 tile_b = gbInvertTab[tile_b];343 }345 u8 mask = 0x80;347 while (mask > 0)348 {349 u8 c = (tile_a & mask) ? 1 : 0;350 c += (tile_b & mask) ? 2 : 0;352 if (gbCgbMode)353 c = c + (attrs & 7)*4;355 u16 color = gbPalette[c];357 *bmp++ = ((color >> 10) & 0x1f) << 3;358 *bmp++ = ((color >> 5) & 0x1f) << 3;359 *bmp++ = (color & 0x1f) << 3;361 mask >>= 1;362 }363 bmp += 31*24;364 }365 }366 }367 }369 void GBMapView::paint()370 {371 if (gbRom == NULL)372 return;373 render();375 SIZE s;376 if (mapView.getStretch())377 {378 mapView.setSize(w, h);379 s.cx = s.cy = 1;380 mapView.SetScrollSizes(MM_TEXT, s);381 }382 else383 {384 mapView.setSize(w, h);385 s.cx = w;386 s.cy = h;387 mapView.SetScrollSizes(MM_TEXT, s);388 }390 mapView.refresh();391 }393 void GBMapView::OnRefresh()394 {395 paint();396 }398 void GBMapView::update()399 {400 paint();401 }403 BOOL GBMapView::OnInitDialog()404 {405 CDialog::OnInitDialog();407 DIALOG_SIZER_START(sz)408 DIALOG_SIZER_ENTRY(IDC_MAP_VIEW, DS_SizeX | DS_SizeY)409 DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY)410 DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY)411 DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY)412 DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY)413 DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY)414 DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY)415 DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY)416 DIALOG_SIZER_END()417 SetData(sz,418 TRUE,419 HKEY_CURRENT_USER,420 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\GBMapView",421 NULL);423 int s = regQueryDwordValue("mapViewStretch", 0);424 if (s)425 mapView.setStretch(true);426 ((CButton *)GetDlgItem(IDC_STRETCH))->SetCheck(s);428 UINT id = IDC_BANK_0;429 if (bank == 1)430 id = IDC_BANK_1;431 CheckRadioButton(IDC_BANK_0, IDC_BANK_1, id);432 id = IDC_BG0;433 if (bg == 1)434 id = IDC_BG1;435 CheckRadioButton(IDC_BG0, IDC_BG1, id);436 paint();438 return TRUE; // return TRUE unless you set the focus to a control439 // EXCEPTION: OCX Property Pages should return FALSE440 }442 void GBMapView::OnBg0()443 {444 bg = 0;445 paint();446 }448 void GBMapView::OnBg1()449 {450 bg = 1;451 paint();452 }454 void GBMapView::OnBank0()455 {456 bank = 0;457 paint();458 }460 void GBMapView::OnBank1()461 {462 bank = 1;463 paint();464 }466 void GBMapView::OnStretch()467 {468 mapView.setStretch(!mapView.getStretch());469 paint();470 regSetDwordValue("mapViewStretch", mapView.getStretch());471 }473 void GBMapView::OnAutoUpdate()474 {475 autoUpdate = !autoUpdate;476 if (autoUpdate)477 {478 theApp.winAddUpdateListener(this);479 }480 else481 {482 theApp.winRemoveUpdateListener(this);483 }484 }486 void GBMapView::OnClose()487 {488 theApp.winRemoveUpdateListener(this);490 DestroyWindow();491 }493 u32 GBMapView::GetClickAddress(int x, int y)494 {495 u32 base = 0x9800;496 if (bg == 1)497 base = 0x9c00;499 return base + (y >> 3)*32 + (x >> 3);500 }502 LRESULT GBMapView::OnMapInfo(WPARAM wParam, LPARAM lParam)503 {504 u8 *colors = (u8 *)lParam;505 mapViewZoom.setColors(colors);507 int x = wParam & 0xffff;508 int y = (wParam >> 16);510 CString buffer;511 buffer.Format("(%d,%d)", x, y);512 GetDlgItem(IDC_XY)->SetWindowText(buffer);514 u32 address = GetClickAddress(x, y);515 buffer.Format("0x%08X", address);516 GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer);518 u8 attrs = 0;520 u8 tile = gbReadMemoryQuick(0x9000 | (address & 0xfff));521 if (gbCgbMode)522 {523 attrs = gbVram[0x2000 + address - 0x8000];524 tile = gbVram[address & 0x1fff];525 }527 if (bank == 1)528 {529 if (tile > 128)530 tile -= 128;531 else532 tile += 128;533 }535 buffer.Format("%d", tile);536 GetDlgItem(IDC_TILE_NUM)->SetWindowText(buffer);538 buffer.Empty();539 buffer += attrs & 0x20 ? 'H' : '-';540 buffer += attrs & 0x40 ? 'V' : '-';541 GetDlgItem(IDC_FLIP)->SetWindowText(buffer);543 if (gbCgbMode)544 {545 buffer.Format("%d", (attrs & 7));546 }547 else548 buffer = "---";549 GetDlgItem(IDC_PALETTE_NUM)->SetWindowText(buffer);551 buffer.Empty();552 if (gbCgbMode)553 buffer += attrs & 0x80 ? 'P' : '-';554 else555 buffer += '-';556 GetDlgItem(IDC_PRIORITY)->SetWindowText(buffer);558 return TRUE;559 }561 LRESULT GBMapView::OnColInfo(WPARAM wParam, LPARAM)562 {563 u16 c = (u16)wParam;565 color.setColor(c);567 int r = (c & 0x1f);568 int g = (c & 0x3e0) >> 5;569 int b = (c & 0x7c00) >> 10;571 CString buffer;572 buffer.Format("R: %d", r);573 GetDlgItem(IDC_R)->SetWindowText(buffer);575 buffer.Format("G: %d", g);576 GetDlgItem(IDC_G)->SetWindowText(buffer);578 buffer.Format("B: %d", b);579 GetDlgItem(IDC_B)->SetWindowText(buffer);581 return TRUE;582 }584 void GBMapView::PostNcDestroy()585 {586 delete this;587 CDialog::PostNcDestroy();588 }