Mercurial > vba-clojure
view src/win32/GBTileView.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 // GBTileView.cpp : implementation file2 //4 #include "stdafx.h"5 #include "resource.h"6 #include "GBTileView.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 /////////////////////////////////////////////////////////////////////////////22 // GBTileView dialog24 GBTileView::GBTileView(CWnd*pParent /*=NULL*/)25 : ResizeDlg(GBTileView::IDD, pParent)26 {27 //{{AFX_DATA_INIT(GBTileView)28 m_charBase = -1;29 m_bank = -1;30 m_stretch = FALSE;31 //}}AFX_DATA_INIT32 autoUpdate = false;34 memset(&bmpInfo, 0, sizeof(bmpInfo));36 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);37 bmpInfo.bmiHeader.biWidth = 32*8;38 bmpInfo.bmiHeader.biHeight = 32*8;39 bmpInfo.bmiHeader.biPlanes = 1;40 bmpInfo.bmiHeader.biBitCount = 24;41 bmpInfo.bmiHeader.biCompression = BI_RGB;42 data = (u8 *)calloc(1, 3 * 32*32 * 64);44 tileView.setData(data);45 tileView.setBmpInfo(&bmpInfo);47 charBase = 0;48 palette = 0;49 bank = 0;50 w = h = 0;51 }53 GBTileView::~GBTileView()54 {55 free(data);56 data = NULL;57 }59 void GBTileView::DoDataExchange(CDataExchange*pDX)60 {61 CDialog::DoDataExchange(pDX);62 //{{AFX_DATA_MAP(GBTileView)63 DDX_Control(pDX, IDC_PALETTE_SLIDER, m_slider);64 DDX_Radio(pDX, IDC_CHARBASE_0, m_charBase);65 DDX_Radio(pDX, IDC_BANK_0, m_bank);66 DDX_Check(pDX, IDC_STRETCH, m_stretch);67 //}}AFX_DATA_MAP68 DDX_Control(pDX, IDC_TILE_VIEW, tileView);69 DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, zoom);70 DDX_Control(pDX, IDC_COLOR, color);71 }73 BEGIN_MESSAGE_MAP(GBTileView, CDialog)74 //{{AFX_MSG_MAP(GBTileView)75 ON_BN_CLICKED(IDC_SAVE, OnSave)76 ON_BN_CLICKED(IDC_CLOSE, OnClose)77 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)78 ON_BN_CLICKED(IDC_CHARBASE_0, OnCharbase0)79 ON_BN_CLICKED(IDC_CHARBASE_1, OnCharbase1)80 ON_BN_CLICKED(IDC_BANK_0, OnBank0)81 ON_BN_CLICKED(IDC_BANK_1, OnBank1)82 ON_BN_CLICKED(IDC_STRETCH, OnStretch)83 ON_WM_HSCROLL()84 //}}AFX_MSG_MAP85 ON_MESSAGE(WM_MAPINFO, OnMapInfo)86 ON_MESSAGE(WM_COLINFO, OnColInfo)87 END_MESSAGE_MAP()89 /////////////////////////////////////////////////////////////////////////////90 // GBTileView message handlers92 void GBTileView::saveBMP(const char *name)93 {94 u8 writeBuffer[1024 * 3];96 FILE *fp = fopen(name, "wb");98 if (!fp)99 {100 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);101 return;102 }104 struct105 {106 u8 ident[2];107 u8 filesize[4];108 u8 reserved[4];109 u8 dataoffset[4];110 u8 headersize[4];111 u8 width[4];112 u8 height[4];113 u8 planes[2];114 u8 bitsperpixel[2];115 u8 compression[4];116 u8 datasize[4];117 u8 hres[4];118 u8 vres[4];119 u8 colors[4];120 u8 importantcolors[4];121 u8 pad[2];122 } bmpheader;123 memset(&bmpheader, 0, sizeof(bmpheader));125 bmpheader.ident[0] = 'B';126 bmpheader.ident[1] = 'M';128 u32 fsz = sizeof(bmpheader) + w*h*3;129 utilPutDword(bmpheader.filesize, fsz);130 utilPutDword(bmpheader.dataoffset, 0x38);131 utilPutDword(bmpheader.headersize, 0x28);132 utilPutDword(bmpheader.width, w);133 utilPutDword(bmpheader.height, h);134 utilPutDword(bmpheader.planes, 1);135 utilPutDword(bmpheader.bitsperpixel, 24);136 utilPutDword(bmpheader.datasize, 3*w*h);138 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);140 u8 *b = writeBuffer;142 int sizeX = w;143 int sizeY = h;145 u8 *pixU8 = (u8 *)data+3*w*(h-1);146 for (int y = 0; y < sizeY; y++)147 {148 for (int x = 0; x < sizeX; x++)149 {150 *b++ = *pixU8++; // B151 *b++ = *pixU8++; // G152 *b++ = *pixU8++; // R153 }154 pixU8 -= 2*3*w;155 fwrite(writeBuffer, 1, 3*w, fp);157 b = writeBuffer;158 }160 fclose(fp);161 }163 void GBTileView::savePNG(const char *name)164 {165 u8 writeBuffer[1024 * 3];167 FILE *fp = fopen(name, "wb");169 if (!fp)170 {171 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);172 return;173 }175 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,176 NULL,177 NULL,178 NULL);179 if (!png_ptr)180 {181 fclose(fp);182 return;183 }185 png_infop info_ptr = png_create_info_struct(png_ptr);187 if (!info_ptr)188 {189 png_destroy_write_struct(&png_ptr, NULL);190 fclose(fp);191 return;192 }194 if (setjmp(png_ptr->jmpbuf))195 {196 png_destroy_write_struct(&png_ptr, NULL);197 fclose(fp);198 return;199 }201 png_init_io(png_ptr, fp);203 png_set_IHDR(png_ptr,204 info_ptr,205 w,206 h,207 8,208 PNG_COLOR_TYPE_RGB,209 PNG_INTERLACE_NONE,210 PNG_COMPRESSION_TYPE_DEFAULT,211 PNG_FILTER_TYPE_DEFAULT);213 png_write_info(png_ptr, info_ptr);215 u8 *b = writeBuffer;217 int sizeX = w;218 int sizeY = h;220 u8 *pixU8 = (u8 *)data;221 for (int y = 0; y < sizeY; y++)222 {223 for (int x = 0; x < sizeX; x++)224 {225 int blue = *pixU8++;226 int green = *pixU8++;227 int red = *pixU8++;229 *b++ = red;230 *b++ = green;231 *b++ = blue;232 }233 png_write_row(png_ptr, writeBuffer);235 b = writeBuffer;236 }238 png_write_end(png_ptr, info_ptr);240 png_destroy_write_struct(&png_ptr, &info_ptr);242 fclose(fp);243 }245 void GBTileView::OnSave()246 {247 CString captureBuffer;249 if (theApp.captureFormat == 0)250 captureBuffer = "tiles.png";251 else252 captureBuffer = "tiles.bmp";254 LPCTSTR exts[] = {".png", ".bmp", NULL };256 CString filter = winResLoadFilter(IDS_FILTER_PNG);257 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);259 FileDlg dlg(this,260 captureBuffer,261 filter,262 theApp.captureFormat ? 2 : 1,263 theApp.captureFormat ? "BMP" : "PNG",264 exts,265 "",266 title,267 true);269 if (dlg.DoModal() == IDCANCEL)270 {271 return;272 }274 captureBuffer = dlg.GetPathName();276 if (theApp.captureFormat)277 saveBMP(captureBuffer);278 else279 savePNG(captureBuffer);280 }282 void GBTileView::renderTile(int tile, int x, int y, u8 *charBase)283 {284 u8 *bmp = &data[24*x + 8*16*24*y];286 for (int j = 0; j < 8; j++)287 {288 u8 mask = 0x80;289 u8 tile_a = charBase[tile*16+j*2];290 u8 tile_b = charBase[tile*16+j*2+1];292 for (int i = 0; i < 8; i++)293 {294 u8 c = (tile_a & mask) ? 1 : 0;295 c += ((tile_b & mask) ? 2 : 0);297 if (gbCgbMode)298 {299 c = c + palette*4;300 }301 else302 {303 c = gbBgp[c];304 }306 u16 color = gbPalette[c];308 *bmp++ = ((color >> 10) & 0x1f) << 3;309 *bmp++ = ((color >> 5) & 0x1f) << 3;310 *bmp++ = (color & 0x1f) << 3;312 mask >>= 1;313 }314 bmp += 15*24; // advance line315 }316 }318 void GBTileView::render()319 {320 int tiles = 0x0000;321 if (charBase)322 tiles = 0x0800;323 u8 *charBase = (gbVram != NULL) ?324 (bank ? &gbVram[0x2000+tiles] : &gbVram[tiles]) :325 &gbMemory[0x8000+tiles];327 int tile = 0;328 for (int y = 0; y < 16; y++)329 {330 for (int x = 0; x < 16; x++)331 {332 renderTile(tile, x, y, charBase);333 tile++;334 }335 }336 tileView.setSize(16*8, 16*8);337 w = 16*8;338 h = 16*8;339 SIZE s;340 s.cx = s.cy = 16*8;341 if (tileView.getStretch())342 {343 s.cx = s.cy = 1;344 }345 tileView.SetScrollSizes(MM_TEXT, s);346 }348 void GBTileView::update()349 {350 paint();351 }353 BOOL GBTileView::OnInitDialog()354 {355 CDialog::OnInitDialog();357 DIALOG_SIZER_START(sz)358 DIALOG_SIZER_ENTRY(IDC_TILE_VIEW, DS_SizeX | DS_SizeY)359 DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY)360 DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY)361 DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY)362 DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY)363 DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY)364 DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY)365 DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY)366 DIALOG_SIZER_END()367 SetData(sz,368 TRUE,369 HKEY_CURRENT_USER,370 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\GBTileView",371 NULL);373 m_charBase = charBase;374 m_bank = bank;376 m_slider.SetRange(0, 7);377 m_slider.SetPageSize(2);378 m_slider.SetTicFreq(1);379 paint();381 m_stretch = regQueryDwordValue("tileViewStretch", 0);382 if (m_stretch)383 tileView.setStretch(true);384 UpdateData(FALSE);386 return TRUE; // return TRUE unless you set the focus to a control387 // EXCEPTION: OCX Property Pages should return FALSE388 }390 void GBTileView::OnClose()391 {392 theApp.winRemoveUpdateListener(this);394 DestroyWindow();395 }397 void GBTileView::OnAutoUpdate()398 {399 autoUpdate = !autoUpdate;400 if (autoUpdate)401 {402 theApp.winAddUpdateListener(this);403 }404 else405 {406 theApp.winRemoveUpdateListener(this);407 }408 }410 void GBTileView::paint()411 {412 if (gbRom != NULL)413 {414 render();415 tileView.refresh();416 }417 }419 void GBTileView::OnCharbase0()420 {421 charBase = 0;422 paint();423 }425 void GBTileView::OnCharbase1()426 {427 charBase = 1;428 paint();429 }431 void GBTileView::OnBank0()432 {433 bank = 0;434 paint();435 }437 void GBTileView::OnBank1()438 {439 bank = 1;440 paint();441 }443 void GBTileView::OnStretch()444 {445 tileView.setStretch(!tileView.getStretch());446 paint();447 regSetDwordValue("tileViewStretch", tileView.getStretch());448 }450 LRESULT GBTileView::OnMapInfo(WPARAM wParam, LPARAM lParam)451 {452 u8 *colors = (u8 *)lParam;453 zoom.setColors(colors);455 int x = (wParam & 0xFFFF)/8;456 int y = ((wParam >> 16) & 0xFFFF)/8;458 int tiles = 0x0000;459 if (charBase)460 tiles = 0x0800;461 u32 address = 0x8000 + tiles;462 int tile = 16 * y + x;464 address += 16 * tile;466 CString buffer;467 buffer.Format("%d", tile);468 GetDlgItem(IDC_TILE_NUMBER)->SetWindowText(buffer);470 buffer.Format("%04x", address);471 GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer);473 return TRUE;474 }476 LRESULT GBTileView::OnColInfo(WPARAM wParam, LPARAM)477 {478 u16 c = (u16)wParam;480 color.setColor(c);482 int r = (c & 0x1f);483 int g = (c & 0x3e0) >> 5;484 int b = (c & 0x7c00) >> 10;486 CString buffer;487 buffer.Format("R: %d", r);488 GetDlgItem(IDC_R)->SetWindowText(buffer);490 buffer.Format("G: %d", g);491 GetDlgItem(IDC_G)->SetWindowText(buffer);493 buffer.Format("B: %d", b);494 GetDlgItem(IDC_B)->SetWindowText(buffer);496 return TRUE;497 }499 void GBTileView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar)500 {501 switch (nSBCode)502 {503 case TB_THUMBPOSITION:504 palette = nPos;505 break;506 default:507 palette = m_slider.GetPos();508 break;509 }510 paint();511 }513 void GBTileView::PostNcDestroy()514 {515 delete this;516 }