Files
itgmania212121/stepmania/src/StepMania.cpp
T

645 lines
17 KiB
C++
Raw Normal View History

2001-11-03 10:52:42 +00:00
#include "stdafx.h"
/*
-----------------------------------------------------------------------------
File: StepMania.cpp
Desc:
Copyright (c) 2001 Chris Danford. All rights reserved.
-----------------------------------------------------------------------------
*/
2001-11-03 10:52:42 +00:00
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "resource.h"
#include "RageScreen.h"
#include "RageTextureManager.h"
#include "RageSound.h"
#include "RageMusic.h"
#include "RageInput.h"
#include "GameInfo.h"
2002-01-16 10:01:32 +00:00
#include "ThemeManager.h"
2001-11-03 10:52:42 +00:00
#include "WindowManager.h"
2001-11-20 11:49:10 +00:00
#include "WindowSandbox.h"
#include "WindowLoading.h"
2002-01-16 10:01:32 +00:00
#include "WindowMenuResults.h"
2001-12-20 12:37:38 +00:00
#include "WindowTitleMenu.h"
2002-01-16 10:01:32 +00:00
#include "WindowPlayerOptions.h"
2001-11-03 10:52:42 +00:00
#include <DXUtil.h>
//-----------------------------------------------------------------------------
// Links
//-----------------------------------------------------------------------------
#pragma comment(lib, "d3dx8.lib")
#pragma comment(lib, "d3d8.lib")
//-----------------------------------------------------------------------------
// Application globals
//-----------------------------------------------------------------------------
const CString g_sAppName = "StepMania";
const CString g_sAppClassName = "StepMania Class";
HWND g_hWndMain; // Main Window Handle
HINSTANCE g_hInstance; // The Handle to Window Instance
#include "ScreenDimensions.h"
2001-11-03 10:52:42 +00:00
const DWORD g_dwWindowStyle = WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU;
BOOL g_bIsActive = FALSE; // Whether the focus is on our app
//LPRageMovieTexture g_pMovieTexture = NULL;
//-----------------------------------------------------------------------------
// Function prototypes
//-----------------------------------------------------------------------------
// Main game functions
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
void Update(); // Update the game logic
void Render(); // Render a frame
void ShowFrame(); // Display the contents of the back buffer to the screen
// Functions that work with game objects
HRESULT CreateObjects( HWND hWnd ); // allocate and initialize game objects
HRESULT InvalidateObjects(); // invalidate game objects before a display mode change
HRESULT RestoreObjects(); // restore game objects after a display mode change
VOID DestroyObjects(); // deallocate game objects when we're done with them
BOOL SwitchDisplayMode( BOOL bWindowed, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP );
2001-12-19 01:50:57 +00:00
BOOL WeAreAlone( LPSTR szName );
2001-11-03 10:52:42 +00:00
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Application entry point
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow )
{
2001-12-19 01:50:57 +00:00
if( !WeAreAlone("StepMania") )
{
RageError( "StepMania is already running!" );
}
// Make sure the current directory is the root program directory
2002-01-16 10:01:32 +00:00
if( !DoesFileExist("Songs") )
{
// change dir to path of the execuctable
TCHAR szFullAppPath[MAX_PATH];
GetModuleFileName(NULL, szFullAppPath, MAX_PATH);
// strip off executable name
LPSTR pLastBackslash = strrchr(szFullAppPath, '\\');
*pLastBackslash = '\0'; // terminate the string
SetCurrentDirectory(szFullAppPath);
}
2002-01-16 10:01:32 +00:00
2001-11-03 10:52:42 +00:00
CoInitialize (NULL); // Initialize COM
// Register the window class
WNDCLASS wndClass = {
0,
WndProc, // callback handler
0, // cbClsExtra;
0, // cbWndExtra;
hInstance,
LoadIcon( hInstance, MAKEINTRESOURCE(IDI_ICON) ),
LoadCursor( hInstance, IDC_ARROW),
(HBRUSH)GetStockObject( BLACK_BRUSH ),
NULL, // lpszMenuName;
g_sAppClassName // lpszClassName;
};
RegisterClass( &wndClass );
// Set the window's initial width
RECT rcWnd;
SetRect( &rcWnd, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
2001-11-03 10:52:42 +00:00
AdjustWindowRect( &rcWnd, g_dwWindowStyle, FALSE );
// Create our main window
g_hWndMain = CreateWindow(
g_sAppClassName,// pointer to registered class name
g_sAppName, // pointer to window name
g_dwWindowStyle, // window style
CW_USEDEFAULT, // horizontal position of window
CW_USEDEFAULT, // vertical position of window
RECTWIDTH(rcWnd), // window width
RECTHEIGHT(rcWnd),// window height
NULL, // handle to parent or owner window
NULL, // handle to menu, or child-window identifier
hInstance, // handle to application instance
NULL // pointer to window-creation data
);
if( NULL == g_hWndMain )
exit(1);
// Load keyboard accelerators
HACCEL hAccel = LoadAccelerators( NULL, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
// run the game
CreateObjects( g_hWndMain ); // Create the game objects
// Now we're ready to recieve and process Windows messages.
MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( WM_QUIT != msg.message )
{
// Look for messages, if none are found then
// update the state and display it
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
GetMessage(&msg, NULL, 0, 0 );
// Translate and dispatch the message
if( 0 == TranslateAccelerator( g_hWndMain, hAccel, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
else // No messages are waiting. Render a frame during idle time.
{
Update();
Render();
//if( !g_bFullscreen )
2002-01-16 10:01:32 +00:00
::Sleep(4 ); // give some time for the movie decoding thread
2001-11-03 10:52:42 +00:00
}
} // end while( WM_QUIT != msg.message )
// clean up after a normal exit
DestroyObjects(); // deallocate our game objects and leave fullscreen
DestroyWindow( g_hWndMain );
UnregisterClass( g_sAppClassName, hInstance );
CoUninitialize(); // Uninitialize COM
return 0L;
}
//-----------------------------------------------------------------------------
// Name: WndProc()
// Desc: Callback for all Windows messages
//-----------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_ACTIVATEAPP:
// Check to see if we are losing our window...
g_bIsActive = (BOOL)wParam;
break;
case WM_SIZE:
// Check to see if we are losing our window...
if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
2001-11-03 10:52:42 +00:00
g_bIsActive = FALSE;
else
g_bIsActive = TRUE;
break;
case WM_GETMINMAXINFO:
{
// Don't allow the window to be resized smaller than the screen resolution.
// This should snap to multiples of the screen size two!
2001-11-03 10:52:42 +00:00
RECT rcWnd;
SetRect( &rcWnd, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
2001-11-03 10:52:42 +00:00
DWORD dwWindowStyle = GetWindowLong( g_hWndMain, GWL_STYLE );
AdjustWindowRect( &rcWnd, dwWindowStyle, FALSE );
((MINMAXINFO*)lParam)->ptMinTrackSize.x = RECTWIDTH(rcWnd);
((MINMAXINFO*)lParam)->ptMinTrackSize.y = RECTHEIGHT(rcWnd);
}
break;
case WM_SETCURSOR:
// Turn off Windows cursor in fullscreen mode
if( !SCREEN->IsWindowed() )
2001-11-03 10:52:42 +00:00
{
SetCursor( NULL );
return TRUE; // prevent Windows from setting the cursor
}
break;
case WM_SYSCOMMAND:
// Prevent moving/sizing and power loss
switch( wParam )
{
case SC_MOVE:
case SC_SIZE:
case SC_KEYMENU:
case SC_MONITORPOWER:
return 1;
case SC_MAXIMIZE:
//SendMessage( g_hWndMain, WM_COMMAND, IDM_TOGGLEFULLSCREEN, 0 );
//return 1;
2001-11-03 10:52:42 +00:00
break;
}
break;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDM_TOGGLEFULLSCREEN:
SwitchDisplayMode( !SCREEN->IsWindowed(), SCREEN_WIDTH, SCREEN_HEIGHT, 16 );
2001-11-03 10:52:42 +00:00
return 0;
case IDM_EXIT:
// Recieved key/menu command to exit app
SendMessage( hWnd, WM_CLOSE, 0, 0 );
return 0;
}
break;
case WM_NCHITTEST:
// Prevent the user from selecting the menu in fullscreen mode
if( !SCREEN->IsWindowed() )
2001-11-03 10:52:42 +00:00
return HTCLIENT;
break;
case WM_PAINT:
// redisplay the contents of the back buffer if the window needs to be redrawn
ShowFrame();
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Name: CreateObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CreateObjects( HWND hWnd )
{
////////////////////////////////
// Draw a splash bitmap so the user isn't looking at a black screen
////////////////////////////////
HBITMAP hSplashBitmap = (HBITMAP)LoadImage(
GetModuleHandle( NULL ),
TEXT("SPLASH"),
IMAGE_BITMAP,
0, 0, LR_CREATEDIBSECTION );
BITMAP bmp;
RECT rc;
GetClientRect( hWnd, &rc );
// Display the splash bitmap in the window
HDC hDCWindow = GetDC( hWnd );
HDC hDCImage = CreateCompatibleDC( NULL );
SelectObject( hDCImage, hSplashBitmap );
GetObject( hSplashBitmap, sizeof(bmp), &bmp );
StretchBlt( hDCWindow, 0, 0, rc.right, rc.bottom,
hDCImage, 0, 0,
bmp.bmWidth, bmp.bmHeight, SRCCOPY );
DeleteDC( hDCImage );
ReleaseDC( hWnd, hDCWindow );
// Delete the bitmap
DeleteObject( hSplashBitmap );
/////////////////////////////////
// Create game objects
/////////////////////////////////
srand( (unsigned)time(NULL) ); // seed number generator
RageLogStart();
2001-11-03 10:52:42 +00:00
SOUND = new RageSound( hWnd );
2002-01-16 10:01:32 +00:00
MUSIC = new RageSoundStream;
2001-11-03 10:52:42 +00:00
INPUT = new RageInput( hWnd );
2001-12-20 12:37:38 +00:00
GAMEINFO= new GameInfo;
SCREEN = new RageScreen( hWnd );
2001-12-20 12:37:38 +00:00
BringWindowToTop( hWnd );
SetForegroundWindow( hWnd );
// switch the screen resolution according to user's prefs
GameOptions &go = GAMEINFO->m_GameOptions;
SwitchDisplayMode(
go.m_bWindowed,
go.m_iResolution,
go.m_iResolution==640 ? 480 : 240,
go.m_iDisplayColor
);
TM = new RageTextureManager( SCREEN );
THEME = new ThemeManager;
WM = new WindowManager;
2001-11-03 10:52:42 +00:00
2002-01-29 21:56:14 +00:00
// Ugly... Switch the screen resolution again so that the system message will display
SwitchDisplayMode(
go.m_bWindowed,
go.m_iResolution,
go.m_iResolution==640 ? 480 : 240,
go.m_iDisplayColor
);
WM->SystemMessage( ssprintf("Found %d songs.", GAMEINFO->m_pSongs.GetSize()) );
//WM->SetNewWindow( new WindowLoading );
//WM->SetNewWindow( new WindowSandbox );
2002-01-16 10:01:32 +00:00
//WM->SetNewWindow( new WindowMenuResults );
//WM->SetNewWindow( new WindowPlayerOptions );
WM->SetNewWindow( new WindowTitleMenu );
2001-12-19 14:56:22 +00:00
2001-11-28 01:26:58 +00:00
DXUtil_Timer( TIMER_START ); // Start the accurate timer
2001-11-03 10:52:42 +00:00
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DestroyObjects()
// Desc:
//-----------------------------------------------------------------------------
void DestroyObjects()
{
DXUtil_Timer( TIMER_STOP );
SAFE_DELETE( WM );
SAFE_DELETE( GAMEINFO );
2001-11-03 10:52:42 +00:00
SAFE_DELETE( INPUT );
SAFE_DELETE( MUSIC );
SAFE_DELETE( SOUND );
SAFE_DELETE( TM );
SAFE_DELETE( SCREEN );
}
//-----------------------------------------------------------------------------
// Name: RestoreObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT RestoreObjects()
{
/////////////////////
// Restore the window
/////////////////////
// Set window size
RECT rcWnd;
if( SCREEN->IsWindowed() )
2001-11-03 10:52:42 +00:00
{
SetRect( &rcWnd, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
2001-11-03 10:52:42 +00:00
AdjustWindowRect( &rcWnd, g_dwWindowStyle, FALSE );
}
else // if fullscreen
{
SetRect( &rcWnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) );
}
2001-11-03 10:52:42 +00:00
// Bring the window to the foreground
SetWindowPos( g_hWndMain,
HWND_NOTOPMOST,
0,
0,
RECTWIDTH(rcWnd),
RECTHEIGHT(rcWnd),
0 );
///////////////////////////
// Restore all game objects
///////////////////////////
SCREEN->Restore();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InvalidateObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT InvalidateObjects()
{
SCREEN->Invalidate();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Update()
// Desc:
//-----------------------------------------------------------------------------
void Update()
{
2001-12-28 10:15:59 +00:00
float fDeltaTime = DXUtil_Timer( TIMER_GETELAPSEDTIME );
2001-11-03 10:52:42 +00:00
// This was a hack to fix timing issues with the old WindowSelectSong
//
2002-01-16 10:01:32 +00:00
if( fDeltaTime > 0.050f ) // we dropped > 5 frames
fDeltaTime = 0.050f;
2001-11-03 10:52:42 +00:00
MUSIC->Update( fDeltaTime );
WM->Update( fDeltaTime );
2001-11-25 04:31:44 +00:00
static DeviceInputArray diArray;
diArray.RemoveAll();
INPUT->GetDeviceInputs( diArray );
2001-11-03 10:52:42 +00:00
2001-12-19 01:50:57 +00:00
DeviceInput DeviceI;
PadInput PadI;
PlayerInput PlayerI;
2001-11-25 04:31:44 +00:00
for( int i=0; i<diArray.GetSize(); i++ )
2001-11-03 10:52:42 +00:00
{
2001-12-19 01:50:57 +00:00
DeviceI = diArray[i];
GAMEINFO->DeviceToPad( DeviceI, PadI );
GAMEINFO->PadToPlayer( PadI, PlayerI );
WM->Input( DeviceI, PadI, PlayerI );
2001-11-03 10:52:42 +00:00
}
}
//-----------------------------------------------------------------------------
// Name: Render()
// Desc:
//-----------------------------------------------------------------------------
void Render()
{
HRESULT hr = SCREEN->BeginFrame();
switch( hr )
{
case D3DERR_DEVICELOST:
// The user probably alt-tabbed out of fullscreen.
// Do not render a frame until we re-acquire the device
break;
case D3DERR_DEVICENOTRESET:
InvalidateObjects();
// Resize the device
if( SUCCEEDED( hr = SCREEN->Reset() ) )
2001-11-03 10:52:42 +00:00
{
// Initialize the app's device-dependent objects
RestoreObjects();
return;
}
else
{
RageErrorHr( "Failed to SCREEN->Reset()", hr );
}
2001-11-03 10:52:42 +00:00
break;
case S_OK:
2001-11-28 20:26:45 +00:00
{
// set texture and alpha properties
LPDIRECT3DDEVICE8 pd3dDevice = SCREEN->GetDevice();
// calculate view and projection transforms
2002-01-16 10:01:32 +00:00
D3DXMATRIX matProj;
D3DXMatrixOrthoOffCenterLH( &matProj, 0, 640, 480, 0, -100, 100 );
pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
2001-11-28 20:26:45 +00:00
D3DXMATRIX matView;
D3DXMatrixIdentity( &matView );
pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
2002-01-16 10:01:32 +00:00
D3DXMATRIX matWorld;
D3DXMatrixIdentity( &matWorld );
SCREEN->ResetMatrixStack( matWorld );
2001-11-03 10:52:42 +00:00
2001-11-28 20:26:45 +00:00
// draw the game
WM->Draw();
SCREEN->EndFrame();
}
2001-11-03 10:52:42 +00:00
break;
}
ShowFrame();
2001-11-03 10:52:42 +00:00
}
//-----------------------------------------------------------------------------
// Name: ShowFrame()
// Desc:
//-----------------------------------------------------------------------------
void ShowFrame()
{
// display the contents of the back buffer to the front
if( SCREEN )
SCREEN->ShowFrame();
}
//-----------------------------------------------------------------------------
// Name: SwitchDisplayMode()
2001-11-03 10:52:42 +00:00
// Desc:
//-----------------------------------------------------------------------------
BOOL SwitchDisplayMode( BOOL bWindowed, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP )
2001-11-03 10:52:42 +00:00
{
InvalidateObjects();
// If the requested resolution doesn't work, keep switching until we find one that does.
if( !SCREEN->SwitchDisplayMode( bWindowed, dwWidth, dwHeight, dwBPP ) )
{
// We failed. Try full screen with same params.
bWindowed = false;
if( !SCREEN->SwitchDisplayMode( bWindowed, dwWidth, dwHeight, dwBPP ) )
{
// Failed again. Try 16 BPP
dwBPP = 16;
if( !SCREEN->SwitchDisplayMode( bWindowed, dwWidth, dwHeight, dwBPP ) )
{
// Failed again. Try 640x480
dwWidth = 640;
dwHeight = 480;
if( !SCREEN->SwitchDisplayMode( bWindowed, dwWidth, dwHeight, dwBPP ) )
{
// Failed again. Try 640x480
dwWidth = 320;
dwHeight = 240;
if( !SCREEN->SwitchDisplayMode( bWindowed, dwWidth, dwHeight, dwBPP ) )
{
RageError( "Tried every possible display mode, and couldn't change to any of them." );
return false;
}
}
}
}
}
2001-11-03 10:52:42 +00:00
RestoreObjects();
2001-12-20 12:37:38 +00:00
if( GAMEINFO )
{
GAMEINFO->m_GameOptions.m_bWindowed = bWindowed;
GAMEINFO->m_GameOptions.m_iDisplayColor = dwBPP;
GAMEINFO->m_GameOptions.m_iResolution = dwWidth;
2001-12-20 12:37:38 +00:00
GAMEINFO->SaveConfigToDisk();
}
if( WM )
{
2002-01-29 21:56:14 +00:00
WM->SystemMessage( ssprintf("%s - %ux%u - %u bits", bWindowed ? "Windowed" : "FullScreen", dwWidth, dwHeight, dwBPP) );
}
return true;
2001-11-03 10:52:42 +00:00
}
//-----------------------------------------------------------------------------
2001-12-19 01:50:57 +00:00
// Name: WeAreAlone()
// Desc: check for DirectX 8
//-----------------------------------------------------------------------------
2001-12-19 01:50:57 +00:00
BOOL WeAreAlone (LPSTR szName)
{
HANDLE hMutex = CreateMutex (NULL, TRUE, szName);
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hMutex);
return FALSE;
}
return TRUE;
}