home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / win32 / TileView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  12.2 KB  |  588 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. // TileView.cpp : implementation file
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "vba.h"
  24. #include "FileDlg.h"
  25. #include "Reg.h"
  26. #include "TileView.h"
  27. #include "WinResUtil.h"
  28.  
  29. #include "../System.h"
  30. #include "../GBA.h"
  31. #include "../Globals.h"
  32. #include "../NLS.h"
  33. #include "../Util.h"
  34.  
  35. extern "C" {
  36. #include <png.h>
  37. }
  38.  
  39. #ifdef _DEBUG
  40. #define new DEBUG_NEW
  41. #undef THIS_FILE
  42. static char THIS_FILE[] = __FILE__;
  43. #endif
  44.  
  45. /////////////////////////////////////////////////////////////////////////////
  46. // TileView dialog
  47.  
  48.  
  49. TileView::TileView(CWnd* pParent /*=NULL*/)
  50.   : ResizeDlg(TileView::IDD, pParent)
  51. {
  52.   //{{AFX_DATA_INIT(TileView)
  53.   m_colors = -1;
  54.   m_charBase = -1;
  55.   m_stretch = FALSE;
  56.   //}}AFX_DATA_INIT
  57.   autoUpdate = false;
  58.   
  59.   memset(&bmpInfo, 0, sizeof(bmpInfo));
  60.  
  61.   bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
  62.   bmpInfo.bmiHeader.biWidth = 32*8;
  63.   bmpInfo.bmiHeader.biHeight = 32*8;
  64.   bmpInfo.bmiHeader.biPlanes = 1;
  65.   bmpInfo.bmiHeader.biBitCount = 24;
  66.   bmpInfo.bmiHeader.biCompression = BI_RGB;
  67.   data = (u8 *)calloc(1, 3 * 32*32 * 64);
  68.  
  69.   tileView.setData(data);
  70.   tileView.setBmpInfo(&bmpInfo);
  71.  
  72.   charBase = 0;
  73.   is256Colors = 0;
  74.   palette = 0;
  75.   w = h = 0;
  76. }
  77.  
  78. TileView::~TileView()
  79. {
  80.   free(data);
  81.   data = NULL;
  82. }
  83.  
  84. void TileView::DoDataExchange(CDataExchange* pDX)
  85. {
  86.   CDialog::DoDataExchange(pDX);
  87.   //{{AFX_DATA_MAP(TileView)
  88.   DDX_Control(pDX, IDC_PALETTE_SLIDER, m_slider);
  89.   DDX_Radio(pDX, IDC_16_COLORS, m_colors);
  90.   DDX_Radio(pDX, IDC_CHARBASE_0, m_charBase);
  91.   DDX_Check(pDX, IDC_STRETCH, m_stretch);
  92.   //}}AFX_DATA_MAP
  93.   DDX_Control(pDX, IDC_TILE_VIEW, tileView);
  94.   DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, zoom);
  95.   DDX_Control(pDX, IDC_COLOR, color);
  96. }
  97.  
  98.  
  99. BEGIN_MESSAGE_MAP(TileView, CDialog)
  100.   //{{AFX_MSG_MAP(TileView)
  101.   ON_BN_CLICKED(IDC_SAVE, OnSave)
  102.   ON_BN_CLICKED(IDC_CLOSE, OnClose)
  103.   ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)
  104.   ON_BN_CLICKED(IDC_16_COLORS, On16Colors)
  105.   ON_BN_CLICKED(IDC_256_COLORS, On256Colors)
  106.   ON_BN_CLICKED(IDC_CHARBASE_0, OnCharbase0)
  107.   ON_BN_CLICKED(IDC_CHARBASE_1, OnCharbase1)
  108.   ON_BN_CLICKED(IDC_CHARBASE_2, OnCharbase2)
  109.   ON_BN_CLICKED(IDC_CHARBASE_3, OnCharbase3)
  110.   ON_BN_CLICKED(IDC_CHARBASE_4, OnCharbase4)
  111.   ON_BN_CLICKED(IDC_STRETCH, OnStretch)
  112.   ON_WM_HSCROLL()
  113.   //}}AFX_MSG_MAP
  114.   ON_MESSAGE(WM_MAPINFO, OnMapInfo)
  115.   ON_MESSAGE(WM_COLINFO, OnColInfo)
  116.   END_MESSAGE_MAP()
  117.  
  118.   /////////////////////////////////////////////////////////////////////////////
  119. // TileView message handlers
  120.  
  121. void TileView::saveBMP(const char *name)
  122. {
  123.   u8 writeBuffer[1024 * 3];
  124.   
  125.   FILE *fp = fopen(name,"wb");
  126.  
  127.   if(!fp) {
  128.     systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
  129.     return;
  130.   }
  131.  
  132.   struct {
  133.     u8 ident[2];
  134.     u8 filesize[4];
  135.     u8 reserved[4];
  136.     u8 dataoffset[4];
  137.     u8 headersize[4];
  138.     u8 width[4];
  139.     u8 height[4];
  140.     u8 planes[2];
  141.     u8 bitsperpixel[2];
  142.     u8 compression[4];
  143.     u8 datasize[4];
  144.     u8 hres[4];
  145.     u8 vres[4];
  146.     u8 colors[4];
  147.     u8 importantcolors[4];
  148.     u8 pad[2];
  149.   } bmpheader;
  150.   memset(&bmpheader, 0, sizeof(bmpheader));
  151.  
  152.   bmpheader.ident[0] = 'B';
  153.   bmpheader.ident[1] = 'M';
  154.  
  155.   u32 fsz = sizeof(bmpheader) + w*h*3;
  156.   utilPutDword(bmpheader.filesize, fsz);
  157.   utilPutDword(bmpheader.dataoffset, 0x38);
  158.   utilPutDword(bmpheader.headersize, 0x28);
  159.   utilPutDword(bmpheader.width, w);
  160.   utilPutDword(bmpheader.height, h);
  161.   utilPutDword(bmpheader.planes, 1);
  162.   utilPutDword(bmpheader.bitsperpixel, 24);
  163.   utilPutDword(bmpheader.datasize, 3*w*h);
  164.  
  165.   fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
  166.  
  167.   u8 *b = writeBuffer;
  168.  
  169.   int sizeX = w;
  170.   int sizeY = h;
  171.  
  172.   u8 *pixU8 = (u8 *)data+3*w*(h-1);
  173.   for(int y = 0; y < sizeY; y++) {
  174.     for(int x = 0; x < sizeX; x++) {
  175.       *b++ = *pixU8++; // B
  176.       *b++ = *pixU8++; // G
  177.       *b++ = *pixU8++; // R
  178.     }
  179.     pixU8 -= 2*3*w;
  180.     fwrite(writeBuffer, 1, 3*w, fp);
  181.     
  182.     b = writeBuffer;
  183.   }
  184.  
  185.   fclose(fp);
  186. }
  187.  
  188.  
  189. void TileView::savePNG(const char *name)
  190. {
  191.   u8 writeBuffer[1024 * 3];
  192.   
  193.   FILE *fp = fopen(name,"wb");
  194.  
  195.   if(!fp) {
  196.     systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
  197.     return;
  198.   }
  199.   
  200.   png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
  201.                                                 NULL,
  202.                                                 NULL,
  203.                                                 NULL);
  204.   if(!png_ptr) {
  205.     fclose(fp);
  206.     return;
  207.   }
  208.  
  209.   png_infop info_ptr = png_create_info_struct(png_ptr);
  210.  
  211.   if(!info_ptr) {
  212.     png_destroy_write_struct(&png_ptr,NULL);
  213.     fclose(fp);
  214.     return;
  215.   }
  216.  
  217.   if(setjmp(png_ptr->jmpbuf)) {
  218.     png_destroy_write_struct(&png_ptr,NULL);
  219.     fclose(fp);
  220.     return;
  221.   }
  222.  
  223.   png_init_io(png_ptr,fp);
  224.  
  225.   png_set_IHDR(png_ptr,
  226.                info_ptr,
  227.                w,
  228.                h,
  229.                8,
  230.                PNG_COLOR_TYPE_RGB,
  231.                PNG_INTERLACE_NONE,
  232.                PNG_COMPRESSION_TYPE_DEFAULT,
  233.                PNG_FILTER_TYPE_DEFAULT);
  234.  
  235.   png_write_info(png_ptr,info_ptr);
  236.  
  237.   u8 *b = writeBuffer;
  238.  
  239.   int sizeX = w;
  240.   int sizeY = h;
  241.  
  242.   u8 *pixU8 = (u8 *)data;
  243.   for(int y = 0; y < sizeY; y++) {
  244.     for(int x = 0; x < sizeX; x++) {
  245.       int blue = *pixU8++;
  246.       int green = *pixU8++;
  247.       int red = *pixU8++;
  248.       
  249.       *b++ = red;
  250.       *b++ = green;
  251.       *b++ = blue;
  252.     }
  253.     png_write_row(png_ptr,writeBuffer);
  254.     
  255.     b = writeBuffer;
  256.   }
  257.   
  258.   png_write_end(png_ptr, info_ptr);
  259.  
  260.   png_destroy_write_struct(&png_ptr, &info_ptr);
  261.  
  262.   fclose(fp);
  263. }
  264.  
  265.  
  266. void TileView::OnSave() 
  267. {
  268.   CString captureBuffer;
  269.  
  270.   if(theApp.captureFormat == 0)
  271.     captureBuffer = "tiles.png";
  272.   else
  273.     captureBuffer = "tiles.bmp";
  274.  
  275.   LPCTSTR exts[] = {".png", ".bmp" };
  276.  
  277.   CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
  278.   CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
  279.  
  280.   FileDlg dlg(this,
  281.               captureBuffer,
  282.               filter,
  283.               theApp.captureFormat ? 2 : 1,
  284.               theApp.captureFormat ? "BMP" : "PNG",
  285.               exts,
  286.               "",
  287.               title,
  288.               true);
  289.  
  290.   if(dlg.DoModal() == IDCANCEL) {
  291.     return;
  292.   }
  293.  
  294.   captureBuffer = dlg.GetPathName();
  295.  
  296.   if(dlg.getFilterIndex() == 2)
  297.     saveBMP(captureBuffer);
  298.   else
  299.     savePNG(captureBuffer);  
  300. }
  301.  
  302. void TileView::renderTile256(int tile, int x, int y, u8 *charBase, u16 *palette)
  303. {
  304.   u8 *bmp = &data[24*x + 8*32*24*y];
  305.  
  306.   for(int j = 0; j < 8; j++) {
  307.     for(int i = 0; i < 8; i++) {
  308.       u8 c = charBase[tile*64 + j * 8 + i];
  309.  
  310.       u16 color = palette[c];
  311.  
  312.       *bmp++ = ((color >> 10) & 0x1f) << 3;
  313.       *bmp++ = ((color >> 5) & 0x1f) << 3;
  314.       *bmp++ = (color & 0x1f) << 3;      
  315.  
  316.     }
  317.     bmp += 31*24; // advance line
  318.   }
  319. }
  320.  
  321. void TileView::renderTile16(int tile, int x, int y, u8 *charBase, u16 *palette)
  322. {
  323.   u8 *bmp = &data[24*x + 8*32*24*y];
  324.  
  325.   int pal = this->palette;
  326.  
  327.   if(this->charBase == 4)
  328.     pal += 16;
  329.  
  330.   for(int j = 0; j < 8; j++) {
  331.     for(int i = 0; i < 8; i++) {
  332.       u8 c = charBase[tile*32 + j * 4 + (i>>1)];
  333.  
  334.       if(i & 1)
  335.         c = c>>4;
  336.       else
  337.         c = c & 15;
  338.  
  339.       u16 color = palette[pal*16+c];
  340.  
  341.       *bmp++ = ((color >> 10) & 0x1f) << 3;
  342.       *bmp++ = ((color >> 5) & 0x1f) << 3;
  343.       *bmp++ = (color & 0x1f) << 3;
  344.     }
  345.     bmp += 31*24; // advance line
  346.   }
  347. }
  348.  
  349.  
  350. void TileView::render()
  351. {
  352.   u16 *palette = (u16 *)paletteRAM;
  353.   u8 *charBase = &vram[this->charBase * 0x4000];
  354.  
  355.   int maxY;
  356.  
  357.   if(is256Colors) {
  358.     int tile = 0;
  359.     maxY = 16;
  360.     for(int y = 0; y < maxY; y++) {
  361.       for(int x = 0; x < 32; x++) {
  362.         if(this->charBase == 4)
  363.           renderTile256(tile, x, y, charBase, &palette[256]);
  364.         else
  365.           renderTile256(tile, x, y, charBase, palette);
  366.         tile++;
  367.       }
  368.     }
  369.     tileView.setSize(32*8, maxY*8);
  370.     w = 32*8;
  371.     h = maxY*8;
  372.     SIZE s;
  373.     s.cx = 32*8;
  374.     s.cy = maxY*8;
  375.     if(tileView.getStretch()) {
  376.       s.cx = s.cy = 1;
  377.     }
  378.     tileView.SetScrollSizes(MM_TEXT,s);
  379.   } else {
  380.     int tile = 0;
  381.     maxY = 32;
  382.     if(this->charBase == 3)
  383.       maxY = 16;
  384.     for(int y = 0; y < maxY; y++) {
  385.       for(int x = 0; x < 32; x++) {
  386.         renderTile16(tile, x, y, charBase, palette);    
  387.         tile++;
  388.       }
  389.     }
  390.     tileView.setSize(32*8, maxY*8);
  391.     w = 32*8;
  392.     h = maxY*8;
  393.     SIZE s;
  394.     s.cx = 32*8;
  395.     s.cy = maxY*8;
  396.     if(tileView.getStretch()) {
  397.       s.cx = s.cy = 1;
  398.     }
  399.     tileView.SetScrollSizes(MM_TEXT, s);
  400.   }
  401. }
  402.  
  403. void TileView::update()
  404. {
  405.   paint();
  406. }
  407.  
  408.  
  409. BOOL TileView::OnInitDialog() 
  410. {
  411.   CDialog::OnInitDialog();
  412.   
  413.   DIALOG_SIZER_START( sz )
  414.     DIALOG_SIZER_ENTRY( IDC_TILE_VIEW, DS_SizeX | DS_SizeY )
  415.     DIALOG_SIZER_ENTRY( IDC_COLOR, DS_MoveY)
  416.     DIALOG_SIZER_ENTRY( IDC_R, DS_MoveY)
  417.     DIALOG_SIZER_ENTRY( IDC_G, DS_MoveY)
  418.     DIALOG_SIZER_ENTRY( IDC_B, DS_MoveY)
  419.     DIALOG_SIZER_ENTRY( IDC_REFRESH, DS_MoveY)
  420.     DIALOG_SIZER_ENTRY( IDC_CLOSE, DS_MoveY)
  421.     DIALOG_SIZER_ENTRY( IDC_SAVE, DS_MoveY)
  422.     DIALOG_SIZER_END()
  423.     SetData(sz,
  424.             TRUE,
  425.             HKEY_CURRENT_USER,
  426.             "Software\\Emulators\\VisualBoyAdvance\\Viewer\\TileView",
  427.             NULL);
  428.  
  429.   m_colors = is256Colors;
  430.   m_charBase = charBase;
  431.  
  432.   m_slider.SetRange(0, 15);
  433.   m_slider.SetPageSize(4);
  434.   m_slider.SetTicFreq(1);
  435.  
  436.   paint();
  437.  
  438.   m_stretch = regQueryDwordValue("tileViewStretch", 0);
  439.   if(m_stretch)
  440.     tileView.setStretch(true);
  441.   UpdateData(FALSE);
  442.   
  443.   return TRUE;  // return TRUE unless you set the focus to a control
  444.                 // EXCEPTION: OCX Property Pages should return FALSE
  445. }
  446.  
  447. void TileView::OnClose() 
  448. {
  449.   theApp.winRemoveUpdateListener(this);
  450.   
  451.   DestroyWindow();
  452. }
  453.  
  454.  
  455. void TileView::OnAutoUpdate() 
  456. {
  457.   autoUpdate = !autoUpdate;
  458.   if(autoUpdate) {
  459.     theApp.winAddUpdateListener(this);
  460.   } else {
  461.     theApp.winRemoveUpdateListener(this);    
  462.   }  
  463. }
  464.  
  465.  
  466. void TileView::paint()
  467. {
  468.   if(vram != NULL && paletteRAM != NULL) {
  469.     render();
  470.     tileView.refresh();
  471.   }
  472. }
  473.  
  474.  
  475. void TileView::On16Colors() 
  476. {
  477.   is256Colors = 0;
  478.   paint();
  479. }
  480.  
  481. void TileView::On256Colors() 
  482. {
  483.   is256Colors = 1;
  484.   paint();
  485. }
  486.  
  487. void TileView::OnCharbase0() 
  488. {
  489.   charBase = 0;
  490.   paint();
  491. }
  492.  
  493. void TileView::OnCharbase1() 
  494. {
  495.   charBase = 1;
  496.   paint();
  497. }
  498.  
  499. void TileView::OnCharbase2() 
  500. {
  501.   charBase = 2;
  502.   paint();
  503. }
  504.  
  505. void TileView::OnCharbase3() 
  506. {
  507.   charBase = 3;
  508.   paint();
  509. }
  510.  
  511. void TileView::OnCharbase4() 
  512. {
  513.   charBase = 4;
  514.   paint();
  515. }
  516.  
  517. void TileView::OnStretch() 
  518. {
  519.   tileView.setStretch(!tileView.getStretch());
  520.   paint();
  521.   regSetDwordValue("tileViewStretch", tileView.getStretch());  
  522. }
  523.  
  524. LRESULT TileView::OnMapInfo(WPARAM wParam, LPARAM lParam)
  525. {
  526.   u8 *colors = (u8 *)lParam;
  527.   zoom.setColors(colors);
  528.  
  529.   int x = (wParam & 0xFFFF)/8;
  530.   int y = ((wParam >> 16) & 0xFFFF)/8;
  531.  
  532.   u32 address = 0x6000000 + 0x4000 * charBase;
  533.   int tile = 32 * y + x;
  534.   if(is256Colors)
  535.     tile *= 2;
  536.   address += 32 * tile;
  537.  
  538.   CString buffer;
  539.   buffer.Format("%d", tile);
  540.   GetDlgItem(IDC_TILE_NUMBER)->SetWindowText(buffer);
  541.  
  542.   buffer.Format("%08x", address);
  543.   GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer);
  544.   
  545.   return TRUE;
  546. }
  547.  
  548. LRESULT TileView::OnColInfo(WPARAM wParam, LPARAM)
  549. {
  550.   u16 c = (u16)wParam;
  551.  
  552.   color.setColor(c);  
  553.  
  554.   int r = (c & 0x1f);
  555.   int g = (c & 0x3e0) >> 5;
  556.   int b = (c & 0x7c00) >> 10;
  557.  
  558.   CString buffer;
  559.   buffer.Format("R: %d", r);
  560.   GetDlgItem(IDC_R)->SetWindowText(buffer);
  561.  
  562.   buffer.Format("G: %d", g);
  563.   GetDlgItem(IDC_G)->SetWindowText(buffer);
  564.  
  565.   buffer.Format("B: %d", b);
  566.   GetDlgItem(IDC_B)->SetWindowText(buffer);
  567.  
  568.   return TRUE;
  569. }
  570.  
  571. void TileView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  572. {
  573.   switch(nSBCode) {
  574.   case TB_THUMBPOSITION:
  575.     palette = nPos;
  576.     break;
  577.   default:
  578.     palette = m_slider.GetPos();
  579.     break;
  580.   }
  581.   paint();
  582. }
  583.  
  584. void TileView::PostNcDestroy() 
  585. {
  586.   delete this;
  587. }
  588.