home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / win32 / GDIDisplay.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  10.6 KB  |  423 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. #include "stdafx.h"
  20. #include <stdio.h>
  21.  
  22. #include "../System.h"
  23. #include "../GBA.h"
  24. #include "../Globals.h"
  25. #include "../Text.h"
  26.  
  27. #include "VBA.h"
  28. #include "MainWnd.h"
  29. #include "Reg.h"
  30. #include "resource.h"
  31.  
  32. #ifdef _DEBUG
  33. #define new DEBUG_NEW
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37.  
  38. extern void winlog(const char *,...);
  39. extern int RGB_LOW_BITS_MASK;
  40. extern int Init_2xSaI(u32);
  41. extern int systemSpeed;
  42.  
  43. class GDIDisplay : public IDisplay {
  44. private:
  45.   u8 *filterData;
  46.   u8 info[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
  47.   
  48. public:
  49.   GDIDisplay();
  50.   virtual ~GDIDisplay();
  51.  
  52.   virtual bool initialize();
  53.   virtual void cleanup();
  54.   virtual void render();
  55.   virtual void checkFullScreen();
  56.   virtual void renderMenu();
  57.   virtual void clear();
  58.   virtual DISPLAY_TYPE getType() { return GDI; };
  59.   virtual void setOption(const char *, int) {}
  60.   virtual bool isSkinSupported() { return true; }
  61.   virtual int selectFullScreenMode(GUID **);
  62. };
  63.  
  64. static int calculateShift(u32 mask)
  65. {
  66.   int m = 0;
  67.   
  68.   while(mask) {
  69.     m++;
  70.     mask >>= 1;
  71.   }
  72.  
  73.   return m-5;
  74. }
  75.  
  76. GDIDisplay::GDIDisplay()
  77. {
  78.   filterData = (u8 *)malloc(4*4*256*240);
  79. }
  80.  
  81. GDIDisplay::~GDIDisplay()
  82. {
  83.   cleanup();
  84. }
  85.  
  86. void GDIDisplay::cleanup()
  87. {
  88.   if(filterData) {
  89.     free(filterData);
  90.     filterData = NULL;
  91.   }
  92. }
  93.  
  94. bool GDIDisplay::initialize()
  95. {
  96.   theApp.sizeX = 240;
  97.   theApp.sizeY = 160;
  98.   switch(theApp.videoOption) {
  99.   case VIDEO_1X:
  100.     theApp.surfaceSizeX = theApp.sizeX;
  101.     theApp.surfaceSizeY = theApp.sizeY;
  102.     break;
  103.   case VIDEO_2X:
  104.     theApp.surfaceSizeX = theApp.sizeX * 2;
  105.     theApp.surfaceSizeY = theApp.sizeY * 2;
  106.     break;
  107.   case VIDEO_3X:
  108.     theApp.surfaceSizeX = theApp.sizeX * 3;
  109.     theApp.surfaceSizeY = theApp.sizeY * 3;
  110.     break;
  111.   case VIDEO_4X:
  112.     theApp.surfaceSizeX = theApp.sizeX * 4;
  113.     theApp.surfaceSizeY = theApp.sizeY * 4;
  114.     break;
  115.   case VIDEO_320x240:
  116.   case VIDEO_640x480:
  117.   case VIDEO_800x600:
  118.   case VIDEO_OTHER:
  119.     {
  120.       int scaleX = (theApp.fsWidth / theApp.sizeX);
  121.       int scaleY = (theApp.fsHeight / theApp.sizeY);
  122.       int min = scaleX < scaleY ? scaleX : scaleY;
  123.       if(theApp.fsMaxScale)
  124.         min = min > theApp.fsMaxScale ? theApp.fsMaxScale : min;
  125.       theApp.surfaceSizeX = theApp.sizeX * min;
  126.       theApp.surfaceSizeY = theApp.sizeY * min;
  127.       if(theApp.fullScreenStretch) {
  128.         theApp.surfaceSizeX = theApp.fsWidth;
  129.         theApp.surfaceSizeY = theApp.fsHeight;
  130.       }
  131.     }
  132.     break;
  133.   }
  134.   
  135.   theApp.rect.left = 0;
  136.   theApp.rect.top = 0;
  137.   theApp.rect.right = theApp.sizeX;
  138.   theApp.rect.bottom = theApp.sizeY;
  139.  
  140.   theApp.dest.left = 0;
  141.   theApp.dest.top = 0;
  142.   theApp.dest.right = theApp.surfaceSizeX;
  143.   theApp.dest.bottom = theApp.surfaceSizeY;
  144.  
  145.   DWORD style = WS_POPUP | WS_VISIBLE;
  146.   DWORD styleEx = 0;
  147.   
  148.   if(theApp.videoOption <= VIDEO_4X)
  149.     style |= WS_OVERLAPPEDWINDOW;
  150.   else
  151.     styleEx = 0;
  152.  
  153.   if(theApp.videoOption <= VIDEO_4X)
  154.     AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
  155.   else
  156.     AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);    
  157.  
  158.   int winSizeX = theApp.dest.right-theApp.dest.left;
  159.   int winSizeY = theApp.dest.bottom-theApp.dest.top;
  160.  
  161.   if(theApp.videoOption > VIDEO_4X) {
  162.     winSizeX = theApp.fsWidth;
  163.     winSizeY = theApp.fsHeight;
  164.   }
  165.   
  166.   int x = 0;
  167.   int y = 0;
  168.  
  169.   if(theApp.videoOption <= VIDEO_4X) {
  170.     x = theApp.windowPositionX;
  171.     y = theApp.windowPositionY;
  172.   }
  173.   
  174.   // Create a window
  175.   MainWnd *pWnd = new MainWnd;
  176.   theApp.m_pMainWnd = pWnd;
  177.  
  178.   pWnd->CreateEx(styleEx,
  179.                  theApp.wndClass,
  180.                  "VisualBoyAdvance",
  181.                  style,
  182.                  x,y,winSizeX,winSizeY,
  183.                  NULL,
  184.                  0);
  185.   
  186.   if (!(HWND)*pWnd) {
  187.     winlog("Error creating Window %08x\n", GetLastError());
  188.     return FALSE;
  189.   }
  190.   
  191.   theApp.updateMenuBar();
  192.   
  193.   theApp.adjustDestRect();
  194.   
  195.   theApp.mode320Available = false;
  196.   theApp.mode640Available = false;
  197.   theApp.mode800Available = false;
  198.   
  199.   HDC dc = GetDC(NULL);
  200.   HBITMAP hbm = CreateCompatibleBitmap(dc, 1, 1);
  201.   BITMAPINFO *bi = (BITMAPINFO *)info;
  202.   ZeroMemory(bi, sizeof(info));
  203.   bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  204.   GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);  
  205.   GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
  206.   DeleteObject(hbm);
  207.   ReleaseDC(NULL, dc);
  208.  
  209.   if(bi->bmiHeader.biCompression == BI_BITFIELDS) {
  210.     systemColorDepth = bi->bmiHeader.biBitCount;
  211.     if(systemColorDepth == 15)
  212.       systemColorDepth = 16;
  213.     systemRedShift = calculateShift(*((DWORD *)&bi->bmiColors[0]));
  214.     systemGreenShift = calculateShift(*((DWORD *)&bi->bmiColors[1]));
  215.     systemBlueShift = calculateShift(*((DWORD *)&bi->bmiColors[2]));
  216.     if(systemColorDepth == 16) {
  217.       if(systemGreenShift == 6) {
  218.         Init_2xSaI(565);
  219.         RGB_LOW_BITS_MASK=0x821;
  220.       } else {
  221.         Init_2xSaI(555);
  222.         RGB_LOW_BITS_MASK=0x421;        
  223.       }
  224.     } else if(systemColorDepth == 32)
  225.       Init_2xSaI(32);
  226.   } else {
  227.     systemColorDepth = 32;
  228.     systemRedShift = 19;
  229.     systemGreenShift = 11;
  230.     systemBlueShift = 3;
  231.  
  232.     Init_2xSaI(32);    
  233.   }
  234.   theApp.fsColorDepth = systemColorDepth;
  235.   if(systemColorDepth == 24)
  236.     theApp.filterFunction = NULL;
  237. #ifdef MMX
  238.   if(!theApp.disableMMX)
  239.     cpu_mmx = theApp.detectMMX();
  240.   else
  241.     cpu_mmx = 0;
  242. #endif
  243.   
  244.   switch(systemColorDepth) {
  245.   case 16:
  246.     {
  247.       for(int i = 0; i < 0x10000; i++) {
  248.         systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
  249.           (((i & 0x3e0) >> 5) << systemGreenShift) |
  250.           (((i & 0x7c00) >> 10) << systemBlueShift);
  251.       }
  252.     }
  253.     break;
  254.   case 24:
  255.   case 32:
  256.     {
  257.       for(int i = 0; i < 0x10000; i++) {
  258.         systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
  259.           (((i & 0x3e0) >> 5) << systemGreenShift) |
  260.           (((i & 0x7c00) >> 10) << systemBlueShift);
  261.       }      
  262.     }
  263.     break;
  264.   }
  265.   theApp.updateFilter();
  266.   theApp.updateIFB();
  267.   
  268.   pWnd->DragAcceptFiles(TRUE);
  269.   
  270.   return TRUE;  
  271. }
  272.  
  273. void GDIDisplay::clear()
  274. {
  275. }
  276.  
  277. void GDIDisplay::renderMenu()
  278. {
  279.   checkFullScreen();
  280.   theApp.m_pMainWnd->DrawMenuBar();
  281. }
  282.  
  283. void GDIDisplay::checkFullScreen()
  284. {
  285. }
  286.  
  287. void GDIDisplay::render()
  288.   BITMAPINFO *bi = (BITMAPINFO *)info;
  289.   bi->bmiHeader.biWidth = theApp.filterWidth+1;
  290.   bi->bmiHeader.biHeight = -theApp.filterHeight;
  291.  
  292.   int pitch = theApp.filterWidth * 2 + 4;
  293.   if(systemColorDepth == 24)
  294.     pitch = theApp.filterWidth * 3;
  295.   else if(systemColorDepth == 32)
  296.     pitch = theApp.filterWidth * 4 + 4;
  297.   
  298.   if(theApp.filterFunction) {
  299.     bi->bmiHeader.biWidth = theApp.filterWidth * 2;
  300.     bi->bmiHeader.biHeight = -theApp.filterHeight * 2;
  301.     
  302.     if(systemColorDepth == 16)
  303.       (*theApp.filterFunction)(pix+pitch,
  304.                                pitch,
  305.                                (u8*)theApp.delta,
  306.                                (u8*)filterData,
  307.                                theApp.filterWidth*2*2,
  308.                                theApp.filterWidth,
  309.                                theApp.filterHeight);
  310.     else
  311.       (*theApp.filterFunction)(pix+pitch,
  312.                                pitch,
  313.                                (u8*)theApp.delta,
  314.                                (u8*)filterData,
  315.                                theApp.filterWidth*4*2,
  316.                                theApp.filterWidth,
  317.                                theApp.filterHeight);
  318.   }
  319.  
  320.   if(theApp.showSpeed && (theApp.videoOption > VIDEO_4X || theApp.skin != NULL)) {
  321.     char buffer[30];
  322.     if(theApp.showSpeed == 1)
  323.       sprintf(buffer, "%3d%%", systemSpeed);
  324.     else
  325.       sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
  326.               systemFrameSkip,
  327.               theApp.showRenderedFrames);
  328.  
  329.     if(theApp.filterFunction) {
  330.       int p = theApp.filterWidth * 4;
  331.       if(systemColorDepth == 24)
  332.         p = theApp.filterWidth * 6;
  333.       else if(systemColorDepth == 32)
  334.         p = theApp.filterWidth * 8;
  335.       if(theApp.showSpeedTransparent)
  336.         drawTextTransp((u8*)filterData,
  337.                        p,
  338.                        10,
  339.                        theApp.filterHeight*2-10,
  340.                        buffer);
  341.       else
  342.         drawText((u8*)filterData,
  343.                  p,
  344.                  10,
  345.                  theApp.filterHeight*2-10,
  346.                  buffer);      
  347.     } else {
  348.       if(theApp.showSpeedTransparent)
  349.         drawTextTransp((u8*)pix,
  350.                        pitch,
  351.                        10,
  352.                        theApp.filterHeight-10,
  353.                        buffer);
  354.       else
  355.         drawText((u8*)pix,
  356.                  pitch,
  357.                  10,
  358.                  theApp.filterHeight-10,
  359.                  buffer);
  360.     }
  361.   }
  362.  
  363.   POINT p;
  364.   p.x = theApp.dest.left;
  365.   p.y = theApp.dest.top;
  366.   CWnd *pWnd = theApp.m_pMainWnd;
  367.   pWnd->ScreenToClient(&p);
  368.   POINT p2;
  369.   p2.x = theApp.dest.right;
  370.   p2.y = theApp.dest.bottom;
  371.   pWnd->ScreenToClient(&p2);
  372.   
  373.   CDC *dc = pWnd->GetDC();
  374.  
  375.   StretchDIBits((HDC)*dc,
  376.                 p.x,
  377.                 p.y,
  378.                 p2.x - p.x,
  379.                 p2.y - p.y,
  380.                 0,
  381.                 0,
  382.                 theApp.rect.right,
  383.                 theApp.rect.bottom,
  384.                 theApp.filterFunction ? filterData : pix+pitch,
  385.                 bi,
  386.                 DIB_RGB_COLORS,
  387.                 SRCCOPY);
  388.  
  389.   if(theApp.screenMessage) {
  390.     if(((GetTickCount() - theApp.screenMessageTime) < 3000) &&
  391.        !theApp.disableStatusMessage) {
  392.       dc->SetTextColor(RGB(255,0,0));
  393.       dc->SetBkMode(TRANSPARENT);
  394.       dc->TextOut(p.x+10, p2.y - 20, theApp.screenMessageBuffer);
  395.     } else {
  396.       theApp.screenMessage = false;
  397.     }
  398.   }
  399.   
  400.   pWnd->ReleaseDC(dc);
  401. }
  402.  
  403. int GDIDisplay::selectFullScreenMode(GUID **)
  404. {
  405.   HWND wnd = GetDesktopWindow();
  406.   RECT r;
  407.   GetWindowRect(wnd, &r);
  408.   int w = (r.right - r.left) & 4095;
  409.   int h = (r.bottom - r.top) & 4095;
  410.   HDC dc = GetDC(wnd);
  411.   int c = GetDeviceCaps(dc, BITSPIXEL);
  412.   ReleaseDC(wnd, dc);
  413.  
  414.   return (c << 24) | (w << 12) | h;
  415. }
  416.  
  417. IDisplay *newGDIDisplay()
  418. {
  419.   return new GDIDisplay();
  420. }
  421.  
  422.