Mercurial > vba-clojure
view src/win32/OamView.cpp @ 5:8fe0c57e53d2
concentrating on lua first
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:39:40 -0600 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 // OamView.cpp : implementation file2 //4 #include "stdafx.h"5 #include "resource.h"6 #include "OamView.h"7 #include "FileDlg.h"8 #include "Reg.h"9 #include "WinResUtil.h"10 #include "VBA.h"12 #include "../gba/GBAGlobals.h"13 #include "../NLS.h"14 #include "../common/Util.h"16 extern "C" {17 #include <png.h>18 }20 /////////////////////////////////////////////////////////////////////////////21 // OamView dialog23 OamView::OamView(CWnd*pParent /*=NULL*/)24 : ResizeDlg(OamView::IDD, pParent)25 {26 //{{AFX_DATA_INIT(OamView)27 m_stretch = FALSE;28 //}}AFX_DATA_INIT29 autoUpdate = false;31 memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader));33 bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);34 bmpInfo.bmiHeader.biWidth = 32;35 bmpInfo.bmiHeader.biHeight = 32;36 bmpInfo.bmiHeader.biPlanes = 1;37 bmpInfo.bmiHeader.biBitCount = 24;38 bmpInfo.bmiHeader.biCompression = BI_RGB;39 data = (u8 *)calloc(1, 3 * 64 * 64);41 oamView.setData(data);42 oamView.setBmpInfo(&bmpInfo);44 number = 0;45 }47 void OamView::DoDataExchange(CDataExchange*pDX)48 {49 CDialog::DoDataExchange(pDX);50 //{{AFX_DATA_MAP(OamView)51 DDX_Control(pDX, IDC_SPRITE, m_sprite);52 DDX_Check(pDX, IDC_STRETCH, m_stretch);53 //}}AFX_DATA_MAP54 DDX_Control(pDX, IDC_COLOR, color);55 DDX_Control(pDX, IDC_OAM_VIEW, oamView);56 DDX_Control(pDX, IDC_OAM_VIEW_ZOOM, oamZoom);57 }59 BEGIN_MESSAGE_MAP(OamView, CDialog)60 //{{AFX_MSG_MAP(OamView)61 ON_BN_CLICKED(IDC_SAVE, OnSave)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 // OamView message handlers75 OamView::~OamView()76 {77 free(data);78 data = NULL;79 }81 void OamView::paint()82 {83 if (oam == NULL || paletteRAM == NULL || vram == NULL)84 return;86 render();87 oamView.setSize(w, h);88 oamView.refresh();89 }91 void OamView::update()92 {93 paint();94 }96 void OamView::setAttributes(u16 a0, u16 a1, u16 a2)97 {98 CString buffer;100 int y = a0 & 255;101 int rot = a0 & 512;102 int mode = (a0 >> 10) & 3;103 int mosaic = a0 & 4096;104 int color = a0 & 8192;105 int duple = a0 & 1024;106 int shape = (a0 >> 14) & 3;107 int x = a1 & 511;108 int rotParam = (a1 >> 9) & 31;109 int flipH = a1 & 4096;110 int flipV = a1 & 8192;111 int size = (a1 >> 14) & 3;112 int tile = a2 & 1023;113 int prio = (a2 >> 10) & 3;114 int pal = (a2 >> 12) & 15;116 buffer.Format("%d,%d", x, y);117 GetDlgItem(IDC_POS)->SetWindowText(buffer);119 buffer.Format("%d", mode);120 GetDlgItem(IDC_MODE)->SetWindowText(buffer);122 GetDlgItem(IDC_COLORS)->SetWindowText(color ? "256" : "16");124 buffer.Format("%d", pal);125 GetDlgItem(IDC_PALETTE)->SetWindowText(buffer);127 buffer.Format("%d", tile);128 GetDlgItem(IDC_TILE)->SetWindowText(buffer);130 buffer.Format("%d", prio);131 GetDlgItem(IDC_PRIO)->SetWindowText(buffer);133 buffer.Format("%d,%d", w, h);134 GetDlgItem(IDC_SIZE2)->SetWindowText(buffer);136 if (rot)137 {138 buffer.Format("%d", rotParam);139 }140 else141 buffer.Empty();142 GetDlgItem(IDC_ROT)->SetWindowText(buffer);144 buffer.Empty();146 if (rot)147 buffer += 'R';148 else149 buffer += ' ';150 if (!rot)151 {152 if (flipH)153 buffer += 'H';154 else155 buffer += ' ';156 if (flipV)157 buffer += 'V';158 else159 buffer += ' ';160 }161 else162 {163 buffer += ' ';164 buffer += ' ';165 }166 if (mosaic)167 buffer += 'M';168 else169 buffer += ' ';170 if (duple)171 buffer += 'D';172 else173 buffer += ' ';175 GetDlgItem(IDC_FLAGS)->SetWindowText(buffer);176 }178 void OamView::render()179 {180 int m = 0;181 if (oam == NULL || paletteRAM == NULL || vram == NULL)182 return;184 u16 *sprites = &((u16 *)oam)[4*number];185 u16 *spritePalette = &((u16 *)paletteRAM)[0x100];186 u8 * bmp = data;188 u16 a0 = *sprites++;189 u16 a1 = *sprites++;190 u16 a2 = *sprites++;192 int sizeY = 8;193 int sizeX = 8;195 switch (((a0 >>12) & 0x0c)|(a1>>14))196 {197 case 0:198 break;199 case 1:200 sizeX = sizeY = 16;201 break;202 case 2:203 sizeX = sizeY = 32;204 break;205 case 3:206 sizeX = sizeY = 64;207 break;208 case 4:209 sizeX = 16;210 break;211 case 5:212 sizeX = 32;213 break;214 case 6:215 sizeX = 32;216 sizeY = 16;217 break;218 case 7:219 sizeX = 64;220 sizeY = 32;221 break;222 case 8:223 sizeY = 16;224 break;225 case 9:226 sizeY = 32;227 break;228 case 10:229 sizeX = 16;230 sizeY = 32;231 break;232 case 11:233 sizeX = 32;234 sizeY = 64;235 break;236 default:237 return;238 }240 w = sizeX;241 h = sizeY;243 setAttributes(a0, a1, a2);245 int sy = (a0 & 255);247 if (a0 & 0x2000)248 {249 int c = (a2 & 0x3FF);250 // if((DISPCNT & 7) > 2 && (c < 512))251 // return;252 int inc = 32;253 if (DISPCNT & 0x40)254 inc = sizeX >> 2;255 else256 c &= 0x3FE;258 for (int y = 0; y < sizeY; y++)259 {260 for (int x = 0; x < sizeX; x++)261 {262 u32 color = vram[0x10000 + (((c + (y>>3) * inc)*263 32 + (y & 7) * 8 + (x >> 3) * 64 +264 (x & 7))&0x7FFF)];265 color = spritePalette[color];266 *bmp++ = ((color >> 10) & 0x1f) << 3;267 *bmp++ = ((color >> 5) & 0x1f) << 3;268 *bmp++ = (color & 0x1f) << 3;269 }270 }271 }272 else273 {274 int c = (a2 & 0x3FF);275 // if((DISPCNT & 7) > 2 && (c < 512))276 // continue;278 int inc = 32;279 if (DISPCNT & 0x40)280 inc = sizeX >> 3;281 int palette = (a2 >> 8) & 0xF0;282 for (int y = 0; y < sizeY; y++)283 {284 for (int x = 0; x < sizeX; x++)285 {286 u32 color = vram[0x10000 + (((c + (y>>3) * inc)*287 32 + (y & 7) * 4 + (x >> 3) * 32 +288 ((x & 7)>>1))&0x7FFF)];289 if (x & 1)290 color >>= 4;291 else292 color &= 0x0F;294 color = spritePalette[palette+color];295 *bmp++ = ((color >> 10) & 0x1f) << 3;296 *bmp++ = ((color >> 5) & 0x1f) << 3;297 *bmp++ = (color & 0x1f) << 3;298 }299 }300 }301 }303 void OamView::saveBMP(const char *name)304 {305 u8 writeBuffer[1024 * 3];307 FILE *fp = fopen(name, "wb");309 if (!fp)310 {311 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);312 return;313 }315 struct316 {317 u8 ident[2];318 u8 filesize[4];319 u8 reserved[4];320 u8 dataoffset[4];321 u8 headersize[4];322 u8 width[4];323 u8 height[4];324 u8 planes[2];325 u8 bitsperpixel[2];326 u8 compression[4];327 u8 datasize[4];328 u8 hres[4];329 u8 vres[4];330 u8 colors[4];331 u8 importantcolors[4];332 u8 pad[2];333 } bmpheader;334 memset(&bmpheader, 0, sizeof(bmpheader));336 bmpheader.ident[0] = 'B';337 bmpheader.ident[1] = 'M';339 u32 fsz = sizeof(bmpheader) + w*h*3;340 utilPutDword(bmpheader.filesize, fsz);341 utilPutDword(bmpheader.dataoffset, 0x38);342 utilPutDword(bmpheader.headersize, 0x28);343 utilPutDword(bmpheader.width, w);344 utilPutDword(bmpheader.height, h);345 utilPutDword(bmpheader.planes, 1);346 utilPutDword(bmpheader.bitsperpixel, 24);347 utilPutDword(bmpheader.datasize, 3*w*h);349 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);351 u8 *b = writeBuffer;353 int sizeX = w;354 int sizeY = h;356 u8 *pixU8 = (u8 *)data+3*w*(h-1);357 for (int y = 0; y < sizeY; y++)358 {359 for (int x = 0; x < sizeX; x++)360 {361 *b++ = *pixU8++; // B362 *b++ = *pixU8++; // G363 *b++ = *pixU8++; // R364 }365 pixU8 -= 2*3*w;366 fwrite(writeBuffer, 1, 3*w, fp);368 b = writeBuffer;369 }371 fclose(fp);372 }374 void OamView::savePNG(const char *name)375 {376 u8 writeBuffer[1024 * 3];378 FILE *fp = fopen(name, "wb");380 if (!fp)381 {382 systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);383 return;384 }386 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,387 NULL,388 NULL,389 NULL);390 if (!png_ptr)391 {392 fclose(fp);393 return;394 }396 png_infop info_ptr = png_create_info_struct(png_ptr);398 if (!info_ptr)399 {400 png_destroy_write_struct(&png_ptr, NULL);401 fclose(fp);402 return;403 }405 if (setjmp(png_ptr->jmpbuf))406 {407 png_destroy_write_struct(&png_ptr, NULL);408 fclose(fp);409 return;410 }412 png_init_io(png_ptr, fp);414 png_set_IHDR(png_ptr,415 info_ptr,416 w,417 h,418 8,419 PNG_COLOR_TYPE_RGB,420 PNG_INTERLACE_NONE,421 PNG_COMPRESSION_TYPE_DEFAULT,422 PNG_FILTER_TYPE_DEFAULT);424 png_write_info(png_ptr, info_ptr);426 u8 *b = writeBuffer;428 int sizeX = w;429 int sizeY = h;431 u8 *pixU8 = (u8 *)data;432 for (int y = 0; y < sizeY; y++)433 {434 for (int x = 0; x < sizeX; x++)435 {436 int blue = *pixU8++;437 int green = *pixU8++;438 int red = *pixU8++;440 *b++ = red;441 *b++ = green;442 *b++ = blue;443 }444 png_write_row(png_ptr, writeBuffer);446 b = writeBuffer;447 }449 png_write_end(png_ptr, info_ptr);451 png_destroy_write_struct(&png_ptr, &info_ptr);453 fclose(fp);454 }456 void OamView::OnSave()457 {458 CString captureBuffer;460 if (theApp.captureFormat == 0)461 captureBuffer = "oam.png";462 else463 captureBuffer = "oam.bmp";465 LPCTSTR exts[] = {".png", ".bmp", NULL };467 CString filter = winResLoadFilter(IDS_FILTER_PNG);468 CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);470 FileDlg dlg(this,471 captureBuffer,472 filter,473 theApp.captureFormat ? 2 : 1,474 theApp.captureFormat ? "BMP" : "PNG",475 exts,476 "",477 title,478 true);480 if (dlg.DoModal() == IDCANCEL)481 {482 return;483 }484 captureBuffer = dlg.GetPathName();486 if (dlg.getFilterIndex() == 2)487 saveBMP(captureBuffer);488 else489 savePNG(captureBuffer);490 }492 BOOL OamView::OnInitDialog()493 {494 CDialog::OnInitDialog();496 DIALOG_SIZER_START(sz)497 DIALOG_SIZER_ENTRY(IDC_OAM_VIEW, DS_SizeX | DS_SizeY)498 DIALOG_SIZER_ENTRY(IDC_OAM_VIEW_ZOOM, DS_MoveX)499 DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY)500 DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY)501 DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY)502 DIALOG_SIZER_ENTRY(IDC_COLOR, DS_MoveY)503 DIALOG_SIZER_ENTRY(IDC_R, DS_MoveY)504 DIALOG_SIZER_ENTRY(IDC_G, DS_MoveY)505 DIALOG_SIZER_ENTRY(IDC_B, DS_MoveY)506 DIALOG_SIZER_END()507 SetData(sz,508 TRUE,509 HKEY_CURRENT_USER,510 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\OamView",511 NULL);513 m_sprite.SetWindowText("0");515 updateScrollInfo();517 m_stretch = regQueryDwordValue("oamViewStretch", 0);518 if (m_stretch)519 oamView.setStretch(true);520 UpdateData(FALSE);522 paint();524 return TRUE; // return TRUE unless you set the focus to a control525 // EXCEPTION: OCX Property Pages should return FALSE526 }528 void OamView::OnStretch()529 {530 oamView.setStretch(!oamView.getStretch());531 paint();532 regSetDwordValue("oamViewStretch", oamView.getStretch());533 }535 void OamView::OnAutoUpdate()536 {537 autoUpdate = !autoUpdate;538 if (autoUpdate)539 {540 theApp.winAddUpdateListener(this);541 }542 else543 {544 theApp.winRemoveUpdateListener(this);545 }546 }548 void OamView::OnChangeSprite()549 {550 CString buffer;551 m_sprite.GetWindowText(buffer);552 int n = atoi(buffer);553 if (n < 0 || n > 127)554 {555 buffer.Format("%d", number);556 m_sprite.SetWindowText(buffer);557 return;558 }559 number = n;560 paint();561 updateScrollInfo();562 }564 void OamView::OnClose()565 {566 theApp.winRemoveUpdateListener(this);568 DestroyWindow();569 }571 LRESULT OamView::OnMapInfo(WPARAM wParam, LPARAM lParam)572 {573 u8 *colors = (u8 *)lParam;574 oamZoom.setColors(colors);576 return TRUE;577 }579 LRESULT OamView::OnColInfo(WPARAM wParam, LPARAM lParam)580 {581 u16 c = (u16)wParam;583 color.setColor(c);585 int r = (c & 0x1f);586 int g = (c & 0x3e0) >> 5;587 int b = (c & 0x7c00) >> 10;589 CString buffer;590 buffer.Format("R: %d", r);591 GetDlgItem(IDC_R)->SetWindowText(buffer);593 buffer.Format("G: %d", g);594 GetDlgItem(IDC_G)->SetWindowText(buffer);596 buffer.Format("B: %d", b);597 GetDlgItem(IDC_B)->SetWindowText(buffer);599 return TRUE;600 }602 void OamView::updateScrollInfo()603 {604 SCROLLINFO si;605 ZeroMemory(&si, sizeof(si));606 si.cbSize = sizeof(si);607 si.fMask = SIF_PAGE | SIF_RANGE | SIF_DISABLENOSCROLL | SIF_POS;608 si.nMin = 0;609 si.nMax = 127;610 si.nPage = 1;611 si.nPos = number;612 GetDlgItem(IDC_SCROLLBAR)->SetScrollInfo(SB_CTL,613 &si,614 TRUE);615 }617 void OamView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar)618 {619 switch (nSBCode)620 {621 case SB_BOTTOM:622 number = 127;623 break;624 case SB_LINEDOWN:625 number++;626 if (number > 127)627 number = 127;628 break;629 case SB_LINEUP:630 number--;631 if (number < 0)632 number = 0;633 break;634 case SB_PAGEDOWN:635 number += 16;636 if (number > 127)637 number = 127;638 break;639 case SB_PAGEUP:640 number -= 16;641 if (number < 0)642 number = 0;643 break;644 case SB_TOP:645 number = 0;646 break;647 case SB_THUMBTRACK:648 number = nPos;649 if (number < 0)650 number = 0;651 if (number > 127)652 number = 127;653 break;654 }656 updateScrollInfo();658 CString buffer;659 buffer.Format("%d", number);660 m_sprite.SetWindowText(buffer);661 paint();662 }664 void OamView::PostNcDestroy()665 {666 delete this;667 }