rlm@1: // MapView.cpp : implementation file rlm@1: // rlm@1: rlm@1: #include "stdafx.h" rlm@1: #include "resource.h" rlm@1: #include "MapView.h" rlm@1: #include "FileDlg.h" rlm@1: #include "Reg.h" rlm@1: #include "WinResUtil.h" rlm@1: #include "VBA.h" rlm@1: rlm@1: #include "../gba/GBAGlobals.h" rlm@1: #include "../NLS.h" rlm@1: #include "../common/Util.h" rlm@1: rlm@1: extern "C" { rlm@1: #include rlm@1: } rlm@1: rlm@1: ///////////////////////////////////////////////////////////////////////////// rlm@1: // MapView dialog rlm@1: rlm@1: MapView::MapView(CWnd*pParent /*=NULL*/) rlm@1: : ResizeDlg(MapView::IDD, pParent) rlm@1: { rlm@1: //{{AFX_DATA_INIT(MapView) rlm@1: //}}AFX_DATA_INIT rlm@1: autoUpdate = false; rlm@1: rlm@1: memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader)); rlm@1: rlm@1: bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader); rlm@1: bmpInfo.bmiHeader.biWidth = 1024; rlm@1: bmpInfo.bmiHeader.biHeight = -1024; rlm@1: bmpInfo.bmiHeader.biPlanes = 1; rlm@1: bmpInfo.bmiHeader.biBitCount = 24; rlm@1: bmpInfo.bmiHeader.biCompression = BI_RGB; rlm@1: data = (u8 *)calloc(1, 3 * 1024 * 1024); rlm@1: rlm@1: mapView.setData(data); rlm@1: mapView.setBmpInfo(&bmpInfo); rlm@1: rlm@1: control = BG0CNT; rlm@1: rlm@1: bg = 0; rlm@1: frame = 0; rlm@1: } rlm@1: rlm@1: MapView::~MapView() rlm@1: { rlm@1: free(data); rlm@1: data = NULL; rlm@1: } rlm@1: rlm@1: void MapView::DoDataExchange(CDataExchange*pDX) rlm@1: { rlm@1: CDialog::DoDataExchange(pDX); rlm@1: //{{AFX_DATA_MAP(MapView) rlm@1: DDX_Control(pDX, IDC_NUMCOLORS, m_numcolors); rlm@1: DDX_Control(pDX, IDC_MODE, m_mode); rlm@1: DDX_Control(pDX, IDC_OVERFLOW, m_overflow); rlm@1: DDX_Control(pDX, IDC_MOSAIC, m_mosaic); rlm@1: DDX_Control(pDX, IDC_PRIORITY, m_priority); rlm@1: DDX_Control(pDX, IDC_DIM, m_dim); rlm@1: DDX_Control(pDX, IDC_CHARBASE, m_charbase); rlm@1: DDX_Control(pDX, IDC_MAPBASE, m_mapbase); rlm@1: //}}AFX_DATA_MAP rlm@1: DDX_Control(pDX, IDC_MAP_VIEW, mapView); rlm@1: DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, mapViewZoom); rlm@1: DDX_Control(pDX, IDC_COLOR, color); rlm@1: } rlm@1: rlm@1: BEGIN_MESSAGE_MAP(MapView, CDialog) rlm@1: //{{AFX_MSG_MAP(MapView) rlm@1: ON_BN_CLICKED(IDC_REFRESH, OnRefresh) rlm@1: ON_BN_CLICKED(IDC_FRAME_0, OnFrame0) rlm@1: ON_BN_CLICKED(IDC_FRAME_1, OnFrame1) rlm@1: ON_BN_CLICKED(IDC_BG0, OnBg0) rlm@1: ON_BN_CLICKED(IDC_BG1, OnBg1) rlm@1: ON_BN_CLICKED(IDC_BG2, OnBg2) rlm@1: ON_BN_CLICKED(IDC_BG3, OnBg3) rlm@1: ON_BN_CLICKED(IDC_STRETCH, OnStretch) rlm@1: ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate) rlm@1: ON_BN_CLICKED(IDC_CLOSE, OnClose) rlm@1: ON_BN_CLICKED(IDC_SAVE, OnSave) rlm@1: //}}AFX_MSG_MAP rlm@1: ON_MESSAGE(WM_MAPINFO, OnMapInfo) rlm@1: ON_MESSAGE(WM_COLINFO, OnColInfo) rlm@1: END_MESSAGE_MAP() rlm@1: rlm@1: ///////////////////////////////////////////////////////////////////////////// rlm@1: // MapView message handlers rlm@1: rlm@1: void MapView::renderTextScreen(u16 control) rlm@1: { rlm@1: u16 *palette = (u16 *)paletteRAM; rlm@1: u8 * charBase = &vram[((control >> 2) & 0x03) * 0x4000]; rlm@1: u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800]; rlm@1: u8 * bmp = data; rlm@1: rlm@1: int sizeX = 256; rlm@1: int sizeY = 256; rlm@1: switch ((control >> 14) & 3) rlm@1: { rlm@1: case 0: rlm@1: break; rlm@1: case 1: rlm@1: sizeX = 512; rlm@1: break; rlm@1: case 2: rlm@1: sizeY = 512; rlm@1: break; rlm@1: case 3: rlm@1: sizeX = 512; rlm@1: sizeY = 512; rlm@1: break; rlm@1: } rlm@1: rlm@1: w = sizeX; rlm@1: h = sizeY; rlm@1: rlm@1: if (control & 0x80) rlm@1: { rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: int yy = y & 255; rlm@1: rlm@1: if (y == 256 && sizeY > 256) rlm@1: { rlm@1: screenBase += 0x400; rlm@1: if (sizeX > 256) rlm@1: screenBase += 0x400; rlm@1: } rlm@1: u16 *screenSource = screenBase + ((yy>>3)*32); rlm@1: rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: u16 data = *screenSource; rlm@1: rlm@1: int tile = data & 0x3FF; rlm@1: int tileX = (x & 7); rlm@1: int tileY = y & 7; rlm@1: rlm@1: if (data & 0x0400) rlm@1: tileX = 7 - tileX; rlm@1: if (data & 0x0800) rlm@1: tileY = 7 - tileY; rlm@1: rlm@1: u8 c = charBase[tile * 64 + tileY * 8 + tileX]; rlm@1: rlm@1: u16 color = palette[c]; rlm@1: rlm@1: *bmp++ = ((color >> 10) & 0x1f) << 3; rlm@1: *bmp++ = ((color >> 5) & 0x1f) << 3; rlm@1: *bmp++ = (color & 0x1f) << 3; rlm@1: rlm@1: if (data & 0x0400) rlm@1: { rlm@1: if (tileX == 0) rlm@1: screenSource++; rlm@1: } rlm@1: else if (tileX == 7) rlm@1: screenSource++; rlm@1: if (x == 255 && sizeX > 256) rlm@1: { rlm@1: screenSource = screenBase + 0x400 + ((yy>>3)*32); rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: int yy = y & 255; rlm@1: rlm@1: if (y == 256 && sizeY > 256) rlm@1: { rlm@1: screenBase += 0x400; rlm@1: if (sizeX > 256) rlm@1: screenBase += 0x400; rlm@1: } rlm@1: u16 *screenSource = screenBase + ((yy>>3)*32); rlm@1: rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: u16 data = *screenSource; rlm@1: rlm@1: int tile = data & 0x3FF; rlm@1: int tileX = (x & 7); rlm@1: int tileY = y & 7; rlm@1: rlm@1: if (data & 0x0400) rlm@1: tileX = 7 - tileX; rlm@1: if (data & 0x0800) rlm@1: tileY = 7 - tileY; rlm@1: rlm@1: u8 color = charBase[tile * 32 + tileY * 4 + (tileX>>1)]; rlm@1: rlm@1: if (tileX & 1) rlm@1: { rlm@1: color = (color >> 4); rlm@1: } rlm@1: else rlm@1: { rlm@1: color &= 0x0F; rlm@1: } rlm@1: rlm@1: int pal = (*screenSource>>8) & 0xF0; rlm@1: u16 color2 = palette[pal + color]; rlm@1: rlm@1: *bmp++ = ((color2 >> 10) & 0x1f) << 3; rlm@1: *bmp++ = ((color2 >> 5) & 0x1f) << 3; rlm@1: *bmp++ = (color2 & 0x1f) << 3; rlm@1: rlm@1: if (data & 0x0400) rlm@1: { rlm@1: if (tileX == 0) rlm@1: screenSource++; rlm@1: } rlm@1: else if (tileX == 7) rlm@1: screenSource++; rlm@1: rlm@1: if (x == 255 && sizeX > 256) rlm@1: { rlm@1: screenSource = screenBase + 0x400 + ((yy>>3)*32); rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: /* rlm@1: switch(bg) { rlm@1: case 0: rlm@1: renderView(BG0HOFS<<8, BG0VOFS<<8, rlm@1: 0x100, 0x000, rlm@1: 0x000, 0x100, rlm@1: (sizeX -1) <<8, rlm@1: (sizeY -1) << 8, rlm@1: true); rlm@1: break; rlm@1: case 1: rlm@1: renderView(BG1HOFS<<8, BG1VOFS<<8, rlm@1: 0x100, 0x000, rlm@1: 0x000, 0x100, rlm@1: (sizeX -1) <<8, rlm@1: (sizeY -1) << 8, rlm@1: true); rlm@1: break; rlm@1: case 2: rlm@1: renderView(BG2HOFS<<8, BG2VOFS<<8, rlm@1: 0x100, 0x000, rlm@1: 0x000, 0x100, rlm@1: (sizeX -1) <<8, rlm@1: (sizeY -1) << 8, rlm@1: true); rlm@1: break; rlm@1: case 3: rlm@1: renderView(BG3HOFS<<8, BG3VOFS<<8, rlm@1: 0x100, 0x000, rlm@1: 0x000, 0x100, rlm@1: (sizeX -1) <<8, rlm@1: (sizeY -1) << 8, rlm@1: true); rlm@1: break; rlm@1: } rlm@1: */ rlm@1: } rlm@1: rlm@1: void MapView::renderRotScreen(u16 control) rlm@1: { rlm@1: u16 *palette = (u16 *)paletteRAM; rlm@1: u8 * charBase = &vram[((control >> 2) & 0x03) * 0x4000]; rlm@1: u8 * screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800]; rlm@1: u8 * bmp = data; rlm@1: rlm@1: int sizeX = 128; rlm@1: int sizeY = 128; rlm@1: switch ((control >> 14) & 3) rlm@1: { rlm@1: case 0: rlm@1: break; rlm@1: case 1: rlm@1: sizeX = sizeY = 256; rlm@1: break; rlm@1: case 2: rlm@1: sizeX = sizeY = 512; rlm@1: break; rlm@1: case 3: rlm@1: sizeX = sizeY = 1024; rlm@1: break; rlm@1: } rlm@1: rlm@1: w = sizeX; rlm@1: h = sizeY; rlm@1: rlm@1: if (control & 0x80) rlm@1: { rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: int tile = screenBase[(x>>3) + (y>>3)*(w>>3)]; rlm@1: rlm@1: int tileX = (x & 7); rlm@1: int tileY = y & 7; rlm@1: rlm@1: u8 color = charBase[tile * 64 + tileY * 8 + tileX]; rlm@1: u16 color2 = palette[color]; rlm@1: rlm@1: *bmp++ = ((color2 >> 10) & 0x1f) << 3; rlm@1: *bmp++ = ((color2 >> 5) & 0x1f) << 3; rlm@1: *bmp++ = (color2 & 0x1f) << 3; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: int tile = screenBase[(x>>3) + (y>>3)*(w>>3)]; rlm@1: rlm@1: int tileX = (x & 7); rlm@1: int tileY = y & 7; rlm@1: rlm@1: u8 color = charBase[tile * 64 + tileY * 8 + tileX]; rlm@1: u16 color2 = palette[color]; rlm@1: rlm@1: *bmp++ = ((color2 >> 10) & 0x1f) << 3; rlm@1: *bmp++ = ((color2 >> 5) & 0x1f) << 3; rlm@1: *bmp++ = (color2 & 0x1f) << 3; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: u32 xx; rlm@1: u32 yy; rlm@1: rlm@1: switch (bg) rlm@1: { rlm@1: case 2: rlm@1: xx = BG2X_L | BG2X_H << 16; rlm@1: yy = BG2Y_L | BG2Y_H << 16; rlm@1: rlm@1: /* rlm@1: renderView(xx, yy, rlm@1: BG2PA, BG2PC, rlm@1: BG2PB, BG2PD, rlm@1: (sizeX -1) <<8, rlm@1: (sizeY -1) << 8, rlm@1: (control & 0x2000) != 0); rlm@1: */ rlm@1: break; rlm@1: case 3: rlm@1: xx = BG3X_L | BG3X_H << 16; rlm@1: yy = BG3Y_L | BG3Y_H << 16; rlm@1: /* rlm@1: renderView(xx, yy, rlm@1: BG3PA, BG3PC, rlm@1: BG3PB, BG3PD, rlm@1: (sizeX -1) <<8, rlm@1: (sizeY -1) << 8, rlm@1: (control & 0x2000) != 0); rlm@1: */ rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: void MapView::renderMode0() rlm@1: { rlm@1: renderTextScreen(control); rlm@1: } rlm@1: rlm@1: void MapView::renderMode1() rlm@1: { rlm@1: switch (bg) rlm@1: { rlm@1: case 0: rlm@1: case 1: rlm@1: renderTextScreen(control); rlm@1: break; rlm@1: case 2: rlm@1: renderRotScreen(control); rlm@1: break; rlm@1: default: rlm@1: bg = 0; rlm@1: control = BG0CNT; rlm@1: renderTextScreen(control); rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: void MapView::renderMode2() rlm@1: { rlm@1: switch (bg) rlm@1: { rlm@1: case 2: rlm@1: case 3: rlm@1: renderRotScreen(control); rlm@1: break; rlm@1: default: rlm@1: bg = 2; rlm@1: control = BG2CNT; rlm@1: renderRotScreen(control); rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: void MapView::renderMode3() rlm@1: { rlm@1: u8 * bmp = data; rlm@1: u16 *src = (u16 *)&vram[0]; rlm@1: rlm@1: w = 240; rlm@1: h = 160; rlm@1: rlm@1: for (int y = 0; y < 160; y++) rlm@1: { rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: u16 data = *src++; rlm@1: *bmp++ = ((data >> 10) & 0x1f) << 3; rlm@1: *bmp++ = ((data >> 5) & 0x1f) << 3; rlm@1: *bmp++ = (data & 0x1f) << 3; rlm@1: } rlm@1: } rlm@1: bg = 2; rlm@1: } rlm@1: rlm@1: void MapView::renderMode4() rlm@1: { rlm@1: u8 * bmp = data; rlm@1: u8 * src = frame ? &vram[0xa000] : &vram[0]; rlm@1: u16 *pal = (u16 *)&paletteRAM[0]; rlm@1: rlm@1: w = 240; rlm@1: h = 160; rlm@1: rlm@1: for (int y = 0; y < 160; y++) rlm@1: { rlm@1: for (int x = 0; x < 240; x++) rlm@1: { rlm@1: u8 c = *src++; rlm@1: u16 data = pal[c]; rlm@1: *bmp++ = ((data >> 10) & 0x1f) << 3; rlm@1: *bmp++ = ((data >> 5) & 0x1f) << 3; rlm@1: *bmp++ = (data & 0x1f) << 3; rlm@1: } rlm@1: } rlm@1: bg = 2; rlm@1: } rlm@1: rlm@1: void MapView::renderMode5() rlm@1: { rlm@1: u8 * bmp = data; rlm@1: u16 *src = (u16 *)(frame ? &vram[0xa000] : &vram[0]); rlm@1: rlm@1: w = 160; rlm@1: h = 128; rlm@1: rlm@1: for (int y = 0; y < 128; y++) rlm@1: { rlm@1: for (int x = 0; x < 160; x++) rlm@1: { rlm@1: u16 data = *src++; rlm@1: *bmp++ = ((data >> 10) & 0x1f) << 3; rlm@1: *bmp++ = ((data >> 5) & 0x1f) << 3; rlm@1: *bmp++ = (data & 0x1f) << 3; rlm@1: } rlm@1: } rlm@1: bg = 2; rlm@1: } rlm@1: rlm@1: void MapView::OnRefresh() rlm@1: { rlm@1: paint(); rlm@1: } rlm@1: rlm@1: void MapView::paint() rlm@1: { rlm@1: if (vram == NULL) rlm@1: return; rlm@1: int mode = DISPCNT & 7; rlm@1: rlm@1: switch (bg) rlm@1: { rlm@1: default: rlm@1: case 0: rlm@1: control = BG0CNT; rlm@1: break; rlm@1: case 1: rlm@1: control = BG1CNT; rlm@1: break; rlm@1: case 2: rlm@1: control = BG2CNT; rlm@1: break; rlm@1: case 3: rlm@1: control = BG3CNT; rlm@1: break; rlm@1: } rlm@1: rlm@1: switch (mode) rlm@1: { rlm@1: case 0: rlm@1: renderMode0(); rlm@1: break; rlm@1: case 1: rlm@1: renderMode1(); rlm@1: break; rlm@1: case 2: rlm@1: renderMode2(); rlm@1: break; rlm@1: case 3: rlm@1: renderMode3(); rlm@1: break; rlm@1: case 4: rlm@1: renderMode4(); rlm@1: break; rlm@1: case 5: rlm@1: renderMode5(); rlm@1: break; rlm@1: } rlm@1: enableButtons(mode); rlm@1: SIZE s; rlm@1: rlm@1: if (mapView.getStretch()) rlm@1: { rlm@1: mapView.setSize(w, h); rlm@1: s.cx = s.cy = 1; rlm@1: mapView.SetScrollSizes(MM_TEXT, s); rlm@1: } rlm@1: else rlm@1: { rlm@1: mapView.setSize(w, h); rlm@1: s.cx = w; rlm@1: s.cy = h; rlm@1: mapView.SetScrollSizes(MM_TEXT, s); rlm@1: } rlm@1: rlm@1: mapView.refresh(); rlm@1: rlm@1: CString buffer; rlm@1: rlm@1: u32 charBase = ((control >> 2) & 0x03) * 0x4000 + 0x6000000; rlm@1: u32 screenBase = ((control >> 8) & 0x1f) * 0x800 + 0x6000000; rlm@1: rlm@1: buffer.Format("%d", mode); rlm@1: m_mode.SetWindowText(buffer); rlm@1: rlm@1: if (mode >= 3) rlm@1: { rlm@1: m_mapbase.SetWindowText(""); rlm@1: m_charbase.SetWindowText(""); rlm@1: } rlm@1: else rlm@1: { rlm@1: buffer.Format("0x%08X", screenBase); rlm@1: m_mapbase.SetWindowText(buffer); rlm@1: rlm@1: buffer.Format("0x%08X", charBase); rlm@1: m_charbase.SetWindowText(buffer); rlm@1: } rlm@1: rlm@1: buffer.Format("%dx%d", w, h); rlm@1: m_dim.SetWindowText(buffer); rlm@1: rlm@1: m_numcolors.SetWindowText(control & 0x80 ? "256" : "16"); rlm@1: rlm@1: buffer.Format("%d", control & 3); rlm@1: m_priority.SetWindowText(buffer); rlm@1: rlm@1: m_mosaic.SetWindowText(control & 0x40 ? "1" : "0"); rlm@1: rlm@1: m_overflow.SetWindowText(bg <= 1 ? "" : rlm@1: control & 0x2000 ? "1" : "0"); rlm@1: } rlm@1: rlm@1: BOOL MapView::OnInitDialog() rlm@1: { rlm@1: CDialog::OnInitDialog(); rlm@1: rlm@1: DIALOG_SIZER_START(sz) rlm@1: DIALOG_SIZER_ENTRY(IDC_MAP_VIEW, DS_SizeX | DS_SizeY) rlm@1: DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY) rlm@1: DIALOG_SIZER_END() rlm@1: SetData(sz, rlm@1: TRUE, rlm@1: HKEY_CURRENT_USER, rlm@1: "Software\\Emulators\\VisualBoyAdvance\\Viewer\\MapView", rlm@1: NULL); rlm@1: rlm@1: SIZE size; rlm@1: size.cx = 1; rlm@1: size.cy = 1; rlm@1: mapView.SetScrollSizes(MM_TEXT, size); rlm@1: int s = regQueryDwordValue("mapViewStretch", 0); rlm@1: if (s) rlm@1: mapView.setStretch(true); rlm@1: ((CButton *)GetDlgItem(IDC_STRETCH))->SetCheck(s); rlm@1: paint(); rlm@1: rlm@1: return TRUE; // return TRUE unless you set the focus to a control rlm@1: // EXCEPTION: OCX Property Pages should return FALSE rlm@1: } rlm@1: rlm@1: void MapView::PostNcDestroy() rlm@1: { rlm@1: delete this; rlm@1: } rlm@1: rlm@1: void MapView::enableButtons(int mode) rlm@1: { rlm@1: bool enable[6] = { true, true, true, true, true, true }; rlm@1: rlm@1: switch (mode) rlm@1: { rlm@1: case 0: rlm@1: enable[4] = false; rlm@1: enable[5] = false; rlm@1: break; rlm@1: case 1: rlm@1: enable[3] = false; rlm@1: enable[4] = false; rlm@1: enable[5] = false; rlm@1: break; rlm@1: case 2: rlm@1: enable[0] = false; rlm@1: enable[1] = false; rlm@1: enable[4] = false; rlm@1: enable[5] = false; rlm@1: break; rlm@1: case 3: rlm@1: enable[0] = false; rlm@1: enable[1] = false; rlm@1: enable[2] = false; rlm@1: enable[3] = false; rlm@1: enable[4] = false; rlm@1: enable[5] = false; rlm@1: break; rlm@1: case 4: rlm@1: enable[0] = false; rlm@1: enable[1] = false; rlm@1: enable[2] = false; rlm@1: enable[3] = false; rlm@1: break; rlm@1: case 5: rlm@1: enable[0] = false; rlm@1: enable[1] = false; rlm@1: enable[2] = false; rlm@1: enable[3] = false; rlm@1: break; rlm@1: } rlm@1: GetDlgItem(IDC_BG0)->EnableWindow(enable[0]); rlm@1: GetDlgItem(IDC_BG1)->EnableWindow(enable[1]); rlm@1: GetDlgItem(IDC_BG2)->EnableWindow(enable[2]); rlm@1: GetDlgItem(IDC_BG3)->EnableWindow(enable[3]); rlm@1: GetDlgItem(IDC_FRAME_0)->EnableWindow(enable[4]); rlm@1: GetDlgItem(IDC_FRAME_1)->EnableWindow(enable[5]); rlm@1: int id = IDC_BG0; rlm@1: switch (bg) rlm@1: { rlm@1: case 1: rlm@1: id = IDC_BG1; rlm@1: break; rlm@1: case 2: rlm@1: id = IDC_BG2; rlm@1: break; rlm@1: case 3: rlm@1: id = IDC_BG3; rlm@1: break; rlm@1: } rlm@1: CheckRadioButton(IDC_BG0, IDC_BG3, id); rlm@1: id = IDC_FRAME_0; rlm@1: if (frame != 0) rlm@1: id = IDC_FRAME_1; rlm@1: CheckRadioButton(IDC_FRAME_0, IDC_FRAME_1, id); rlm@1: } rlm@1: rlm@1: void MapView::OnFrame0() rlm@1: { rlm@1: frame = 0; rlm@1: paint(); rlm@1: } rlm@1: rlm@1: void MapView::OnFrame1() rlm@1: { rlm@1: frame = 1; rlm@1: paint(); rlm@1: } rlm@1: rlm@1: void MapView::OnBg0() rlm@1: { rlm@1: bg = 0; rlm@1: control = BG0CNT; rlm@1: paint(); rlm@1: } rlm@1: rlm@1: void MapView::OnBg1() rlm@1: { rlm@1: bg = 1; rlm@1: control = BG1CNT; rlm@1: paint(); rlm@1: } rlm@1: rlm@1: void MapView::OnBg2() rlm@1: { rlm@1: bg = 2; rlm@1: control = BG2CNT; rlm@1: paint(); rlm@1: } rlm@1: rlm@1: void MapView::OnBg3() rlm@1: { rlm@1: bg = 3; rlm@1: control = BG3CNT; rlm@1: paint(); rlm@1: } rlm@1: rlm@1: void MapView::OnStretch() rlm@1: { rlm@1: mapView.setStretch(!mapView.getStretch()); rlm@1: paint(); rlm@1: regSetDwordValue("mapViewStretch", mapView.getStretch()); rlm@1: } rlm@1: rlm@1: void MapView::OnAutoUpdate() rlm@1: { rlm@1: autoUpdate = !autoUpdate; rlm@1: if (autoUpdate) rlm@1: { rlm@1: theApp.winAddUpdateListener(this); rlm@1: } rlm@1: else rlm@1: { rlm@1: theApp.winRemoveUpdateListener(this); rlm@1: } rlm@1: } rlm@1: rlm@1: void MapView::update() rlm@1: { rlm@1: paint(); rlm@1: } rlm@1: rlm@1: void MapView::OnClose() rlm@1: { rlm@1: theApp.winRemoveUpdateListener(this); rlm@1: rlm@1: DestroyWindow(); rlm@1: } rlm@1: rlm@1: u32 MapView::GetTextClickAddress(u32 base, int x, int y) rlm@1: { rlm@1: if (y > 255 && h > 256) rlm@1: { rlm@1: base += 0x800; rlm@1: if (w > 256) rlm@1: base += 0x800; rlm@1: } rlm@1: if (x >= 256) rlm@1: base += 0x800; rlm@1: x &= 255; rlm@1: y &= 255; rlm@1: base += (x>>3)*2 + 64*(y>>3); rlm@1: rlm@1: return base; rlm@1: } rlm@1: rlm@1: u32 MapView::GetClickAddress(int x, int y) rlm@1: { rlm@1: int mode = DISPCNT & 7; rlm@1: rlm@1: u32 base = ((control >> 8) & 0x1f) * 0x800 + 0x6000000; rlm@1: rlm@1: // all text bgs (16 bits) rlm@1: if (mode == 0 || (mode < 3 && bg < 2)) rlm@1: { rlm@1: return GetTextClickAddress(base, x, y); rlm@1: } rlm@1: // rot bgs (8 bits) rlm@1: if (mode < 3) rlm@1: { rlm@1: return base + (x>>3) + (w>>3)*(y>>3); rlm@1: } rlm@1: // mode 3/5 (16 bits) rlm@1: if (mode != 4) rlm@1: { rlm@1: return 0x6000000 + 0xa000*frame + 2*x + w*y*2; rlm@1: } rlm@1: // mode 4 (8 bits) rlm@1: return 0x6000000 + 0xa000*frame + x + w*y; rlm@1: } rlm@1: rlm@1: LRESULT MapView::OnMapInfo(WPARAM wParam, LPARAM lParam) rlm@1: { rlm@1: u8 *colors = (u8 *)lParam; rlm@1: mapViewZoom.setColors(colors); rlm@1: rlm@1: int x = wParam & 0xffff; rlm@1: int y = (wParam >> 16); rlm@1: rlm@1: CString buffer; rlm@1: buffer.Format("(%d,%d)", x, y); rlm@1: GetDlgItem(IDC_XY)->SetWindowText(buffer); rlm@1: rlm@1: u32 address = GetClickAddress(x, y); rlm@1: buffer.Format("0x%08X", address); rlm@1: GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer); rlm@1: rlm@1: int mode = DISPCNT & 7; rlm@1: if (mode >= 3) rlm@1: { rlm@1: // bitmap modes rlm@1: GetDlgItem(IDC_TILE_NUM)->SetWindowText("---"); rlm@1: GetDlgItem(IDC_FLIP)->SetWindowText("--"); rlm@1: GetDlgItem(IDC_PALETTE_NUM)->SetWindowText("---"); rlm@1: } rlm@1: else if (mode == 0 || bg < 2) rlm@1: { rlm@1: // text bgs rlm@1: u16 value = *((u16 *)&vram[address - 0x6000000]); rlm@1: rlm@1: int tile = value & 1023; rlm@1: buffer.Format("%d", tile); rlm@1: GetDlgItem(IDC_TILE_NUM)->SetWindowText(buffer); rlm@1: buffer.Empty(); rlm@1: buffer += value & 1024 ? 'H' : '-'; rlm@1: buffer += value & 2048 ? 'V' : '-'; rlm@1: GetDlgItem(IDC_FLIP)->SetWindowText(buffer); rlm@1: rlm@1: if (!(control & 0x80)) rlm@1: { rlm@1: buffer.Format("%d", (value >> 12) & 15); rlm@1: } rlm@1: else rlm@1: buffer = "---"; rlm@1: GetDlgItem(IDC_PALETTE_NUM)->SetWindowText(buffer); rlm@1: } rlm@1: else rlm@1: { rlm@1: // rot bgs rlm@1: GetDlgItem(IDC_TILE_NUM)->SetWindowText("---"); rlm@1: GetDlgItem(IDC_FLIP)->SetWindowText("--"); rlm@1: GetDlgItem(IDC_PALETTE_NUM)->SetWindowText("---"); rlm@1: } rlm@1: rlm@1: return TRUE; rlm@1: } rlm@1: rlm@1: LRESULT MapView::OnColInfo(WPARAM wParam, LPARAM lParam) rlm@1: { rlm@1: u16 c = (u16)wParam; rlm@1: rlm@1: color.setColor(c); rlm@1: rlm@1: int r = (c & 0x1f); rlm@1: int g = (c & 0x3e0) >> 5; rlm@1: int b = (c & 0x7c00) >> 10; rlm@1: rlm@1: CString buffer; rlm@1: buffer.Format("R: %d", r); rlm@1: GetDlgItem(IDC_R)->SetWindowText(buffer); rlm@1: rlm@1: buffer.Format("G: %d", g); rlm@1: GetDlgItem(IDC_G)->SetWindowText(buffer); rlm@1: rlm@1: buffer.Format("B: %d", b); rlm@1: GetDlgItem(IDC_B)->SetWindowText(buffer); rlm@1: rlm@1: return TRUE; rlm@1: } rlm@1: rlm@1: void MapView::saveBMP(const char *name) rlm@1: { rlm@1: u8 writeBuffer[1024 * 3]; rlm@1: rlm@1: FILE *fp = fopen(name, "wb"); rlm@1: rlm@1: if (!fp) rlm@1: { rlm@1: systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); rlm@1: return; rlm@1: } rlm@1: rlm@1: struct rlm@1: { rlm@1: u8 ident[2]; rlm@1: u8 filesize[4]; rlm@1: u8 reserved[4]; rlm@1: u8 dataoffset[4]; rlm@1: u8 headersize[4]; rlm@1: u8 width[4]; rlm@1: u8 height[4]; rlm@1: u8 planes[2]; rlm@1: u8 bitsperpixel[2]; rlm@1: u8 compression[4]; rlm@1: u8 datasize[4]; rlm@1: u8 hres[4]; rlm@1: u8 vres[4]; rlm@1: u8 colors[4]; rlm@1: u8 importantcolors[4]; rlm@1: u8 pad[2]; rlm@1: } bmpheader; rlm@1: memset(&bmpheader, 0, sizeof(bmpheader)); rlm@1: rlm@1: bmpheader.ident[0] = 'B'; rlm@1: bmpheader.ident[1] = 'M'; rlm@1: rlm@1: u32 fsz = sizeof(bmpheader) + w*h*3; rlm@1: utilPutDword(bmpheader.filesize, fsz); rlm@1: utilPutDword(bmpheader.dataoffset, 0x38); rlm@1: utilPutDword(bmpheader.headersize, 0x28); rlm@1: utilPutDword(bmpheader.width, w); rlm@1: utilPutDword(bmpheader.height, h); rlm@1: utilPutDword(bmpheader.planes, 1); rlm@1: utilPutDword(bmpheader.bitsperpixel, 24); rlm@1: utilPutDword(bmpheader.datasize, 3*w*h); rlm@1: rlm@1: fwrite(&bmpheader, 1, sizeof(bmpheader), fp); rlm@1: rlm@1: u8 *b = writeBuffer; rlm@1: rlm@1: int sizeX = w; rlm@1: int sizeY = h; rlm@1: rlm@1: u8 *pixU8 = (u8 *)data+3*w*(h-1); rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: *b++ = *pixU8++; // B rlm@1: *b++ = *pixU8++; // G rlm@1: *b++ = *pixU8++; // R rlm@1: } rlm@1: pixU8 -= 2*3*w; rlm@1: fwrite(writeBuffer, 1, 3*w, fp); rlm@1: rlm@1: b = writeBuffer; rlm@1: } rlm@1: rlm@1: fclose(fp); rlm@1: } rlm@1: rlm@1: void MapView::savePNG(const char *name) rlm@1: { rlm@1: u8 writeBuffer[1024 * 3]; rlm@1: rlm@1: FILE *fp = fopen(name, "wb"); rlm@1: rlm@1: if (!fp) rlm@1: { rlm@1: systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); rlm@1: return; rlm@1: } rlm@1: rlm@1: png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL); rlm@1: if (!png_ptr) rlm@1: { rlm@1: fclose(fp); rlm@1: return; rlm@1: } rlm@1: rlm@1: png_infop info_ptr = png_create_info_struct(png_ptr); rlm@1: rlm@1: if (!info_ptr) rlm@1: { rlm@1: png_destroy_write_struct(&png_ptr, NULL); rlm@1: fclose(fp); rlm@1: return; rlm@1: } rlm@1: rlm@1: if (setjmp(png_ptr->jmpbuf)) rlm@1: { rlm@1: png_destroy_write_struct(&png_ptr, NULL); rlm@1: fclose(fp); rlm@1: return; rlm@1: } rlm@1: rlm@1: png_init_io(png_ptr, fp); rlm@1: rlm@1: png_set_IHDR(png_ptr, rlm@1: info_ptr, rlm@1: w, rlm@1: h, rlm@1: 8, rlm@1: PNG_COLOR_TYPE_RGB, rlm@1: PNG_INTERLACE_NONE, rlm@1: PNG_COMPRESSION_TYPE_DEFAULT, rlm@1: PNG_FILTER_TYPE_DEFAULT); rlm@1: rlm@1: png_write_info(png_ptr, info_ptr); rlm@1: rlm@1: u8 *b = writeBuffer; rlm@1: rlm@1: int sizeX = w; rlm@1: int sizeY = h; rlm@1: rlm@1: u8 *pixU8 = (u8 *)data; rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: int blue = *pixU8++; rlm@1: int green = *pixU8++; rlm@1: int red = *pixU8++; rlm@1: rlm@1: *b++ = red; rlm@1: *b++ = green; rlm@1: *b++ = blue; rlm@1: } rlm@1: png_write_row(png_ptr, writeBuffer); rlm@1: rlm@1: b = writeBuffer; rlm@1: } rlm@1: rlm@1: png_write_end(png_ptr, info_ptr); rlm@1: rlm@1: png_destroy_write_struct(&png_ptr, &info_ptr); rlm@1: rlm@1: fclose(fp); rlm@1: } rlm@1: rlm@1: void MapView::OnSave() rlm@1: { rlm@1: CString filename; rlm@1: rlm@1: if (theApp.captureFormat == 0) rlm@1: filename = "map.png"; rlm@1: else rlm@1: filename = "map.bmp"; rlm@1: rlm@1: LPCTSTR exts[] = {".png", ".bmp", NULL }; rlm@1: rlm@1: CString filter = winResLoadFilter(IDS_FILTER_PNG); rlm@1: CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); rlm@1: rlm@1: FileDlg dlg(this, rlm@1: filename, rlm@1: filter, rlm@1: theApp.captureFormat ? 2 : 1, rlm@1: theApp.captureFormat ? "BMP" : "PNG", rlm@1: exts, rlm@1: "", rlm@1: title, rlm@1: true); rlm@1: rlm@1: if (dlg.DoModal() == IDCANCEL) rlm@1: { rlm@1: return; rlm@1: } rlm@1: rlm@1: if (dlg.getFilterIndex() == 2) rlm@1: saveBMP(dlg.GetPathName()); rlm@1: else rlm@1: savePNG(dlg.GetPathName()); rlm@1: } rlm@1: