home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / win32 / GBTileView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  11.0 KB  |  525 lines

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