home *** CD-ROM | disk | FTP | other *** search
- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
- // Copyright (C) 1999-2003 Forgotten
- // Copyright (C) 2004 Forgotten and the VBA development team
-
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2, or(at your option)
- // any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software Foundation,
- // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- #include "stdafx.h"
- #include "MainWnd.h"
- #include <gl/GL.h>
-
- #include "../System.h"
- #include "../GBA.h"
- #include "../Globals.h"
- #include "../Text.h"
-
- #include "Reg.h"
- #include "resource.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #ifdef MMX
- extern "C" bool cpu_mmx;
-
- extern bool detectMMX();
- #endif
-
- extern int Init_2xSaI(u32);
- extern void winlog(const char *,...);
- extern int systemSpeed;
-
- class OpenGLDisplay : public IDisplay {
- private:
- HDC hDC;
- HGLRC hglrc;
- GLuint texture;
- int width;
- int height;
- float size;
- u8 *filterData;
- bool failed;
-
- bool initializeTexture(int w, int h);
- void updateFiltering(int);
- public:
- OpenGLDisplay();
- virtual ~OpenGLDisplay();
-
- virtual bool initialize();
- virtual void cleanup();
- virtual void render();
- virtual void checkFullScreen();
- virtual void renderMenu();
- virtual void clear();
- virtual bool changeRenderSize(int w, int h);
- virtual void resize(int w, int h);
- virtual DISPLAY_TYPE getType() { return OPENGL; };
- virtual void setOption(const char *, int);
- virtual int selectFullScreenMode(GUID **);
- };
-
- OpenGLDisplay::OpenGLDisplay()
- {
- hDC = NULL;
- hglrc = NULL;
- texture = 0;
- width = 0;
- height = 0;
- size = 0.0f;
- filterData = (u8 *)malloc(4*4*256*240);
- failed = false;
- }
-
- OpenGLDisplay::~OpenGLDisplay()
- {
- cleanup();
- }
-
- void OpenGLDisplay::cleanup()
- {
- if(texture != 0) {
- glDeleteTextures(1, &texture);
- texture = 0;
- }
- if(hglrc != NULL) {
- wglDeleteContext(hglrc);
- wglMakeCurrent(NULL, NULL);
- hglrc = NULL;
- }
- if(hDC != NULL) {
- ReleaseDC(*theApp.m_pMainWnd, hDC);
- hDC = NULL;
- }
- if(filterData) {
- free(filterData);
- filterData = NULL;
- }
- width = 0;
- height = 0;
- size = 0.0f;
- }
-
- bool OpenGLDisplay::initialize()
- {
- theApp.sizeX = 240;
- theApp.sizeY = 160;
-
- switch(theApp.videoOption) {
- case VIDEO_1X:
- theApp.surfaceSizeX = theApp.sizeX;
- theApp.surfaceSizeY = theApp.sizeY;
- break;
- case VIDEO_2X:
- theApp.surfaceSizeX = theApp.sizeX * 2;
- theApp.surfaceSizeY = theApp.sizeY * 2;
- break;
- case VIDEO_3X:
- theApp.surfaceSizeX = theApp.sizeX * 3;
- theApp.surfaceSizeY = theApp.sizeY * 3;
- break;
- case VIDEO_4X:
- theApp.surfaceSizeX = theApp.sizeX * 4;
- theApp.surfaceSizeY = theApp.sizeY * 4;
- break;
- case VIDEO_320x240:
- case VIDEO_640x480:
- case VIDEO_800x600:
- case VIDEO_OTHER:
- {
- RECT r;
- ::GetWindowRect(GetDesktopWindow(), &r);
- theApp.fsWidth = r.right - r.left;
- theApp.fsHeight = r.bottom - r.top;
-
- /* Need to fix this code later. For now, Fullscreen takes the whole
- screen.
- int scaleX = (fsWidth / sizeX);
- int scaleY = (fsHeight / sizeY);
- int min = scaleX < scaleY ? scaleX : scaleY;
- surfaceSizeX = sizeX * min;
- surfaceSizeY = sizeY * min;
- if(fullScreenStretch) {
- */
- theApp.surfaceSizeX = theApp.fsWidth;
- theApp.surfaceSizeY = theApp.fsHeight;
- // }
- }
- break;
- }
-
- theApp.rect.left = 0;
- theApp.rect.top = 0;
- theApp.rect.right = theApp.sizeX;
- theApp.rect.bottom = theApp.sizeY;
-
- theApp.dest.left = 0;
- theApp.dest.top = 0;
- theApp.dest.right = theApp.surfaceSizeX;
- theApp.dest.bottom = theApp.surfaceSizeY;
-
- DWORD style = WS_POPUP | WS_VISIBLE;
- DWORD styleEx = 0;
-
- if(theApp.videoOption <= VIDEO_4X)
- style |= WS_OVERLAPPEDWINDOW;
- else
- styleEx = 0;
-
- if(theApp.videoOption <= VIDEO_4X)
- AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
- else
- AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);
-
- int winSizeX = theApp.dest.right-theApp.dest.left;
- int winSizeY = theApp.dest.bottom-theApp.dest.top;
-
- if(theApp.videoOption > VIDEO_4X) {
- winSizeX = theApp.fsWidth;
- winSizeY = theApp.fsHeight;
- }
-
- int x = 0;
- int y = 0;
-
- if(theApp.videoOption <= VIDEO_4X) {
- x = theApp.windowPositionX;
- y = theApp.windowPositionY;
- }
-
- // Create a window
- MainWnd *pWnd = new MainWnd;
- theApp.m_pMainWnd = pWnd;
-
- pWnd->CreateEx(styleEx,
- theApp.wndClass,
- "VisualBoyAdvance",
- style,
- x,y,winSizeX,winSizeY,
- NULL,
- 0);
-
- if (!(HWND)*pWnd) {
- winlog("Error creating Window %08x\n", GetLastError());
- return FALSE;
- }
-
- theApp.updateMenuBar();
-
- theApp.adjustDestRect();
-
- theApp.mode320Available = FALSE;
- theApp.mode640Available = FALSE;
- theApp.mode800Available = FALSE;
-
- CDC *dc = pWnd->GetDC();
- HDC hDC = dc->GetSafeHdc();
-
- PIXELFORMATDESCRIPTOR pfd = {
- sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
- 1, // version number
- PFD_DRAW_TO_WINDOW | // support window
- PFD_SUPPORT_OPENGL | // support OpenGL
- PFD_DOUBLEBUFFER, // double buffered
- PFD_TYPE_RGBA, // RGBA type
- 16, // 16-bit color depth
- 0, 0, 0, 0, 0, 0, // color bits ignored
- 0, // no alpha buffer
- 0, // shift bit ignored
- 0, // no accumulation buffer
- 0, 0, 0, 0, // accum bits ignored
- 32, // 32-bit z-buffer
- 0, // no stencil buffer
- 0, // no auxiliary buffer
- PFD_MAIN_PLANE, // main layer
- 0, // reserved
- 0, 0, 0 // layer masks ignored
- };
- int iPixelFormat;
-
- if(!(iPixelFormat = ChoosePixelFormat(hDC, &pfd))) {
- winlog("Failed ChoosePixelFormat\n");
- return false;
- }
-
- // obtain detailed information about
- // the device context's first pixel format
- if(!(DescribePixelFormat(hDC, iPixelFormat,
- sizeof(PIXELFORMATDESCRIPTOR), &pfd))) {
- winlog("Failed DescribePixelFormat\n");
- return false;
- }
-
- if(!SetPixelFormat(hDC, iPixelFormat, &pfd)) {
- winlog("Failed SetPixelFormat\n");
- return false;
- }
-
- if(!(hglrc = wglCreateContext(hDC))) {
- winlog("Failed wglCreateContext\n");
- return false;
- }
-
- if(!wglMakeCurrent(hDC, hglrc)) {
- winlog("Failed wglMakeCurrent\n");
- return false;
- }
- pWnd->ReleaseDC(dc);
-
- // setup 2D gl environment
- glPushAttrib(GL_ENABLE_BIT);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glEnable(GL_TEXTURE_2D);
-
- glViewport(0, 0, theApp.surfaceSizeX, theApp.surfaceSizeY);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glOrtho(0.0, (GLdouble)(theApp.surfaceSizeX), (GLdouble)(theApp.surfaceSizeY),
- 0.0, 0.0,1.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- systemRedShift = 3;
- systemGreenShift = 11;
- systemBlueShift = 19;
- systemColorDepth = 32;
- theApp.fsColorDepth = 32;
-
- Init_2xSaI(32);
- #ifdef MMX
- if(!theApp.disableMMX)
- cpu_mmx = theApp.detectMMX();
- else
- cpu_mmx = 0;
- #endif
-
- if(theApp.ddrawDebug) {
- winlog("R shift: %d\n", systemRedShift);
- winlog("G shift: %d\n", systemGreenShift);
- winlog("B shift: %d\n", systemBlueShift);
- }
-
- switch(systemColorDepth) {
- case 16:
- {
- for(int i = 0; i < 0x10000; i++) {
- systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
- (((i & 0x3e0) >> 5) << systemGreenShift) |
- (((i & 0x7c00) >> 10) << systemBlueShift);
- }
- }
- break;
- case 24:
- case 32:
- {
- for(int i = 0; i < 0x10000; i++) {
- systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
- (((i & 0x3e0) >> 5) << systemGreenShift) |
- (((i & 0x7c00) >> 10) << systemBlueShift);
- }
- }
- break;
- }
- theApp.updateFilter();
- theApp.updateIFB();
-
- if(failed)
- return false;
-
- pWnd->DragAcceptFiles(TRUE);
-
- return TRUE;
- }
-
- void OpenGLDisplay::clear()
- {
- }
-
- void OpenGLDisplay::renderMenu()
- {
- checkFullScreen();
- if(theApp.m_pMainWnd)
- theApp.m_pMainWnd->DrawMenuBar();
- }
-
- void OpenGLDisplay::checkFullScreen()
- {
- // if(tripleBuffering)
- // pOpenGL->FlipToGDISurface();
- }
-
- void OpenGLDisplay::render()
- {
- int pitch = theApp.filterWidth * 4 + 4;
- u8 *data = pix + (theApp.sizeX+1)*4;
-
- if(theApp.filterFunction) {
- data = filterData;
- theApp.filterFunction(pix+pitch,
- pitch,
- (u8*)theApp.delta,
- (u8*)filterData,
- theApp.filterWidth*4*2,
- theApp.filterWidth,
- theApp.filterHeight);
- }
-
- if(theApp.videoOption > VIDEO_4X && theApp.showSpeed) {
- char buffer[30];
- if(theApp.showSpeed == 1)
- sprintf(buffer, "%3d%%", systemSpeed);
- else
- sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
- systemFrameSkip,
- theApp.showRenderedFrames);
-
- if(theApp.filterFunction) {
- int p = theApp.filterWidth * 4;
- if(systemColorDepth == 24)
- p = theApp.filterWidth * 6;
- else if(systemColorDepth == 32)
- p = theApp.filterWidth * 8;
- if(theApp.showSpeedTransparent)
- drawTextTransp((u8*)filterData,
- p,
- 10,
- theApp.filterHeight*2-10,
- buffer);
- else
- drawText((u8*)filterData,
- p,
- 10,
- theApp.filterHeight*2-10,
- buffer);
- } else {
- if(theApp.showSpeedTransparent)
- drawTextTransp((u8*)pix,
- pitch,
- 10,
- theApp.filterHeight-10,
- buffer);
- else
- drawText((u8*)pix,
- pitch,
- 10,
- theApp.filterHeight-10,
- buffer);
- }
- }
-
- // Texturemap complete texture to surface so we have free scaling
- // and antialiasing
- int mult = 1;
- if(theApp.filterFunction) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 2*theApp.sizeX);
- mult = 2;
- } else {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, theApp.sizeX+1);
- }
-
- glTexSubImage2D( GL_TEXTURE_2D,0,
- 0,0, mult*theApp.sizeX,mult*theApp.sizeY,
- GL_RGBA,GL_UNSIGNED_BYTE,data);
-
- if(theApp.glType == 0) {
- glBegin(GL_TRIANGLE_STRIP);
- glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0);
- glTexCoord2f(mult*theApp.sizeX/size, 0.0); glVertex3i(theApp.surfaceSizeX, 0, 0);
- glTexCoord2f(0.0, mult*theApp.sizeY/size); glVertex3i(0, theApp.surfaceSizeY, 0);
- glTexCoord2f(mult*theApp.sizeX/size, mult*theApp.sizeY/size); glVertex3i(theApp.surfaceSizeX, theApp.surfaceSizeY, 0);
- glEnd();
- } else {
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0);
- glTexCoord2f(mult*theApp.sizeX/size, 0.0); glVertex3i(theApp.surfaceSizeX, 0, 0);
- glTexCoord2f(mult*theApp.sizeX/size, mult*theApp.sizeY/size); glVertex3i(theApp.surfaceSizeX, theApp.surfaceSizeY, 0);
- glTexCoord2f(0.0, mult*theApp.sizeY/size); glVertex3i(0, theApp.surfaceSizeY, 0);
- glEnd();
- }
-
- CDC *dc = theApp.m_pMainWnd->GetDC();
-
- if(theApp.screenMessage) {
- if(((GetTickCount() - theApp.screenMessageTime) < 3000) &&
- !theApp.disableStatusMessage) {
- dc->SetTextColor(RGB(255,0,0));
- dc->SetBkMode(TRANSPARENT);
- dc->TextOut(10, theApp.surfaceSizeY - 20, theApp.screenMessageBuffer);
- } else {
- theApp.screenMessage = false;
- }
- }
-
- SwapBuffers(dc->GetSafeHdc());
-
- theApp.m_pMainWnd->ReleaseDC(dc);
- }
-
- void OpenGLDisplay::resize(int w, int h)
- {
- glViewport(0, 0, w, h);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glOrtho(0.0, (GLdouble)(w), (GLdouble)(h),
- 0.0, 0.0,1.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
-
- void OpenGLDisplay::updateFiltering(int value)
- {
- switch(value) {
- case 0:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- break;
- case 1:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- break;
- }
- }
-
- bool OpenGLDisplay::initializeTexture(int w, int h)
- {
- int mySize = 256;
- size = 256.0f;
- if(w > 255 || h > 255) {
- size = 512.0f;
- mySize = 512;
- }
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
-
- int filter = regQueryDwordValue("glFilter", 0);
- if(filter < 0 || filter > 1)
- filter = 0;
- updateFiltering(filter);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mySize, mySize, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, NULL );
- width = w;
- height = h;
-
- return true;
- }
-
- bool OpenGLDisplay::changeRenderSize(int w, int h)
- {
- if(width != w || height != h) {
- if(texture != 0) {
- glDeleteTextures(1, &texture);
- texture = 0;
- }
- if(!initializeTexture(w, h)) {
- failed = true;
- return false;
- }
- }
- return true;
- }
-
- void OpenGLDisplay::setOption(const char *option, int value)
- {
- if(!strcmp(option, "glFilter"))
- updateFiltering(value);
- }
-
- int OpenGLDisplay::selectFullScreenMode(GUID **)
- {
- HWND wnd = GetDesktopWindow();
- RECT r;
- GetWindowRect(wnd, &r);
- int w = (r.right - r.left) & 4095;
- int h = (r.bottom - r.top) & 4095;
- HDC dc = GetDC(wnd);
- int c = GetDeviceCaps(dc, BITSPIXEL);
- ReleaseDC(wnd, dc);
-
- return (c << 24) | (w << 12) | h;
- }
-
- IDisplay *newOpenGLDisplay()
- {
- return new OpenGLDisplay();
- }
-
-