Mercurial > vba-linux
view src/win32/GBOamView.cpp @ 2:3549bbe597ed
adding makefile.am
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:47 -0600 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 // GBOamView.cpp : implementation file2 //4 #include "stdafx.h"5 #include "resource.h"6 #include "GBOamView.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 // GBOamView dialog24 GBOamView::GBOamView(CWnd*pParent /*=NULL*/)25 : ResizeDlg(GBOamView::IDD, pParent)26 {27 //{{AFX_DATA_INIT(GBOamView)28 m_stretch = FALSE;29 //}}AFX_DATA_INIT30 autoUpdate = false;32 memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader));34 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);35 bmpInfo.bmiHeader.biWidth = 8;36 bmpInfo.bmiHeader.biHeight = 16;37 bmpInfo.bmiHeader.biPlanes = 1;38 bmpInfo.bmiHeader.biBitCount = 24;39 bmpInfo.bmiHeader.biCompression = BI_RGB;40 data = (u8 *)calloc(1, 3 * 8 * 16);42 oamView.setData(data);43 oamView.setBmpInfo(&bmpInfo);45 number = 0;46 }48 void GBOamView::DoDataExchange(CDataExchange*pDX)49 {50 CDialog::DoDataExchange(pDX);51 //{{AFX_DATA_MAP(GBOamView)52 DDX_Control(pDX, IDC_SPRITE, m_sprite);53 DDX_Check(pDX, IDC_STRETCH, m_stretch);54 //}}AFX_DATA_MAP55 DDX_Control(pDX, IDC_COLOR, color);56 DDX_Control(pDX, IDC_OAM_VIEW, oamView);57 DDX_Control(pDX, IDC_OAM_VIEW_ZOOM, oamZoom);58 }60 BEGIN_MESSAGE_MAP(GBOamView, CDialog)61 //{{AFX_MSG_MAP(GBOamView)62 ON_BN_CLICKED(IDC_STRETCH, OnStretch)63 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)64 ON_EN_CHANGE(IDC_SPRITE, OnChangeSprite)65 ON_BN_CLICKED(IDC_CLOSE, OnClose)66 ON_WM_HSCROLL()67 //}}AFX_MSG_MAP68 ON_MESSAGE(WM_MAPINFO, OnMapInfo)69 ON_MESSAGE(WM_COLINFO, OnColInfo)70 END_MESSAGE_MAP()72 /////////////////////////////////////////////////////////////////////////////73 // GBOamView message handlers75 GBOamView::~GBOamView()76 {77 free(data);78 data = NULL;79 }81 void GBOamView::paint()82 {83 if (gbRom == NULL)84 return;86 render();87 oamView.setSize(w, h);88 oamView.refresh();89 }91 void GBOamView::update()92 {93 paint();94 }96 void GBOamView::setAttributes(int y, int x, int tile, int flags)97 {98 CString buffer;100 int flipH = flags & 0x20;101 int flipV = flags & 0x40;102 int prio = (flags & 0x80) >> 7;103 int pal = flags & 0x7;104 int oap = (flags & 0x08) >> 3;105 int bank = (flags & 0x10) >> 4;107 buffer.Format("%d,%d", x, y);108 GetDlgItem(IDC_POS)->SetWindowText(buffer);110 buffer.Format("%d", pal);111 GetDlgItem(IDC_PALETTE)->SetWindowText(buffer);113 buffer.Format("%d", tile);114 GetDlgItem(IDC_TILE)->SetWindowText(buffer);116 buffer.Format("%d", prio);117 GetDlgItem(IDC_PRIO)->SetWindowText(buffer);119 buffer.Format("%d", bank);120 GetDlgItem(IDC_BANK)->SetWindowText(buffer);122 buffer.Empty();123 if (flipH)124 buffer += 'H';125 else126 buffer += ' ';127 if (flipV)128 buffer += 'V';129 else130 buffer += ' ';131 GetDlgItem(IDC_FLAGS)->SetWindowText(buffer);133 buffer.Format("%d", oap);134 GetDlgItem(IDC_OAP)->SetWindowText(buffer);135 }137 void GBOamView::render()138 {139 int m = 0;140 if (gbRom == NULL)141 return;143 u16 addr = number * 4 + 0xfe00;145 int size = register_LCDC & 4;147 u8 y = gbReadMemoryQuick(addr++);148 u8 x = gbReadMemoryQuick(addr++);149 u8 tile = gbReadMemoryQuick(addr++);150 if (size)151 tile &= 254;152 u8 flags = gbReadMemoryQuick(addr++);154 u8 *bmp = data;156 w = 8;157 h = size ? 16 : 8;159 setAttributes(y, x, tile, flags);161 u8 *bank0;162 u8 *bank1;163 if (gbCgbMode)164 {165 if (register_VBK & 1)166 {167 bank0 = &gbVram[0x0000];168 bank1 = &gbVram[0x2000];169 }170 else171 {172 bank0 = &gbVram[0x0000];173 bank1 = &gbVram[0x2000];174 }175 }176 else177 {178 bank0 = &gbMemory[0x8000];179 bank1 = NULL;180 }182 int init = 0x0000;184 u8 *pal = gbObp0;186 if ((flags & 0x10))187 pal = gbObp1;189 for (int yy = 0; yy < h; yy++)190 {191 int address = init + tile * 16 + 2*yy;192 int a = 0;193 int b = 0;195 if (gbCgbMode && flags & 0x08)196 {197 a = bank1[address++];198 b = bank1[address++];199 }200 else201 {202 a = bank0[address++];203 b = bank0[address++];204 }206 for (int xx = 0; xx < 8; xx++)207 {208 u8 mask = 1 << (7-xx);209 u8 c = 0;210 if ((a & mask))211 c++;212 if ((b & mask))213 c += 2;215 // make sure that sprites will work even in CGB mode216 if (gbCgbMode)217 {218 c = c + (flags & 0x07)*4 + 32;219 }220 else221 {222 c = pal[c];223 }225 u16 color = gbPalette[c];226 *bmp++ = ((color >> 10) & 0x1f) << 3;227 *bmp++ = ((color >> 5) & 0x1f) << 3;228 *bmp++ = (color & 0x1f) << 3;229 }230 }231 }233 void GBOamView::saveBMP(const char *name)234 {235 u8 writeBuffer[1024 * 3];237 FILE *fp = fopen(name, "wb");239 if (!fp)240 {241 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);242 return;243 }245 struct246 {247 u8 ident[2];248 u8 filesize[4];249 u8 reserved[4];250 u8 dataoffset[4];251 u8 headersize[4];252 u8 width[4];253 u8 height[4];254 u8 planes[2];255 u8 bitsperpixel[2];256 u8 compression[4];257 u8 datasize[4];258 u8 hres[4];259 u8 vres[4];260 u8 colors[4];261 u8 importantcolors[4];262 u8 pad[2];263 } bmpheader;264 memset(&bmpheader, 0, sizeof(bmpheader));266 bmpheader.ident[0] = 'B';267 bmpheader.ident[1] = 'M';269 u32 fsz = sizeof(bmpheader) + w*h*3;270 utilPutDword(bmpheader.filesize, fsz);271 utilPutDword(bmpheader.dataoffset, 0x38);272 utilPutDword(bmpheader.headersize, 0x28);273 utilPutDword(bmpheader.width, w);274 utilPutDword(bmpheader.height, h);275 utilPutDword(bmpheader.planes, 1);276 utilPutDword(bmpheader.bitsperpixel, 24);277 utilPutDword(bmpheader.datasize, 3*w*h);279 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);281 u8 *b = writeBuffer;283 int sizeX = w;284 int sizeY = h;286 u8 *pixU8 = (u8 *)data+3*w*(h-1);287 for (int y = 0; y < sizeY; y++)288 {289 for (int x = 0; x < sizeX; x++)290 {291 *b++ = *pixU8++; // B292 *b++ = *pixU8++; // G293 *b++ = *pixU8++; // R294 }295 pixU8 -= 2*3*w;296 fwrite(writeBuffer, 1, 3*w, fp);298 b = writeBuffer;299 }301 fclose(fp);302 }304 void GBOamView::savePNG(const char *name)305 {306 u8 writeBuffer[1024 * 3];308 FILE *fp = fopen(name, "wb");310 if (!fp)311 {312 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);313 return;314 }316 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,317 NULL,318 NULL,319 NULL);320 if (!png_ptr)321 {322 fclose(fp);323 return;324 }326 png_infop info_ptr = png_create_info_struct(png_ptr);328 if (!info_ptr)329 {330 png_destroy_write_struct(&png_ptr, NULL);331 fclose(fp);332 return;333 }335 if (setjmp(png_ptr->jmpbuf))336 {337 png_destroy_write_struct(&png_ptr, NULL);338 fclose(fp);339 return;340 }342 png_init_io(png_ptr, fp);344 png_set_IHDR(png_ptr,345 info_ptr,346 w,347 h,348 8,349 PNG_COLOR_TYPE_RGB,350 PNG_INTERLACE_NONE,351 PNG_COMPRESSION_TYPE_DEFAULT,352 PNG_FILTER_TYPE_DEFAULT);354 png_write_info(png_ptr, info_ptr);356 u8 *b = writeBuffer;358 int sizeX = w;359 int sizeY = h;361 u8 *pixU8 = (u8 *)data;362 for (int y = 0; y < sizeY; y++)363 {364 for (int x = 0; x < sizeX; x++)365 {366 int blue = *pixU8++;367 int green = *pixU8++;368 int red = *pixU8++;370 *b++ = red;371 *b++ = green;372 *b++ = blue;373 }374 png_write_row(png_ptr, writeBuffer);376 b = writeBuffer;377 }379 png_write_end(png_ptr, info_ptr);381 png_destroy_write_struct(&png_ptr, &info_ptr);383 fclose(fp);384 }386 void GBOamView::save()387 {388 CString captureBuffer;390 if (theApp.captureFormat == 0)391 captureBuffer = "oam.png";392 else393 captureBuffer = "oam.bmp";395 LPCTSTR exts[] = {".png", ".bmp", NULL };397 CString filter = winResLoadFilter(IDS_FILTER_PNG);398 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);400 FileDlg dlg(this,401 captureBuffer,402 filter,403 theApp.captureFormat ? 2 : 1,404 theApp.captureFormat ? "BMP" : "PNG",405 exts,406 "",407 title,408 true);410 if (dlg.DoModal() == IDCANCEL)411 {412 return;413 }414 captureBuffer = dlg.GetPathName();416 if (dlg.getFilterIndex() == 2)417 saveBMP(captureBuffer);418 else419 savePNG(captureBuffer);420 }422 BOOL GBOamView::OnInitDialog()423 {424 CDialog::OnInitDialog();426 DIALOG_SIZER_START(sz)427 DIALOG_SIZER_ENTRY(IDC_OAM_VIEW, DS_SizeX | DS_SizeY)428 DIALOG_SIZER_ENTRY(IDC_OAM_VIEW_ZOOM, DS_MoveX)429 DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY)430 DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY)431 DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY)432 DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY)433 DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY)434 DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY)435 DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY)436 DIALOG_SIZER_END()437 SetData(sz,438 TRUE,439 HKEY_CURRENT_USER,440 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\GBOamView",441 NULL);443 m_sprite.SetWindowText("0");445 updateScrollInfo();447 m_stretch = regQueryDwordValue("GBOamViewStretch", 0);448 if (m_stretch)449 oamView.setStretch(true);450 UpdateData(FALSE);452 paint();454 return TRUE; // return TRUE unless you set the focus to a control455 // EXCEPTION: OCX Property Pages should return FALSE456 }458 void GBOamView::OnStretch()459 {460 oamView.setStretch(!oamView.getStretch());461 paint();462 regSetDwordValue("GBOamViewStretch", oamView.getStretch());463 }465 void GBOamView::OnAutoUpdate()466 {467 autoUpdate = !autoUpdate;468 if (autoUpdate)469 {470 theApp.winAddUpdateListener(this);471 }472 else473 {474 theApp.winRemoveUpdateListener(this);475 }476 }478 void GBOamView::OnChangeSprite()479 {480 CString buffer;481 m_sprite.GetWindowText(buffer);482 int n = atoi(buffer);483 if (n < 0 || n > 39)484 {485 buffer.Format("%d", number);486 m_sprite.SetWindowText(buffer);487 return;488 }489 number = n;490 paint();491 updateScrollInfo();492 }494 void GBOamView::OnClose()495 {496 theApp.winRemoveUpdateListener(this);498 DestroyWindow();499 }501 LRESULT GBOamView::OnMapInfo(WPARAM, LPARAM lParam)502 {503 u8 *colors = (u8 *)lParam;504 oamZoom.setColors(colors);506 return TRUE;507 }509 LRESULT GBOamView::OnColInfo(WPARAM wParam, LPARAM lParam)510 {511 u16 c = (u16)wParam;513 color.setColor(c);515 int r = (c & 0x1f);516 int g = (c & 0x3e0) >> 5;517 int b = (c & 0x7c00) >> 10;519 CString buffer;520 buffer.Format("R: %d", r);521 GetDlgItem(IDC_R)->SetWindowText(buffer);523 buffer.Format("G: %d", g);524 GetDlgItem(IDC_G)->SetWindowText(buffer);526 buffer.Format("B: %d", b);527 GetDlgItem(IDC_B)->SetWindowText(buffer);529 return TRUE;530 }532 void GBOamView::updateScrollInfo()533 {534 SCROLLINFO si;535 ZeroMemory(&si, sizeof(si));536 si.cbSize = sizeof(si);537 si.fMask = SIF_PAGE | SIF_RANGE | SIF_DISABLENOSCROLL | SIF_POS;538 si.nMin = 0;539 si.nMax = 39;540 si.nPage = 1;541 si.nPos = number;542 GetDlgItem(IDC_SCROLLBAR)->SetScrollInfo(SB_CTL,543 &si,544 TRUE);545 }547 void GBOamView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar)548 {549 switch (nSBCode)550 {551 case SB_BOTTOM:552 number = 39;553 break;554 case SB_LINEDOWN:555 number++;556 if (number > 39)557 number = 39;558 break;559 case SB_LINEUP:560 number--;561 if (number < 0)562 number = 0;563 break;564 case SB_PAGEDOWN:565 number += 16;566 if (number > 39)567 number = 39;568 break;569 case SB_PAGEUP:570 number -= 16;571 if (number < 0)572 number = 0;573 break;574 case SB_TOP:575 number = 0;576 break;577 case SB_THUMBTRACK:578 number = nPos;579 if (number < 0)580 number = 0;581 if (number > 39)582 number = 39;583 break;584 }586 updateScrollInfo();588 CString buffer;589 buffer.Format("%d", number);590 m_sprite.SetWindowText(buffer);591 paint();592 }594 void GBOamView::PostNcDestroy()595 {596 delete this;597 }