annotate src/win32/MapView.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 // MapView.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 "MapView.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 "../gba/GBAGlobals.h"
rlm@1 13 #include "../NLS.h"
rlm@1 14 #include "../common/Util.h"
rlm@1 15
rlm@1 16 extern "C" {
rlm@1 17 #include <png.h>
rlm@1 18 }
rlm@1 19
rlm@1 20 /////////////////////////////////////////////////////////////////////////////
rlm@1 21 // MapView dialog
rlm@1 22
rlm@1 23 MapView::MapView(CWnd*pParent /*=NULL*/)
rlm@1 24 : ResizeDlg(MapView::IDD, pParent)
rlm@1 25 {
rlm@1 26 //{{AFX_DATA_INIT(MapView)
rlm@1 27 //}}AFX_DATA_INIT
rlm@1 28 autoUpdate = false;
rlm@1 29
rlm@1 30 memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader));
rlm@1 31
rlm@1 32 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
rlm@1 33 bmpInfo.bmiHeader.biWidth = 1024;
rlm@1 34 bmpInfo.bmiHeader.biHeight = -1024;
rlm@1 35 bmpInfo.bmiHeader.biPlanes = 1;
rlm@1 36 bmpInfo.bmiHeader.biBitCount = 24;
rlm@1 37 bmpInfo.bmiHeader.biCompression = BI_RGB;
rlm@1 38 data = (u8 *)calloc(1, 3 * 1024 * 1024);
rlm@1 39
rlm@1 40 mapView.setData(data);
rlm@1 41 mapView.setBmpInfo(&bmpInfo);
rlm@1 42
rlm@1 43 control = BG0CNT;
rlm@1 44
rlm@1 45 bg = 0;
rlm@1 46 frame = 0;
rlm@1 47 }
rlm@1 48
rlm@1 49 MapView::~MapView()
rlm@1 50 {
rlm@1 51 free(data);
rlm@1 52 data = NULL;
rlm@1 53 }
rlm@1 54
rlm@1 55 void MapView::DoDataExchange(CDataExchange*pDX)
rlm@1 56 {
rlm@1 57 CDialog::DoDataExchange(pDX);
rlm@1 58 //{{AFX_DATA_MAP(MapView)
rlm@1 59 DDX_Control(pDX, IDC_NUMCOLORS, m_numcolors);
rlm@1 60 DDX_Control(pDX, IDC_MODE, m_mode);
rlm@1 61 DDX_Control(pDX, IDC_OVERFLOW, m_overflow);
rlm@1 62 DDX_Control(pDX, IDC_MOSAIC, m_mosaic);
rlm@1 63 DDX_Control(pDX, IDC_PRIORITY, m_priority);
rlm@1 64 DDX_Control(pDX, IDC_DIM, m_dim);
rlm@1 65 DDX_Control(pDX, IDC_CHARBASE, m_charbase);
rlm@1 66 DDX_Control(pDX, IDC_MAPBASE, m_mapbase);
rlm@1 67 //}}AFX_DATA_MAP
rlm@1 68 DDX_Control(pDX, IDC_MAP_VIEW, mapView);
rlm@1 69 DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, mapViewZoom);
rlm@1 70 DDX_Control(pDX, IDC_COLOR, color);
rlm@1 71 }
rlm@1 72
rlm@1 73 BEGIN_MESSAGE_MAP(MapView, CDialog)
rlm@1 74 //{{AFX_MSG_MAP(MapView)
rlm@1 75 ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
rlm@1 76 ON_BN_CLICKED(IDC_FRAME_0, OnFrame0)
rlm@1 77 ON_BN_CLICKED(IDC_FRAME_1, OnFrame1)
rlm@1 78 ON_BN_CLICKED(IDC_BG0, OnBg0)
rlm@1 79 ON_BN_CLICKED(IDC_BG1, OnBg1)
rlm@1 80 ON_BN_CLICKED(IDC_BG2, OnBg2)
rlm@1 81 ON_BN_CLICKED(IDC_BG3, OnBg3)
rlm@1 82 ON_BN_CLICKED(IDC_STRETCH, OnStretch)
rlm@1 83 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)
rlm@1 84 ON_BN_CLICKED(IDC_CLOSE, OnClose)
rlm@1 85 ON_BN_CLICKED(IDC_SAVE, OnSave)
rlm@1 86 //}}AFX_MSG_MAP
rlm@1 87 ON_MESSAGE(WM_MAPINFO, OnMapInfo)
rlm@1 88 ON_MESSAGE(WM_COLINFO, OnColInfo)
rlm@1 89 END_MESSAGE_MAP()
rlm@1 90
rlm@1 91 /////////////////////////////////////////////////////////////////////////////
rlm@1 92 // MapView message handlers
rlm@1 93
rlm@1 94 void MapView::renderTextScreen(u16 control)
rlm@1 95 {
rlm@1 96 u16 *palette = (u16 *)paletteRAM;
rlm@1 97 u8 * charBase = &vram[((control >> 2) & 0x03) * 0x4000];
rlm@1 98 u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
rlm@1 99 u8 * bmp = data;
rlm@1 100
rlm@1 101 int sizeX = 256;
rlm@1 102 int sizeY = 256;
rlm@1 103 switch ((control >> 14) & 3)
rlm@1 104 {
rlm@1 105 case 0:
rlm@1 106 break;
rlm@1 107 case 1:
rlm@1 108 sizeX = 512;
rlm@1 109 break;
rlm@1 110 case 2:
rlm@1 111 sizeY = 512;
rlm@1 112 break;
rlm@1 113 case 3:
rlm@1 114 sizeX = 512;
rlm@1 115 sizeY = 512;
rlm@1 116 break;
rlm@1 117 }
rlm@1 118
rlm@1 119 w = sizeX;
rlm@1 120 h = sizeY;
rlm@1 121
rlm@1 122 if (control & 0x80)
rlm@1 123 {
rlm@1 124 for (int y = 0; y < sizeY; y++)
rlm@1 125 {
rlm@1 126 int yy = y & 255;
rlm@1 127
rlm@1 128 if (y == 256 && sizeY > 256)
rlm@1 129 {
rlm@1 130 screenBase += 0x400;
rlm@1 131 if (sizeX > 256)
rlm@1 132 screenBase += 0x400;
rlm@1 133 }
rlm@1 134 u16 *screenSource = screenBase + ((yy>>3)*32);
rlm@1 135
rlm@1 136 for (int x = 0; x < sizeX; x++)
rlm@1 137 {
rlm@1 138 u16 data = *screenSource;
rlm@1 139
rlm@1 140 int tile = data & 0x3FF;
rlm@1 141 int tileX = (x & 7);
rlm@1 142 int tileY = y & 7;
rlm@1 143
rlm@1 144 if (data & 0x0400)
rlm@1 145 tileX = 7 - tileX;
rlm@1 146 if (data & 0x0800)
rlm@1 147 tileY = 7 - tileY;
rlm@1 148
rlm@1 149 u8 c = charBase[tile * 64 + tileY * 8 + tileX];
rlm@1 150
rlm@1 151 u16 color = palette[c];
rlm@1 152
rlm@1 153 *bmp++ = ((color >> 10) & 0x1f) << 3;
rlm@1 154 *bmp++ = ((color >> 5) & 0x1f) << 3;
rlm@1 155 *bmp++ = (color & 0x1f) << 3;
rlm@1 156
rlm@1 157 if (data & 0x0400)
rlm@1 158 {
rlm@1 159 if (tileX == 0)
rlm@1 160 screenSource++;
rlm@1 161 }
rlm@1 162 else if (tileX == 7)
rlm@1 163 screenSource++;
rlm@1 164 if (x == 255 && sizeX > 256)
rlm@1 165 {
rlm@1 166 screenSource = screenBase + 0x400 + ((yy>>3)*32);
rlm@1 167 }
rlm@1 168 }
rlm@1 169 }
rlm@1 170 }
rlm@1 171 else
rlm@1 172 {
rlm@1 173 for (int y = 0; y < sizeY; y++)
rlm@1 174 {
rlm@1 175 int yy = y & 255;
rlm@1 176
rlm@1 177 if (y == 256 && sizeY > 256)
rlm@1 178 {
rlm@1 179 screenBase += 0x400;
rlm@1 180 if (sizeX > 256)
rlm@1 181 screenBase += 0x400;
rlm@1 182 }
rlm@1 183 u16 *screenSource = screenBase + ((yy>>3)*32);
rlm@1 184
rlm@1 185 for (int x = 0; x < sizeX; x++)
rlm@1 186 {
rlm@1 187 u16 data = *screenSource;
rlm@1 188
rlm@1 189 int tile = data & 0x3FF;
rlm@1 190 int tileX = (x & 7);
rlm@1 191 int tileY = y & 7;
rlm@1 192
rlm@1 193 if (data & 0x0400)
rlm@1 194 tileX = 7 - tileX;
rlm@1 195 if (data & 0x0800)
rlm@1 196 tileY = 7 - tileY;
rlm@1 197
rlm@1 198 u8 color = charBase[tile * 32 + tileY * 4 + (tileX>>1)];
rlm@1 199
rlm@1 200 if (tileX & 1)
rlm@1 201 {
rlm@1 202 color = (color >> 4);
rlm@1 203 }
rlm@1 204 else
rlm@1 205 {
rlm@1 206 color &= 0x0F;
rlm@1 207 }
rlm@1 208
rlm@1 209 int pal = (*screenSource>>8) & 0xF0;
rlm@1 210 u16 color2 = palette[pal + color];
rlm@1 211
rlm@1 212 *bmp++ = ((color2 >> 10) & 0x1f) << 3;
rlm@1 213 *bmp++ = ((color2 >> 5) & 0x1f) << 3;
rlm@1 214 *bmp++ = (color2 & 0x1f) << 3;
rlm@1 215
rlm@1 216 if (data & 0x0400)
rlm@1 217 {
rlm@1 218 if (tileX == 0)
rlm@1 219 screenSource++;
rlm@1 220 }
rlm@1 221 else if (tileX == 7)
rlm@1 222 screenSource++;
rlm@1 223
rlm@1 224 if (x == 255 && sizeX > 256)
rlm@1 225 {
rlm@1 226 screenSource = screenBase + 0x400 + ((yy>>3)*32);
rlm@1 227 }
rlm@1 228 }
rlm@1 229 }
rlm@1 230 }
rlm@1 231 /*
rlm@1 232 switch(bg) {
rlm@1 233 case 0:
rlm@1 234 renderView(BG0HOFS<<8, BG0VOFS<<8,
rlm@1 235 0x100, 0x000,
rlm@1 236 0x000, 0x100,
rlm@1 237 (sizeX -1) <<8,
rlm@1 238 (sizeY -1) << 8,
rlm@1 239 true);
rlm@1 240 break;
rlm@1 241 case 1:
rlm@1 242 renderView(BG1HOFS<<8, BG1VOFS<<8,
rlm@1 243 0x100, 0x000,
rlm@1 244 0x000, 0x100,
rlm@1 245 (sizeX -1) <<8,
rlm@1 246 (sizeY -1) << 8,
rlm@1 247 true);
rlm@1 248 break;
rlm@1 249 case 2:
rlm@1 250 renderView(BG2HOFS<<8, BG2VOFS<<8,
rlm@1 251 0x100, 0x000,
rlm@1 252 0x000, 0x100,
rlm@1 253 (sizeX -1) <<8,
rlm@1 254 (sizeY -1) << 8,
rlm@1 255 true);
rlm@1 256 break;
rlm@1 257 case 3:
rlm@1 258 renderView(BG3HOFS<<8, BG3VOFS<<8,
rlm@1 259 0x100, 0x000,
rlm@1 260 0x000, 0x100,
rlm@1 261 (sizeX -1) <<8,
rlm@1 262 (sizeY -1) << 8,
rlm@1 263 true);
rlm@1 264 break;
rlm@1 265 }
rlm@1 266 */
rlm@1 267 }
rlm@1 268
rlm@1 269 void MapView::renderRotScreen(u16 control)
rlm@1 270 {
rlm@1 271 u16 *palette = (u16 *)paletteRAM;
rlm@1 272 u8 * charBase = &vram[((control >> 2) & 0x03) * 0x4000];
rlm@1 273 u8 * screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800];
rlm@1 274 u8 * bmp = data;
rlm@1 275
rlm@1 276 int sizeX = 128;
rlm@1 277 int sizeY = 128;
rlm@1 278 switch ((control >> 14) & 3)
rlm@1 279 {
rlm@1 280 case 0:
rlm@1 281 break;
rlm@1 282 case 1:
rlm@1 283 sizeX = sizeY = 256;
rlm@1 284 break;
rlm@1 285 case 2:
rlm@1 286 sizeX = sizeY = 512;
rlm@1 287 break;
rlm@1 288 case 3:
rlm@1 289 sizeX = sizeY = 1024;
rlm@1 290 break;
rlm@1 291 }
rlm@1 292
rlm@1 293 w = sizeX;
rlm@1 294 h = sizeY;
rlm@1 295
rlm@1 296 if (control & 0x80)
rlm@1 297 {
rlm@1 298 for (int y = 0; y < sizeY; y++)
rlm@1 299 {
rlm@1 300 for (int x = 0; x < sizeX; x++)
rlm@1 301 {
rlm@1 302 int tile = screenBase[(x>>3) + (y>>3)*(w>>3)];
rlm@1 303
rlm@1 304 int tileX = (x & 7);
rlm@1 305 int tileY = y & 7;
rlm@1 306
rlm@1 307 u8 color = charBase[tile * 64 + tileY * 8 + tileX];
rlm@1 308 u16 color2 = palette[color];
rlm@1 309
rlm@1 310 *bmp++ = ((color2 >> 10) & 0x1f) << 3;
rlm@1 311 *bmp++ = ((color2 >> 5) & 0x1f) << 3;
rlm@1 312 *bmp++ = (color2 & 0x1f) << 3;
rlm@1 313 }
rlm@1 314 }
rlm@1 315 }
rlm@1 316 else
rlm@1 317 {
rlm@1 318 for (int y = 0; y < sizeY; y++)
rlm@1 319 {
rlm@1 320 for (int x = 0; x < sizeX; x++)
rlm@1 321 {
rlm@1 322 int tile = screenBase[(x>>3) + (y>>3)*(w>>3)];
rlm@1 323
rlm@1 324 int tileX = (x & 7);
rlm@1 325 int tileY = y & 7;
rlm@1 326
rlm@1 327 u8 color = charBase[tile * 64 + tileY * 8 + tileX];
rlm@1 328 u16 color2 = palette[color];
rlm@1 329
rlm@1 330 *bmp++ = ((color2 >> 10) & 0x1f) << 3;
rlm@1 331 *bmp++ = ((color2 >> 5) & 0x1f) << 3;
rlm@1 332 *bmp++ = (color2 & 0x1f) << 3;
rlm@1 333 }
rlm@1 334 }
rlm@1 335 }
rlm@1 336
rlm@1 337 u32 xx;
rlm@1 338 u32 yy;
rlm@1 339
rlm@1 340 switch (bg)
rlm@1 341 {
rlm@1 342 case 2:
rlm@1 343 xx = BG2X_L | BG2X_H << 16;
rlm@1 344 yy = BG2Y_L | BG2Y_H << 16;
rlm@1 345
rlm@1 346 /*
rlm@1 347 renderView(xx, yy,
rlm@1 348 BG2PA, BG2PC,
rlm@1 349 BG2PB, BG2PD,
rlm@1 350 (sizeX -1) <<8,
rlm@1 351 (sizeY -1) << 8,
rlm@1 352 (control & 0x2000) != 0);
rlm@1 353 */
rlm@1 354 break;
rlm@1 355 case 3:
rlm@1 356 xx = BG3X_L | BG3X_H << 16;
rlm@1 357 yy = BG3Y_L | BG3Y_H << 16;
rlm@1 358 /*
rlm@1 359 renderView(xx, yy,
rlm@1 360 BG3PA, BG3PC,
rlm@1 361 BG3PB, BG3PD,
rlm@1 362 (sizeX -1) <<8,
rlm@1 363 (sizeY -1) << 8,
rlm@1 364 (control & 0x2000) != 0);
rlm@1 365 */
rlm@1 366 break;
rlm@1 367 }
rlm@1 368 }
rlm@1 369
rlm@1 370 void MapView::renderMode0()
rlm@1 371 {
rlm@1 372 renderTextScreen(control);
rlm@1 373 }
rlm@1 374
rlm@1 375 void MapView::renderMode1()
rlm@1 376 {
rlm@1 377 switch (bg)
rlm@1 378 {
rlm@1 379 case 0:
rlm@1 380 case 1:
rlm@1 381 renderTextScreen(control);
rlm@1 382 break;
rlm@1 383 case 2:
rlm@1 384 renderRotScreen(control);
rlm@1 385 break;
rlm@1 386 default:
rlm@1 387 bg = 0;
rlm@1 388 control = BG0CNT;
rlm@1 389 renderTextScreen(control);
rlm@1 390 break;
rlm@1 391 }
rlm@1 392 }
rlm@1 393
rlm@1 394 void MapView::renderMode2()
rlm@1 395 {
rlm@1 396 switch (bg)
rlm@1 397 {
rlm@1 398 case 2:
rlm@1 399 case 3:
rlm@1 400 renderRotScreen(control);
rlm@1 401 break;
rlm@1 402 default:
rlm@1 403 bg = 2;
rlm@1 404 control = BG2CNT;
rlm@1 405 renderRotScreen(control);
rlm@1 406 break;
rlm@1 407 }
rlm@1 408 }
rlm@1 409
rlm@1 410 void MapView::renderMode3()
rlm@1 411 {
rlm@1 412 u8 * bmp = data;
rlm@1 413 u16 *src = (u16 *)&vram[0];
rlm@1 414
rlm@1 415 w = 240;
rlm@1 416 h = 160;
rlm@1 417
rlm@1 418 for (int y = 0; y < 160; y++)
rlm@1 419 {
rlm@1 420 for (int x = 0; x < 240; x++)
rlm@1 421 {
rlm@1 422 u16 data = *src++;
rlm@1 423 *bmp++ = ((data >> 10) & 0x1f) << 3;
rlm@1 424 *bmp++ = ((data >> 5) & 0x1f) << 3;
rlm@1 425 *bmp++ = (data & 0x1f) << 3;
rlm@1 426 }
rlm@1 427 }
rlm@1 428 bg = 2;
rlm@1 429 }
rlm@1 430
rlm@1 431 void MapView::renderMode4()
rlm@1 432 {
rlm@1 433 u8 * bmp = data;
rlm@1 434 u8 * src = frame ? &vram[0xa000] : &vram[0];
rlm@1 435 u16 *pal = (u16 *)&paletteRAM[0];
rlm@1 436
rlm@1 437 w = 240;
rlm@1 438 h = 160;
rlm@1 439
rlm@1 440 for (int y = 0; y < 160; y++)
rlm@1 441 {
rlm@1 442 for (int x = 0; x < 240; x++)
rlm@1 443 {
rlm@1 444 u8 c = *src++;
rlm@1 445 u16 data = pal[c];
rlm@1 446 *bmp++ = ((data >> 10) & 0x1f) << 3;
rlm@1 447 *bmp++ = ((data >> 5) & 0x1f) << 3;
rlm@1 448 *bmp++ = (data & 0x1f) << 3;
rlm@1 449 }
rlm@1 450 }
rlm@1 451 bg = 2;
rlm@1 452 }
rlm@1 453
rlm@1 454 void MapView::renderMode5()
rlm@1 455 {
rlm@1 456 u8 * bmp = data;
rlm@1 457 u16 *src = (u16 *)(frame ? &vram[0xa000] : &vram[0]);
rlm@1 458
rlm@1 459 w = 160;
rlm@1 460 h = 128;
rlm@1 461
rlm@1 462 for (int y = 0; y < 128; y++)
rlm@1 463 {
rlm@1 464 for (int x = 0; x < 160; x++)
rlm@1 465 {
rlm@1 466 u16 data = *src++;
rlm@1 467 *bmp++ = ((data >> 10) & 0x1f) << 3;
rlm@1 468 *bmp++ = ((data >> 5) & 0x1f) << 3;
rlm@1 469 *bmp++ = (data & 0x1f) << 3;
rlm@1 470 }
rlm@1 471 }
rlm@1 472 bg = 2;
rlm@1 473 }
rlm@1 474
rlm@1 475 void MapView::OnRefresh()
rlm@1 476 {
rlm@1 477 paint();
rlm@1 478 }
rlm@1 479
rlm@1 480 void MapView::paint()
rlm@1 481 {
rlm@1 482 if (vram == NULL)
rlm@1 483 return;
rlm@1 484 int mode = DISPCNT & 7;
rlm@1 485
rlm@1 486 switch (bg)
rlm@1 487 {
rlm@1 488 default:
rlm@1 489 case 0:
rlm@1 490 control = BG0CNT;
rlm@1 491 break;
rlm@1 492 case 1:
rlm@1 493 control = BG1CNT;
rlm@1 494 break;
rlm@1 495 case 2:
rlm@1 496 control = BG2CNT;
rlm@1 497 break;
rlm@1 498 case 3:
rlm@1 499 control = BG3CNT;
rlm@1 500 break;
rlm@1 501 }
rlm@1 502
rlm@1 503 switch (mode)
rlm@1 504 {
rlm@1 505 case 0:
rlm@1 506 renderMode0();
rlm@1 507 break;
rlm@1 508 case 1:
rlm@1 509 renderMode1();
rlm@1 510 break;
rlm@1 511 case 2:
rlm@1 512 renderMode2();
rlm@1 513 break;
rlm@1 514 case 3:
rlm@1 515 renderMode3();
rlm@1 516 break;
rlm@1 517 case 4:
rlm@1 518 renderMode4();
rlm@1 519 break;
rlm@1 520 case 5:
rlm@1 521 renderMode5();
rlm@1 522 break;
rlm@1 523 }
rlm@1 524 enableButtons(mode);
rlm@1 525 SIZE s;
rlm@1 526
rlm@1 527 if (mapView.getStretch())
rlm@1 528 {
rlm@1 529 mapView.setSize(w, h);
rlm@1 530 s.cx = s.cy = 1;
rlm@1 531 mapView.SetScrollSizes(MM_TEXT, s);
rlm@1 532 }
rlm@1 533 else
rlm@1 534 {
rlm@1 535 mapView.setSize(w, h);
rlm@1 536 s.cx = w;
rlm@1 537 s.cy = h;
rlm@1 538 mapView.SetScrollSizes(MM_TEXT, s);
rlm@1 539 }
rlm@1 540
rlm@1 541 mapView.refresh();
rlm@1 542
rlm@1 543 CString buffer;
rlm@1 544
rlm@1 545 u32 charBase = ((control >> 2) & 0x03) * 0x4000 + 0x6000000;
rlm@1 546 u32 screenBase = ((control >> 8) & 0x1f) * 0x800 + 0x6000000;
rlm@1 547
rlm@1 548 buffer.Format("%d", mode);
rlm@1 549 m_mode.SetWindowText(buffer);
rlm@1 550
rlm@1 551 if (mode >= 3)
rlm@1 552 {
rlm@1 553 m_mapbase.SetWindowText("");
rlm@1 554 m_charbase.SetWindowText("");
rlm@1 555 }
rlm@1 556 else
rlm@1 557 {
rlm@1 558 buffer.Format("0x%08X", screenBase);
rlm@1 559 m_mapbase.SetWindowText(buffer);
rlm@1 560
rlm@1 561 buffer.Format("0x%08X", charBase);
rlm@1 562 m_charbase.SetWindowText(buffer);
rlm@1 563 }
rlm@1 564
rlm@1 565 buffer.Format("%dx%d", w, h);
rlm@1 566 m_dim.SetWindowText(buffer);
rlm@1 567
rlm@1 568 m_numcolors.SetWindowText(control & 0x80 ? "256" : "16");
rlm@1 569
rlm@1 570 buffer.Format("%d", control & 3);
rlm@1 571 m_priority.SetWindowText(buffer);
rlm@1 572
rlm@1 573 m_mosaic.SetWindowText(control & 0x40 ? "1" : "0");
rlm@1 574
rlm@1 575 m_overflow.SetWindowText(bg <= 1 ? "" :
rlm@1 576 control & 0x2000 ? "1" : "0");
rlm@1 577 }
rlm@1 578
rlm@1 579 BOOL MapView::OnInitDialog()
rlm@1 580 {
rlm@1 581 CDialog::OnInitDialog();
rlm@1 582
rlm@1 583 DIALOG_SIZER_START(sz)
rlm@1 584 DIALOG_SIZER_ENTRY(IDC_MAP_VIEW, DS_SizeX | DS_SizeY)
rlm@1 585 DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY)
rlm@1 586 DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY)
rlm@1 587 DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY)
rlm@1 588 DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY)
rlm@1 589 DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY)
rlm@1 590 DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY)
rlm@1 591 DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY)
rlm@1 592 DIALOG_SIZER_END()
rlm@1 593 SetData(sz,
rlm@1 594 TRUE,
rlm@1 595 HKEY_CURRENT_USER,
rlm@1 596 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\MapView",
rlm@1 597 NULL);
rlm@1 598
rlm@1 599 SIZE size;
rlm@1 600 size.cx = 1;
rlm@1 601 size.cy = 1;
rlm@1 602 mapView.SetScrollSizes(MM_TEXT, size);
rlm@1 603 int s = regQueryDwordValue("mapViewStretch", 0);
rlm@1 604 if (s)
rlm@1 605 mapView.setStretch(true);
rlm@1 606 ((CButton *)GetDlgItem(IDC_STRETCH))->SetCheck(s);
rlm@1 607 paint();
rlm@1 608
rlm@1 609 return TRUE; // return TRUE unless you set the focus to a control
rlm@1 610 // EXCEPTION: OCX Property Pages should return FALSE
rlm@1 611 }
rlm@1 612
rlm@1 613 void MapView::PostNcDestroy()
rlm@1 614 {
rlm@1 615 delete this;
rlm@1 616 }
rlm@1 617
rlm@1 618 void MapView::enableButtons(int mode)
rlm@1 619 {
rlm@1 620 bool enable[6] = { true, true, true, true, true, true };
rlm@1 621
rlm@1 622 switch (mode)
rlm@1 623 {
rlm@1 624 case 0:
rlm@1 625 enable[4] = false;
rlm@1 626 enable[5] = false;
rlm@1 627 break;
rlm@1 628 case 1:
rlm@1 629 enable[3] = false;
rlm@1 630 enable[4] = false;
rlm@1 631 enable[5] = false;
rlm@1 632 break;
rlm@1 633 case 2:
rlm@1 634 enable[0] = false;
rlm@1 635 enable[1] = false;
rlm@1 636 enable[4] = false;
rlm@1 637 enable[5] = false;
rlm@1 638 break;
rlm@1 639 case 3:
rlm@1 640 enable[0] = false;
rlm@1 641 enable[1] = false;
rlm@1 642 enable[2] = false;
rlm@1 643 enable[3] = false;
rlm@1 644 enable[4] = false;
rlm@1 645 enable[5] = false;
rlm@1 646 break;
rlm@1 647 case 4:
rlm@1 648 enable[0] = false;
rlm@1 649 enable[1] = false;
rlm@1 650 enable[2] = false;
rlm@1 651 enable[3] = false;
rlm@1 652 break;
rlm@1 653 case 5:
rlm@1 654 enable[0] = false;
rlm@1 655 enable[1] = false;
rlm@1 656 enable[2] = false;
rlm@1 657 enable[3] = false;
rlm@1 658 break;
rlm@1 659 }
rlm@1 660 GetDlgItem(IDC_BG0)->EnableWindow(enable[0]);
rlm@1 661 GetDlgItem(IDC_BG1)->EnableWindow(enable[1]);
rlm@1 662 GetDlgItem(IDC_BG2)->EnableWindow(enable[2]);
rlm@1 663 GetDlgItem(IDC_BG3)->EnableWindow(enable[3]);
rlm@1 664 GetDlgItem(IDC_FRAME_0)->EnableWindow(enable[4]);
rlm@1 665 GetDlgItem(IDC_FRAME_1)->EnableWindow(enable[5]);
rlm@1 666 int id = IDC_BG0;
rlm@1 667 switch (bg)
rlm@1 668 {
rlm@1 669 case 1:
rlm@1 670 id = IDC_BG1;
rlm@1 671 break;
rlm@1 672 case 2:
rlm@1 673 id = IDC_BG2;
rlm@1 674 break;
rlm@1 675 case 3:
rlm@1 676 id = IDC_BG3;
rlm@1 677 break;
rlm@1 678 }
rlm@1 679 CheckRadioButton(IDC_BG0, IDC_BG3, id);
rlm@1 680 id = IDC_FRAME_0;
rlm@1 681 if (frame != 0)
rlm@1 682 id = IDC_FRAME_1;
rlm@1 683 CheckRadioButton(IDC_FRAME_0, IDC_FRAME_1, id);
rlm@1 684 }
rlm@1 685
rlm@1 686 void MapView::OnFrame0()
rlm@1 687 {
rlm@1 688 frame = 0;
rlm@1 689 paint();
rlm@1 690 }
rlm@1 691
rlm@1 692 void MapView::OnFrame1()
rlm@1 693 {
rlm@1 694 frame = 1;
rlm@1 695 paint();
rlm@1 696 }
rlm@1 697
rlm@1 698 void MapView::OnBg0()
rlm@1 699 {
rlm@1 700 bg = 0;
rlm@1 701 control = BG0CNT;
rlm@1 702 paint();
rlm@1 703 }
rlm@1 704
rlm@1 705 void MapView::OnBg1()
rlm@1 706 {
rlm@1 707 bg = 1;
rlm@1 708 control = BG1CNT;
rlm@1 709 paint();
rlm@1 710 }
rlm@1 711
rlm@1 712 void MapView::OnBg2()
rlm@1 713 {
rlm@1 714 bg = 2;
rlm@1 715 control = BG2CNT;
rlm@1 716 paint();
rlm@1 717 }
rlm@1 718
rlm@1 719 void MapView::OnBg3()
rlm@1 720 {
rlm@1 721 bg = 3;
rlm@1 722 control = BG3CNT;
rlm@1 723 paint();
rlm@1 724 }
rlm@1 725
rlm@1 726 void MapView::OnStretch()
rlm@1 727 {
rlm@1 728 mapView.setStretch(!mapView.getStretch());
rlm@1 729 paint();
rlm@1 730 regSetDwordValue("mapViewStretch", mapView.getStretch());
rlm@1 731 }
rlm@1 732
rlm@1 733 void MapView::OnAutoUpdate()
rlm@1 734 {
rlm@1 735 autoUpdate = !autoUpdate;
rlm@1 736 if (autoUpdate)
rlm@1 737 {
rlm@1 738 theApp.winAddUpdateListener(this);
rlm@1 739 }
rlm@1 740 else
rlm@1 741 {
rlm@1 742 theApp.winRemoveUpdateListener(this);
rlm@1 743 }
rlm@1 744 }
rlm@1 745
rlm@1 746 void MapView::update()
rlm@1 747 {
rlm@1 748 paint();
rlm@1 749 }
rlm@1 750
rlm@1 751 void MapView::OnClose()
rlm@1 752 {
rlm@1 753 theApp.winRemoveUpdateListener(this);
rlm@1 754
rlm@1 755 DestroyWindow();
rlm@1 756 }
rlm@1 757
rlm@1 758 u32 MapView::GetTextClickAddress(u32 base, int x, int y)
rlm@1 759 {
rlm@1 760 if (y > 255 && h > 256)
rlm@1 761 {
rlm@1 762 base += 0x800;
rlm@1 763 if (w > 256)
rlm@1 764 base += 0x800;
rlm@1 765 }
rlm@1 766 if (x >= 256)
rlm@1 767 base += 0x800;
rlm@1 768 x &= 255;
rlm@1 769 y &= 255;
rlm@1 770 base += (x>>3)*2 + 64*(y>>3);
rlm@1 771
rlm@1 772 return base;
rlm@1 773 }
rlm@1 774
rlm@1 775 u32 MapView::GetClickAddress(int x, int y)
rlm@1 776 {
rlm@1 777 int mode = DISPCNT & 7;
rlm@1 778
rlm@1 779 u32 base = ((control >> 8) & 0x1f) * 0x800 + 0x6000000;
rlm@1 780
rlm@1 781 // all text bgs (16 bits)
rlm@1 782 if (mode == 0 || (mode < 3 && bg < 2))
rlm@1 783 {
rlm@1 784 return GetTextClickAddress(base, x, y);
rlm@1 785 }
rlm@1 786 // rot bgs (8 bits)
rlm@1 787 if (mode < 3)
rlm@1 788 {
rlm@1 789 return base + (x>>3) + (w>>3)*(y>>3);
rlm@1 790 }
rlm@1 791 // mode 3/5 (16 bits)
rlm@1 792 if (mode != 4)
rlm@1 793 {
rlm@1 794 return 0x6000000 + 0xa000*frame + 2*x + w*y*2;
rlm@1 795 }
rlm@1 796 // mode 4 (8 bits)
rlm@1 797 return 0x6000000 + 0xa000*frame + x + w*y;
rlm@1 798 }
rlm@1 799
rlm@1 800 LRESULT MapView::OnMapInfo(WPARAM wParam, LPARAM lParam)
rlm@1 801 {
rlm@1 802 u8 *colors = (u8 *)lParam;
rlm@1 803 mapViewZoom.setColors(colors);
rlm@1 804
rlm@1 805 int x = wParam & 0xffff;
rlm@1 806 int y = (wParam >> 16);
rlm@1 807
rlm@1 808 CString buffer;
rlm@1 809 buffer.Format("(%d,%d)", x, y);
rlm@1 810 GetDlgItem(IDC_XY)->SetWindowText(buffer);
rlm@1 811
rlm@1 812 u32 address = GetClickAddress(x, y);
rlm@1 813 buffer.Format("0x%08X", address);
rlm@1 814 GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer);
rlm@1 815
rlm@1 816 int mode = DISPCNT & 7;
rlm@1 817 if (mode >= 3)
rlm@1 818 {
rlm@1 819 // bitmap modes
rlm@1 820 GetDlgItem(IDC_TILE_NUM)->SetWindowText("---");
rlm@1 821 GetDlgItem(IDC_FLIP)->SetWindowText("--");
rlm@1 822 GetDlgItem(IDC_PALETTE_NUM)->SetWindowText("---");
rlm@1 823 }
rlm@1 824 else if (mode == 0 || bg < 2)
rlm@1 825 {
rlm@1 826 // text bgs
rlm@1 827 u16 value = *((u16 *)&vram[address - 0x6000000]);
rlm@1 828
rlm@1 829 int tile = value & 1023;
rlm@1 830 buffer.Format("%d", tile);
rlm@1 831 GetDlgItem(IDC_TILE_NUM)->SetWindowText(buffer);
rlm@1 832 buffer.Empty();
rlm@1 833 buffer += value & 1024 ? 'H' : '-';
rlm@1 834 buffer += value & 2048 ? 'V' : '-';
rlm@1 835 GetDlgItem(IDC_FLIP)->SetWindowText(buffer);
rlm@1 836
rlm@1 837 if (!(control & 0x80))
rlm@1 838 {
rlm@1 839 buffer.Format("%d", (value >> 12) & 15);
rlm@1 840 }
rlm@1 841 else
rlm@1 842 buffer = "---";
rlm@1 843 GetDlgItem(IDC_PALETTE_NUM)->SetWindowText(buffer);
rlm@1 844 }
rlm@1 845 else
rlm@1 846 {
rlm@1 847 // rot bgs
rlm@1 848 GetDlgItem(IDC_TILE_NUM)->SetWindowText("---");
rlm@1 849 GetDlgItem(IDC_FLIP)->SetWindowText("--");
rlm@1 850 GetDlgItem(IDC_PALETTE_NUM)->SetWindowText("---");
rlm@1 851 }
rlm@1 852
rlm@1 853 return TRUE;
rlm@1 854 }
rlm@1 855
rlm@1 856 LRESULT MapView::OnColInfo(WPARAM wParam, LPARAM lParam)
rlm@1 857 {
rlm@1 858 u16 c = (u16)wParam;
rlm@1 859
rlm@1 860 color.setColor(c);
rlm@1 861
rlm@1 862 int r = (c & 0x1f);
rlm@1 863 int g = (c & 0x3e0) >> 5;
rlm@1 864 int b = (c & 0x7c00) >> 10;
rlm@1 865
rlm@1 866 CString buffer;
rlm@1 867 buffer.Format("R: %d", r);
rlm@1 868 GetDlgItem(IDC_R)->SetWindowText(buffer);
rlm@1 869
rlm@1 870 buffer.Format("G: %d", g);
rlm@1 871 GetDlgItem(IDC_G)->SetWindowText(buffer);
rlm@1 872
rlm@1 873 buffer.Format("B: %d", b);
rlm@1 874 GetDlgItem(IDC_B)->SetWindowText(buffer);
rlm@1 875
rlm@1 876 return TRUE;
rlm@1 877 }
rlm@1 878
rlm@1 879 void MapView::saveBMP(const char *name)
rlm@1 880 {
rlm@1 881 u8 writeBuffer[1024 * 3];
rlm@1 882
rlm@1 883 FILE *fp = fopen(name, "wb");
rlm@1 884
rlm@1 885 if (!fp)
rlm@1 886 {
rlm@1 887 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
rlm@1 888 return;
rlm@1 889 }
rlm@1 890
rlm@1 891 struct
rlm@1 892 {
rlm@1 893 u8 ident[2];
rlm@1 894 u8 filesize[4];
rlm@1 895 u8 reserved[4];
rlm@1 896 u8 dataoffset[4];
rlm@1 897 u8 headersize[4];
rlm@1 898 u8 width[4];
rlm@1 899 u8 height[4];
rlm@1 900 u8 planes[2];
rlm@1 901 u8 bitsperpixel[2];
rlm@1 902 u8 compression[4];
rlm@1 903 u8 datasize[4];
rlm@1 904 u8 hres[4];
rlm@1 905 u8 vres[4];
rlm@1 906 u8 colors[4];
rlm@1 907 u8 importantcolors[4];
rlm@1 908 u8 pad[2];
rlm@1 909 } bmpheader;
rlm@1 910 memset(&bmpheader, 0, sizeof(bmpheader));
rlm@1 911
rlm@1 912 bmpheader.ident[0] = 'B';
rlm@1 913 bmpheader.ident[1] = 'M';
rlm@1 914
rlm@1 915 u32 fsz = sizeof(bmpheader) + w*h*3;
rlm@1 916 utilPutDword(bmpheader.filesize, fsz);
rlm@1 917 utilPutDword(bmpheader.dataoffset, 0x38);
rlm@1 918 utilPutDword(bmpheader.headersize, 0x28);
rlm@1 919 utilPutDword(bmpheader.width, w);
rlm@1 920 utilPutDword(bmpheader.height, h);
rlm@1 921 utilPutDword(bmpheader.planes, 1);
rlm@1 922 utilPutDword(bmpheader.bitsperpixel, 24);
rlm@1 923 utilPutDword(bmpheader.datasize, 3*w*h);
rlm@1 924
rlm@1 925 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
rlm@1 926
rlm@1 927 u8 *b = writeBuffer;
rlm@1 928
rlm@1 929 int sizeX = w;
rlm@1 930 int sizeY = h;
rlm@1 931
rlm@1 932 u8 *pixU8 = (u8 *)data+3*w*(h-1);
rlm@1 933 for (int y = 0; y < sizeY; y++)
rlm@1 934 {
rlm@1 935 for (int x = 0; x < sizeX; x++)
rlm@1 936 {
rlm@1 937 *b++ = *pixU8++; // B
rlm@1 938 *b++ = *pixU8++; // G
rlm@1 939 *b++ = *pixU8++; // R
rlm@1 940 }
rlm@1 941 pixU8 -= 2*3*w;
rlm@1 942 fwrite(writeBuffer, 1, 3*w, fp);
rlm@1 943
rlm@1 944 b = writeBuffer;
rlm@1 945 }
rlm@1 946
rlm@1 947 fclose(fp);
rlm@1 948 }
rlm@1 949
rlm@1 950 void MapView::savePNG(const char *name)
rlm@1 951 {
rlm@1 952 u8 writeBuffer[1024 * 3];
rlm@1 953
rlm@1 954 FILE *fp = fopen(name, "wb");
rlm@1 955
rlm@1 956 if (!fp)
rlm@1 957 {
rlm@1 958 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
rlm@1 959 return;
rlm@1 960 }
rlm@1 961
rlm@1 962 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
rlm@1 963 NULL,
rlm@1 964 NULL,
rlm@1 965 NULL);
rlm@1 966 if (!png_ptr)
rlm@1 967 {
rlm@1 968 fclose(fp);
rlm@1 969 return;
rlm@1 970 }
rlm@1 971
rlm@1 972 png_infop info_ptr = png_create_info_struct(png_ptr);
rlm@1 973
rlm@1 974 if (!info_ptr)
rlm@1 975 {
rlm@1 976 png_destroy_write_struct(&png_ptr, NULL);
rlm@1 977 fclose(fp);
rlm@1 978 return;
rlm@1 979 }
rlm@1 980
rlm@1 981 if (setjmp(png_ptr->jmpbuf))
rlm@1 982 {
rlm@1 983 png_destroy_write_struct(&png_ptr, NULL);
rlm@1 984 fclose(fp);
rlm@1 985 return;
rlm@1 986 }
rlm@1 987
rlm@1 988 png_init_io(png_ptr, fp);
rlm@1 989
rlm@1 990 png_set_IHDR(png_ptr,
rlm@1 991 info_ptr,
rlm@1 992 w,
rlm@1 993 h,
rlm@1 994 8,
rlm@1 995 PNG_COLOR_TYPE_RGB,
rlm@1 996 PNG_INTERLACE_NONE,
rlm@1 997 PNG_COMPRESSION_TYPE_DEFAULT,
rlm@1 998 PNG_FILTER_TYPE_DEFAULT);
rlm@1 999
rlm@1 1000 png_write_info(png_ptr, info_ptr);
rlm@1 1001
rlm@1 1002 u8 *b = writeBuffer;
rlm@1 1003
rlm@1 1004 int sizeX = w;
rlm@1 1005 int sizeY = h;
rlm@1 1006
rlm@1 1007 u8 *pixU8 = (u8 *)data;
rlm@1 1008 for (int y = 0; y < sizeY; y++)
rlm@1 1009 {
rlm@1 1010 for (int x = 0; x < sizeX; x++)
rlm@1 1011 {
rlm@1 1012 int blue = *pixU8++;
rlm@1 1013 int green = *pixU8++;
rlm@1 1014 int red = *pixU8++;
rlm@1 1015
rlm@1 1016 *b++ = red;
rlm@1 1017 *b++ = green;
rlm@1 1018 *b++ = blue;
rlm@1 1019 }
rlm@1 1020 png_write_row(png_ptr, writeBuffer);
rlm@1 1021
rlm@1 1022 b = writeBuffer;
rlm@1 1023 }
rlm@1 1024
rlm@1 1025 png_write_end(png_ptr, info_ptr);
rlm@1 1026
rlm@1 1027 png_destroy_write_struct(&png_ptr, &info_ptr);
rlm@1 1028
rlm@1 1029 fclose(fp);
rlm@1 1030 }
rlm@1 1031
rlm@1 1032 void MapView::OnSave()
rlm@1 1033 {
rlm@1 1034 CString filename;
rlm@1 1035
rlm@1 1036 if (theApp.captureFormat == 0)
rlm@1 1037 filename = "map.png";
rlm@1 1038 else
rlm@1 1039 filename = "map.bmp";
rlm@1 1040
rlm@1 1041 LPCTSTR exts[] = {".png", ".bmp", NULL };
rlm@1 1042
rlm@1 1043 CString filter = winResLoadFilter(IDS_FILTER_PNG);
rlm@1 1044 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
rlm@1 1045
rlm@1 1046 FileDlg dlg(this,
rlm@1 1047 filename,
rlm@1 1048 filter,
rlm@1 1049 theApp.captureFormat ? 2 : 1,
rlm@1 1050 theApp.captureFormat ? "BMP" : "PNG",
rlm@1 1051 exts,
rlm@1 1052 "",
rlm@1 1053 title,
rlm@1 1054 true);
rlm@1 1055
rlm@1 1056 if (dlg.DoModal() == IDCANCEL)
rlm@1 1057 {
rlm@1 1058 return;
rlm@1 1059 }
rlm@1 1060
rlm@1 1061 if (dlg.getFilterIndex() == 2)
rlm@1 1062 saveBMP(dlg.GetPathName());
rlm@1 1063 else
rlm@1 1064 savePNG(dlg.GetPathName());
rlm@1 1065 }
rlm@1 1066