Mercurial > vba-clojure
view src/win32/TileView.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 // TileView.cpp : implementation file2 //4 #include "stdafx.h"5 #include "resource.h"6 #include "FileDlg.h"7 #include "Reg.h"8 #include "TileView.h"9 #include "WinResUtil.h"10 #include "VBA.h" // for theApp12 #include "../gba/GBAGlobals.h"13 #include "../NLS.h"14 #include "../common/Util.h"16 extern "C" {17 #include <png.h>18 }20 /////////////////////////////////////////////////////////////////////////////21 // TileView dialog23 TileView::TileView(CWnd*pParent /*=NULL*/)24 : ResizeDlg(TileView::IDD, pParent)25 {26 //{{AFX_DATA_INIT(TileView)27 m_colors = -1;28 m_charBase = -1;29 m_stretch = FALSE;30 //}}AFX_DATA_INIT31 autoUpdate = false;33 memset(&bmpInfo, 0, sizeof(bmpInfo));35 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);36 bmpInfo.bmiHeader.biWidth = 32*8;37 bmpInfo.bmiHeader.biHeight = 32*8;38 bmpInfo.bmiHeader.biPlanes = 1;39 bmpInfo.bmiHeader.biBitCount = 24;40 bmpInfo.bmiHeader.biCompression = BI_RGB;41 data = (u8 *)calloc(1, 3 * 32*32 * 64);43 tileView.setData(data);44 tileView.setBmpInfo(&bmpInfo);46 charBase = 0;47 is256Colors = 0;48 palette = 0;49 w = h = 0;50 }52 TileView::~TileView()53 {54 free(data);55 data = NULL;56 }58 void TileView::DoDataExchange(CDataExchange*pDX)59 {60 CDialog::DoDataExchange(pDX);61 //{{AFX_DATA_MAP(TileView)62 DDX_Control(pDX, IDC_PALETTE_SLIDER, m_slider);63 DDX_Radio(pDX, IDC_16_COLORS, m_colors);64 DDX_Radio(pDX, IDC_CHARBASE_0, m_charBase);65 DDX_Check(pDX, IDC_STRETCH, m_stretch);66 //}}AFX_DATA_MAP67 DDX_Control(pDX, IDC_TILE_VIEW, tileView);68 DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, zoom);69 DDX_Control(pDX, IDC_COLOR, color);70 }72 BEGIN_MESSAGE_MAP(TileView, CDialog)73 //{{AFX_MSG_MAP(TileView)74 ON_BN_CLICKED(IDC_SAVE, OnSave)75 ON_BN_CLICKED(IDC_CLOSE, OnClose)76 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)77 ON_BN_CLICKED(IDC_16_COLORS, On16Colors)78 ON_BN_CLICKED(IDC_256_COLORS, On256Colors)79 ON_BN_CLICKED(IDC_CHARBASE_0, OnCharbase0)80 ON_BN_CLICKED(IDC_CHARBASE_1, OnCharbase1)81 ON_BN_CLICKED(IDC_CHARBASE_2, OnCharbase2)82 ON_BN_CLICKED(IDC_CHARBASE_3, OnCharbase3)83 ON_BN_CLICKED(IDC_CHARBASE_4, OnCharbase4)84 ON_BN_CLICKED(IDC_STRETCH, OnStretch)85 ON_WM_HSCROLL()86 //}}AFX_MSG_MAP87 ON_MESSAGE(WM_MAPINFO, OnMapInfo)88 ON_MESSAGE(WM_COLINFO, OnColInfo)89 END_MESSAGE_MAP()91 /////////////////////////////////////////////////////////////////////////////92 // TileView message handlers94 void TileView::saveBMP(const char *name)95 {96 u8 writeBuffer[1024 * 3];98 FILE *fp = fopen(name, "wb");100 if (!fp)101 {102 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);103 return;104 }106 struct107 {108 u8 ident[2];109 u8 filesize[4];110 u8 reserved[4];111 u8 dataoffset[4];112 u8 headersize[4];113 u8 width[4];114 u8 height[4];115 u8 planes[2];116 u8 bitsperpixel[2];117 u8 compression[4];118 u8 datasize[4];119 u8 hres[4];120 u8 vres[4];121 u8 colors[4];122 u8 importantcolors[4];123 u8 pad[2];124 } bmpheader;125 memset(&bmpheader, 0, sizeof(bmpheader));127 bmpheader.ident[0] = 'B';128 bmpheader.ident[1] = 'M';130 u32 fsz = sizeof(bmpheader) + w*h*3;131 utilPutDword(bmpheader.filesize, fsz);132 utilPutDword(bmpheader.dataoffset, 0x38);133 utilPutDword(bmpheader.headersize, 0x28);134 utilPutDword(bmpheader.width, w);135 utilPutDword(bmpheader.height, h);136 utilPutDword(bmpheader.planes, 1);137 utilPutDword(bmpheader.bitsperpixel, 24);138 utilPutDword(bmpheader.datasize, 3*w*h);140 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);142 u8 *b = writeBuffer;144 int sizeX = w;145 int sizeY = h;147 u8 *pixU8 = (u8 *)data+3*w*(h-1);148 for (int y = 0; y < sizeY; y++)149 {150 for (int x = 0; x < sizeX; x++)151 {152 *b++ = *pixU8++; // B153 *b++ = *pixU8++; // G154 *b++ = *pixU8++; // R155 }156 pixU8 -= 2*3*w;157 fwrite(writeBuffer, 1, 3*w, fp);159 b = writeBuffer;160 }162 fclose(fp);163 }165 void TileView::savePNG(const char *name)166 {167 u8 writeBuffer[1024 * 3];169 FILE *fp = fopen(name, "wb");171 if (!fp)172 {173 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);174 return;175 }177 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,178 NULL,179 NULL,180 NULL);181 if (!png_ptr)182 {183 fclose(fp);184 return;185 }187 png_infop info_ptr = png_create_info_struct(png_ptr);189 if (!info_ptr)190 {191 png_destroy_write_struct(&png_ptr, NULL);192 fclose(fp);193 return;194 }196 if (setjmp(png_ptr->jmpbuf))197 {198 png_destroy_write_struct(&png_ptr, NULL);199 fclose(fp);200 return;201 }203 png_init_io(png_ptr, fp);205 png_set_IHDR(png_ptr,206 info_ptr,207 w,208 h,209 8,210 PNG_COLOR_TYPE_RGB,211 PNG_INTERLACE_NONE,212 PNG_COMPRESSION_TYPE_DEFAULT,213 PNG_FILTER_TYPE_DEFAULT);215 png_write_info(png_ptr, info_ptr);217 u8 *b = writeBuffer;219 int sizeX = w;220 int sizeY = h;222 u8 *pixU8 = (u8 *)data;223 for (int y = 0; y < sizeY; y++)224 {225 for (int x = 0; x < sizeX; x++)226 {227 int blue = *pixU8++;228 int green = *pixU8++;229 int red = *pixU8++;231 *b++ = red;232 *b++ = green;233 *b++ = blue;234 }235 png_write_row(png_ptr, writeBuffer);237 b = writeBuffer;238 }240 png_write_end(png_ptr, info_ptr);242 png_destroy_write_struct(&png_ptr, &info_ptr);244 fclose(fp);245 }247 void TileView::OnSave()248 {249 CString captureBuffer;251 if (theApp.captureFormat == 0)252 captureBuffer = "tiles.png";253 else254 captureBuffer = "tiles.bmp";256 LPCTSTR exts[] = {".png", ".bmp", NULL };258 CString filter = winResLoadFilter(IDS_FILTER_PNG);259 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);261 FileDlg dlg(this,262 captureBuffer,263 filter,264 theApp.captureFormat ? 2 : 1,265 theApp.captureFormat ? "BMP" : "PNG",266 exts,267 "",268 title,269 true);271 if (dlg.DoModal() == IDCANCEL)272 {273 return;274 }276 captureBuffer = dlg.GetPathName();278 if (dlg.getFilterIndex() == 2)279 saveBMP(captureBuffer);280 else281 savePNG(captureBuffer);282 }284 void TileView::renderTile256(int tile, int x, int y, u8 *charBase, u16 *palette)285 {286 u8 *bmp = &data[24*x + 8*32*24*y];288 for (int j = 0; j < 8; j++)289 {290 for (int i = 0; i < 8; i++)291 {292 u8 c = charBase[tile*64 + j * 8 + i];294 u16 color = palette[c];296 *bmp++ = ((color >> 10) & 0x1f) << 3;297 *bmp++ = ((color >> 5) & 0x1f) << 3;298 *bmp++ = (color & 0x1f) << 3;299 }300 bmp += 31*24; // advance line301 }302 }304 void TileView::renderTile16(int tile, int x, int y, u8 *charBase, u16 *palette)305 {306 u8 *bmp = &data[24*x + 8*32*24*y];308 int pal = this->palette;310 if (this->charBase == 4)311 pal += 16;313 for (int j = 0; j < 8; j++)314 {315 for (int i = 0; i < 8; i++)316 {317 u8 c = charBase[tile*32 + j * 4 + (i>>1)];319 if (i & 1)320 c = c>>4;321 else322 c = c & 15;324 u16 color = palette[pal*16+c];326 *bmp++ = ((color >> 10) & 0x1f) << 3;327 *bmp++ = ((color >> 5) & 0x1f) << 3;328 *bmp++ = (color & 0x1f) << 3;329 }330 bmp += 31*24; // advance line331 }332 }334 void TileView::render()335 {336 u16 *palette = (u16 *)paletteRAM;337 u8 * charBase = &vram[this->charBase * 0x4000];339 int maxY;341 if (is256Colors)342 {343 int tile = 0;344 maxY = 16;345 for (int y = 0; y < maxY; y++)346 {347 for (int x = 0; x < 32; x++)348 {349 if (this->charBase == 4)350 renderTile256(tile, x, y, charBase, &palette[256]);351 else352 renderTile256(tile, x, y, charBase, palette);353 tile++;354 }355 }356 tileView.setSize(32*8, maxY*8);357 w = 32*8;358 h = maxY*8;359 SIZE s;360 s.cx = 32*8;361 s.cy = maxY*8;362 if (tileView.getStretch())363 {364 s.cx = s.cy = 1;365 }366 tileView.SetScrollSizes(MM_TEXT, s);367 }368 else369 {370 int tile = 0;371 maxY = 32;372 if (this->charBase == 3)373 maxY = 16;374 for (int y = 0; y < maxY; y++)375 {376 for (int x = 0; x < 32; x++)377 {378 renderTile16(tile, x, y, charBase, palette);379 tile++;380 }381 }382 tileView.setSize(32*8, maxY*8);383 w = 32*8;384 h = maxY*8;385 SIZE s;386 s.cx = 32*8;387 s.cy = maxY*8;388 if (tileView.getStretch())389 {390 s.cx = s.cy = 1;391 }392 tileView.SetScrollSizes(MM_TEXT, s);393 }394 }396 void TileView::update()397 {398 paint();399 }401 BOOL TileView::OnInitDialog()402 {403 CDialog::OnInitDialog();405 DIALOG_SIZER_START(sz)406 DIALOG_SIZER_ENTRY(IDC_TILE_VIEW, DS_SizeX | DS_SizeY)407 DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY)408 DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY)409 DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY)410 DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY)411 DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY)412 DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY)413 DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY)414 DIALOG_SIZER_END()415 SetData(sz,416 TRUE,417 HKEY_CURRENT_USER,418 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\TileView",419 NULL);421 m_colors = is256Colors;422 m_charBase = charBase;424 m_slider.SetRange(0, 15);425 m_slider.SetPageSize(4);426 m_slider.SetTicFreq(1);428 paint();430 m_stretch = regQueryDwordValue("tileViewStretch", 0);431 if (m_stretch)432 tileView.setStretch(true);433 UpdateData(FALSE);435 return TRUE; // return TRUE unless you set the focus to a control436 // EXCEPTION: OCX Property Pages should return FALSE437 }439 void TileView::OnClose()440 {441 theApp.winRemoveUpdateListener(this);443 DestroyWindow();444 }446 void TileView::OnAutoUpdate()447 {448 autoUpdate = !autoUpdate;449 if (autoUpdate)450 {451 theApp.winAddUpdateListener(this);452 }453 else454 {455 theApp.winRemoveUpdateListener(this);456 }457 }459 void TileView::paint()460 {461 if (vram != NULL && paletteRAM != NULL)462 {463 render();464 tileView.refresh();465 }466 }468 void TileView::On16Colors()469 {470 is256Colors = 0;471 paint();472 }474 void TileView::On256Colors()475 {476 is256Colors = 1;477 paint();478 }480 void TileView::OnCharbase0()481 {482 charBase = 0;483 paint();484 }486 void TileView::OnCharbase1()487 {488 charBase = 1;489 paint();490 }492 void TileView::OnCharbase2()493 {494 charBase = 2;495 paint();496 }498 void TileView::OnCharbase3()499 {500 charBase = 3;501 paint();502 }504 void TileView::OnCharbase4()505 {506 charBase = 4;507 paint();508 }510 void TileView::OnStretch()511 {512 tileView.setStretch(!tileView.getStretch());513 paint();514 regSetDwordValue("tileViewStretch", tileView.getStretch());515 }517 LRESULT TileView::OnMapInfo(WPARAM wParam, LPARAM lParam)518 {519 u8 *colors = (u8 *)lParam;520 zoom.setColors(colors);522 int x = (wParam & 0xFFFF)/8;523 int y = ((wParam >> 16) & 0xFFFF)/8;525 u32 address = 0x6000000 + 0x4000 * charBase;526 int tile = 32 * y + x;527 if (is256Colors)528 tile *= 2;529 address += 32 * tile;531 CString buffer;532 buffer.Format("%d", tile);533 GetDlgItem(IDC_TILE_NUMBER)->SetWindowText(buffer);535 buffer.Format("%08x", address);536 GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer);538 return TRUE;539 }541 LRESULT TileView::OnColInfo(WPARAM wParam, LPARAM)542 {543 u16 c = (u16)wParam;545 color.setColor(c);547 int r = (c & 0x1f);548 int g = (c & 0x3e0) >> 5;549 int b = (c & 0x7c00) >> 10;551 CString buffer;552 buffer.Format("R: %d", r);553 GetDlgItem(IDC_R)->SetWindowText(buffer);555 buffer.Format("G: %d", g);556 GetDlgItem(IDC_G)->SetWindowText(buffer);558 buffer.Format("B: %d", b);559 GetDlgItem(IDC_B)->SetWindowText(buffer);561 return TRUE;562 }564 void TileView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar)565 {566 switch (nSBCode)567 {568 case TB_THUMBPOSITION:569 palette = nPos;570 break;571 default:572 palette = m_slider.GetPos();573 break;574 }575 paint();576 }578 void TileView::PostNcDestroy()579 {580 delete this;581 }