annotate src/win32/GBTileView.cpp @ 1:f9f4f1b99eed

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