home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / win32 / MapView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  21.2 KB  |  1,027 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. // MapView.cpp : implementation file
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "vba.h"
  24. #include "FileDlg.h"
  25. #include "MapView.h"
  26. #include "Reg.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. // MapView dialog
  47.  
  48.  
  49. MapView::MapView(CWnd* pParent /*=NULL*/)
  50.   : ResizeDlg(MapView::IDD, pParent)
  51. {
  52.   //{{AFX_DATA_INIT(MapView)
  53.   //}}AFX_DATA_INIT
  54.   autoUpdate = false;
  55.   
  56.   memset(&bmpInfo.bmiHeader, 0, sizeof(bmpInfo.bmiHeader));
  57.   
  58.   bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
  59.   bmpInfo.bmiHeader.biWidth = 1024;
  60.   bmpInfo.bmiHeader.biHeight = -1024;
  61.   bmpInfo.bmiHeader.biPlanes = 1;
  62.   bmpInfo.bmiHeader.biBitCount = 24;
  63.   bmpInfo.bmiHeader.biCompression = BI_RGB;
  64.   data = (u8 *)calloc(1, 3 * 1024 * 1024);
  65.  
  66.   mapView.setData(data);
  67.   mapView.setBmpInfo(&bmpInfo);
  68.   
  69.   control = BG0CNT;
  70.  
  71.   bg = 0;
  72.   frame = 0;
  73. }
  74.  
  75. MapView::~MapView()
  76. {
  77.   free(data);
  78.   data = NULL;
  79. }
  80.  
  81. void MapView::DoDataExchange(CDataExchange* pDX)
  82. {
  83.   CDialog::DoDataExchange(pDX);
  84.   //{{AFX_DATA_MAP(MapView)
  85.   DDX_Control(pDX, IDC_NUMCOLORS, m_numcolors);
  86.   DDX_Control(pDX, IDC_MODE, m_mode);
  87.   DDX_Control(pDX, IDC_OVERFLOW, m_overflow);
  88.   DDX_Control(pDX, IDC_MOSAIC, m_mosaic);
  89.   DDX_Control(pDX, IDC_PRIORITY, m_priority);
  90.   DDX_Control(pDX, IDC_DIM, m_dim);
  91.   DDX_Control(pDX, IDC_CHARBASE, m_charbase);
  92.   DDX_Control(pDX, IDC_MAPBASE, m_mapbase);
  93.   //}}AFX_DATA_MAP
  94.   DDX_Control(pDX, IDC_MAP_VIEW, mapView);
  95.   DDX_Control(pDX, IDC_MAP_VIEW_ZOOM, mapViewZoom);
  96.   DDX_Control(pDX, IDC_COLOR, color);
  97. }
  98.  
  99.  
  100. BEGIN_MESSAGE_MAP(MapView, CDialog)
  101.   //{{AFX_MSG_MAP(MapView)
  102.   ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
  103.   ON_BN_CLICKED(IDC_FRAME_0, OnFrame0)
  104.   ON_BN_CLICKED(IDC_FRAME_1, OnFrame1)
  105.   ON_BN_CLICKED(IDC_BG0, OnBg0)
  106.   ON_BN_CLICKED(IDC_BG1, OnBg1)
  107.   ON_BN_CLICKED(IDC_BG2, OnBg2)
  108.   ON_BN_CLICKED(IDC_BG3, OnBg3)
  109.   ON_BN_CLICKED(IDC_STRETCH, OnStretch)
  110.   ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)
  111.   ON_BN_CLICKED(IDC_CLOSE, OnClose)
  112.   ON_BN_CLICKED(IDC_SAVE, OnSave)
  113.   //}}AFX_MSG_MAP
  114.   ON_MESSAGE(WM_MAPINFO, OnMapInfo)
  115.   ON_MESSAGE(WM_COLINFO, OnColInfo)
  116.   END_MESSAGE_MAP()
  117.  
  118.   /////////////////////////////////////////////////////////////////////////////
  119. // MapView message handlers
  120.  
  121. void MapView::renderTextScreen(u16 control)
  122. {
  123.   u16 *palette = (u16 *)paletteRAM;
  124.   u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
  125.   u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
  126.   u8 *bmp = data;
  127.  
  128.   int sizeX = 256;
  129.   int sizeY = 256;
  130.   switch((control >> 14) & 3) {
  131.   case 0:
  132.     break;
  133.   case 1:
  134.     sizeX = 512;
  135.     break;
  136.   case 2:
  137.     sizeY = 512;
  138.     break;
  139.   case 3:
  140.     sizeX = 512;
  141.     sizeY = 512;
  142.     break;
  143.   }
  144.  
  145.   w = sizeX;
  146.   h = sizeY;
  147.   
  148.   if(control & 0x80) {
  149.     for(int y = 0; y < sizeY; y++) {
  150.       int yy = y & 255;
  151.  
  152.       if(y == 256 && sizeY > 256) {
  153.         screenBase += 0x400;
  154.         if(sizeX > 256)
  155.           screenBase += 0x400;
  156.       }
  157.       u16 *screenSource = screenBase + ((yy>>3)*32);
  158.  
  159.       for(int x = 0; x < sizeX; x++) {
  160.         u16 data = *screenSource;
  161.       
  162.         int tile = data & 0x3FF;
  163.         int tileX = (x & 7);
  164.         int tileY = y & 7;
  165.         
  166.         if(data & 0x0400)
  167.           tileX = 7 - tileX;
  168.         if(data & 0x0800)
  169.           tileY = 7 - tileY;
  170.  
  171.         u8 c = charBase[tile * 64 + tileY * 8 + tileX];
  172.         
  173.         u16 color = palette[c];
  174.         
  175.         *bmp++ = ((color >> 10) & 0x1f) << 3;
  176.         *bmp++ = ((color >> 5) & 0x1f) << 3;
  177.         *bmp++ = (color & 0x1f) << 3;      
  178.       
  179.         if(data & 0x0400) {
  180.           if(tileX == 0)
  181.             screenSource++;
  182.         } else if(tileX == 7)
  183.           screenSource++;
  184.         if(x == 255 && sizeX > 256) {
  185.           screenSource = screenBase + 0x400 + ((yy>>3)*32);
  186.         }
  187.       }
  188.     }
  189.   } else {
  190.     for(int y = 0; y < sizeY; y++) {
  191.       int yy = y & 255;
  192.  
  193.       if(y == 256 && sizeY > 256) {
  194.         screenBase += 0x400;
  195.         if(sizeX > 256)
  196.           screenBase += 0x400;
  197.       }
  198.       u16 *screenSource = screenBase + ((yy>>3)*32);
  199.  
  200.       for(int x = 0; x < sizeX; x++) {
  201.         u16 data = *screenSource;
  202.         
  203.         int tile = data & 0x3FF;
  204.         int tileX = (x & 7);
  205.         int tileY = y & 7;
  206.  
  207.         if(data & 0x0400)
  208.           tileX = 7 - tileX;
  209.         if(data & 0x0800)
  210.           tileY = 7 - tileY;
  211.         
  212.         u8 color = charBase[tile * 32 + tileY * 4 + (tileX>>1)];
  213.         
  214.         if(tileX & 1) {
  215.           color = (color >> 4);
  216.         } else {
  217.           color &= 0x0F;
  218.         }
  219.  
  220.         int pal = (*screenSource>>8) & 0xF0;
  221.         u16 color2 = palette[pal + color];
  222.  
  223.         *bmp++ = ((color2 >> 10) & 0x1f) << 3;
  224.         *bmp++ = ((color2 >> 5) & 0x1f) << 3;
  225.         *bmp++ = (color2 & 0x1f) << 3;
  226.         
  227.         if(data & 0x0400) {
  228.           if(tileX == 0)
  229.             screenSource++;
  230.         } else if(tileX == 7)
  231.           screenSource++;
  232.  
  233.         if(x == 255 && sizeX > 256) {
  234.           screenSource = screenBase + 0x400 + ((yy>>3)*32);
  235.         }        
  236.       }
  237.     }
  238.   }
  239.   /*
  240.     switch(bg) {
  241.     case 0:
  242.     renderView(BG0HOFS<<8, BG0VOFS<<8,
  243.     0x100, 0x000,
  244.     0x000, 0x100,
  245.     (sizeX -1) <<8,
  246.     (sizeY -1) << 8,
  247.     true);
  248.     break;
  249.     case 1:
  250.     renderView(BG1HOFS<<8, BG1VOFS<<8,
  251.     0x100, 0x000,
  252.     0x000, 0x100,
  253.     (sizeX -1) <<8,
  254.     (sizeY -1) << 8,
  255.     true);
  256.     break;
  257.     case 2:
  258.     renderView(BG2HOFS<<8, BG2VOFS<<8,
  259.     0x100, 0x000,
  260.     0x000, 0x100,
  261.     (sizeX -1) <<8,
  262.     (sizeY -1) << 8,
  263.     true);
  264.     break;
  265.     case 3:
  266.     renderView(BG3HOFS<<8, BG3VOFS<<8,
  267.     0x100, 0x000,
  268.     0x000, 0x100,
  269.     (sizeX -1) <<8,
  270.     (sizeY -1) << 8,
  271.     true);
  272.     break;
  273.     }
  274.   */
  275. }
  276.  
  277. void MapView::renderRotScreen(u16 control)
  278. {
  279.   u16 *palette = (u16 *)paletteRAM;
  280.   u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
  281.   u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800];
  282.   u8 *bmp = data;
  283.  
  284.   int sizeX = 128;
  285.   int sizeY = 128;
  286.   switch((control >> 14) & 3) {
  287.   case 0:
  288.     break;
  289.   case 1:
  290.     sizeX = sizeY = 256;
  291.     break;
  292.   case 2:
  293.     sizeX = sizeY = 512;
  294.     break;
  295.   case 3:
  296.     sizeX = sizeY = 1024;
  297.     break;
  298.   }
  299.  
  300.   w = sizeX;
  301.   h = sizeY;
  302.   
  303.   if(control & 0x80) {
  304.     for(int y = 0; y < sizeY; y++) {
  305.       for(int x = 0; x < sizeX; x++) {
  306.         int tile = screenBase[(x>>3) + (y>>3)*(w>>3)];
  307.         
  308.         int tileX = (x & 7);
  309.         int tileY = y & 7;
  310.         
  311.         u8 color = charBase[tile * 64 + tileY * 8 + tileX];
  312.         u16 color2 = palette[color];
  313.  
  314.         *bmp++ = ((color2 >> 10) & 0x1f) << 3;
  315.         *bmp++ = ((color2 >> 5) & 0x1f) << 3;
  316.         *bmp++ = (color2 & 0x1f) << 3;
  317.       }
  318.     }
  319.   } else {
  320.     for(int y = 0; y < sizeY; y++) {
  321.       for(int x = 0; x < sizeX; x++) {
  322.         int tile = screenBase[(x>>3) + (y>>3)*(w>>3)];
  323.         
  324.         int tileX = (x & 7);
  325.         int tileY = y & 7;
  326.         
  327.         u8 color = charBase[tile * 64 + tileY * 8 + tileX];
  328.         u16 color2 = palette[color];
  329.  
  330.         *bmp++ = ((color2 >> 10) & 0x1f) << 3;
  331.         *bmp++ = ((color2 >> 5) & 0x1f) << 3;
  332.         *bmp++ = (color2 & 0x1f) << 3;        
  333.       }
  334.     }    
  335.   }
  336.  
  337.   u32 xx;
  338.   u32 yy;
  339.   
  340.   switch(bg) {
  341.   case 2:
  342.     xx = BG2X_L | BG2X_H << 16;
  343.     yy = BG2Y_L | BG2Y_H << 16;
  344.  
  345.     /*    
  346.           renderView(xx, yy, 
  347.           BG2PA, BG2PC,
  348.           BG2PB, BG2PD,
  349.           (sizeX -1) <<8,
  350.           (sizeY -1) << 8,
  351.           (control & 0x2000) != 0);
  352.     */
  353.     break;
  354.   case 3:
  355.     xx = BG3X_L | BG3X_H << 16;
  356.     yy = BG3Y_L | BG3Y_H << 16;
  357.     /*    
  358.           renderView(xx, yy, 
  359.           BG3PA, BG3PC,
  360.           BG3PB, BG3PD,
  361.           (sizeX -1) <<8,
  362.           (sizeY -1) << 8,
  363.           (control & 0x2000) != 0);
  364.     */
  365.     break;
  366.   }
  367. }
  368.  
  369. void MapView::renderMode0()
  370. {
  371.   renderTextScreen(control);
  372. }
  373.  
  374. void MapView::renderMode1()
  375. {
  376.   switch(bg) {
  377.   case 0:
  378.   case 1:
  379.     renderTextScreen(control);
  380.     break;
  381.   case 2:
  382.     renderRotScreen(control);
  383.     break;
  384.   default:
  385.     bg = 0;
  386.     control = BG0CNT;
  387.     renderTextScreen(control);
  388.     break;
  389.   }
  390. }
  391.  
  392. void MapView::renderMode2()
  393. {
  394.   switch(bg) {
  395.   case 2:
  396.   case 3:
  397.     renderRotScreen(control);
  398.     break;
  399.   default:
  400.     bg = 2;
  401.     control = BG2CNT;
  402.     renderRotScreen(control);
  403.     break;
  404.   }  
  405. }
  406.  
  407. void MapView::renderMode3()
  408. {
  409.   u8 *bmp = data;
  410.   u16 *src = (u16 *)&vram[0];
  411.  
  412.   w = 240;
  413.   h = 160;
  414.   
  415.   for(int y = 0; y < 160; y++) {
  416.     for(int x = 0; x < 240; x++) {
  417.       u16 data = *src++;
  418.       *bmp++ = ((data >> 10) & 0x1f) << 3;
  419.       *bmp++ = ((data >> 5) & 0x1f) << 3;
  420.       *bmp++ = (data & 0x1f) << 3;      
  421.     }
  422.   }
  423.   bg = 2;
  424. }
  425.  
  426.  
  427. void MapView::renderMode4()
  428. {
  429.   u8 *bmp = data;
  430.   u8 *src = frame ? &vram[0xa000] : &vram[0];
  431.   u16 *pal = (u16 *)&paletteRAM[0];
  432.   
  433.   w = 240;
  434.   h = 160;
  435.   
  436.   for(int y = 0; y < 160; y++) {
  437.     for(int x = 0; x < 240; x++) {
  438.       u8 c = *src++;
  439.       u16 data = pal[c];
  440.       *bmp++ = ((data >> 10) & 0x1f) << 3;
  441.       *bmp++ = ((data >> 5) & 0x1f) << 3;
  442.       *bmp++ = (data & 0x1f) << 3;      
  443.     }
  444.   }
  445.   bg = 2;
  446. }
  447.  
  448.  
  449. void MapView::renderMode5()
  450. {
  451.   u8 *bmp = data;
  452.   u16 *src = (u16 *)(frame ? &vram[0xa000] : &vram[0]);
  453.  
  454.   w = 160;
  455.   h = 128;
  456.   
  457.   for(int y = 0; y < 128; y++) {
  458.     for(int x = 0; x < 160; x++) {
  459.       u16 data = *src++;
  460.       *bmp++ = ((data >> 10) & 0x1f) << 3;
  461.       *bmp++ = ((data >> 5) & 0x1f) << 3;
  462.       *bmp++ = (data & 0x1f) << 3;      
  463.     }
  464.   }
  465.   bg = 2;
  466. }
  467.  
  468. void MapView::OnRefresh() 
  469. {
  470.   paint();  
  471. }
  472.  
  473. void MapView::paint()
  474. {
  475.   if(vram == NULL)
  476.     return;
  477.   int mode = DISPCNT & 7;
  478.  
  479.   switch(bg) {
  480.   default:
  481.   case 0:
  482.     control = BG0CNT;
  483.     break;
  484.   case 1:
  485.     control = BG1CNT;
  486.     break;
  487.   case 2:
  488.     control = BG2CNT;
  489.     break;
  490.   case 3:
  491.     control = BG3CNT;
  492.     break;
  493.   }
  494.   
  495.   switch(mode) {
  496.   case 0:
  497.     renderMode0();
  498.     break;
  499.   case 1:
  500.     renderMode1();
  501.     break;
  502.   case 2:
  503.     renderMode2();
  504.     break;
  505.   case 3:
  506.     renderMode3();
  507.     break;
  508.   case 4:
  509.     renderMode4();
  510.     break;
  511.   case 5:
  512.     renderMode5();
  513.     break;
  514.   }
  515.   enableButtons(mode);
  516.   SIZE s;
  517.   
  518.   if(mapView.getStretch()) {
  519.     mapView.setSize(w, h);
  520.     s.cx = s.cy = 1;
  521.     mapView.SetScrollSizes(MM_TEXT, s);
  522.   } else {
  523.     mapView.setSize(w, h);
  524.     s.cx = w;
  525.     s.cy = h;
  526.     mapView.SetScrollSizes(MM_TEXT, s);
  527.   }
  528.  
  529.   mapView.refresh();
  530.  
  531.   CString buffer;
  532.   
  533.   u32 charBase = ((control >> 2) & 0x03) * 0x4000 + 0x6000000;
  534.   u32 screenBase = ((control >> 8) & 0x1f) * 0x800 + 0x6000000;  
  535.  
  536.   buffer.Format("%d", mode);
  537.   m_mode.SetWindowText(buffer);
  538.  
  539.   if(mode >= 3) {
  540.     m_mapbase.SetWindowText("");
  541.     m_charbase.SetWindowText("");
  542.   } else {
  543.     buffer.Format("0x%08X", screenBase);
  544.     m_mapbase.SetWindowText(buffer);
  545.     
  546.     buffer.Format("0x%08X", charBase);
  547.     m_charbase.SetWindowText(buffer);
  548.   }
  549.  
  550.   buffer.Format("%dx%d", w, h);
  551.   m_dim.SetWindowText(buffer);
  552.  
  553.   m_numcolors.SetWindowText(control & 0x80 ? "256" : "16");
  554.  
  555.   buffer.Format("%d", control & 3);
  556.   m_priority.SetWindowText(buffer);
  557.  
  558.   m_mosaic.SetWindowText(control & 0x40 ? "1" : "0");
  559.  
  560.   m_overflow.SetWindowText(bg <= 1 ? "" :
  561.                            control & 0x2000 ? "1" : "0");
  562. }
  563.  
  564. BOOL MapView::OnInitDialog() 
  565. {
  566.   CDialog::OnInitDialog();
  567.   
  568.   DIALOG_SIZER_START( sz )
  569.     DIALOG_SIZER_ENTRY( IDC_MAP_VIEW, DS_SizeX | DS_SizeY )
  570.     DIALOG_SIZER_ENTRY( IDC_REFRESH, DS_MoveY)
  571.     DIALOG_SIZER_ENTRY( IDC_CLOSE, DS_MoveY)
  572.     DIALOG_SIZER_ENTRY( IDC_SAVE,  DS_MoveY)
  573.     DIALOG_SIZER_ENTRY( IDC_COLOR, DS_MoveY)
  574.     DIALOG_SIZER_ENTRY( IDC_R, DS_MoveY)
  575.     DIALOG_SIZER_ENTRY( IDC_G, DS_MoveY)
  576.     DIALOG_SIZER_ENTRY( IDC_B, DS_MoveY)    
  577.     DIALOG_SIZER_END()
  578.     SetData(sz,
  579.             TRUE,
  580.             HKEY_CURRENT_USER,
  581.             "Software\\Emulators\\VisualBoyAdvance\\Viewer\\MapView",
  582.             NULL);
  583.   SIZE size;
  584.   size.cx = 1;
  585.   size.cy = 1;
  586.   mapView.SetScrollSizes(MM_TEXT,size);
  587.   int s = regQueryDwordValue("mapViewStretch", 0);
  588.   if(s)
  589.     mapView.setStretch(true);
  590.   ((CButton *)GetDlgItem(IDC_STRETCH))->SetCheck(s);
  591.   paint();
  592.   
  593.   return TRUE;  // return TRUE unless you set the focus to a control
  594.                 // EXCEPTION: OCX Property Pages should return FALSE
  595. }
  596.  
  597. void MapView::PostNcDestroy() 
  598. {
  599.   delete this;
  600. }
  601.  
  602. void MapView::enableButtons(int mode)
  603. {
  604.   bool enable[6] = { true, true, true, true, true, true };
  605.  
  606.   switch(mode) {
  607.   case 0:
  608.     enable[4] = false;
  609.     enable[5] = false;
  610.     break;
  611.   case 1:
  612.     enable[3] = false;
  613.     enable[4] = false;
  614.     enable[5] = false;
  615.     break;
  616.   case 2:
  617.     enable[0] = false;
  618.     enable[1] = false;
  619.     enable[4] = false;
  620.     enable[5] = false;
  621.     break;
  622.   case 3:
  623.     enable[0] = false;
  624.     enable[1] = false;
  625.     enable[2] = false;
  626.     enable[3] = false;
  627.     enable[4] = false;
  628.     enable[5] = false;
  629.     break;
  630.   case 4:
  631.     enable[0] = false;
  632.     enable[1] = false;
  633.     enable[2] = false;
  634.     enable[3] = false;
  635.     break;    
  636.   case 5:
  637.     enable[0] = false;
  638.     enable[1] = false;
  639.     enable[2] = false;
  640.     enable[3] = false;
  641.     break;    
  642.   }
  643.   GetDlgItem(IDC_BG0)->EnableWindow(enable[0]);
  644.   GetDlgItem(IDC_BG1)->EnableWindow(enable[1]);
  645.   GetDlgItem(IDC_BG2)->EnableWindow(enable[2]);
  646.   GetDlgItem(IDC_BG3)->EnableWindow(enable[3]);
  647.   GetDlgItem(IDC_FRAME_0)->EnableWindow(enable[4]);
  648.   GetDlgItem(IDC_FRAME_1)->EnableWindow(enable[5]);
  649.   int id = IDC_BG0;
  650.   switch(bg) {
  651.   case 1:
  652.     id = IDC_BG1;
  653.     break;
  654.   case 2:
  655.     id = IDC_BG2;
  656.     break;
  657.   case 3:
  658.     id = IDC_BG3;
  659.     break;
  660.   }
  661.   CheckRadioButton(IDC_BG0, IDC_BG3, id);
  662.   id = IDC_FRAME_0;
  663.   if(frame != 0)
  664.     id = IDC_FRAME_1;
  665.   CheckRadioButton(IDC_FRAME_0, IDC_FRAME_1, id);
  666. }
  667.  
  668. void MapView::OnFrame0() 
  669. {
  670.   frame = 0;
  671.   paint();  
  672. }
  673.  
  674. void MapView::OnFrame1() 
  675. {
  676.   frame = 1;
  677.   paint();
  678. }
  679.  
  680. void MapView::OnBg0() 
  681. {
  682.   bg = 0;
  683.   control = BG0CNT;
  684.   paint();
  685. }
  686.  
  687. void MapView::OnBg1() 
  688. {
  689.   bg = 1;
  690.   control = BG1CNT;
  691.   paint();
  692. }
  693.  
  694. void MapView::OnBg2() 
  695. {
  696.   bg = 2;
  697.   control = BG2CNT;
  698.   paint();
  699. }
  700.  
  701. void MapView::OnBg3() 
  702. {
  703.   bg = 3;
  704.   control = BG3CNT;
  705.   paint();
  706. }
  707.  
  708. void MapView::OnStretch() 
  709. {
  710.   mapView.setStretch(!mapView.getStretch());
  711.   paint();
  712.   regSetDwordValue("mapViewStretch", mapView.getStretch());  
  713. }
  714.  
  715. void MapView::OnAutoUpdate() 
  716. {
  717.   autoUpdate = !autoUpdate;
  718.   if(autoUpdate) {
  719.     theApp.winAddUpdateListener(this);
  720.   } else {
  721.     theApp.winRemoveUpdateListener(this);    
  722.   }
  723. }
  724.  
  725. void MapView::update()
  726. {
  727.   paint();
  728. }
  729.  
  730. void MapView::OnClose() 
  731. {
  732.   theApp.winRemoveUpdateListener(this);
  733.   
  734.   DestroyWindow();
  735. }
  736.  
  737. u32 MapView::GetTextClickAddress(u32 base, int x, int y)
  738. {
  739.   if(y > 255 && h > 256) {
  740.     base += 0x800;
  741.     if(w > 256)
  742.       base += 0x800;
  743.   }
  744.   if(x >= 256)
  745.     base += 0x800;
  746.   x &= 255;
  747.   y &= 255;
  748.   base += (x>>3)*2 + 64*(y>>3);
  749.  
  750.   return base;
  751. }
  752.  
  753.  
  754.  
  755. u32 MapView::GetClickAddress(int x, int y)
  756. {
  757.   int mode = DISPCNT & 7;
  758.  
  759.   u32 base = ((control >> 8) & 0x1f) * 0x800 + 0x6000000;
  760.   
  761.   // all text bgs (16 bits)
  762.   if(mode == 0 ||(mode < 3 && bg < 2)) {
  763.     return GetTextClickAddress(base, x, y);
  764.   }
  765.   // rot bgs (8 bits)
  766.   if(mode < 3) {
  767.     return base + (x>>3) + (w>>3)*(y>>3);
  768.   }
  769.   // mode 3/5 (16 bits)
  770.   if(mode != 4) {
  771.     return 0x6000000 + 0xa000*frame + 2*x + w*y*2;
  772.   }
  773.   // mode 4 (8 bits)
  774.   return 0x6000000 + 0xa000*frame + x + w*y;
  775. }
  776.  
  777. LRESULT MapView::OnMapInfo(WPARAM wParam, LPARAM lParam)
  778. {
  779.   u8 *colors = (u8 *)lParam;
  780.   mapViewZoom.setColors(colors);
  781.  
  782.   int x = wParam & 0xffff;
  783.   int y = (wParam >> 16);
  784.   
  785.   CString buffer;
  786.   buffer.Format("(%d,%d)", x, y);
  787.   GetDlgItem(IDC_XY)->SetWindowText(buffer);
  788.  
  789.   u32 address = GetClickAddress(x,y);
  790.   buffer.Format("0x%08X", address);
  791.   GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer);
  792.  
  793.   int mode = DISPCNT & 7;  
  794.   if(mode >= 3) {
  795.     // bitmap modes
  796.     GetDlgItem(IDC_TILE_NUM)->SetWindowText("---");
  797.     GetDlgItem(IDC_FLIP)->SetWindowText("--");
  798.     GetDlgItem(IDC_PALETTE_NUM)->SetWindowText("---");
  799.   } else if(mode == 0 || bg < 2) {
  800.     // text bgs
  801.     u16 value = *((u16 *)&vram[address - 0x6000000]);
  802.  
  803.     int tile = value & 1023;
  804.     buffer.Format("%d", tile);
  805.     GetDlgItem(IDC_TILE_NUM)->SetWindowText(buffer);
  806.     buffer.Empty();
  807.     buffer += value & 1024 ? 'H' : '-';
  808.     buffer += value & 2048 ? 'V' : '-';
  809.     GetDlgItem(IDC_FLIP)->SetWindowText(buffer);
  810.  
  811.     if(!(control & 0x80)) {
  812.       buffer.Format("%d", (value >> 12) & 15);
  813.     } else
  814.       buffer = "---";
  815.     GetDlgItem(IDC_PALETTE_NUM)->SetWindowText(buffer);
  816.   } else {
  817.     // rot bgs
  818.     GetDlgItem(IDC_TILE_NUM)->SetWindowText("---");
  819.     GetDlgItem(IDC_FLIP)->SetWindowText("--");
  820.     GetDlgItem(IDC_PALETTE_NUM)->SetWindowText("---");
  821.   }
  822.   
  823.   return TRUE;
  824. }
  825.  
  826. LRESULT MapView::OnColInfo(WPARAM wParam, LPARAM lParam)
  827. {
  828.   u16 c = (u16)wParam;
  829.  
  830.   color.setColor(c);  
  831.  
  832.   int r = (c & 0x1f);
  833.   int g = (c & 0x3e0) >> 5;
  834.   int b = (c & 0x7c00) >> 10;
  835.  
  836.   CString buffer;
  837.   buffer.Format("R: %d", r);
  838.   GetDlgItem(IDC_R)->SetWindowText(buffer);
  839.  
  840.   buffer.Format("G: %d", g);
  841.   GetDlgItem(IDC_G)->SetWindowText(buffer);
  842.  
  843.   buffer.Format("B: %d", b);
  844.   GetDlgItem(IDC_B)->SetWindowText(buffer);
  845.  
  846.   return TRUE;
  847. }
  848.  
  849. void MapView::saveBMP(const char *name)
  850. {
  851.   u8 writeBuffer[1024 * 3];
  852.   
  853.   FILE *fp = fopen(name,"wb");
  854.  
  855.   if(!fp) {
  856.     systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
  857.     return;
  858.   }
  859.  
  860.   struct {
  861.     u8 ident[2];
  862.     u8 filesize[4];
  863.     u8 reserved[4];
  864.     u8 dataoffset[4];
  865.     u8 headersize[4];
  866.     u8 width[4];
  867.     u8 height[4];
  868.     u8 planes[2];
  869.     u8 bitsperpixel[2];
  870.     u8 compression[4];
  871.     u8 datasize[4];
  872.     u8 hres[4];
  873.     u8 vres[4];
  874.     u8 colors[4];
  875.     u8 importantcolors[4];
  876.     u8 pad[2];
  877.   } bmpheader;
  878.   memset(&bmpheader, 0, sizeof(bmpheader));
  879.  
  880.   bmpheader.ident[0] = 'B';
  881.   bmpheader.ident[1] = 'M';
  882.  
  883.   u32 fsz = sizeof(bmpheader) + w*h*3;
  884.   utilPutDword(bmpheader.filesize, fsz);
  885.   utilPutDword(bmpheader.dataoffset, 0x38);
  886.   utilPutDword(bmpheader.headersize, 0x28);
  887.   utilPutDword(bmpheader.width, w);
  888.   utilPutDword(bmpheader.height, h);
  889.   utilPutDword(bmpheader.planes, 1);
  890.   utilPutDword(bmpheader.bitsperpixel, 24);
  891.   utilPutDword(bmpheader.datasize, 3*w*h);
  892.  
  893.   fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
  894.  
  895.   u8 *b = writeBuffer;
  896.  
  897.   int sizeX = w;
  898.   int sizeY = h;
  899.  
  900.   u8 *pixU8 = (u8 *)data+3*w*(h-1);
  901.   for(int y = 0; y < sizeY; y++) {
  902.     for(int x = 0; x < sizeX; x++) {
  903.       *b++ = *pixU8++; // B
  904.       *b++ = *pixU8++; // G
  905.       *b++ = *pixU8++; // R
  906.     }
  907.     pixU8 -= 2*3*w;
  908.     fwrite(writeBuffer, 1, 3*w, fp);
  909.     
  910.     b = writeBuffer;
  911.   }
  912.  
  913.   fclose(fp);
  914. }
  915.  
  916.  
  917.  
  918. void MapView::savePNG(const char *name)
  919. {
  920.   u8 writeBuffer[1024 * 3];
  921.   
  922.   FILE *fp = fopen(name,"wb");
  923.  
  924.   if(!fp) {
  925.     systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
  926.     return;
  927.   }
  928.   
  929.   png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
  930.                                                 NULL,
  931.                                                 NULL,
  932.                                                 NULL);
  933.   if(!png_ptr) {
  934.     fclose(fp);
  935.     return;
  936.   }
  937.  
  938.   png_infop info_ptr = png_create_info_struct(png_ptr);
  939.  
  940.   if(!info_ptr) {
  941.     png_destroy_write_struct(&png_ptr,NULL);
  942.     fclose(fp);
  943.     return;
  944.   }
  945.  
  946.   if(setjmp(png_ptr->jmpbuf)) {
  947.     png_destroy_write_struct(&png_ptr,NULL);
  948.     fclose(fp);
  949.     return;
  950.   }
  951.  
  952.   png_init_io(png_ptr,fp);
  953.  
  954.   png_set_IHDR(png_ptr,
  955.                info_ptr,
  956.                w,
  957.                h,
  958.                8,
  959.                PNG_COLOR_TYPE_RGB,
  960.                PNG_INTERLACE_NONE,
  961.                PNG_COMPRESSION_TYPE_DEFAULT,
  962.                PNG_FILTER_TYPE_DEFAULT);
  963.  
  964.   png_write_info(png_ptr,info_ptr);
  965.  
  966.   u8 *b = writeBuffer;
  967.  
  968.   int sizeX = w;
  969.   int sizeY = h;
  970.  
  971.   u8 *pixU8 = (u8 *)data;
  972.   for(int y = 0; y < sizeY; y++) {
  973.     for(int x = 0; x < sizeX; x++) {
  974.       int blue = *pixU8++;
  975.       int green = *pixU8++;
  976.       int red = *pixU8++;
  977.       
  978.       *b++ = red;
  979.       *b++ = green;
  980.       *b++ = blue;
  981.     }
  982.     png_write_row(png_ptr,writeBuffer);
  983.     
  984.     b = writeBuffer;
  985.   }
  986.   
  987.   png_write_end(png_ptr, info_ptr);
  988.  
  989.   png_destroy_write_struct(&png_ptr, &info_ptr);
  990.  
  991.   fclose(fp);
  992. }
  993.  
  994. void MapView::OnSave() 
  995. {
  996.   CString filename;
  997.  
  998.   if(theApp.captureFormat == 0)
  999.     filename = "map.png";
  1000.   else
  1001.     filename = "map.bmp";
  1002.  
  1003.   LPCTSTR exts[] = {".png", ".bmp" };
  1004.  
  1005.   CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
  1006.   CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
  1007.  
  1008.   FileDlg dlg(this,
  1009.               filename,
  1010.               filter,
  1011.               theApp.captureFormat ? 2 : 1,
  1012.               theApp.captureFormat ? "BMP" : "PNG",
  1013.               exts,
  1014.               "",
  1015.               title,
  1016.               true);
  1017.  
  1018.   if(dlg.DoModal() == IDCANCEL) {
  1019.     return;
  1020.   }
  1021.  
  1022.   if(dlg.getFilterIndex() == 2)
  1023.     saveBMP(dlg.GetPathName());
  1024.   else
  1025.     savePNG(dlg.GetPathName());
  1026. }
  1027.