diff --git a/V01/Demo.aps b/V01/Demo.aps new file mode 100644 index 0000000..685c861 Binary files /dev/null and b/V01/Demo.aps differ diff --git a/V01/Demo.cpp b/V01/Demo.cpp new file mode 100644 index 0000000..a75efd8 --- /dev/null +++ b/V01/Demo.cpp @@ -0,0 +1,113 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +/* +** ultris_windowhandler +*/ +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + // Hier koennen wir uns um das Spiel kuemmern + } + } + } + + + diff --git a/V01/Demo.h b/V01/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V01/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V01/Demo.ncb b/V01/Demo.ncb new file mode 100644 index 0000000..049f11d Binary files /dev/null and b/V01/Demo.ncb differ diff --git a/V01/Demo.rc b/V01/Demo.rc new file mode 100644 index 0000000..99afe80 --- /dev/null +++ b/V01/Demo.rc @@ -0,0 +1,109 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Ende", IDM_EXIT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT +END + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V01/Demo.sln b/V01/Demo.sln new file mode 100644 index 0000000..a8cd38c --- /dev/null +++ b/V01/Demo.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{706BAF73-83F9-4402-B5BE-F0D9F045363D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {706BAF73-83F9-4402-B5BE-F0D9F045363D}.Debug|Win32.ActiveCfg = Debug|Win32 + {706BAF73-83F9-4402-B5BE-F0D9F045363D}.Debug|Win32.Build.0 = Debug|Win32 + {706BAF73-83F9-4402-B5BE-F0D9F045363D}.Release|Win32.ActiveCfg = Release|Win32 + {706BAF73-83F9-4402-B5BE-F0D9F045363D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/V01/Demo.sln.old b/V01/Demo.sln.old new file mode 100644 index 0000000..dd19edf --- /dev/null +++ b/V01/Demo.sln.old @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{706BAF73-83F9-4402-B5BE-F0D9F045363D}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {706BAF73-83F9-4402-B5BE-F0D9F045363D}.Debug.ActiveCfg = Debug|Win32 + {706BAF73-83F9-4402-B5BE-F0D9F045363D}.Debug.Build.0 = Debug|Win32 + {706BAF73-83F9-4402-B5BE-F0D9F045363D}.Release.ActiveCfg = Release|Win32 + {706BAF73-83F9-4402-B5BE-F0D9F045363D}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V01/Demo.suo b/V01/Demo.suo new file mode 100644 index 0000000..167f271 Binary files /dev/null and b/V01/Demo.suo differ diff --git a/V01/Demo.suo.old b/V01/Demo.suo.old new file mode 100644 index 0000000..94151eb Binary files /dev/null and b/V01/Demo.suo.old differ diff --git a/V01/Demo.vcproj b/V01/Demo.vcproj new file mode 100644 index 0000000..c753190 --- /dev/null +++ b/V01/Demo.vcproj @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V01/Demo.vcproj.7.10.old b/V01/Demo.vcproj.7.10.old new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V01/Demo.vcproj.7.10.old @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V01/Demo.vcproj.SASCHA.Sasch.user b/V01/Demo.vcproj.SASCHA.Sasch.user new file mode 100644 index 0000000..86f2a09 --- /dev/null +++ b/V01/Demo.vcproj.SASCHA.Sasch.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/V01/Icon.ico b/V01/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V01/Icon.ico differ diff --git a/V01/UpgradeLog.XML b/V01/UpgradeLog.XML new file mode 100644 index 0000000..e60875d --- /dev/null +++ b/V01/UpgradeLog.XML @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/V01/_UpgradeReport_Files/UpgradeReport.css b/V01/_UpgradeReport_Files/UpgradeReport.css new file mode 100644 index 0000000..3411f63 --- /dev/null +++ b/V01/_UpgradeReport_Files/UpgradeReport.css @@ -0,0 +1,207 @@ +BODY +{ + BACKGROUND-COLOR: white; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px +} +P +{ + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 70%; + LINE-HEIGHT: 12pt; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 10px +} +.note +{ + BACKGROUND-COLOR: #ffffff; + COLOR: #336699; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px; + PADDING-RIGHT: 10px +} +.infotable +{ + BACKGROUND-COLOR: #f0f0e0; + BORDER-BOTTOM: #ffffff 0px solid; + BORDER-COLLAPSE: collapse; + BORDER-LEFT: #ffffff 0px solid; + BORDER-RIGHT: #ffffff 0px solid; + BORDER-TOP: #ffffff 0px solid; + FONT-SIZE: 70%; + MARGIN-LEFT: 10px +} +.issuetable +{ + BACKGROUND-COLOR: #ffffe8; + BORDER-COLLAPSE: collapse; + COLOR: #000000; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 10px; + MARGIN-LEFT: 13px; + MARGIN-TOP: 0px +} +.issuetitle +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px; + COLOR: #003366; + FONT-WEIGHT: normal +} +.header +{ + BACKGROUND-COLOR: #cecf9c; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + COLOR: #000000; + FONT-WEIGHT: bold +} +.issuehdr +{ + BACKGROUND-COLOR: #E0EBF5; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + COLOR: #000000; + FONT-WEIGHT: normal +} +.issuenone +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: 0px; + BORDER-LEFT: 0px; + BORDER-RIGHT: 0px; + BORDER-TOP: 0px; + COLOR: #000000; + FONT-WEIGHT: normal +} +.content +{ + BACKGROUND-COLOR: #e7e7ce; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + PADDING-LEFT: 3px +} +.issuecontent +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + PADDING-LEFT: 3px +} +A:link +{ + COLOR: #cc6633; + TEXT-DECORATION: underline +} +A:visited +{ + COLOR: #cc6633; +} +A:active +{ + COLOR: #cc6633; +} +A:hover +{ + COLOR: #cc3300; + TEXT-DECORATION: underline +} +H1 +{ + BACKGROUND-COLOR: #003366; + BORDER-BOTTOM: #336699 6px solid; + COLOR: #ffffff; + FONT-SIZE: 130%; + FONT-WEIGHT: normal; + MARGIN: 0em 0em 0em -20px; + PADDING-BOTTOM: 8px; + PADDING-LEFT: 30px; + PADDING-TOP: 16px +} +H2 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 3px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px; + PADDING-LEFT: 0px +} +H3 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: -5px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px +} +H4 +{ + COLOR: #000000; + FONT-SIZE: 70%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 0px; + MARGIN-TOP: 15px; + PADDING-BOTTOM: 0px +} +UL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +OL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +LI +{ + LIST-STYLE: square; + MARGIN-LEFT: 0px +} +.expandable +{ + CURSOR: hand +} +.expanded +{ + color: black +} +.collapsed +{ + DISPLAY: none +} +.foot +{ +BACKGROUND-COLOR: #ffffff; +BORDER-BOTTOM: #cecf9c 1px solid; +BORDER-TOP: #cecf9c 2px solid +} +.settings +{ +MARGIN-LEFT: 25PX; +} +.help +{ +TEXT-ALIGN: right; +margin-right: 10px; +} diff --git a/V01/_UpgradeReport_Files/UpgradeReport.xslt b/V01/_UpgradeReport_Files/UpgradeReport.xslt new file mode 100644 index 0000000..6fb44ed --- /dev/null +++ b/V01/_UpgradeReport_Files/UpgradeReport.xslt @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Projektmappe: + Projekt: + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + src + + + + + + + + + + + + +
DateinameStatusFehlerWarnungen
+ javascript:document.images[''].click()src + + + + Konvertiert + + + + Konvertiert + +
+ + Dateien + + + 1 Datei + + + Konvertiert:
+ Nicht konvertiert: +
+
+
+ + + + : + + + + + + + + + Konvertierungsbericht + <xsl:if test="Properties/Property[@Name='LogNumber']"> + <xsl:value-of select="Properties/Property[@Name='LogNumber']/@Value"/> + </xsl:if> + + + + +

Konvertierungsbericht -

+ +

+ Konvertierungsdauer:
+

+ + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + +
+ Konvertierungseinstellungen +

+ + +
+
diff --git a/V01/_UpgradeReport_Files/UpgradeReport_Minus.gif b/V01/_UpgradeReport_Files/UpgradeReport_Minus.gif new file mode 100644 index 0000000..17751cb Binary files /dev/null and b/V01/_UpgradeReport_Files/UpgradeReport_Minus.gif differ diff --git a/V01/_UpgradeReport_Files/UpgradeReport_Plus.gif b/V01/_UpgradeReport_Files/UpgradeReport_Plus.gif new file mode 100644 index 0000000..f6009ca Binary files /dev/null and b/V01/_UpgradeReport_Files/UpgradeReport_Plus.gif differ diff --git a/V01/ddutil.cpp b/V01/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V01/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V01/ddutil.h b/V01/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V01/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V01/dsutil.cpp b/V01/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V01/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V01/dsutil.h b/V01/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V01/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V01/resource.h b/V01/resource.h new file mode 100644 index 0000000..338f739 --- /dev/null +++ b/V01/resource.h @@ -0,0 +1,21 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDM_EXIT 1001 +#define ID_OTTO_OTTO1 40024 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40025 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V02/Debug/BuildLog.htm b/V02/Debug/BuildLog.htm new file mode 100644 index 0000000..c95b7bb Binary files /dev/null and b/V02/Debug/BuildLog.htm differ diff --git a/V02/Debug/Demo.obj b/V02/Debug/Demo.obj new file mode 100644 index 0000000..961aa5f Binary files /dev/null and b/V02/Debug/Demo.obj differ diff --git a/V02/Debug/Demo.res b/V02/Debug/Demo.res new file mode 100644 index 0000000..b67fe70 Binary files /dev/null and b/V02/Debug/Demo.res differ diff --git a/V02/Debug/Ultris.exe b/V02/Debug/Ultris.exe new file mode 100644 index 0000000..5e45b81 Binary files /dev/null and b/V02/Debug/Ultris.exe differ diff --git a/V02/Debug/Ultris.exe.intermediate.manifest b/V02/Debug/Ultris.exe.intermediate.manifest new file mode 100644 index 0000000..1c06b61 --- /dev/null +++ b/V02/Debug/Ultris.exe.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/V02/Debug/Ultris.pdb b/V02/Debug/Ultris.pdb new file mode 100644 index 0000000..f535cd7 Binary files /dev/null and b/V02/Debug/Ultris.pdb differ diff --git a/V02/Debug/ddutil.obj b/V02/Debug/ddutil.obj new file mode 100644 index 0000000..c729bd9 Binary files /dev/null and b/V02/Debug/ddutil.obj differ diff --git a/V02/Debug/dsutil.obj b/V02/Debug/dsutil.obj new file mode 100644 index 0000000..fcacc99 Binary files /dev/null and b/V02/Debug/dsutil.obj differ diff --git a/V02/Debug/mt.dep b/V02/Debug/mt.dep new file mode 100644 index 0000000..51533a5 --- /dev/null +++ b/V02/Debug/mt.dep @@ -0,0 +1 @@ + die Manifestressource wurde zuletzt um 13:58:27,17 am 18.02.2010 aktualisiert diff --git a/V02/Debug/vc90.idb b/V02/Debug/vc90.idb new file mode 100644 index 0000000..2488f87 Binary files /dev/null and b/V02/Debug/vc90.idb differ diff --git a/V02/Debug/vc90.pdb b/V02/Debug/vc90.pdb new file mode 100644 index 0000000..d7b7224 Binary files /dev/null and b/V02/Debug/vc90.pdb differ diff --git a/V02/Demo.aps b/V02/Demo.aps new file mode 100644 index 0000000..c4f4825 Binary files /dev/null and b/V02/Demo.aps differ diff --git a/V02/Demo.cpp b/V02/Demo.cpp new file mode 100644 index 0000000..f5e47c5 --- /dev/null +++ b/V02/Demo.cpp @@ -0,0 +1,224 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +// V2 Beginn +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; +// V2 Ende + + + +/* +** ultris_windowhandler +*/ +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; +// V2 Beginn + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case IDM_TEST: // Testcode + static int testno = 0; + ultris_sounds.play( testno % anzahl_sounds); + testno++; + return 0; +// V2 Ende + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + +// V2 Beginn + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); +// V2 Ende + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + // Hier koennen wir uns um das Spiel kuemmern + } + } + } + + + diff --git a/V02/Demo.h b/V02/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V02/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V02/Demo.ncb b/V02/Demo.ncb new file mode 100644 index 0000000..39b204b Binary files /dev/null and b/V02/Demo.ncb differ diff --git a/V02/Demo.rc b/V02/Demo.rc new file mode 100644 index 0000000..2d4c8ed --- /dev/null +++ b/V02/Demo.rc @@ -0,0 +1,115 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT +END + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V02/Demo.sln b/V02/Demo.sln new file mode 100644 index 0000000..b89675c --- /dev/null +++ b/V02/Demo.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{04396D0D-D714-427C-8628-CBB24A64786F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {04396D0D-D714-427C-8628-CBB24A64786F}.Debug|Win32.ActiveCfg = Debug|Win32 + {04396D0D-D714-427C-8628-CBB24A64786F}.Debug|Win32.Build.0 = Debug|Win32 + {04396D0D-D714-427C-8628-CBB24A64786F}.Release|Win32.ActiveCfg = Release|Win32 + {04396D0D-D714-427C-8628-CBB24A64786F}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/V02/Demo.sln.old b/V02/Demo.sln.old new file mode 100644 index 0000000..3d7120f --- /dev/null +++ b/V02/Demo.sln.old @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{04396D0D-D714-427C-8628-CBB24A64786F}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {04396D0D-D714-427C-8628-CBB24A64786F}.Debug.ActiveCfg = Debug|Win32 + {04396D0D-D714-427C-8628-CBB24A64786F}.Debug.Build.0 = Debug|Win32 + {04396D0D-D714-427C-8628-CBB24A64786F}.Release.ActiveCfg = Release|Win32 + {04396D0D-D714-427C-8628-CBB24A64786F}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V02/Demo.suo b/V02/Demo.suo new file mode 100644 index 0000000..6b9b58a Binary files /dev/null and b/V02/Demo.suo differ diff --git a/V02/Demo.suo.old b/V02/Demo.suo.old new file mode 100644 index 0000000..5c0eb23 Binary files /dev/null and b/V02/Demo.suo.old differ diff --git a/V02/Demo.vcproj b/V02/Demo.vcproj new file mode 100644 index 0000000..3db9719 --- /dev/null +++ b/V02/Demo.vcproj @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V02/Demo.vcproj.7.10.old b/V02/Demo.vcproj.7.10.old new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V02/Demo.vcproj.7.10.old @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V02/Demo.vcproj.SASCHA.Sasch.user b/V02/Demo.vcproj.SASCHA.Sasch.user new file mode 100644 index 0000000..86f2a09 --- /dev/null +++ b/V02/Demo.vcproj.SASCHA.Sasch.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/V02/Icon.ico b/V02/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V02/Icon.ico differ diff --git a/V02/UpgradeLog.XML b/V02/UpgradeLog.XML new file mode 100644 index 0000000..0b6aa62 --- /dev/null +++ b/V02/UpgradeLog.XML @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/V02/_UpgradeReport_Files/UpgradeReport.css b/V02/_UpgradeReport_Files/UpgradeReport.css new file mode 100644 index 0000000..3411f63 --- /dev/null +++ b/V02/_UpgradeReport_Files/UpgradeReport.css @@ -0,0 +1,207 @@ +BODY +{ + BACKGROUND-COLOR: white; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px +} +P +{ + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 70%; + LINE-HEIGHT: 12pt; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 10px +} +.note +{ + BACKGROUND-COLOR: #ffffff; + COLOR: #336699; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px; + PADDING-RIGHT: 10px +} +.infotable +{ + BACKGROUND-COLOR: #f0f0e0; + BORDER-BOTTOM: #ffffff 0px solid; + BORDER-COLLAPSE: collapse; + BORDER-LEFT: #ffffff 0px solid; + BORDER-RIGHT: #ffffff 0px solid; + BORDER-TOP: #ffffff 0px solid; + FONT-SIZE: 70%; + MARGIN-LEFT: 10px +} +.issuetable +{ + BACKGROUND-COLOR: #ffffe8; + BORDER-COLLAPSE: collapse; + COLOR: #000000; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 10px; + MARGIN-LEFT: 13px; + MARGIN-TOP: 0px +} +.issuetitle +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px; + COLOR: #003366; + FONT-WEIGHT: normal +} +.header +{ + BACKGROUND-COLOR: #cecf9c; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + COLOR: #000000; + FONT-WEIGHT: bold +} +.issuehdr +{ + BACKGROUND-COLOR: #E0EBF5; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + COLOR: #000000; + FONT-WEIGHT: normal +} +.issuenone +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: 0px; + BORDER-LEFT: 0px; + BORDER-RIGHT: 0px; + BORDER-TOP: 0px; + COLOR: #000000; + FONT-WEIGHT: normal +} +.content +{ + BACKGROUND-COLOR: #e7e7ce; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + PADDING-LEFT: 3px +} +.issuecontent +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + PADDING-LEFT: 3px +} +A:link +{ + COLOR: #cc6633; + TEXT-DECORATION: underline +} +A:visited +{ + COLOR: #cc6633; +} +A:active +{ + COLOR: #cc6633; +} +A:hover +{ + COLOR: #cc3300; + TEXT-DECORATION: underline +} +H1 +{ + BACKGROUND-COLOR: #003366; + BORDER-BOTTOM: #336699 6px solid; + COLOR: #ffffff; + FONT-SIZE: 130%; + FONT-WEIGHT: normal; + MARGIN: 0em 0em 0em -20px; + PADDING-BOTTOM: 8px; + PADDING-LEFT: 30px; + PADDING-TOP: 16px +} +H2 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 3px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px; + PADDING-LEFT: 0px +} +H3 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: -5px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px +} +H4 +{ + COLOR: #000000; + FONT-SIZE: 70%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 0px; + MARGIN-TOP: 15px; + PADDING-BOTTOM: 0px +} +UL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +OL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +LI +{ + LIST-STYLE: square; + MARGIN-LEFT: 0px +} +.expandable +{ + CURSOR: hand +} +.expanded +{ + color: black +} +.collapsed +{ + DISPLAY: none +} +.foot +{ +BACKGROUND-COLOR: #ffffff; +BORDER-BOTTOM: #cecf9c 1px solid; +BORDER-TOP: #cecf9c 2px solid +} +.settings +{ +MARGIN-LEFT: 25PX; +} +.help +{ +TEXT-ALIGN: right; +margin-right: 10px; +} diff --git a/V02/_UpgradeReport_Files/UpgradeReport.xslt b/V02/_UpgradeReport_Files/UpgradeReport.xslt new file mode 100644 index 0000000..6fb44ed --- /dev/null +++ b/V02/_UpgradeReport_Files/UpgradeReport.xslt @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Projektmappe: + Projekt: + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + src + + + + + + + + + + + + +
DateinameStatusFehlerWarnungen
+ javascript:document.images[''].click()src + + + + Konvertiert + + + + Konvertiert + +
+ + Dateien + + + 1 Datei + + + Konvertiert:
+ Nicht konvertiert: +
+
+
+ + + + : + + + + + + + + + Konvertierungsbericht + <xsl:if test="Properties/Property[@Name='LogNumber']"> + <xsl:value-of select="Properties/Property[@Name='LogNumber']/@Value"/> + </xsl:if> + + + + +

Konvertierungsbericht -

+ +

+ Konvertierungsdauer:
+

+ + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + +
+ Konvertierungseinstellungen +

+ + +
+
diff --git a/V02/_UpgradeReport_Files/UpgradeReport_Minus.gif b/V02/_UpgradeReport_Files/UpgradeReport_Minus.gif new file mode 100644 index 0000000..17751cb Binary files /dev/null and b/V02/_UpgradeReport_Files/UpgradeReport_Minus.gif differ diff --git a/V02/_UpgradeReport_Files/UpgradeReport_Plus.gif b/V02/_UpgradeReport_Files/UpgradeReport_Plus.gif new file mode 100644 index 0000000..f6009ca Binary files /dev/null and b/V02/_UpgradeReport_Files/UpgradeReport_Plus.gif differ diff --git a/V02/ddutil.cpp b/V02/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V02/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V02/ddutil.h b/V02/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V02/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V02/dsutil.cpp b/V02/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V02/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V02/dsutil.h b/V02/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V02/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V02/resource.h b/V02/resource.h new file mode 100644 index 0000000..b65a9ae --- /dev/null +++ b/V02/resource.h @@ -0,0 +1,25 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDM_EXIT 1001 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define otto 40028 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40029 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V02/ul_adeck.bmp b/V02/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V02/ul_adeck.bmp differ diff --git a/V02/ul_down.wav b/V02/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V02/ul_down.wav differ diff --git a/V02/ul_dreh.WAV b/V02/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V02/ul_dreh.WAV differ diff --git a/V02/ul_ende.WAV b/V02/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V02/ul_ende.WAV differ diff --git a/V02/ul_feld.bmp b/V02/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V02/ul_feld.bmp differ diff --git a/V02/ul_hgrnd.bmp b/V02/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V02/ul_hgrnd.bmp differ diff --git a/V02/ul_move.WAV b/V02/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V02/ul_move.WAV differ diff --git a/V02/ul_prev.bmp b/V02/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V02/ul_prev.bmp differ diff --git a/V02/ul_row1.WAV b/V02/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V02/ul_row1.WAV differ diff --git a/V02/ul_row2.WAV b/V02/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V02/ul_row2.WAV differ diff --git a/V02/ul_start.WAV b/V02/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V02/ul_start.WAV differ diff --git a/V02/ul_stein.bmp b/V02/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V02/ul_stein.bmp differ diff --git a/V02/ul_win.wav b/V02/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V02/ul_win.wav differ diff --git a/V02/ul_z0.bmp b/V02/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V02/ul_z0.bmp differ diff --git a/V02/ul_z1.bmp b/V02/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V02/ul_z1.bmp differ diff --git a/V02/ul_z2.bmp b/V02/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V02/ul_z2.bmp differ diff --git a/V02/ul_z3.bmp b/V02/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V02/ul_z3.bmp differ diff --git a/V02/ul_z4.bmp b/V02/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V02/ul_z4.bmp differ diff --git a/V02/ul_z5.bmp b/V02/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V02/ul_z5.bmp differ diff --git a/V02/ul_z6.bmp b/V02/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V02/ul_z6.bmp differ diff --git a/V02/ul_z7.bmp b/V02/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V02/ul_z7.bmp differ diff --git a/V02/ul_z8.bmp b/V02/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V02/ul_z8.bmp differ diff --git a/V02/ul_z9.bmp b/V02/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V02/ul_z9.bmp differ diff --git a/V03/Debug/BuildLog.htm b/V03/Debug/BuildLog.htm new file mode 100644 index 0000000..ca33e11 Binary files /dev/null and b/V03/Debug/BuildLog.htm differ diff --git a/V03/Debug/Demo.obj b/V03/Debug/Demo.obj new file mode 100644 index 0000000..3102e21 Binary files /dev/null and b/V03/Debug/Demo.obj differ diff --git a/V03/Debug/Demo.res b/V03/Debug/Demo.res new file mode 100644 index 0000000..b67fe70 Binary files /dev/null and b/V03/Debug/Demo.res differ diff --git a/V03/Debug/Ultris.exe b/V03/Debug/Ultris.exe new file mode 100644 index 0000000..9584915 Binary files /dev/null and b/V03/Debug/Ultris.exe differ diff --git a/V03/Debug/Ultris.exe.intermediate.manifest b/V03/Debug/Ultris.exe.intermediate.manifest new file mode 100644 index 0000000..1c06b61 --- /dev/null +++ b/V03/Debug/Ultris.exe.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/V03/Debug/Ultris.pdb b/V03/Debug/Ultris.pdb new file mode 100644 index 0000000..51aea47 Binary files /dev/null and b/V03/Debug/Ultris.pdb differ diff --git a/V03/Debug/ddutil.obj b/V03/Debug/ddutil.obj new file mode 100644 index 0000000..625ae4c Binary files /dev/null and b/V03/Debug/ddutil.obj differ diff --git a/V03/Debug/dsutil.obj b/V03/Debug/dsutil.obj new file mode 100644 index 0000000..489cbd6 Binary files /dev/null and b/V03/Debug/dsutil.obj differ diff --git a/V03/Debug/mt.dep b/V03/Debug/mt.dep new file mode 100644 index 0000000..8e76a3c --- /dev/null +++ b/V03/Debug/mt.dep @@ -0,0 +1 @@ + die Manifestressource wurde zuletzt um 15:15:25,76 am 19.02.2010 aktualisiert diff --git a/V03/Debug/vc90.idb b/V03/Debug/vc90.idb new file mode 100644 index 0000000..fcc8185 Binary files /dev/null and b/V03/Debug/vc90.idb differ diff --git a/V03/Debug/vc90.pdb b/V03/Debug/vc90.pdb new file mode 100644 index 0000000..bde69d0 Binary files /dev/null and b/V03/Debug/vc90.pdb differ diff --git a/V03/Demo.aps b/V03/Demo.aps new file mode 100644 index 0000000..ed0edd6 Binary files /dev/null and b/V03/Demo.aps differ diff --git a/V03/Demo.cpp b/V03/Demo.cpp new file mode 100644 index 0000000..361fd0d --- /dev/null +++ b/V03/Demo.cpp @@ -0,0 +1,409 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + + +// V3 Beginn +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + LPDIRECTDRAWPALETTE pal = 0; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +// V3 Ende +/* +** ultris_windowhandler +*/ +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case IDM_TEST: // Testcode + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; +// V3 Beginn + case WM_MOVE: + ultris_display.update(); + return 0; + case WM_PAINT: + int i; + + ultris_display.hintergrund(); + ultris_display.abdeckung(); + for( i = 0; i < 6; i++) + ultris_display.ziffer( i, i+1); + for( i = 0; i < 10; i++) + ultris_display.feldstein( 19-i, i); + for( i = 0; i < 10; i++) + ultris_display.fallstein( 1, i, 2*i); + for( i = 0; i < 4; i++) + ultris_display.prevstein( 3, 0, i, 4, 1); + ultris_display.present(); + break; +// V3 Ende + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + +// V3 Beginn + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } +// V3 Ende + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { +// V3 Beginn + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + // Hier koennen wir uns um das Spiel kuemmern + } +// V3 Ende + } + } + } + + + diff --git a/V03/Demo.h b/V03/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V03/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V03/Demo.ncb b/V03/Demo.ncb new file mode 100644 index 0000000..32eb411 Binary files /dev/null and b/V03/Demo.ncb differ diff --git a/V03/Demo.plg b/V03/Demo.plg new file mode 100644 index 0000000..e44be48 --- /dev/null +++ b/V03/Demo.plg @@ -0,0 +1,48 @@ + + +
+

Erstellungsprotokoll

+

+--------------------Konfiguration: Demo - Win32 Debug-------------------- +

+

Befehlszeilen

+Creating command line "rc.exe /l 0x407 /fo"Debug/Demo.res" /d "_DEBUG" "C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V03\Demo.rc"" +Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSP6.tmp" mit Inhalten +[ +/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR"Debug/" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V03\Demo.cpp" +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V03\ddutil.cpp" +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V03\dsutil.cpp" +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V03\dxutil.cpp" +] +Creating command line "cl.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSP6.tmp" +Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSP7.tmp" mit Inhalten +[ +winmm.lib dxguid.lib dxerr8.lib ddraw.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib dsound.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/Ultris.pdb" /debug /machine:I386 /out:"Debug/Ultris.exe" /pdbtype:sept +.\Debug\Demo.obj +.\Debug\ddutil.obj +.\Debug\dsutil.obj +.\Debug\dxutil.obj +.\Debug\Demo.res +] +Erstellen der Befehlzeile "link.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSP7.tmp" +

Ausgabefenster

+Ressourcen werden kompiliert... +Kompilierung läuft... +Demo.cpp +ddutil.cpp +dsutil.cpp +dxutil.cpp +Generieren von Code... +Linker-Vorgang läuft... +Erstellen der Befehlzeile "bscmake.exe /nologo /o"Debug/Demo.bsc" .\Debug\Demo.sbr .\Debug\ddutil.sbr .\Debug\dsutil.sbr .\Debug\dxutil.sbr" +Browse-Informationsdatei wird erstellt... +

Ausgabefenster

+ + + +

Ergebnisse

+Ultris.exe - 0 Fehler, 0 Warnung(en) +
+ + diff --git a/V03/Demo.rc b/V03/Demo.rc new file mode 100644 index 0000000..2d4c8ed --- /dev/null +++ b/V03/Demo.rc @@ -0,0 +1,115 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT +END + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V03/Demo.sln b/V03/Demo.sln new file mode 100644 index 0000000..a190765 --- /dev/null +++ b/V03/Demo.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{EF6643BF-F016-4942-A188-0478C19AB31F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EF6643BF-F016-4942-A188-0478C19AB31F}.Debug|Win32.ActiveCfg = Debug|Win32 + {EF6643BF-F016-4942-A188-0478C19AB31F}.Debug|Win32.Build.0 = Debug|Win32 + {EF6643BF-F016-4942-A188-0478C19AB31F}.Release|Win32.ActiveCfg = Release|Win32 + {EF6643BF-F016-4942-A188-0478C19AB31F}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/V03/Demo.sln.old b/V03/Demo.sln.old new file mode 100644 index 0000000..5033808 --- /dev/null +++ b/V03/Demo.sln.old @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{EF6643BF-F016-4942-A188-0478C19AB31F}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {EF6643BF-F016-4942-A188-0478C19AB31F}.Debug.ActiveCfg = Debug|Win32 + {EF6643BF-F016-4942-A188-0478C19AB31F}.Debug.Build.0 = Debug|Win32 + {EF6643BF-F016-4942-A188-0478C19AB31F}.Release.ActiveCfg = Release|Win32 + {EF6643BF-F016-4942-A188-0478C19AB31F}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V03/Demo.suo b/V03/Demo.suo new file mode 100644 index 0000000..a7d6603 Binary files /dev/null and b/V03/Demo.suo differ diff --git a/V03/Demo.suo.old b/V03/Demo.suo.old new file mode 100644 index 0000000..f4e2393 Binary files /dev/null and b/V03/Demo.suo.old differ diff --git a/V03/Demo.vcproj b/V03/Demo.vcproj new file mode 100644 index 0000000..d18cfb7 --- /dev/null +++ b/V03/Demo.vcproj @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V03/Demo.vcproj.7.10.old b/V03/Demo.vcproj.7.10.old new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V03/Demo.vcproj.7.10.old @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V03/Demo.vcproj.SASCHA.Sasch.user b/V03/Demo.vcproj.SASCHA.Sasch.user new file mode 100644 index 0000000..86f2a09 --- /dev/null +++ b/V03/Demo.vcproj.SASCHA.Sasch.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/V03/Icon.ico b/V03/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V03/Icon.ico differ diff --git a/V03/UpgradeLog.XML b/V03/UpgradeLog.XML new file mode 100644 index 0000000..3b0d64f --- /dev/null +++ b/V03/UpgradeLog.XML @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/V03/_UpgradeReport_Files/UpgradeReport.css b/V03/_UpgradeReport_Files/UpgradeReport.css new file mode 100644 index 0000000..3411f63 --- /dev/null +++ b/V03/_UpgradeReport_Files/UpgradeReport.css @@ -0,0 +1,207 @@ +BODY +{ + BACKGROUND-COLOR: white; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px +} +P +{ + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 70%; + LINE-HEIGHT: 12pt; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 10px +} +.note +{ + BACKGROUND-COLOR: #ffffff; + COLOR: #336699; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px; + PADDING-RIGHT: 10px +} +.infotable +{ + BACKGROUND-COLOR: #f0f0e0; + BORDER-BOTTOM: #ffffff 0px solid; + BORDER-COLLAPSE: collapse; + BORDER-LEFT: #ffffff 0px solid; + BORDER-RIGHT: #ffffff 0px solid; + BORDER-TOP: #ffffff 0px solid; + FONT-SIZE: 70%; + MARGIN-LEFT: 10px +} +.issuetable +{ + BACKGROUND-COLOR: #ffffe8; + BORDER-COLLAPSE: collapse; + COLOR: #000000; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 10px; + MARGIN-LEFT: 13px; + MARGIN-TOP: 0px +} +.issuetitle +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px; + COLOR: #003366; + FONT-WEIGHT: normal +} +.header +{ + BACKGROUND-COLOR: #cecf9c; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + COLOR: #000000; + FONT-WEIGHT: bold +} +.issuehdr +{ + BACKGROUND-COLOR: #E0EBF5; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + COLOR: #000000; + FONT-WEIGHT: normal +} +.issuenone +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: 0px; + BORDER-LEFT: 0px; + BORDER-RIGHT: 0px; + BORDER-TOP: 0px; + COLOR: #000000; + FONT-WEIGHT: normal +} +.content +{ + BACKGROUND-COLOR: #e7e7ce; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + PADDING-LEFT: 3px +} +.issuecontent +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + PADDING-LEFT: 3px +} +A:link +{ + COLOR: #cc6633; + TEXT-DECORATION: underline +} +A:visited +{ + COLOR: #cc6633; +} +A:active +{ + COLOR: #cc6633; +} +A:hover +{ + COLOR: #cc3300; + TEXT-DECORATION: underline +} +H1 +{ + BACKGROUND-COLOR: #003366; + BORDER-BOTTOM: #336699 6px solid; + COLOR: #ffffff; + FONT-SIZE: 130%; + FONT-WEIGHT: normal; + MARGIN: 0em 0em 0em -20px; + PADDING-BOTTOM: 8px; + PADDING-LEFT: 30px; + PADDING-TOP: 16px +} +H2 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 3px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px; + PADDING-LEFT: 0px +} +H3 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: -5px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px +} +H4 +{ + COLOR: #000000; + FONT-SIZE: 70%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 0px; + MARGIN-TOP: 15px; + PADDING-BOTTOM: 0px +} +UL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +OL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +LI +{ + LIST-STYLE: square; + MARGIN-LEFT: 0px +} +.expandable +{ + CURSOR: hand +} +.expanded +{ + color: black +} +.collapsed +{ + DISPLAY: none +} +.foot +{ +BACKGROUND-COLOR: #ffffff; +BORDER-BOTTOM: #cecf9c 1px solid; +BORDER-TOP: #cecf9c 2px solid +} +.settings +{ +MARGIN-LEFT: 25PX; +} +.help +{ +TEXT-ALIGN: right; +margin-right: 10px; +} diff --git a/V03/_UpgradeReport_Files/UpgradeReport.xslt b/V03/_UpgradeReport_Files/UpgradeReport.xslt new file mode 100644 index 0000000..6fb44ed --- /dev/null +++ b/V03/_UpgradeReport_Files/UpgradeReport.xslt @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Projektmappe: + Projekt: + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + src + + + + + + + + + + + + +
DateinameStatusFehlerWarnungen
+ javascript:document.images[''].click()src + + + + Konvertiert + + + + Konvertiert + +
+ + Dateien + + + 1 Datei + + + Konvertiert:
+ Nicht konvertiert: +
+
+
+ + + + : + + + + + + + + + Konvertierungsbericht + <xsl:if test="Properties/Property[@Name='LogNumber']"> + <xsl:value-of select="Properties/Property[@Name='LogNumber']/@Value"/> + </xsl:if> + + + + +

Konvertierungsbericht -

+ +

+ Konvertierungsdauer:
+

+ + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + +
+ Konvertierungseinstellungen +

+ + +
+
diff --git a/V03/_UpgradeReport_Files/UpgradeReport_Minus.gif b/V03/_UpgradeReport_Files/UpgradeReport_Minus.gif new file mode 100644 index 0000000..17751cb Binary files /dev/null and b/V03/_UpgradeReport_Files/UpgradeReport_Minus.gif differ diff --git a/V03/_UpgradeReport_Files/UpgradeReport_Plus.gif b/V03/_UpgradeReport_Files/UpgradeReport_Plus.gif new file mode 100644 index 0000000..f6009ca Binary files /dev/null and b/V03/_UpgradeReport_Files/UpgradeReport_Plus.gif differ diff --git a/V03/ddutil.cpp b/V03/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V03/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V03/ddutil.h b/V03/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V03/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V03/dsutil.cpp b/V03/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V03/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V03/dsutil.h b/V03/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V03/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V03/resource.h b/V03/resource.h new file mode 100644 index 0000000..23c118f --- /dev/null +++ b/V03/resource.h @@ -0,0 +1,24 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDM_EXIT 1001 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 134 +#define _APS_NEXT_COMMAND_VALUE 40028 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V03/ul_adeck.bmp b/V03/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V03/ul_adeck.bmp differ diff --git a/V03/ul_down.wav b/V03/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V03/ul_down.wav differ diff --git a/V03/ul_dreh.WAV b/V03/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V03/ul_dreh.WAV differ diff --git a/V03/ul_ende.WAV b/V03/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V03/ul_ende.WAV differ diff --git a/V03/ul_feld.bmp b/V03/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V03/ul_feld.bmp differ diff --git a/V03/ul_hgrnd.bmp b/V03/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V03/ul_hgrnd.bmp differ diff --git a/V03/ul_move.WAV b/V03/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V03/ul_move.WAV differ diff --git a/V03/ul_prev.bmp b/V03/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V03/ul_prev.bmp differ diff --git a/V03/ul_row1.WAV b/V03/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V03/ul_row1.WAV differ diff --git a/V03/ul_row2.WAV b/V03/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V03/ul_row2.WAV differ diff --git a/V03/ul_start.WAV b/V03/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V03/ul_start.WAV differ diff --git a/V03/ul_stein.bmp b/V03/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V03/ul_stein.bmp differ diff --git a/V03/ul_win.wav b/V03/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V03/ul_win.wav differ diff --git a/V03/ul_z0.bmp b/V03/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V03/ul_z0.bmp differ diff --git a/V03/ul_z1.bmp b/V03/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V03/ul_z1.bmp differ diff --git a/V03/ul_z2.bmp b/V03/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V03/ul_z2.bmp differ diff --git a/V03/ul_z3.bmp b/V03/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V03/ul_z3.bmp differ diff --git a/V03/ul_z4.bmp b/V03/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V03/ul_z4.bmp differ diff --git a/V03/ul_z5.bmp b/V03/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V03/ul_z5.bmp differ diff --git a/V03/ul_z6.bmp b/V03/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V03/ul_z6.bmp differ diff --git a/V03/ul_z7.bmp b/V03/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V03/ul_z7.bmp differ diff --git a/V03/ul_z8.bmp b/V03/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V03/ul_z8.bmp differ diff --git a/V03/ul_z9.bmp b/V03/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V03/ul_z9.bmp differ diff --git a/V04/Demo.aps b/V04/Demo.aps new file mode 100644 index 0000000..507ce09 Binary files /dev/null and b/V04/Demo.aps differ diff --git a/V04/Demo.cpp b/V04/Demo.cpp new file mode 100644 index 0000000..ef8310e --- /dev/null +++ b/V04/Demo.cpp @@ -0,0 +1,834 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + + +// V4 Beginn + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + +// V4 Ende + +/* +** ultris_windowhandler +*/ + +// V4 Beginn +int testform = 0; +// V4 Ende + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; +// V4 Beginn + case IDM_TEST: // Testcode + testform = (testform + 1) % anzahl_formen; + PostMessage( hWnd, WM_PAINT, 0, 0); + return 0; +// V4 Ende + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; +// V4 Beginn + case WM_PAINT: + int variante; + int z, s, x, y; + const form *f; + + ultris_display.hintergrund(); + + for( variante = 0; variante < 4; variante++) + { + z = 1 + 5*variante; + s = 3; + f = ultris_form[testform][variante]; + for( x = 0; x < f->b; x++) + { + for( y = 0; y < f->h; y++) + { + if( f->data[y][x]) + ultris_display.fallstein(z+y,s+x,0); + } + } + } + ultris_display.present(); + break; + } +// V4 Ende + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + // Hier koennen wir uns um das Spiel kuemmern + } + } + } + } + + + diff --git a/V04/Demo.h b/V04/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V04/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V04/Demo.ncb b/V04/Demo.ncb new file mode 100644 index 0000000..a6a970d Binary files /dev/null and b/V04/Demo.ncb differ diff --git a/V04/Demo.rc b/V04/Demo.rc new file mode 100644 index 0000000..2d4c8ed --- /dev/null +++ b/V04/Demo.rc @@ -0,0 +1,115 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT +END + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V04/Demo.sln b/V04/Demo.sln new file mode 100644 index 0000000..67d59f5 --- /dev/null +++ b/V04/Demo.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{03EE9EF4-D248-41BC-98D7-43F16FE8AD16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {03EE9EF4-D248-41BC-98D7-43F16FE8AD16}.Debug|Win32.ActiveCfg = Debug|Win32 + {03EE9EF4-D248-41BC-98D7-43F16FE8AD16}.Debug|Win32.Build.0 = Debug|Win32 + {03EE9EF4-D248-41BC-98D7-43F16FE8AD16}.Release|Win32.ActiveCfg = Release|Win32 + {03EE9EF4-D248-41BC-98D7-43F16FE8AD16}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/V04/Demo.sln.old b/V04/Demo.sln.old new file mode 100644 index 0000000..f619333 --- /dev/null +++ b/V04/Demo.sln.old @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{03EE9EF4-D248-41BC-98D7-43F16FE8AD16}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {03EE9EF4-D248-41BC-98D7-43F16FE8AD16}.Debug.ActiveCfg = Debug|Win32 + {03EE9EF4-D248-41BC-98D7-43F16FE8AD16}.Debug.Build.0 = Debug|Win32 + {03EE9EF4-D248-41BC-98D7-43F16FE8AD16}.Release.ActiveCfg = Release|Win32 + {03EE9EF4-D248-41BC-98D7-43F16FE8AD16}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V04/Demo.suo b/V04/Demo.suo new file mode 100644 index 0000000..2668043 Binary files /dev/null and b/V04/Demo.suo differ diff --git a/V04/Demo.suo.old b/V04/Demo.suo.old new file mode 100644 index 0000000..98e84da Binary files /dev/null and b/V04/Demo.suo.old differ diff --git a/V04/Demo.vcproj b/V04/Demo.vcproj new file mode 100644 index 0000000..fb0ec93 --- /dev/null +++ b/V04/Demo.vcproj @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V04/Demo.vcproj.7.10.old b/V04/Demo.vcproj.7.10.old new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V04/Demo.vcproj.7.10.old @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V04/Demo.vcproj.SASCHA.Sasch.user b/V04/Demo.vcproj.SASCHA.Sasch.user new file mode 100644 index 0000000..86f2a09 --- /dev/null +++ b/V04/Demo.vcproj.SASCHA.Sasch.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/V04/Icon.ico b/V04/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V04/Icon.ico differ diff --git a/V04/UpgradeLog.XML b/V04/UpgradeLog.XML new file mode 100644 index 0000000..1ac1c14 --- /dev/null +++ b/V04/UpgradeLog.XML @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/V04/_UpgradeReport_Files/UpgradeReport.css b/V04/_UpgradeReport_Files/UpgradeReport.css new file mode 100644 index 0000000..3411f63 --- /dev/null +++ b/V04/_UpgradeReport_Files/UpgradeReport.css @@ -0,0 +1,207 @@ +BODY +{ + BACKGROUND-COLOR: white; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px +} +P +{ + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 70%; + LINE-HEIGHT: 12pt; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 10px +} +.note +{ + BACKGROUND-COLOR: #ffffff; + COLOR: #336699; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px; + PADDING-RIGHT: 10px +} +.infotable +{ + BACKGROUND-COLOR: #f0f0e0; + BORDER-BOTTOM: #ffffff 0px solid; + BORDER-COLLAPSE: collapse; + BORDER-LEFT: #ffffff 0px solid; + BORDER-RIGHT: #ffffff 0px solid; + BORDER-TOP: #ffffff 0px solid; + FONT-SIZE: 70%; + MARGIN-LEFT: 10px +} +.issuetable +{ + BACKGROUND-COLOR: #ffffe8; + BORDER-COLLAPSE: collapse; + COLOR: #000000; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 10px; + MARGIN-LEFT: 13px; + MARGIN-TOP: 0px +} +.issuetitle +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px; + COLOR: #003366; + FONT-WEIGHT: normal +} +.header +{ + BACKGROUND-COLOR: #cecf9c; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + COLOR: #000000; + FONT-WEIGHT: bold +} +.issuehdr +{ + BACKGROUND-COLOR: #E0EBF5; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + COLOR: #000000; + FONT-WEIGHT: normal +} +.issuenone +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: 0px; + BORDER-LEFT: 0px; + BORDER-RIGHT: 0px; + BORDER-TOP: 0px; + COLOR: #000000; + FONT-WEIGHT: normal +} +.content +{ + BACKGROUND-COLOR: #e7e7ce; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + PADDING-LEFT: 3px +} +.issuecontent +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + PADDING-LEFT: 3px +} +A:link +{ + COLOR: #cc6633; + TEXT-DECORATION: underline +} +A:visited +{ + COLOR: #cc6633; +} +A:active +{ + COLOR: #cc6633; +} +A:hover +{ + COLOR: #cc3300; + TEXT-DECORATION: underline +} +H1 +{ + BACKGROUND-COLOR: #003366; + BORDER-BOTTOM: #336699 6px solid; + COLOR: #ffffff; + FONT-SIZE: 130%; + FONT-WEIGHT: normal; + MARGIN: 0em 0em 0em -20px; + PADDING-BOTTOM: 8px; + PADDING-LEFT: 30px; + PADDING-TOP: 16px +} +H2 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 3px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px; + PADDING-LEFT: 0px +} +H3 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: -5px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px +} +H4 +{ + COLOR: #000000; + FONT-SIZE: 70%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 0px; + MARGIN-TOP: 15px; + PADDING-BOTTOM: 0px +} +UL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +OL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +LI +{ + LIST-STYLE: square; + MARGIN-LEFT: 0px +} +.expandable +{ + CURSOR: hand +} +.expanded +{ + color: black +} +.collapsed +{ + DISPLAY: none +} +.foot +{ +BACKGROUND-COLOR: #ffffff; +BORDER-BOTTOM: #cecf9c 1px solid; +BORDER-TOP: #cecf9c 2px solid +} +.settings +{ +MARGIN-LEFT: 25PX; +} +.help +{ +TEXT-ALIGN: right; +margin-right: 10px; +} diff --git a/V04/_UpgradeReport_Files/UpgradeReport.xslt b/V04/_UpgradeReport_Files/UpgradeReport.xslt new file mode 100644 index 0000000..6fb44ed --- /dev/null +++ b/V04/_UpgradeReport_Files/UpgradeReport.xslt @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Projektmappe: + Projekt: + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + src + + + + + + + + + + + + +
DateinameStatusFehlerWarnungen
+ javascript:document.images[''].click()src + + + + Konvertiert + + + + Konvertiert + +
+ + Dateien + + + 1 Datei + + + Konvertiert:
+ Nicht konvertiert: +
+
+
+ + + + : + + + + + + + + + Konvertierungsbericht + <xsl:if test="Properties/Property[@Name='LogNumber']"> + <xsl:value-of select="Properties/Property[@Name='LogNumber']/@Value"/> + </xsl:if> + + + + +

Konvertierungsbericht -

+ +

+ Konvertierungsdauer:
+

+ + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + +
+ Konvertierungseinstellungen +

+ + +
+
diff --git a/V04/_UpgradeReport_Files/UpgradeReport_Minus.gif b/V04/_UpgradeReport_Files/UpgradeReport_Minus.gif new file mode 100644 index 0000000..17751cb Binary files /dev/null and b/V04/_UpgradeReport_Files/UpgradeReport_Minus.gif differ diff --git a/V04/_UpgradeReport_Files/UpgradeReport_Plus.gif b/V04/_UpgradeReport_Files/UpgradeReport_Plus.gif new file mode 100644 index 0000000..f6009ca Binary files /dev/null and b/V04/_UpgradeReport_Files/UpgradeReport_Plus.gif differ diff --git a/V04/ddutil.cpp b/V04/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V04/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V04/ddutil.h b/V04/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V04/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V04/dsutil.cpp b/V04/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V04/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V04/dsutil.h b/V04/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V04/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V04/resource.h b/V04/resource.h new file mode 100644 index 0000000..e35bf2f --- /dev/null +++ b/V04/resource.h @@ -0,0 +1,24 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDM_EXIT 1001 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40028 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V04/ul_adeck.bmp b/V04/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V04/ul_adeck.bmp differ diff --git a/V04/ul_down.wav b/V04/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V04/ul_down.wav differ diff --git a/V04/ul_dreh.WAV b/V04/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V04/ul_dreh.WAV differ diff --git a/V04/ul_ende.WAV b/V04/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V04/ul_ende.WAV differ diff --git a/V04/ul_feld.bmp b/V04/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V04/ul_feld.bmp differ diff --git a/V04/ul_hgrnd.bmp b/V04/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V04/ul_hgrnd.bmp differ diff --git a/V04/ul_move.WAV b/V04/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V04/ul_move.WAV differ diff --git a/V04/ul_prev.bmp b/V04/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V04/ul_prev.bmp differ diff --git a/V04/ul_row1.WAV b/V04/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V04/ul_row1.WAV differ diff --git a/V04/ul_row2.WAV b/V04/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V04/ul_row2.WAV differ diff --git a/V04/ul_start.WAV b/V04/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V04/ul_start.WAV differ diff --git a/V04/ul_stein.bmp b/V04/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V04/ul_stein.bmp differ diff --git a/V04/ul_win.wav b/V04/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V04/ul_win.wav differ diff --git a/V04/ul_z0.bmp b/V04/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V04/ul_z0.bmp differ diff --git a/V04/ul_z1.bmp b/V04/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V04/ul_z1.bmp differ diff --git a/V04/ul_z2.bmp b/V04/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V04/ul_z2.bmp differ diff --git a/V04/ul_z3.bmp b/V04/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V04/ul_z3.bmp differ diff --git a/V04/ul_z4.bmp b/V04/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V04/ul_z4.bmp differ diff --git a/V04/ul_z5.bmp b/V04/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V04/ul_z5.bmp differ diff --git a/V04/ul_z6.bmp b/V04/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V04/ul_z6.bmp differ diff --git a/V04/ul_z7.bmp b/V04/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V04/ul_z7.bmp differ diff --git a/V04/ul_z8.bmp b/V04/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V04/ul_z8.bmp differ diff --git a/V04/ul_z9.bmp b/V04/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V04/ul_z9.bmp differ diff --git a/V05/Demo.aps b/V05/Demo.aps new file mode 100644 index 0000000..573262e Binary files /dev/null and b/V05/Demo.aps differ diff --git a/V05/Demo.cpp b/V05/Demo.cpp new file mode 100644 index 0000000..acfc324 --- /dev/null +++ b/V05/Demo.cpp @@ -0,0 +1,843 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + + +// V5 Beginn +BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if( wParam == IDC_WEITERE_INFO) + { + ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); + return TRUE; + } + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } +// V5 Ende + + +/* +** ultris_windowhandler +*/ + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; +// V5 Beginn + case ID_INFO_HILFE: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); + return 0; + case ID_INFO_ULTRIS: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); + return 0; +// V5 Ende + case IDM_TEST: // Testcode + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; + case WM_PAINT: + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + // Hier koennen wir uns um das Spiel kuemmern + } + } + } + } + + + diff --git a/V05/Demo.h b/V05/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V05/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V05/Demo.ncb b/V05/Demo.ncb new file mode 100644 index 0000000..564ba37 Binary files /dev/null and b/V05/Demo.ncb differ diff --git a/V05/Demo.rc b/V05/Demo.rc new file mode 100644 index 0000000..43ccb57 --- /dev/null +++ b/V05/Demo.rc @@ -0,0 +1,202 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END + POPUP "Einstellungen" + BEGIN + MENUITEM "Konfiguration", ID_EINSTELLUNGEN_KONFIGURATION + + END + POPUP "Info" + BEGIN + MENUITEM "Hilfe", ID_INFO_HILFE + MENUITEM "Highscores", ID_INFO_HIGHSCORES + MENUITEM "Ultris", ID_INFO_ULTRIS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_HILFE DIALOG DISCARDABLE 0, 0, 302, 107 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Hilfe" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,245,90,50,14 + LTEXT "F1: Neues Spiel",IDC_STATIC,15,22,130,8 + LTEXT "F2: Pause (ein/aus)",IDC_STATIC,15,34,130,8 + LTEXT "F3: Schneller",IDC_STATIC,15,46,130,8 + LTEXT "F4: Langsamer",IDC_STATIC,15,58,130,8 + LTEXT "F5: Sound (ein/aus)",IDC_STATIC,15,70,130,8 + GROUPBOX "Steuerung des Spiels",IDC_STATIC,7,7,142,78 + GROUPBOX "Steuerung der Steine",IDC_STATIC,153,7,142,78 + LTEXT "J oder Cursor left: Links",IDC_STATIC,159,22,131,8 + LTEXT "L oder Cursor right: Rechts",IDC_STATIC,159,34,131,8 + LTEXT "K oder Cursor down: Linksdrehung",IDC_STATIC,159,46,131, + 8 + LTEXT "I oder Cursor up: Rechtsdrehung",IDC_STATIC,159,58,131, + 8 + LTEXT "Space: Stein fallen lassen",IDC_STATIC,159,70,126,8 +END + +IDD_ULTRIS DIALOG DISCARDABLE 0, 0, 204, 142 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Über Ultris" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,125,50,14 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_BORDER,7,7,190,78 + CTEXT "Demoprogramm\rzur Vorlesung\rGrafik und Spieleprogrammierung", + IDC_STATIC,7,92,195,28 + PUSHBUTTON "Weitere Informationen",IDC_WEITERE_INFO,5,125,140,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_HILFE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_ULTRIS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 197 + TOPMARGIN, 7 + BOTTOMMARGIN, 135 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ULTRIS BITMAP DISCARDABLE "bmp00001.bmp" +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V05/Demo.sln b/V05/Demo.sln new file mode 100644 index 0000000..737efb7 --- /dev/null +++ b/V05/Demo.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{E4D498D1-702B-4430-8EA5-1A667B2BD793}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {E4D498D1-702B-4430-8EA5-1A667B2BD793}.Debug.ActiveCfg = Debug|Win32 + {E4D498D1-702B-4430-8EA5-1A667B2BD793}.Debug.Build.0 = Debug|Win32 + {E4D498D1-702B-4430-8EA5-1A667B2BD793}.Release.ActiveCfg = Release|Win32 + {E4D498D1-702B-4430-8EA5-1A667B2BD793}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V05/Demo.suo b/V05/Demo.suo new file mode 100644 index 0000000..3f5f215 Binary files /dev/null and b/V05/Demo.suo differ diff --git a/V05/Demo.vcproj b/V05/Demo.vcproj new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V05/Demo.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V05/Icon.ico b/V05/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V05/Icon.ico differ diff --git a/V05/bmp00001.bmp b/V05/bmp00001.bmp new file mode 100644 index 0000000..12d2027 Binary files /dev/null and b/V05/bmp00001.bmp differ diff --git a/V05/ddutil.cpp b/V05/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V05/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V05/ddutil.h b/V05/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V05/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V05/dsutil.cpp b/V05/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V05/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V05/dsutil.h b/V05/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V05/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V05/resource.h b/V05/resource.h new file mode 100644 index 0000000..c041f0c --- /dev/null +++ b/V05/resource.h @@ -0,0 +1,32 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDD_HILFE 124 +#define IDD_ULTRIS 129 +#define IDB_ULTRIS 130 +#define IDM_EXIT 1001 +#define IDC_WEITERE_INFO 1018 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define ID_EINSTELLUNGEN_KONFIGURATION 40028 +#define ID_INFO_HILFE 40029 +#define ID_INFO_HIGHSCORES 40030 +#define ID_INFO_ULTRIS 40031 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40032 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V05/ul_adeck.bmp b/V05/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V05/ul_adeck.bmp differ diff --git a/V05/ul_down.wav b/V05/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V05/ul_down.wav differ diff --git a/V05/ul_dreh.WAV b/V05/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V05/ul_dreh.WAV differ diff --git a/V05/ul_ende.WAV b/V05/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V05/ul_ende.WAV differ diff --git a/V05/ul_feld.bmp b/V05/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V05/ul_feld.bmp differ diff --git a/V05/ul_hgrnd.bmp b/V05/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V05/ul_hgrnd.bmp differ diff --git a/V05/ul_move.WAV b/V05/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V05/ul_move.WAV differ diff --git a/V05/ul_prev.bmp b/V05/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V05/ul_prev.bmp differ diff --git a/V05/ul_row1.WAV b/V05/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V05/ul_row1.WAV differ diff --git a/V05/ul_row2.WAV b/V05/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V05/ul_row2.WAV differ diff --git a/V05/ul_start.WAV b/V05/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V05/ul_start.WAV differ diff --git a/V05/ul_stein.bmp b/V05/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V05/ul_stein.bmp differ diff --git a/V05/ul_win.wav b/V05/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V05/ul_win.wav differ diff --git a/V05/ul_z0.bmp b/V05/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V05/ul_z0.bmp differ diff --git a/V05/ul_z1.bmp b/V05/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V05/ul_z1.bmp differ diff --git a/V05/ul_z2.bmp b/V05/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V05/ul_z2.bmp differ diff --git a/V05/ul_z3.bmp b/V05/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V05/ul_z3.bmp differ diff --git a/V05/ul_z4.bmp b/V05/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V05/ul_z4.bmp differ diff --git a/V05/ul_z5.bmp b/V05/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V05/ul_z5.bmp differ diff --git a/V05/ul_z6.bmp b/V05/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V05/ul_z6.bmp differ diff --git a/V05/ul_z7.bmp b/V05/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V05/ul_z7.bmp differ diff --git a/V05/ul_z8.bmp b/V05/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V05/ul_z8.bmp differ diff --git a/V05/ul_z9.bmp b/V05/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V05/ul_z9.bmp differ diff --git a/V06/Demo.cpp b/V06/Demo.cpp new file mode 100644 index 0000000..40daa7b --- /dev/null +++ b/V06/Demo.cpp @@ -0,0 +1,938 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + +// V6 Beginn + +// Array mit den aktuell im Spiel aktivierten Steinformen +// Zu Programmstart sind dies die ueblichen Tetris Spielsteine (0-6) +char aktive_formen[anzahl_formen] = + { + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 + }; + +// Anzahl der aktuell aktivierten Steinformen +int anz_aktive_formen = 7; + +class ultris + { + private: + int vorbelegung; // Anzahl der bei Spielbeginn vorzubelegenden Zeilen + int vorschau; // Anzahl der Formen in der Vorschau + public: + ultris(){ vorbelegung = 0; vorschau = 1;} + int get_vorbelegung() { return vorbelegung;} + void set_vorbelegung( int v) {if( v < 0) v = 0; if( v > 20) v = 20; vorbelegung = v;} + int get_vorschau() { return vorschau;} + void set_vorschau( int v) {if( v < 0) v = 0; if(v > 5) v = 5; vorschau = v;} + }; + +ultris mein_spiel; +// V6 Ende + + +BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if( wParam == IDC_WEITERE_INFO) + { + ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); + return TRUE; + } + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +// V6 Beginn +BOOL CALLBACK konfigurationsdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int i; + + switch (uMsg) + { + case WM_INITDIALOG: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, aktive_formen[i] ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, mein_spiel.get_vorbelegung(), FALSE); + SetDlgItemInt( hwndDlg, IDC_VORSCHAU, mein_spiel.get_vorschau(), FALSE); + return TRUE; + case WM_COMMAND: + if(wParam == IDOK) + { + for( i = 0, anz_aktive_formen = 0; i < anzahl_formen; i++) + { + aktive_formen[i] = 0; + if(IsDlgButtonChecked( hwndDlg, 5000+i) == BST_CHECKED) + { + aktive_formen[i] = 1; + anz_aktive_formen++; + } + } + if( anz_aktive_formen == 0) + { + aktive_formen[0] = 1; + anz_aktive_formen = 1; + } + mein_spiel.set_vorbelegung( GetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, NULL, FALSE)); + mein_spiel.set_vorschau( GetDlgItemInt( hwndDlg, IDC_VORSCHAU, NULL, FALSE)); + EndDialog(hwndDlg, wParam); + return TRUE; + } + if(wParam == IDCANCEL) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + if (HIWORD(wParam) == BN_CLICKED) + { + switch( LOWORD(wParam)) + { + case IDC_LOESCHEN: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_UNCHECKED); + return TRUE; + case IDC_ALLE: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_CHECKED); + return TRUE; + case IDC_STANDARD: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, i < 7 ? BST_CHECKED:BST_UNCHECKED); + return TRUE; + } + } + } + return FALSE; + } +// V6 Ende + +/* +** ultris_windowhandler +*/ + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case ID_INFO_HILFE: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); + return 0; + case ID_INFO_ULTRIS: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); + return 0; +// V6 Beginn + case ID_EINSTELLUNGEN_KONFIGURATION: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_KONFIGURATION), ultris_window, konfigurationsdialog); + return 0; +// V6 Ende + case IDM_TEST: // Testcode + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; + case WM_PAINT: + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + // Hier koennen wir uns um das Spiel kuemmern + } + } + } + } + + + diff --git a/V06/Demo.h b/V06/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V06/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V06/Demo.ncb b/V06/Demo.ncb new file mode 100644 index 0000000..bc6a80f Binary files /dev/null and b/V06/Demo.ncb differ diff --git a/V06/Demo.rc b/V06/Demo.rc new file mode 100644 index 0000000..0b839f4 --- /dev/null +++ b/V06/Demo.rc @@ -0,0 +1,686 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END + POPUP "Einstellungen" + BEGIN + MENUITEM "Konfiguration", ID_EINSTELLUNGEN_KONFIGURATION + + END + POPUP "Info" + BEGIN + MENUITEM "Hilfe", ID_INFO_HILFE + MENUITEM "Highscores", ID_INFO_HIGHSCORES + MENUITEM "Ultris", ID_INFO_ULTRIS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_HILFE DIALOG DISCARDABLE 0, 0, 302, 107 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Hilfe" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,245,90,50,14 + LTEXT "F1: Neues Spiel",IDC_STATIC,15,22,130,8 + LTEXT "F2: Pause (ein/aus)",IDC_STATIC,15,34,130,8 + LTEXT "F3: Schneller",IDC_STATIC,15,46,130,8 + LTEXT "F4: Langsamer",IDC_STATIC,15,58,130,8 + LTEXT "F5: Sound (ein/aus)",IDC_STATIC,15,70,130,8 + GROUPBOX "Steuerung des Spiels",IDC_STATIC,7,7,142,78 + GROUPBOX "Steuerung der Steine",IDC_STATIC,153,7,142,78 + LTEXT "J oder Cursor left: Links",IDC_STATIC,159,22,131,8 + LTEXT "L oder Cursor right: Rechts",IDC_STATIC,159,34,131,8 + LTEXT "K oder Cursor down: Linksdrehung",IDC_STATIC,159,46,131, + 8 + LTEXT "I oder Cursor up: Rechtsdrehung",IDC_STATIC,159,58,131, + 8 + LTEXT "Space: Stein fallen lassen",IDC_STATIC,159,70,126,8 +END + +IDD_ULTRIS DIALOG DISCARDABLE 0, 0, 204, 142 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Über Ultris" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,125,50,14 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_BORDER,7,7,190,78 + CTEXT "Demoprogramm\rzur Vorlesung\rGrafik und Spieleprogrammierung", + IDC_STATIC,7,92,195,28 + PUSHBUTTON "Weitere Informationen",IDC_WEITERE_INFO,5,125,140,14 +END + +IDD_KONFIGURATION DIALOGEX 0, 0, 289, 297 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Einstellungen" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,235,280,50,14 + PUSHBUTTON "Abbrechen",IDCANCEL,180,280,50,14 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,50,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,70,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,30,10,10 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,40,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,10,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,105,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,25,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,55,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,65,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,210,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,15,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,160,10,10 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 43,8,8 + CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 43,8,8 + CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 43,8,8 + CONTROL "10",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 154,43,8,8 + CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 43,8,8 + CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 43,8,8 + CONTROL "6",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 43,8,8 + CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 93,8,8 + CONTROL "",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 93,8,8 + CONTROL "",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 93,8,8 + CONTROL "",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 93,8,8 + CONTROL "",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 93,8,8 + CONTROL "",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 93,8,8 + CONTROL "20",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 274,93,8,8 + CONTROL "",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 143,8,8 + CONTROL "",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 143,8,8 + CONTROL "",IDC_CHECK17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 143,8,8 + CONTROL "",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 143,8,8 + CONTROL "",IDC_CHECK19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 143,8,8 + CONTROL "",IDC_CHECK20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 143,8,8 + CONTROL "",IDC_CHECK21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 143,8,8 + CONTROL "",IDC_CHECK22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 193,8,8 + CONTROL "",IDC_CHECK23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 193,8,8 + CONTROL "",IDC_CHECK24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 193,8,8 + CONTROL "",IDC_CHECK25,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 193,8,8 + CONTROL "",IDC_CHECK26,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 193,8,8 + CONTROL "",IDC_CHECK27,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 193,8,8 + CONTROL "",IDC_CHECK28,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 193,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,210,10,10 + CONTROL "",IDC_CHECK29,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 243,8,8 + CONTROL "",IDC_CHECK30,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 243,8,8 + CONTROL "",IDC_CHECK31,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 243,8,8 + CONTROL "",IDC_CHECK32,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 243,8,8 + CONTROL "",IDC_CHECK33,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 243,8,8 + CONTROL "",IDC_CHECK34,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 243,8,8 + CONTROL "",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 243,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,205,40,50, + WS_EX_DLGMODALFRAME + PUSHBUTTON "Alle auswählen",IDC_ALLE,235,260,50,14 + PUSHBUTTON "Standard",IDC_STANDARD,180,260,50,14 + PUSHBUTTON "Alle Löschen",IDC_LOESCHEN,125,260,50,14 + EDITTEXT IDC_VORBELEGUNG,105,260,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Vorbelegte Zeilen bei Spielstart:",IDC_STATIC,5,260,95, + 13,SS_CENTERIMAGE + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,210,10,10 + LTEXT "1",IDC_STATIC,11,143,8,8 + LTEXT "2",IDC_STATIC,10,193,8,8 + LTEXT "4",IDC_STATIC,50,193,8,8 + LTEXT "6",IDC_STATIC,250,43,8,8 + LTEXT "8",IDC_STATIC,10,43,8,8 + LTEXT "10",IDC_STATIC,130,43,8,8 + LTEXT "10",IDC_STATIC,170,43,8,8 + LTEXT "12",IDC_STATIC,50,43,8,8 + LTEXT "12",IDC_STATIC,90,43,8,8 + LTEXT "10",IDC_STATIC,210,43,8,8 + LTEXT "25",IDC_STATIC,10,93,8,8 + LTEXT "25",IDC_STATIC,50,93,8,8 + LTEXT "4",IDC_STATIC,90,93,8,8 + LTEXT "20",IDC_STATIC,130,93,8,8 + LTEXT "10",IDC_STATIC,170,93,8,8 + LTEXT "10",IDC_STATIC,210,93,8,8 + LTEXT "20",IDC_STATIC,250,93,8,8 + LTEXT "8",IDC_STATIC,50,143,8,8 + LTEXT "25",IDC_STATIC,90,143,8,8 + LTEXT "40",IDC_STATIC,130,143,8,8 + LTEXT "15",IDC_STATIC,170,143,8,8 + LTEXT "25",IDC_STATIC,210,143,8,8 + LTEXT "35",IDC_STATIC,250,143,8,8 + LTEXT "10",IDC_STATIC,90,193,8,8 + LTEXT "10",IDC_STATIC,130,193,8,8 + LTEXT "20",IDC_STATIC,170,193,8,8 + LTEXT "20",IDC_STATIC,210,193,8,8 + LTEXT "25",IDC_STATIC,250,193,8,8 + LTEXT "25",IDC_STATIC,10,243,8,8 + LTEXT "30",IDC_STATIC,50,243,8,8 + LTEXT "25",IDC_STATIC,90,243,8,8 + LTEXT "25",IDC_STATIC,130,243,8,8 + LTEXT "10",IDC_STATIC,170,243,8,8 + LTEXT "15",IDC_STATIC,210,243,8,8 + LTEXT "25",IDC_STATIC,250,243,8,8 + EDITTEXT IDC_VORSCHAU,105,280,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Steine in der Vorschau:",IDC_STATIC,5,280,95,13, + SS_CENTERIMAGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_HILFE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_ULTRIS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 197 + TOPMARGIN, 7 + BOTTOMMARGIN, 135 + END + + IDD_KONFIGURATION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 282 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ULTRIS BITMAP DISCARDABLE "bmp00001.bmp" +IDB_STEIN BITMAP DISCARDABLE "bmp00002.bmp" +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V06/Demo.sln b/V06/Demo.sln new file mode 100644 index 0000000..8778ada --- /dev/null +++ b/V06/Demo.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{E366BFA4-48AF-49A5-B855-06CE431A7FFD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {E366BFA4-48AF-49A5-B855-06CE431A7FFD}.Debug.ActiveCfg = Debug|Win32 + {E366BFA4-48AF-49A5-B855-06CE431A7FFD}.Debug.Build.0 = Debug|Win32 + {E366BFA4-48AF-49A5-B855-06CE431A7FFD}.Release.ActiveCfg = Release|Win32 + {E366BFA4-48AF-49A5-B855-06CE431A7FFD}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V06/Demo.suo b/V06/Demo.suo new file mode 100644 index 0000000..c538610 Binary files /dev/null and b/V06/Demo.suo differ diff --git a/V06/Demo.vcproj b/V06/Demo.vcproj new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V06/Demo.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V06/Icon.ico b/V06/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V06/Icon.ico differ diff --git a/V06/bmp00001.bmp b/V06/bmp00001.bmp new file mode 100644 index 0000000..12d2027 Binary files /dev/null and b/V06/bmp00001.bmp differ diff --git a/V06/bmp00002.bmp b/V06/bmp00002.bmp new file mode 100644 index 0000000..92b8396 Binary files /dev/null and b/V06/bmp00002.bmp differ diff --git a/V06/ddutil.cpp b/V06/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V06/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V06/ddutil.h b/V06/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V06/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V06/dsutil.cpp b/V06/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V06/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V06/dsutil.h b/V06/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V06/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V06/resource.h b/V06/resource.h new file mode 100644 index 0000000..4043885 --- /dev/null +++ b/V06/resource.h @@ -0,0 +1,74 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDD_HILFE 124 +#define IDD_KONFIGURATION 125 +#define IDB_STEIN 126 +#define IDD_ULTRIS 129 +#define IDB_ULTRIS 130 +#define IDM_EXIT 1001 +#define IDC_ALLE 1005 +#define IDC_STANDARD 1006 +#define IDC_LOESCHEN 1007 +#define IDC_VORBELEGUNG 1008 +#define IDC_VORSCHAU 1009 +#define IDC_WEITERE_INFO 1018 +#define IDC_CHECK1 5000 +#define IDC_CHECK2 5001 +#define IDC_CHECK3 5002 +#define IDC_CHECK4 5003 +#define IDC_CHECK5 5004 +#define IDC_CHECK6 5005 +#define IDC_CHECK7 5006 +#define IDC_CHECK8 5007 +#define IDC_CHECK9 5008 +#define IDC_CHECK10 5009 +#define IDC_CHECK11 5010 +#define IDC_CHECK12 5011 +#define IDC_CHECK13 5012 +#define IDC_CHECK14 5013 +#define IDC_CHECK15 5014 +#define IDC_CHECK16 5015 +#define IDC_CHECK17 5016 +#define IDC_CHECK18 5017 +#define IDC_CHECK19 5018 +#define IDC_CHECK20 5019 +#define IDC_CHECK21 5020 +#define IDC_CHECK22 5021 +#define IDC_CHECK23 5022 +#define IDC_CHECK24 5023 +#define IDC_CHECK25 5024 +#define IDC_CHECK26 5025 +#define IDC_CHECK27 5026 +#define IDC_CHECK28 5027 +#define IDC_CHECK29 5028 +#define IDC_CHECK30 5029 +#define IDC_CHECK31 5030 +#define IDC_CHECK32 5031 +#define IDC_CHECK33 5032 +#define IDC_CHECK34 5033 +#define IDC_CHECK35 5034 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define ID_EINSTELLUNGEN_KONFIGURATION 40028 +#define ID_INFO_HILFE 40029 +#define ID_INFO_HIGHSCORES 40030 +#define ID_INFO_ULTRIS 40031 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40032 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V06/ul_adeck.bmp b/V06/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V06/ul_adeck.bmp differ diff --git a/V06/ul_down.wav b/V06/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V06/ul_down.wav differ diff --git a/V06/ul_dreh.WAV b/V06/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V06/ul_dreh.WAV differ diff --git a/V06/ul_ende.WAV b/V06/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V06/ul_ende.WAV differ diff --git a/V06/ul_feld.bmp b/V06/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V06/ul_feld.bmp differ diff --git a/V06/ul_hgrnd.bmp b/V06/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V06/ul_hgrnd.bmp differ diff --git a/V06/ul_move.WAV b/V06/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V06/ul_move.WAV differ diff --git a/V06/ul_prev.bmp b/V06/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V06/ul_prev.bmp differ diff --git a/V06/ul_row1.WAV b/V06/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V06/ul_row1.WAV differ diff --git a/V06/ul_row2.WAV b/V06/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V06/ul_row2.WAV differ diff --git a/V06/ul_start.WAV b/V06/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V06/ul_start.WAV differ diff --git a/V06/ul_stein.bmp b/V06/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V06/ul_stein.bmp differ diff --git a/V06/ul_win.wav b/V06/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V06/ul_win.wav differ diff --git a/V06/ul_z0.bmp b/V06/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V06/ul_z0.bmp differ diff --git a/V06/ul_z1.bmp b/V06/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V06/ul_z1.bmp differ diff --git a/V06/ul_z2.bmp b/V06/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V06/ul_z2.bmp differ diff --git a/V06/ul_z3.bmp b/V06/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V06/ul_z3.bmp differ diff --git a/V06/ul_z4.bmp b/V06/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V06/ul_z4.bmp differ diff --git a/V06/ul_z5.bmp b/V06/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V06/ul_z5.bmp differ diff --git a/V06/ul_z6.bmp b/V06/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V06/ul_z6.bmp differ diff --git a/V06/ul_z7.bmp b/V06/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V06/ul_z7.bmp differ diff --git a/V06/ul_z8.bmp b/V06/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V06/ul_z8.bmp differ diff --git a/V06/ul_z9.bmp b/V06/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V06/ul_z9.bmp differ diff --git a/V07/Demo.aps b/V07/Demo.aps new file mode 100644 index 0000000..4cd726b Binary files /dev/null and b/V07/Demo.aps differ diff --git a/V07/Demo.cpp b/V07/Demo.cpp new file mode 100644 index 0000000..ba884fb --- /dev/null +++ b/V07/Demo.cpp @@ -0,0 +1,1031 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + MessageBox( ultris_window, "Surfaces restauriert", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + + +// Array mit den aktuell im Spiel aktivierten Steinformen +// Zu Programmstart sind dies die ueblichen Tetris Spielsteine (0-6) +char aktive_formen[anzahl_formen] = + { + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 + }; + +// Anzahl der aktuell aktivierten Steinformen +int anz_aktive_formen = 7; + + +// V7 Beginn +class ultris + { + private: + int vorbelegung; // Anzahl der bei Spielbeginn vorzubelegenden Zeilen + int vorschau; // Anzahl der Formen in der Vorschau + int spielfeld[20][10]; // Das Spielfeld + int fuellstand[20]; // Der Fuellstand einer Reihe (= Anzahl Segmente in der Reihe) + int punktestand; // Der aktuelle Punktestand + void initialisieren(); + void vorbelegen(); + void display_spielfeld(); + void display_punktestand(); + public: + int spiel_laeuft; // Indikator, dass das Spiel laeuft + ultris(){ srand( GetTickCount()); initialisieren(); vorbelegung = 0; vorschau = 1;} + int get_vorbelegung() { return vorbelegung;} + void set_vorbelegung( int v) {if( v < 0) v = 0; if( v > 20) v = 20; vorbelegung = v;} + int get_vorschau() { return vorschau;} + void set_vorschau( int v) {if( v < 0) v = 0; if(v > 5) v = 5; vorschau = v;} + void start(); + void display(); + }; + +void ultris::initialisieren() + { + int z, s; + + for( z = 0; z < 20; z++) + { + fuellstand[z] = 0; + for( s = 0; s < 10; s++) + spielfeld[z][s] = 0; + } + spiel_laeuft = 0; + punktestand = 0; + } + +void ultris::vorbelegen() + { + int z, s, i; + + for( i = 0; i < vorbelegung*5; i++) + { + z = 19-rand()%vorbelegung; + s = rand()%10; + if( !spielfeld[z][s]) + { + spielfeld[z][s] = 1; + fuellstand[z]++; + } + } + punktestand = vorbelegung * 2500; + } + +void ultris::start() + { + ultris_sounds.play( sound_start); + initialisieren(); + vorbelegen(); + spiel_laeuft = 1; + } + +void ultris::display_spielfeld() + { + int z, s; + + for( z = 0; z < 20; z++) + { + for( s = 0; s < 10; s++) + { + if( spielfeld[z][s]) + ultris_display.feldstein( z, s); + } + } + } + +void ultris::display_punktestand() + { + int i, z, p; + + for( i = 5, p = punktestand; i >= 0; i--, p/= 10) + { + z = p % 10; + ultris_display.ziffer( i, z); + } + } + +void ultris::display() + { + ultris_display.hintergrund(); + display_spielfeld(); + ultris_display.abdeckung(); + display_punktestand(); + ultris_display.present(); + } + + +// V7 Ende + +ultris mein_spiel; + + +BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if( wParam == IDC_WEITERE_INFO) + { + ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); + return TRUE; + } + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK konfigurationsdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int i; + + switch (uMsg) + { + case WM_INITDIALOG: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, aktive_formen[i] ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, mein_spiel.get_vorbelegung(), FALSE); + SetDlgItemInt( hwndDlg, IDC_VORSCHAU, mein_spiel.get_vorschau(), FALSE); + return TRUE; + case WM_COMMAND: + if(wParam == IDOK) + { + for( i = 0, anz_aktive_formen = 0; i < anzahl_formen; i++) + { + aktive_formen[i] = 0; + if(IsDlgButtonChecked( hwndDlg, 5000+i) == BST_CHECKED) + { + aktive_formen[i] = 1; + anz_aktive_formen++; + } + } + if( anz_aktive_formen == 0) + { + aktive_formen[0] = 1; + anz_aktive_formen = 1; + } + mein_spiel.set_vorbelegung( GetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, NULL, FALSE)); + mein_spiel.set_vorschau( GetDlgItemInt( hwndDlg, IDC_VORSCHAU, NULL, FALSE)); + EndDialog(hwndDlg, wParam); + return TRUE; + } + if(wParam == IDCANCEL) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + if (HIWORD(wParam) == BN_CLICKED) + { + switch( LOWORD(wParam)) + { + case IDC_LOESCHEN: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_UNCHECKED); + return TRUE; + case IDC_ALLE: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_CHECKED); + return TRUE; + case IDC_STANDARD: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, i < 7 ? BST_CHECKED:BST_UNCHECKED); + return TRUE; + } + } + } + return FALSE; + } + +/* +** ultris_windowhandler +*/ + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case ID_INFO_HILFE: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); + return 0; + case ID_INFO_ULTRIS: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); + return 0; + case ID_EINSTELLUNGEN_KONFIGURATION: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_KONFIGURATION), ultris_window, konfigurationsdialog); + return 0; +// V7 Beginn + case ID_ULTRIS_NEUESSPIEL: + mein_spiel.start(); + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, MF_UNCHECKED); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; +// V7 Ende + case IDM_TEST: // Testcode + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; + case WM_PAINT: +// V7 Beginn + mein_spiel.display(); +// V7 Ende + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + // Hier koennen wir uns um das Spiel kuemmern + } + } + } + } + + + diff --git a/V07/Demo.h b/V07/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V07/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V07/Demo.ncb b/V07/Demo.ncb new file mode 100644 index 0000000..84ecc29 Binary files /dev/null and b/V07/Demo.ncb differ diff --git a/V07/Demo.rc b/V07/Demo.rc new file mode 100644 index 0000000..0425332 --- /dev/null +++ b/V07/Demo.rc @@ -0,0 +1,687 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END + POPUP "Einstellungen" + BEGIN + MENUITEM "Konfiguration", ID_EINSTELLUNGEN_KONFIGURATION + + END + POPUP "Info" + BEGIN + MENUITEM "Hilfe", ID_INFO_HILFE + MENUITEM "Highscores", ID_INFO_HIGHSCORES + MENUITEM "Ultris", ID_INFO_ULTRIS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F1, ID_ULTRIS_NEUESSPIEL, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_HILFE DIALOG DISCARDABLE 0, 0, 302, 107 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Hilfe" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,245,90,50,14 + LTEXT "F1: Neues Spiel",IDC_STATIC,15,22,130,8 + LTEXT "F2: Pause (ein/aus)",IDC_STATIC,15,34,130,8 + LTEXT "F3: Schneller",IDC_STATIC,15,46,130,8 + LTEXT "F4: Langsamer",IDC_STATIC,15,58,130,8 + LTEXT "F5: Sound (ein/aus)",IDC_STATIC,15,70,130,8 + GROUPBOX "Steuerung des Spiels",IDC_STATIC,7,7,142,78 + GROUPBOX "Steuerung der Steine",IDC_STATIC,153,7,142,78 + LTEXT "J oder Cursor left: Links",IDC_STATIC,159,22,131,8 + LTEXT "L oder Cursor right: Rechts",IDC_STATIC,159,34,131,8 + LTEXT "K oder Cursor down: Linksdrehung",IDC_STATIC,159,46,131, + 8 + LTEXT "I oder Cursor up: Rechtsdrehung",IDC_STATIC,159,58,131, + 8 + LTEXT "Space: Stein fallen lassen",IDC_STATIC,159,70,126,8 +END + +IDD_ULTRIS DIALOG DISCARDABLE 0, 0, 204, 142 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Über Ultris" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,125,50,14 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_BORDER,7,7,190,78 + CTEXT "Demoprogramm\rzur Vorlesung\rGrafik und Spieleprogrammierung", + IDC_STATIC,7,92,195,28 + PUSHBUTTON "Weitere Informationen",IDC_WEITERE_INFO,5,125,140,14 +END + +IDD_KONFIGURATION DIALOGEX 0, 0, 289, 297 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Einstellungen" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,235,280,50,14 + PUSHBUTTON "Abbrechen",IDCANCEL,180,280,50,14 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,50,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,70,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,30,10,10 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,40,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,10,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,105,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,25,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,55,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,65,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,210,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,15,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,160,10,10 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 43,8,8 + CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 43,8,8 + CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 43,8,8 + CONTROL "10",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 154,43,8,8 + CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 43,8,8 + CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 43,8,8 + CONTROL "6",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 43,8,8 + CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 93,8,8 + CONTROL "",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 93,8,8 + CONTROL "",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 93,8,8 + CONTROL "",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 93,8,8 + CONTROL "",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 93,8,8 + CONTROL "",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 93,8,8 + CONTROL "20",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 274,93,8,8 + CONTROL "",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 143,8,8 + CONTROL "",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 143,8,8 + CONTROL "",IDC_CHECK17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 143,8,8 + CONTROL "",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 143,8,8 + CONTROL "",IDC_CHECK19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 143,8,8 + CONTROL "",IDC_CHECK20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 143,8,8 + CONTROL "",IDC_CHECK21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 143,8,8 + CONTROL "",IDC_CHECK22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 193,8,8 + CONTROL "",IDC_CHECK23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 193,8,8 + CONTROL "",IDC_CHECK24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 193,8,8 + CONTROL "",IDC_CHECK25,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 193,8,8 + CONTROL "",IDC_CHECK26,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 193,8,8 + CONTROL "",IDC_CHECK27,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 193,8,8 + CONTROL "",IDC_CHECK28,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 193,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,210,10,10 + CONTROL "",IDC_CHECK29,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 243,8,8 + CONTROL "",IDC_CHECK30,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 243,8,8 + CONTROL "",IDC_CHECK31,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 243,8,8 + CONTROL "",IDC_CHECK32,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 243,8,8 + CONTROL "",IDC_CHECK33,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 243,8,8 + CONTROL "",IDC_CHECK34,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 243,8,8 + CONTROL "",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 243,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,205,40,50, + WS_EX_DLGMODALFRAME + PUSHBUTTON "Alle auswählen",IDC_ALLE,235,260,50,14 + PUSHBUTTON "Standard",IDC_STANDARD,180,260,50,14 + PUSHBUTTON "Alle Löschen",IDC_LOESCHEN,125,260,50,14 + EDITTEXT IDC_VORBELEGUNG,105,260,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Vorbelegte Zeilen bei Spielstart:",IDC_STATIC,5,260,95, + 13,SS_CENTERIMAGE + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,210,10,10 + LTEXT "1",IDC_STATIC,11,143,8,8 + LTEXT "2",IDC_STATIC,10,193,8,8 + LTEXT "4",IDC_STATIC,50,193,8,8 + LTEXT "6",IDC_STATIC,250,43,8,8 + LTEXT "8",IDC_STATIC,10,43,8,8 + LTEXT "10",IDC_STATIC,130,43,8,8 + LTEXT "10",IDC_STATIC,170,43,8,8 + LTEXT "12",IDC_STATIC,50,43,8,8 + LTEXT "12",IDC_STATIC,90,43,8,8 + LTEXT "10",IDC_STATIC,210,43,8,8 + LTEXT "25",IDC_STATIC,10,93,8,8 + LTEXT "25",IDC_STATIC,50,93,8,8 + LTEXT "4",IDC_STATIC,90,93,8,8 + LTEXT "20",IDC_STATIC,130,93,8,8 + LTEXT "10",IDC_STATIC,170,93,8,8 + LTEXT "10",IDC_STATIC,210,93,8,8 + LTEXT "20",IDC_STATIC,250,93,8,8 + LTEXT "8",IDC_STATIC,50,143,8,8 + LTEXT "25",IDC_STATIC,90,143,8,8 + LTEXT "40",IDC_STATIC,130,143,8,8 + LTEXT "15",IDC_STATIC,170,143,8,8 + LTEXT "25",IDC_STATIC,210,143,8,8 + LTEXT "35",IDC_STATIC,250,143,8,8 + LTEXT "10",IDC_STATIC,90,193,8,8 + LTEXT "10",IDC_STATIC,130,193,8,8 + LTEXT "20",IDC_STATIC,170,193,8,8 + LTEXT "20",IDC_STATIC,210,193,8,8 + LTEXT "25",IDC_STATIC,250,193,8,8 + LTEXT "25",IDC_STATIC,10,243,8,8 + LTEXT "30",IDC_STATIC,50,243,8,8 + LTEXT "25",IDC_STATIC,90,243,8,8 + LTEXT "25",IDC_STATIC,130,243,8,8 + LTEXT "10",IDC_STATIC,170,243,8,8 + LTEXT "15",IDC_STATIC,210,243,8,8 + LTEXT "25",IDC_STATIC,250,243,8,8 + EDITTEXT IDC_VORSCHAU,105,280,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Steine in der Vorschau:",IDC_STATIC,5,280,95,13, + SS_CENTERIMAGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_HILFE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_ULTRIS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 197 + TOPMARGIN, 7 + BOTTOMMARGIN, 135 + END + + IDD_KONFIGURATION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 282 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ULTRIS BITMAP DISCARDABLE "bmp00001.bmp" +IDB_STEIN BITMAP DISCARDABLE "bmp00002.bmp" +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V07/Demo.sln b/V07/Demo.sln new file mode 100644 index 0000000..7980bdf --- /dev/null +++ b/V07/Demo.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{48CC8A7D-E3EA-4AAD-9E36-3DB12B1919C0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {48CC8A7D-E3EA-4AAD-9E36-3DB12B1919C0}.Debug.ActiveCfg = Debug|Win32 + {48CC8A7D-E3EA-4AAD-9E36-3DB12B1919C0}.Debug.Build.0 = Debug|Win32 + {48CC8A7D-E3EA-4AAD-9E36-3DB12B1919C0}.Release.ActiveCfg = Release|Win32 + {48CC8A7D-E3EA-4AAD-9E36-3DB12B1919C0}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V07/Demo.suo b/V07/Demo.suo new file mode 100644 index 0000000..70048d4 Binary files /dev/null and b/V07/Demo.suo differ diff --git a/V07/Demo.vcproj b/V07/Demo.vcproj new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V07/Demo.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V07/Icon.ico b/V07/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V07/Icon.ico differ diff --git a/V07/bmp00001.bmp b/V07/bmp00001.bmp new file mode 100644 index 0000000..12d2027 Binary files /dev/null and b/V07/bmp00001.bmp differ diff --git a/V07/bmp00002.bmp b/V07/bmp00002.bmp new file mode 100644 index 0000000..92b8396 Binary files /dev/null and b/V07/bmp00002.bmp differ diff --git a/V07/ddutil.cpp b/V07/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V07/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V07/ddutil.h b/V07/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V07/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V07/dsutil.cpp b/V07/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V07/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V07/dsutil.h b/V07/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V07/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V07/resource.h b/V07/resource.h new file mode 100644 index 0000000..ca05021 --- /dev/null +++ b/V07/resource.h @@ -0,0 +1,74 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDD_HILFE 124 +#define IDD_KONFIGURATION 125 +#define IDB_STEIN 126 +#define IDD_ULTRIS 129 +#define IDB_ULTRIS 130 +#define IDM_EXIT 1001 +#define IDC_ALLE 1005 +#define IDC_STANDARD 1006 +#define IDC_LOESCHEN 1007 +#define IDC_VORBELEGUNG 1008 +#define IDC_VORSCHAU 1009 +#define IDC_WEITERE_INFO 1018 +#define IDC_CHECK1 5000 +#define IDC_CHECK2 5001 +#define IDC_CHECK3 5002 +#define IDC_CHECK4 5003 +#define IDC_CHECK5 5004 +#define IDC_CHECK6 5005 +#define IDC_CHECK7 5006 +#define IDC_CHECK8 5007 +#define IDC_CHECK9 5008 +#define IDC_CHECK10 5009 +#define IDC_CHECK11 5010 +#define IDC_CHECK12 5011 +#define IDC_CHECK13 5012 +#define IDC_CHECK14 5013 +#define IDC_CHECK15 5014 +#define IDC_CHECK16 5015 +#define IDC_CHECK17 5016 +#define IDC_CHECK18 5017 +#define IDC_CHECK19 5018 +#define IDC_CHECK20 5019 +#define IDC_CHECK21 5020 +#define IDC_CHECK22 5021 +#define IDC_CHECK23 5022 +#define IDC_CHECK24 5023 +#define IDC_CHECK25 5024 +#define IDC_CHECK26 5025 +#define IDC_CHECK27 5026 +#define IDC_CHECK28 5027 +#define IDC_CHECK29 5028 +#define IDC_CHECK30 5029 +#define IDC_CHECK31 5030 +#define IDC_CHECK32 5031 +#define IDC_CHECK33 5032 +#define IDC_CHECK34 5033 +#define IDC_CHECK35 5034 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define ID_EINSTELLUNGEN_KONFIGURATION 40028 +#define ID_INFO_HILFE 40029 +#define ID_INFO_HIGHSCORES 40030 +#define ID_INFO_ULTRIS 40031 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40033 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V07/ul_adeck.bmp b/V07/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V07/ul_adeck.bmp differ diff --git a/V07/ul_down.wav b/V07/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V07/ul_down.wav differ diff --git a/V07/ul_dreh.WAV b/V07/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V07/ul_dreh.WAV differ diff --git a/V07/ul_ende.WAV b/V07/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V07/ul_ende.WAV differ diff --git a/V07/ul_feld.bmp b/V07/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V07/ul_feld.bmp differ diff --git a/V07/ul_hgrnd.bmp b/V07/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V07/ul_hgrnd.bmp differ diff --git a/V07/ul_move.WAV b/V07/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V07/ul_move.WAV differ diff --git a/V07/ul_prev.bmp b/V07/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V07/ul_prev.bmp differ diff --git a/V07/ul_row1.WAV b/V07/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V07/ul_row1.WAV differ diff --git a/V07/ul_row2.WAV b/V07/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V07/ul_row2.WAV differ diff --git a/V07/ul_start.WAV b/V07/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V07/ul_start.WAV differ diff --git a/V07/ul_stein.bmp b/V07/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V07/ul_stein.bmp differ diff --git a/V07/ul_win.wav b/V07/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V07/ul_win.wav differ diff --git a/V07/ul_z0.bmp b/V07/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V07/ul_z0.bmp differ diff --git a/V07/ul_z1.bmp b/V07/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V07/ul_z1.bmp differ diff --git a/V07/ul_z2.bmp b/V07/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V07/ul_z2.bmp differ diff --git a/V07/ul_z3.bmp b/V07/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V07/ul_z3.bmp differ diff --git a/V07/ul_z4.bmp b/V07/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V07/ul_z4.bmp differ diff --git a/V07/ul_z5.bmp b/V07/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V07/ul_z5.bmp differ diff --git a/V07/ul_z6.bmp b/V07/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V07/ul_z6.bmp differ diff --git a/V07/ul_z7.bmp b/V07/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V07/ul_z7.bmp differ diff --git a/V07/ul_z8.bmp b/V07/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V07/ul_z8.bmp differ diff --git a/V07/ul_z9.bmp b/V07/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V07/ul_z9.bmp differ diff --git a/V08/Demo.aps b/V08/Demo.aps new file mode 100644 index 0000000..86b0759 Binary files /dev/null and b/V08/Demo.aps differ diff --git a/V08/Demo.cpp b/V08/Demo.cpp new file mode 100644 index 0000000..3f91ccc --- /dev/null +++ b/V08/Demo.cpp @@ -0,0 +1,1137 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + MessageBox( ultris_window, "Surfaces restauriert", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + + +// Array mit den aktuell im Spiel aktivierten Steinformen +// Zu Programmstart sind dies die ueblichen Tetris Spielsteine (0-6) +char aktive_formen[anzahl_formen] = + { + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 + }; + +// Anzahl der aktuell aktivierten Steinformen +int anz_aktive_formen = 7; + +// V8 Beginn +// Punktwerte aller Steinformen +const int formwert[anzahl_formen] = + { + 8,12,12,10,10,10, 6, + 25,25, 4,20,10,10,20, + 1, 8,25,40,15,25,35, + 2, 4,10,10,20,20,25, + 25,30,25,25,10,15,25 + }; + +class ultris + { + struct formwahl + { + int ix; // Index der Form + int dv; // Drehvariante der Form + }; + private: + int vorbelegung; // Anzahl der bei Spielbeginn vorzubelegenden Zeilen + int vorschau; // Anzahl der Formen in der Vorschau + int spielfeld[20][10]; // Das Spielfeld + int fuellstand[20]; // Der Fuellstand einer Reihe (= Anzahl Segmente in der Reihe) + int punktestand; // Der aktuelle Punktestand + formwahl formen[6]; // 0 aktuelle Form, 1-5 Vorschau + int zeile; + int spalte; + int offset; + int sichtbar; + int zeige_dyn; // Zeige den dynamischen Anteil + void initialisieren(); + void vorbelegen(); + void display_spielfeld(); + void display_punktestand(); + void display_vorschau(); + void display_form(); + void naechste_form(); + const form *aktuelle_form() {return ultris_form[formen[0].ix][formen[0].dv];} + public: + int spiel_laeuft; // Indikator, dass das Spiel laeuft + ultris(){ srand( GetTickCount()); initialisieren(); vorbelegung = 0; vorschau = 1;} + int get_vorbelegung() { return vorbelegung;} + void set_vorbelegung( int v) {if( v < 0) v = 0; if( v > 20) v = 20; vorbelegung = v;} + int get_vorschau() { return vorschau;} + void set_vorschau( int v) {if( v < 0) v = 0; if(v > 5) v = 5; vorschau = v;} + void start(); + void display(); + void neue_form(); + }; + +void ultris::initialisieren() + { + int z, s; + + for( z = 0; z < 20; z++) + { + fuellstand[z] = 0; + for( s = 0; s < 10; s++) + spielfeld[z][s] = 0; + } + spiel_laeuft = 0; + zeige_dyn = 0; + punktestand = 0; + } +// V8 Ende + +void ultris::vorbelegen() + { + int z, s, i; + + for( i = 0; i < vorbelegung*5; i++) + { + z = 19-rand()%vorbelegung; + s = rand()%10; + if( !spielfeld[z][s]) + { + spielfeld[z][s] = 1; + fuellstand[z]++; + } + } + punktestand = vorbelegung * 2500; + } + +// V8 Beginn +void ultris::start() + { + ultris_sounds.play( sound_start); + initialisieren(); + vorbelegen(); + spiel_laeuft = 1; + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + neue_form(); + zeige_dyn = 1; + } +// V8 Ende + +void ultris::display_spielfeld() + { + int z, s; + + for( z = 0; z < 20; z++) + { + for( s = 0; s < 10; s++) + { + if( spielfeld[z][s]) + ultris_display.feldstein( z, s); + } + } + } + +void ultris::display_punktestand() + { + int i, z, p; + + for( i = 5, p = punktestand; i >= 0; i--, p/= 10) + { + z = p % 10; + ultris_display.ziffer( i, z); + } + } + +// V8 Beginn +void ultris::display() + { + ultris_display.hintergrund(); + display_spielfeld(); + if( zeige_dyn) + { + display_vorschau(); + display_form(); + } +// ultris_display.abdeckung(); +// display_punktestand(); + ultris_display.present(); + } + +void ultris::naechste_form() + { + int z, i, ix; + + for( i = 0; i < 5; i++) + formen[i] = formen[i+1]; + + z = rand()%anz_aktive_formen+1; + for( ix = -1; z; z--) + { + while( !aktive_formen[++ix]) + ; + } + formen[5].ix = ix; + formen[5].dv = rand()%4; + } + +void ultris::neue_form() + { + naechste_form(); + zeile = -aktuelle_form()->h; + spalte = 5-(aktuelle_form()->b)/2; + offset = 0; + sichtbar = 0; + punktestand += formwert[formen[0].ix]; + } + +void ultris::display_vorschau() + { + int z, s, p, y; + const form *f; + + if( !sichtbar) + sichtbar = (zeile >= 0); + + for( y = 0, p = sichtbar; y < vorschau; p++, y++) + { + f = ultris_form[formen[p].ix][formen[p].dv]; + for( z = 0; z < f->h; z++) + { + for( s = 0; s < f->b; s++) + { + if( f->data[z][s]) + ultris_display.prevstein(y, z, s, f->b, f->h); + } + } + } + } + +void ultris::display_form() + { + int z, s; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + ultris_display.fallstein( zeile+z, spalte+s, offset); + } + } + } + } + +// V8 Ende + +ultris mein_spiel; + + +BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if( wParam == IDC_WEITERE_INFO) + { + ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); + return TRUE; + } + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK konfigurationsdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int i; + + switch (uMsg) + { + case WM_INITDIALOG: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, aktive_formen[i] ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, mein_spiel.get_vorbelegung(), FALSE); + SetDlgItemInt( hwndDlg, IDC_VORSCHAU, mein_spiel.get_vorschau(), FALSE); + return TRUE; + case WM_COMMAND: + if(wParam == IDOK) + { + for( i = 0, anz_aktive_formen = 0; i < anzahl_formen; i++) + { + aktive_formen[i] = 0; + if(IsDlgButtonChecked( hwndDlg, 5000+i) == BST_CHECKED) + { + aktive_formen[i] = 1; + anz_aktive_formen++; + } + } + if( anz_aktive_formen == 0) + { + aktive_formen[0] = 1; + anz_aktive_formen = 1; + } + mein_spiel.set_vorbelegung( GetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, NULL, FALSE)); + mein_spiel.set_vorschau( GetDlgItemInt( hwndDlg, IDC_VORSCHAU, NULL, FALSE)); + EndDialog(hwndDlg, wParam); + return TRUE; + } + if(wParam == IDCANCEL) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + if (HIWORD(wParam) == BN_CLICKED) + { + switch( LOWORD(wParam)) + { + case IDC_LOESCHEN: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_UNCHECKED); + return TRUE; + case IDC_ALLE: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_CHECKED); + return TRUE; + case IDC_STANDARD: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, i < 7 ? BST_CHECKED:BST_UNCHECKED); + return TRUE; + } + } + } + return FALSE; + } + +/* +** ultris_windowhandler +*/ + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case ID_INFO_HILFE: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); + return 0; + case ID_INFO_ULTRIS: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); + return 0; + case ID_EINSTELLUNGEN_KONFIGURATION: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_KONFIGURATION), ultris_window, konfigurationsdialog); + return 0; + case ID_ULTRIS_NEUESSPIEL: + mein_spiel.start(); + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, MF_UNCHECKED); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + case IDM_TEST: // Testcode +// V8 Beginn + mein_spiel.neue_form(); + PostMessage( ultris_window, WM_PAINT, 0, 0); + return 0; +// V8 Ende + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; + case WM_PAINT: + mein_spiel.display(); + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + // Hier koennen wir uns um das Spiel kuemmern + } + } + } + } + + + diff --git a/V08/Demo.h b/V08/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V08/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V08/Demo.ncb b/V08/Demo.ncb new file mode 100644 index 0000000..00907f3 Binary files /dev/null and b/V08/Demo.ncb differ diff --git a/V08/Demo.plg b/V08/Demo.plg new file mode 100644 index 0000000..85bcc9b --- /dev/null +++ b/V08/Demo.plg @@ -0,0 +1,36 @@ + + +
+

Erstellungsprotokoll

+

+--------------------Konfiguration: Demo - Win32 Debug-------------------- +

+

Befehlszeilen

+Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSP34.tmp" mit Inhalten +[ +/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V08\Demo.cpp" +] +Creating command line "cl.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSP34.tmp" +Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSP35.tmp" mit Inhalten +[ +winmm.lib dxguid.lib dxerr8.lib ddraw.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib dsound.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/Ultris.pdb" /debug /machine:I386 /out:"Debug/Ultris.exe" /pdbtype:sept +.\Debug\Demo.obj +.\Debug\ddutil.obj +.\Debug\dsutil.obj +.\Debug\dxutil.obj +.\Debug\Demo.res +] +Erstellen der Befehlzeile "link.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSP35.tmp" +

Ausgabefenster

+Kompilierung läuft... +Demo.cpp +Linker-Vorgang läuft... + + + +

Ergebnisse

+Ultris.exe - 0 Fehler, 0 Warnung(en) +
+ + diff --git a/V08/Demo.rc b/V08/Demo.rc new file mode 100644 index 0000000..0425332 --- /dev/null +++ b/V08/Demo.rc @@ -0,0 +1,687 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END + POPUP "Einstellungen" + BEGIN + MENUITEM "Konfiguration", ID_EINSTELLUNGEN_KONFIGURATION + + END + POPUP "Info" + BEGIN + MENUITEM "Hilfe", ID_INFO_HILFE + MENUITEM "Highscores", ID_INFO_HIGHSCORES + MENUITEM "Ultris", ID_INFO_ULTRIS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F1, ID_ULTRIS_NEUESSPIEL, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_HILFE DIALOG DISCARDABLE 0, 0, 302, 107 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Hilfe" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,245,90,50,14 + LTEXT "F1: Neues Spiel",IDC_STATIC,15,22,130,8 + LTEXT "F2: Pause (ein/aus)",IDC_STATIC,15,34,130,8 + LTEXT "F3: Schneller",IDC_STATIC,15,46,130,8 + LTEXT "F4: Langsamer",IDC_STATIC,15,58,130,8 + LTEXT "F5: Sound (ein/aus)",IDC_STATIC,15,70,130,8 + GROUPBOX "Steuerung des Spiels",IDC_STATIC,7,7,142,78 + GROUPBOX "Steuerung der Steine",IDC_STATIC,153,7,142,78 + LTEXT "J oder Cursor left: Links",IDC_STATIC,159,22,131,8 + LTEXT "L oder Cursor right: Rechts",IDC_STATIC,159,34,131,8 + LTEXT "K oder Cursor down: Linksdrehung",IDC_STATIC,159,46,131, + 8 + LTEXT "I oder Cursor up: Rechtsdrehung",IDC_STATIC,159,58,131, + 8 + LTEXT "Space: Stein fallen lassen",IDC_STATIC,159,70,126,8 +END + +IDD_ULTRIS DIALOG DISCARDABLE 0, 0, 204, 142 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Über Ultris" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,125,50,14 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_BORDER,7,7,190,78 + CTEXT "Demoprogramm\rzur Vorlesung\rGrafik und Spieleprogrammierung", + IDC_STATIC,7,92,195,28 + PUSHBUTTON "Weitere Informationen",IDC_WEITERE_INFO,5,125,140,14 +END + +IDD_KONFIGURATION DIALOGEX 0, 0, 289, 297 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Einstellungen" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,235,280,50,14 + PUSHBUTTON "Abbrechen",IDCANCEL,180,280,50,14 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,50,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,70,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,30,10,10 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,40,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,10,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,105,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,25,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,55,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,65,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,210,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,15,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,160,10,10 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 43,8,8 + CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 43,8,8 + CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 43,8,8 + CONTROL "10",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 154,43,8,8 + CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 43,8,8 + CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 43,8,8 + CONTROL "6",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 43,8,8 + CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 93,8,8 + CONTROL "",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 93,8,8 + CONTROL "",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 93,8,8 + CONTROL "",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 93,8,8 + CONTROL "",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 93,8,8 + CONTROL "",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 93,8,8 + CONTROL "20",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 274,93,8,8 + CONTROL "",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 143,8,8 + CONTROL "",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 143,8,8 + CONTROL "",IDC_CHECK17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 143,8,8 + CONTROL "",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 143,8,8 + CONTROL "",IDC_CHECK19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 143,8,8 + CONTROL "",IDC_CHECK20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 143,8,8 + CONTROL "",IDC_CHECK21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 143,8,8 + CONTROL "",IDC_CHECK22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 193,8,8 + CONTROL "",IDC_CHECK23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 193,8,8 + CONTROL "",IDC_CHECK24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 193,8,8 + CONTROL "",IDC_CHECK25,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 193,8,8 + CONTROL "",IDC_CHECK26,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 193,8,8 + CONTROL "",IDC_CHECK27,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 193,8,8 + CONTROL "",IDC_CHECK28,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 193,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,210,10,10 + CONTROL "",IDC_CHECK29,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 243,8,8 + CONTROL "",IDC_CHECK30,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 243,8,8 + CONTROL "",IDC_CHECK31,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 243,8,8 + CONTROL "",IDC_CHECK32,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 243,8,8 + CONTROL "",IDC_CHECK33,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 243,8,8 + CONTROL "",IDC_CHECK34,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 243,8,8 + CONTROL "",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 243,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,205,40,50, + WS_EX_DLGMODALFRAME + PUSHBUTTON "Alle auswählen",IDC_ALLE,235,260,50,14 + PUSHBUTTON "Standard",IDC_STANDARD,180,260,50,14 + PUSHBUTTON "Alle Löschen",IDC_LOESCHEN,125,260,50,14 + EDITTEXT IDC_VORBELEGUNG,105,260,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Vorbelegte Zeilen bei Spielstart:",IDC_STATIC,5,260,95, + 13,SS_CENTERIMAGE + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,210,10,10 + LTEXT "1",IDC_STATIC,11,143,8,8 + LTEXT "2",IDC_STATIC,10,193,8,8 + LTEXT "4",IDC_STATIC,50,193,8,8 + LTEXT "6",IDC_STATIC,250,43,8,8 + LTEXT "8",IDC_STATIC,10,43,8,8 + LTEXT "10",IDC_STATIC,130,43,8,8 + LTEXT "10",IDC_STATIC,170,43,8,8 + LTEXT "12",IDC_STATIC,50,43,8,8 + LTEXT "12",IDC_STATIC,90,43,8,8 + LTEXT "10",IDC_STATIC,210,43,8,8 + LTEXT "25",IDC_STATIC,10,93,8,8 + LTEXT "25",IDC_STATIC,50,93,8,8 + LTEXT "4",IDC_STATIC,90,93,8,8 + LTEXT "20",IDC_STATIC,130,93,8,8 + LTEXT "10",IDC_STATIC,170,93,8,8 + LTEXT "10",IDC_STATIC,210,93,8,8 + LTEXT "20",IDC_STATIC,250,93,8,8 + LTEXT "8",IDC_STATIC,50,143,8,8 + LTEXT "25",IDC_STATIC,90,143,8,8 + LTEXT "40",IDC_STATIC,130,143,8,8 + LTEXT "15",IDC_STATIC,170,143,8,8 + LTEXT "25",IDC_STATIC,210,143,8,8 + LTEXT "35",IDC_STATIC,250,143,8,8 + LTEXT "10",IDC_STATIC,90,193,8,8 + LTEXT "10",IDC_STATIC,130,193,8,8 + LTEXT "20",IDC_STATIC,170,193,8,8 + LTEXT "20",IDC_STATIC,210,193,8,8 + LTEXT "25",IDC_STATIC,250,193,8,8 + LTEXT "25",IDC_STATIC,10,243,8,8 + LTEXT "30",IDC_STATIC,50,243,8,8 + LTEXT "25",IDC_STATIC,90,243,8,8 + LTEXT "25",IDC_STATIC,130,243,8,8 + LTEXT "10",IDC_STATIC,170,243,8,8 + LTEXT "15",IDC_STATIC,210,243,8,8 + LTEXT "25",IDC_STATIC,250,243,8,8 + EDITTEXT IDC_VORSCHAU,105,280,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Steine in der Vorschau:",IDC_STATIC,5,280,95,13, + SS_CENTERIMAGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_HILFE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_ULTRIS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 197 + TOPMARGIN, 7 + BOTTOMMARGIN, 135 + END + + IDD_KONFIGURATION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 282 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ULTRIS BITMAP DISCARDABLE "bmp00001.bmp" +IDB_STEIN BITMAP DISCARDABLE "bmp00002.bmp" +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V08/Demo.sln b/V08/Demo.sln new file mode 100644 index 0000000..c137588 --- /dev/null +++ b/V08/Demo.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{E46624DC-B8A8-4BE8-8415-45D7319D1F9F}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {E46624DC-B8A8-4BE8-8415-45D7319D1F9F}.Debug.ActiveCfg = Debug|Win32 + {E46624DC-B8A8-4BE8-8415-45D7319D1F9F}.Debug.Build.0 = Debug|Win32 + {E46624DC-B8A8-4BE8-8415-45D7319D1F9F}.Release.ActiveCfg = Release|Win32 + {E46624DC-B8A8-4BE8-8415-45D7319D1F9F}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V08/Demo.suo b/V08/Demo.suo new file mode 100644 index 0000000..eed695f Binary files /dev/null and b/V08/Demo.suo differ diff --git a/V08/Demo.vcproj b/V08/Demo.vcproj new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V08/Demo.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V08/Icon.ico b/V08/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V08/Icon.ico differ diff --git a/V08/bmp00001.bmp b/V08/bmp00001.bmp new file mode 100644 index 0000000..12d2027 Binary files /dev/null and b/V08/bmp00001.bmp differ diff --git a/V08/bmp00002.bmp b/V08/bmp00002.bmp new file mode 100644 index 0000000..92b8396 Binary files /dev/null and b/V08/bmp00002.bmp differ diff --git a/V08/ddutil.cpp b/V08/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V08/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V08/ddutil.h b/V08/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V08/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V08/dsutil.cpp b/V08/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V08/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V08/dsutil.h b/V08/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V08/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V08/resource.h b/V08/resource.h new file mode 100644 index 0000000..ca05021 --- /dev/null +++ b/V08/resource.h @@ -0,0 +1,74 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDD_HILFE 124 +#define IDD_KONFIGURATION 125 +#define IDB_STEIN 126 +#define IDD_ULTRIS 129 +#define IDB_ULTRIS 130 +#define IDM_EXIT 1001 +#define IDC_ALLE 1005 +#define IDC_STANDARD 1006 +#define IDC_LOESCHEN 1007 +#define IDC_VORBELEGUNG 1008 +#define IDC_VORSCHAU 1009 +#define IDC_WEITERE_INFO 1018 +#define IDC_CHECK1 5000 +#define IDC_CHECK2 5001 +#define IDC_CHECK3 5002 +#define IDC_CHECK4 5003 +#define IDC_CHECK5 5004 +#define IDC_CHECK6 5005 +#define IDC_CHECK7 5006 +#define IDC_CHECK8 5007 +#define IDC_CHECK9 5008 +#define IDC_CHECK10 5009 +#define IDC_CHECK11 5010 +#define IDC_CHECK12 5011 +#define IDC_CHECK13 5012 +#define IDC_CHECK14 5013 +#define IDC_CHECK15 5014 +#define IDC_CHECK16 5015 +#define IDC_CHECK17 5016 +#define IDC_CHECK18 5017 +#define IDC_CHECK19 5018 +#define IDC_CHECK20 5019 +#define IDC_CHECK21 5020 +#define IDC_CHECK22 5021 +#define IDC_CHECK23 5022 +#define IDC_CHECK24 5023 +#define IDC_CHECK25 5024 +#define IDC_CHECK26 5025 +#define IDC_CHECK27 5026 +#define IDC_CHECK28 5027 +#define IDC_CHECK29 5028 +#define IDC_CHECK30 5029 +#define IDC_CHECK31 5030 +#define IDC_CHECK32 5031 +#define IDC_CHECK33 5032 +#define IDC_CHECK34 5033 +#define IDC_CHECK35 5034 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define ID_EINSTELLUNGEN_KONFIGURATION 40028 +#define ID_INFO_HILFE 40029 +#define ID_INFO_HIGHSCORES 40030 +#define ID_INFO_ULTRIS 40031 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40033 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V08/ul_adeck.bmp b/V08/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V08/ul_adeck.bmp differ diff --git a/V08/ul_down.wav b/V08/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V08/ul_down.wav differ diff --git a/V08/ul_dreh.WAV b/V08/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V08/ul_dreh.WAV differ diff --git a/V08/ul_ende.WAV b/V08/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V08/ul_ende.WAV differ diff --git a/V08/ul_feld.bmp b/V08/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V08/ul_feld.bmp differ diff --git a/V08/ul_hgrnd.bmp b/V08/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V08/ul_hgrnd.bmp differ diff --git a/V08/ul_move.WAV b/V08/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V08/ul_move.WAV differ diff --git a/V08/ul_prev.bmp b/V08/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V08/ul_prev.bmp differ diff --git a/V08/ul_row1.WAV b/V08/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V08/ul_row1.WAV differ diff --git a/V08/ul_row2.WAV b/V08/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V08/ul_row2.WAV differ diff --git a/V08/ul_start.WAV b/V08/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V08/ul_start.WAV differ diff --git a/V08/ul_stein.bmp b/V08/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V08/ul_stein.bmp differ diff --git a/V08/ul_win.wav b/V08/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V08/ul_win.wav differ diff --git a/V08/ul_z0.bmp b/V08/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V08/ul_z0.bmp differ diff --git a/V08/ul_z1.bmp b/V08/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V08/ul_z1.bmp differ diff --git a/V08/ul_z2.bmp b/V08/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V08/ul_z2.bmp differ diff --git a/V08/ul_z3.bmp b/V08/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V08/ul_z3.bmp differ diff --git a/V08/ul_z4.bmp b/V08/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V08/ul_z4.bmp differ diff --git a/V08/ul_z5.bmp b/V08/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V08/ul_z5.bmp differ diff --git a/V08/ul_z6.bmp b/V08/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V08/ul_z6.bmp differ diff --git a/V08/ul_z7.bmp b/V08/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V08/ul_z7.bmp differ diff --git a/V08/ul_z8.bmp b/V08/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V08/ul_z8.bmp differ diff --git a/V08/ul_z9.bmp b/V08/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V08/ul_z9.bmp differ diff --git a/V09/Demo.aps b/V09/Demo.aps new file mode 100644 index 0000000..6a3638d Binary files /dev/null and b/V09/Demo.aps differ diff --git a/V09/Demo.cpp b/V09/Demo.cpp new file mode 100644 index 0000000..94b3f35 --- /dev/null +++ b/V09/Demo.cpp @@ -0,0 +1,1250 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + MessageBox( ultris_window, "Surfaces restauriert", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + + +// Array mit den aktuell im Spiel aktivierten Steinformen +// Zu Programmstart sind dies die ueblichen Tetris Spielsteine (0-6) +char aktive_formen[anzahl_formen] = + { + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 + }; + +// Anzahl der aktuell aktivierten Steinformen +int anz_aktive_formen = 7; + +// Punktwerte aller Steinformen +const int formwert[anzahl_formen] = + { + 8,12,12,10,10,10, 6, + 25,25, 4,20,10,10,20, + 1, 8,25,40,15,25,35, + 2, 4,10,10,20,20,25, + 25,30,25,25,10,15,25 + }; + +class ultris + { + struct formwahl + { + int ix; // Index der Form + int dv; // Drehvariante der Form + }; + private: + int vorbelegung; // Anzahl der bei Spielbeginn vorzubelegenden Zeilen + int vorschau; // Anzahl der Formen in der Vorschau + int spielfeld[20][10]; // Das Spielfeld + int fuellstand[20]; // Der Fuellstand einer Reihe (= Anzahl Segmente in der Reihe) + int punktestand; // Der aktuelle Punktestand + formwahl formen[6]; // 0 aktuelle Form, 1-5 Vorschau + int zeile; // Zeile der aktuellen Form + int spalte; // Spalte der aktuellen Form + int offset; // Offset zur Zeile + int sichtbar; // Form war bereits sichtbar + int zeige_dyn; // Zeige den dynamischen Anteil + DWORD time; // Zeitreferenz + int speed; // Geschwindigkeit + void initialisieren(); + void vorbelegen(); + void display_spielfeld(); + void display_punktestand(); + void display_vorschau(); + void display_form(); + void naechste_form(); + void neue_form(); + const form *aktuelle_form() {return ultris_form[formen[0].ix][formen[0].dv];} + int onestep(); // Stein um ein Pixel nach unten bewegen + int blockiert(); + public: + int spiel_laeuft; // Indikator, dass das Spiel laeuft + ultris(){ srand( GetTickCount()); initialisieren(); vorbelegung = 0; vorschau = 1;} + int get_vorbelegung() { return vorbelegung;} + void set_vorbelegung( int v) {if( v < 0) v = 0; if( v > 20) v = 20; vorbelegung = v;} + int get_vorschau() { return vorschau;} + void set_vorschau( int v) {if( v < 0) v = 0; if(v > 5) v = 5; vorschau = v;} + void start(); + void display(); + int step(); + void down(); + void reset_timer(){time = timeGetTime();} + void schneller() { speed += 50;} + void langsamer() { if( speed > 50) speed -= 50;} + }; + +void ultris::initialisieren() + { + int z, s; + + for( z = 0; z < 20; z++) + { + fuellstand[z] = 0; + for( s = 0; s < 10; s++) + spielfeld[z][s] = 0; + } + spiel_laeuft = 0; + zeige_dyn = 0; + punktestand = 0; + } + +void ultris::vorbelegen() + { + int z, s, i; + + for( i = 0; i < vorbelegung*5; i++) + { + z = 19-rand()%vorbelegung; + s = rand()%10; + if( !spielfeld[z][s]) + { + spielfeld[z][s] = 1; + fuellstand[z]++; + } + } + punktestand = vorbelegung * 2500; + } + +void ultris::start() + { + ultris_sounds.play( sound_start); + initialisieren(); + vorbelegen(); + spiel_laeuft = 1; + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + neue_form(); + zeige_dyn = 1; + reset_timer(); + speed = 100; + } + +void ultris::display_spielfeld() + { + int z, s; + + for( z = 0; z < 20; z++) + { + for( s = 0; s < 10; s++) + { + if( spielfeld[z][s]) + ultris_display.feldstein( z, s); + } + } + } + +void ultris::display_punktestand() + { + int i, z, p; + + for( i = 5, p = punktestand; i >= 0; i--, p/= 10) + { + z = p % 10; + ultris_display.ziffer( i, z); + } + } + +void ultris::display() + { + ultris_display.hintergrund(); + display_spielfeld(); + if( zeige_dyn) + { + display_vorschau(); + display_form(); + } + ultris_display.abdeckung(); + display_punktestand(); + ultris_display.present(); + } + +void ultris::naechste_form() + { + int z, i, ix; + + for( i = 0; i < 5; i++) + formen[i] = formen[i+1]; + + z = rand()%anz_aktive_formen+1; + for( ix = -1; z; z--) + { + while( !aktive_formen[++ix]) + ; + } + formen[5].ix = ix; + formen[5].dv = rand()%4; + } + +void ultris::neue_form() + { + naechste_form(); + zeile = -aktuelle_form()->h; + spalte = 5-(aktuelle_form()->b)/2; + offset = 0; + sichtbar = 0; + punktestand += formwert[formen[0].ix]; + } + +void ultris::display_vorschau() + { + int z, s, p, y; + const form *f; + + if( !sichtbar) + sichtbar = (zeile >= 0); + + for( y = 0, p = sichtbar; y < vorschau; p++, y++) + { + f = ultris_form[formen[p].ix][formen[p].dv]; + for( z = 0; z < f->h; z++) + { + for( s = 0; s < f->b; s++) + { + if( f->data[z][s]) + ultris_display.prevstein(y, z, s, f->b, f->h); + } + } + } + } + +void ultris::display_form() + { + int z, s; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + ultris_display.fallstein( zeile+z, spalte+s, offset); + } + } + } + } + +// V9 Beginn + +void ultris::down() + { + while( onestep()) + ; + } + +int ultris::step() + { + DWORD now; + int pixel; + int diff; + + now = timeGetTime(); + diff = (now-time)*speed; + pixel = diff/5000; + if( !pixel) + return 0; + time = now - diff%5000/speed; + for( ; pixel && onestep(); pixel--) + ; + return 1; + } + +int ultris::blockiert() + { + int z, s, zz; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + zz = zeile + z + 1; + if( (zz >= 20) || ((zz >= 0) &&(spielfeld[zz][spalte+s]))) + return 1; + } + } + } + return 0; + } + +int ultris::onestep() + { + if( offset) + { + if( offset < 19) + offset++; + else + { + offset = 0; + zeile++; + } + return 1; + } + else + { + if( blockiert()) + { + ultris_sounds.play( sound_down); // vorlaeufig + neue_form(); // vorlaeufig + return 0; + } + offset++; + return 1; + } + } +// V9 Ende + +ultris mein_spiel; + + +BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if( wParam == IDC_WEITERE_INFO) + { + ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); + return TRUE; + } + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK konfigurationsdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int i; + + switch (uMsg) + { + case WM_INITDIALOG: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, aktive_formen[i] ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, mein_spiel.get_vorbelegung(), FALSE); + SetDlgItemInt( hwndDlg, IDC_VORSCHAU, mein_spiel.get_vorschau(), FALSE); + return TRUE; + case WM_COMMAND: + if(wParam == IDOK) + { + for( i = 0, anz_aktive_formen = 0; i < anzahl_formen; i++) + { + aktive_formen[i] = 0; + if(IsDlgButtonChecked( hwndDlg, 5000+i) == BST_CHECKED) + { + aktive_formen[i] = 1; + anz_aktive_formen++; + } + } + if( anz_aktive_formen == 0) + { + aktive_formen[0] = 1; + anz_aktive_formen = 1; + } + mein_spiel.set_vorbelegung( GetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, NULL, FALSE)); + mein_spiel.set_vorschau( GetDlgItemInt( hwndDlg, IDC_VORSCHAU, NULL, FALSE)); + EndDialog(hwndDlg, wParam); + return TRUE; + } + if(wParam == IDCANCEL) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + if (HIWORD(wParam) == BN_CLICKED) + { + switch( LOWORD(wParam)) + { + case IDC_LOESCHEN: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_UNCHECKED); + return TRUE; + case IDC_ALLE: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_CHECKED); + return TRUE; + case IDC_STANDARD: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, i < 7 ? BST_CHECKED:BST_UNCHECKED); + return TRUE; + } + } + } + return FALSE; + } + +/* +** ultris_windowhandler +*/ + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case ID_INFO_HILFE: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); +// V9 Beginn + mein_spiel.reset_timer(); +// V9 Ende + return 0; + case ID_INFO_ULTRIS: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); +// V9 Beginn + mein_spiel.reset_timer(); +// V9 Ende + return 0; + case ID_EINSTELLUNGEN_KONFIGURATION: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_KONFIGURATION), ultris_window, konfigurationsdialog); +// V9 Beginn + mein_spiel.reset_timer(); +// V9 Ende + return 0; + case ID_ULTRIS_NEUESSPIEL: + mein_spiel.start(); + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, MF_UNCHECKED); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; +// V9 Beginn + case ID_ULTRIS_PAUSE: + mein_spiel.spiel_laeuft = !mein_spiel.spiel_laeuft; + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, mein_spiel.spiel_laeuft ? MF_UNCHECKED:MF_CHECKED); + return 0; + case IDM_DOWN: + if( mein_spiel.spiel_laeuft) + mein_spiel.down(); + return 0; + case IDM_SCHNELLER: + mein_spiel.schneller(); + return 0; + case IDM_LANGSAMER: + mein_spiel.langsamer(); + return 0; +// V9 Ende + case IDM_TEST: // Testcode + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; +// V9 Beginn + case WM_EXITMENULOOP: + case WM_EXITSIZEMOVE: + mein_spiel.reset_timer(); + break; +// V9 Ende + case WM_PAINT: + mein_spiel.display(); + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { +// V9 Beginn + if( mein_spiel.spiel_laeuft) + { + if( mein_spiel.step()) + mein_spiel.display(); + } + else + { + WaitMessage(); + mein_spiel.reset_timer(); // Spieluhr laeuft nicht + } +// V9 Ende + } + } + } + } + + + diff --git a/V09/Demo.h b/V09/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V09/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V09/Demo.ncb b/V09/Demo.ncb new file mode 100644 index 0000000..b3c8625 Binary files /dev/null and b/V09/Demo.ncb differ diff --git a/V09/Demo.plg b/V09/Demo.plg new file mode 100644 index 0000000..eb32736 --- /dev/null +++ b/V09/Demo.plg @@ -0,0 +1,36 @@ + + +
+

Erstellungsprotokoll

+

+--------------------Konfiguration: Demo - Win32 Debug-------------------- +

+

Befehlszeilen

+Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSP44.tmp" mit Inhalten +[ +/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V09\Demo.cpp" +] +Creating command line "cl.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSP44.tmp" +Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSP45.tmp" mit Inhalten +[ +winmm.lib dxguid.lib dxerr8.lib ddraw.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib dsound.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/Ultris.pdb" /debug /machine:I386 /out:"Debug/Ultris.exe" /pdbtype:sept +.\Debug\Demo.obj +.\Debug\ddutil.obj +.\Debug\dsutil.obj +.\Debug\dxutil.obj +.\Debug\Demo.res +] +Erstellen der Befehlzeile "link.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSP45.tmp" +

Ausgabefenster

+Kompilierung läuft... +Demo.cpp +Linker-Vorgang läuft... + + + +

Ergebnisse

+Ultris.exe - 0 Fehler, 0 Warnung(en) +
+ + diff --git a/V09/Demo.rc b/V09/Demo.rc new file mode 100644 index 0000000..4c30ab3 --- /dev/null +++ b/V09/Demo.rc @@ -0,0 +1,691 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END + POPUP "Einstellungen" + BEGIN + MENUITEM "Konfiguration", ID_EINSTELLUNGEN_KONFIGURATION + + END + POPUP "Info" + BEGIN + MENUITEM "Hilfe", ID_INFO_HILFE + MENUITEM "Highscores", ID_INFO_HIGHSCORES + MENUITEM "Ultris", ID_INFO_ULTRIS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F1, ID_ULTRIS_NEUESSPIEL, VIRTKEY, NOINVERT + VK_F2, ID_ULTRIS_PAUSE, VIRTKEY, NOINVERT + VK_F3, IDM_SCHNELLER, VIRTKEY, NOINVERT + VK_F4, IDM_LANGSAMER, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT + VK_SPACE, IDM_DOWN, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_HILFE DIALOG DISCARDABLE 0, 0, 302, 107 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Hilfe" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,245,90,50,14 + LTEXT "F1: Neues Spiel",IDC_STATIC,15,22,130,8 + LTEXT "F2: Pause (ein/aus)",IDC_STATIC,15,34,130,8 + LTEXT "F3: Schneller",IDC_STATIC,15,46,130,8 + LTEXT "F4: Langsamer",IDC_STATIC,15,58,130,8 + LTEXT "F5: Sound (ein/aus)",IDC_STATIC,15,70,130,8 + GROUPBOX "Steuerung des Spiels",IDC_STATIC,7,7,142,78 + GROUPBOX "Steuerung der Steine",IDC_STATIC,153,7,142,78 + LTEXT "J oder Cursor left: Links",IDC_STATIC,159,22,131,8 + LTEXT "L oder Cursor right: Rechts",IDC_STATIC,159,34,131,8 + LTEXT "K oder Cursor down: Linksdrehung",IDC_STATIC,159,46,131, + 8 + LTEXT "I oder Cursor up: Rechtsdrehung",IDC_STATIC,159,58,131, + 8 + LTEXT "Space: Stein fallen lassen",IDC_STATIC,159,70,126,8 +END + +IDD_ULTRIS DIALOG DISCARDABLE 0, 0, 204, 142 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Über Ultris" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,125,50,14 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_BORDER,7,7,190,78 + CTEXT "Demoprogramm\rzur Vorlesung\rGrafik und Spieleprogrammierung", + IDC_STATIC,7,92,195,28 + PUSHBUTTON "Weitere Informationen",IDC_WEITERE_INFO,5,125,140,14 +END + +IDD_KONFIGURATION DIALOGEX 0, 0, 289, 297 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Einstellungen" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,235,280,50,14 + PUSHBUTTON "Abbrechen",IDCANCEL,180,280,50,14 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,50,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,70,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,30,10,10 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,40,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,10,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,105,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,25,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,55,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,65,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,210,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,15,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,160,10,10 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 43,8,8 + CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 43,8,8 + CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 43,8,8 + CONTROL "10",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 154,43,8,8 + CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 43,8,8 + CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 43,8,8 + CONTROL "6",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 43,8,8 + CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 93,8,8 + CONTROL "",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 93,8,8 + CONTROL "",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 93,8,8 + CONTROL "",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 93,8,8 + CONTROL "",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 93,8,8 + CONTROL "",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 93,8,8 + CONTROL "20",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 274,93,8,8 + CONTROL "",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 143,8,8 + CONTROL "",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 143,8,8 + CONTROL "",IDC_CHECK17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 143,8,8 + CONTROL "",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 143,8,8 + CONTROL "",IDC_CHECK19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 143,8,8 + CONTROL "",IDC_CHECK20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 143,8,8 + CONTROL "",IDC_CHECK21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 143,8,8 + CONTROL "",IDC_CHECK22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 193,8,8 + CONTROL "",IDC_CHECK23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 193,8,8 + CONTROL "",IDC_CHECK24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 193,8,8 + CONTROL "",IDC_CHECK25,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 193,8,8 + CONTROL "",IDC_CHECK26,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 193,8,8 + CONTROL "",IDC_CHECK27,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 193,8,8 + CONTROL "",IDC_CHECK28,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 193,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,210,10,10 + CONTROL "",IDC_CHECK29,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 243,8,8 + CONTROL "",IDC_CHECK30,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 243,8,8 + CONTROL "",IDC_CHECK31,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 243,8,8 + CONTROL "",IDC_CHECK32,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 243,8,8 + CONTROL "",IDC_CHECK33,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 243,8,8 + CONTROL "",IDC_CHECK34,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 243,8,8 + CONTROL "",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 243,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,205,40,50, + WS_EX_DLGMODALFRAME + PUSHBUTTON "Alle auswählen",IDC_ALLE,235,260,50,14 + PUSHBUTTON "Standard",IDC_STANDARD,180,260,50,14 + PUSHBUTTON "Alle Löschen",IDC_LOESCHEN,125,260,50,14 + EDITTEXT IDC_VORBELEGUNG,105,260,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Vorbelegte Zeilen bei Spielstart:",IDC_STATIC,5,260,95, + 13,SS_CENTERIMAGE + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,210,10,10 + LTEXT "1",IDC_STATIC,11,143,8,8 + LTEXT "2",IDC_STATIC,10,193,8,8 + LTEXT "4",IDC_STATIC,50,193,8,8 + LTEXT "6",IDC_STATIC,250,43,8,8 + LTEXT "8",IDC_STATIC,10,43,8,8 + LTEXT "10",IDC_STATIC,130,43,8,8 + LTEXT "10",IDC_STATIC,170,43,8,8 + LTEXT "12",IDC_STATIC,50,43,8,8 + LTEXT "12",IDC_STATIC,90,43,8,8 + LTEXT "10",IDC_STATIC,210,43,8,8 + LTEXT "25",IDC_STATIC,10,93,8,8 + LTEXT "25",IDC_STATIC,50,93,8,8 + LTEXT "4",IDC_STATIC,90,93,8,8 + LTEXT "20",IDC_STATIC,130,93,8,8 + LTEXT "10",IDC_STATIC,170,93,8,8 + LTEXT "10",IDC_STATIC,210,93,8,8 + LTEXT "20",IDC_STATIC,250,93,8,8 + LTEXT "8",IDC_STATIC,50,143,8,8 + LTEXT "25",IDC_STATIC,90,143,8,8 + LTEXT "40",IDC_STATIC,130,143,8,8 + LTEXT "15",IDC_STATIC,170,143,8,8 + LTEXT "25",IDC_STATIC,210,143,8,8 + LTEXT "35",IDC_STATIC,250,143,8,8 + LTEXT "10",IDC_STATIC,90,193,8,8 + LTEXT "10",IDC_STATIC,130,193,8,8 + LTEXT "20",IDC_STATIC,170,193,8,8 + LTEXT "20",IDC_STATIC,210,193,8,8 + LTEXT "25",IDC_STATIC,250,193,8,8 + LTEXT "25",IDC_STATIC,10,243,8,8 + LTEXT "30",IDC_STATIC,50,243,8,8 + LTEXT "25",IDC_STATIC,90,243,8,8 + LTEXT "25",IDC_STATIC,130,243,8,8 + LTEXT "10",IDC_STATIC,170,243,8,8 + LTEXT "15",IDC_STATIC,210,243,8,8 + LTEXT "25",IDC_STATIC,250,243,8,8 + EDITTEXT IDC_VORSCHAU,105,280,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Steine in der Vorschau:",IDC_STATIC,5,280,95,13, + SS_CENTERIMAGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_HILFE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_ULTRIS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 197 + TOPMARGIN, 7 + BOTTOMMARGIN, 135 + END + + IDD_KONFIGURATION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 282 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ULTRIS BITMAP DISCARDABLE "bmp00001.bmp" +IDB_STEIN BITMAP DISCARDABLE "bmp00002.bmp" +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V09/Demo.sln b/V09/Demo.sln new file mode 100644 index 0000000..4316410 --- /dev/null +++ b/V09/Demo.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{FB57EEA2-8652-46DA-869F-72206813C120}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {FB57EEA2-8652-46DA-869F-72206813C120}.Debug.ActiveCfg = Debug|Win32 + {FB57EEA2-8652-46DA-869F-72206813C120}.Debug.Build.0 = Debug|Win32 + {FB57EEA2-8652-46DA-869F-72206813C120}.Release.ActiveCfg = Release|Win32 + {FB57EEA2-8652-46DA-869F-72206813C120}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V09/Demo.suo b/V09/Demo.suo new file mode 100644 index 0000000..d8b0671 Binary files /dev/null and b/V09/Demo.suo differ diff --git a/V09/Demo.vcproj b/V09/Demo.vcproj new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V09/Demo.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V09/Icon.ico b/V09/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V09/Icon.ico differ diff --git a/V09/bmp00001.bmp b/V09/bmp00001.bmp new file mode 100644 index 0000000..12d2027 Binary files /dev/null and b/V09/bmp00001.bmp differ diff --git a/V09/bmp00002.bmp b/V09/bmp00002.bmp new file mode 100644 index 0000000..92b8396 Binary files /dev/null and b/V09/bmp00002.bmp differ diff --git a/V09/ddutil.cpp b/V09/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V09/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V09/ddutil.h b/V09/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V09/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V09/dsutil.cpp b/V09/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V09/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V09/dsutil.h b/V09/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V09/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V09/resource.h b/V09/resource.h new file mode 100644 index 0000000..4d847da --- /dev/null +++ b/V09/resource.h @@ -0,0 +1,77 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDD_HILFE 124 +#define IDD_KONFIGURATION 125 +#define IDB_STEIN 126 +#define IDD_ULTRIS 129 +#define IDB_ULTRIS 130 +#define IDM_EXIT 1001 +#define IDC_ALLE 1005 +#define IDC_STANDARD 1006 +#define IDC_LOESCHEN 1007 +#define IDC_VORBELEGUNG 1008 +#define IDC_VORSCHAU 1009 +#define IDC_WEITERE_INFO 1018 +#define IDC_CHECK1 5000 +#define IDC_CHECK2 5001 +#define IDC_CHECK3 5002 +#define IDC_CHECK4 5003 +#define IDC_CHECK5 5004 +#define IDC_CHECK6 5005 +#define IDC_CHECK7 5006 +#define IDC_CHECK8 5007 +#define IDC_CHECK9 5008 +#define IDC_CHECK10 5009 +#define IDC_CHECK11 5010 +#define IDC_CHECK12 5011 +#define IDC_CHECK13 5012 +#define IDC_CHECK14 5013 +#define IDC_CHECK15 5014 +#define IDC_CHECK16 5015 +#define IDC_CHECK17 5016 +#define IDC_CHECK18 5017 +#define IDC_CHECK19 5018 +#define IDC_CHECK20 5019 +#define IDC_CHECK21 5020 +#define IDC_CHECK22 5021 +#define IDC_CHECK23 5022 +#define IDC_CHECK24 5023 +#define IDC_CHECK25 5024 +#define IDC_CHECK26 5025 +#define IDC_CHECK27 5026 +#define IDC_CHECK28 5027 +#define IDC_CHECK29 5028 +#define IDC_CHECK30 5029 +#define IDC_CHECK31 5030 +#define IDC_CHECK32 5031 +#define IDC_CHECK33 5032 +#define IDC_CHECK34 5033 +#define IDC_CHECK35 5034 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define ID_EINSTELLUNGEN_KONFIGURATION 40028 +#define ID_INFO_HILFE 40029 +#define ID_INFO_HIGHSCORES 40030 +#define ID_INFO_ULTRIS 40031 +#define IDM_DOWN 40033 +#define IDM_SCHNELLER 40034 +#define IDM_LANGSAMER 40035 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40036 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V09/ul_adeck.bmp b/V09/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V09/ul_adeck.bmp differ diff --git a/V09/ul_down.wav b/V09/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V09/ul_down.wav differ diff --git a/V09/ul_dreh.WAV b/V09/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V09/ul_dreh.WAV differ diff --git a/V09/ul_ende.WAV b/V09/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V09/ul_ende.WAV differ diff --git a/V09/ul_feld.bmp b/V09/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V09/ul_feld.bmp differ diff --git a/V09/ul_hgrnd.bmp b/V09/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V09/ul_hgrnd.bmp differ diff --git a/V09/ul_move.WAV b/V09/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V09/ul_move.WAV differ diff --git a/V09/ul_prev.bmp b/V09/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V09/ul_prev.bmp differ diff --git a/V09/ul_row1.WAV b/V09/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V09/ul_row1.WAV differ diff --git a/V09/ul_row2.WAV b/V09/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V09/ul_row2.WAV differ diff --git a/V09/ul_start.WAV b/V09/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V09/ul_start.WAV differ diff --git a/V09/ul_stein.bmp b/V09/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V09/ul_stein.bmp differ diff --git a/V09/ul_win.wav b/V09/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V09/ul_win.wav differ diff --git a/V09/ul_z0.bmp b/V09/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V09/ul_z0.bmp differ diff --git a/V09/ul_z1.bmp b/V09/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V09/ul_z1.bmp differ diff --git a/V09/ul_z2.bmp b/V09/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V09/ul_z2.bmp differ diff --git a/V09/ul_z3.bmp b/V09/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V09/ul_z3.bmp differ diff --git a/V09/ul_z4.bmp b/V09/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V09/ul_z4.bmp differ diff --git a/V09/ul_z5.bmp b/V09/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V09/ul_z5.bmp differ diff --git a/V09/ul_z6.bmp b/V09/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V09/ul_z6.bmp differ diff --git a/V09/ul_z7.bmp b/V09/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V09/ul_z7.bmp differ diff --git a/V09/ul_z8.bmp b/V09/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V09/ul_z8.bmp differ diff --git a/V09/ul_z9.bmp b/V09/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V09/ul_z9.bmp differ diff --git a/V10/Demo.aps b/V10/Demo.aps new file mode 100644 index 0000000..a986124 Binary files /dev/null and b/V10/Demo.aps differ diff --git a/V10/Demo.cpp b/V10/Demo.cpp new file mode 100644 index 0000000..c8b39d6 --- /dev/null +++ b/V10/Demo.cpp @@ -0,0 +1,1334 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + MessageBox( ultris_window, "Surfaces restauriert", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + + +// Array mit den aktuell im Spiel aktivierten Steinformen +// Zu Programmstart sind dies die ueblichen Tetris Spielsteine (0-6) +char aktive_formen[anzahl_formen] = + { + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 + }; + +// Anzahl der aktuell aktivierten Steinformen +int anz_aktive_formen = 7; + +// Punktwerte aller Steinformen +const int formwert[anzahl_formen] = + { + 8,12,12,10,10,10, 6, + 25,25, 4,20,10,10,20, + 1, 8,25,40,15,25,35, + 2, 4,10,10,20,20,25, + 25,30,25,25,10,15,25 + }; + +class ultris + { + struct formwahl + { + int ix; // Index der Form + int dv; // Drehvariante der Form + }; + private: + int vorbelegung; // Anzahl der bei Spielbeginn vorzubelegenden Zeilen + int vorschau; // Anzahl der Formen in der Vorschau + int spielfeld[20][10]; // Das Spielfeld + int fuellstand[20]; // Der Fuellstand einer Reihe (= Anzahl Segmente in der Reihe) + int punktestand; // Der aktuelle Punktestand + formwahl formen[6]; // 0 aktuelle Form, 1-5 Vorschau + int zeile; // Zeile der aktuellen Form + int spalte; // Spalte der aktuellen Form + int offset; // Offset zur Zeile + int sichtbar; // Form war bereits sichtbar + int zeige_dyn; // Zeige den dynamischen Anteil + DWORD time; // Zeitreferenz + int speed; // Geschwindigkeit + void initialisieren(); + void vorbelegen(); + void display_spielfeld(); + void display_punktestand(); + void display_vorschau(); + void display_form(); + void naechste_form(); + void neue_form(); + const form *aktuelle_form() {return ultris_form[formen[0].ix][formen[0].dv];} + int onestep(); // Stein um ein Pixel nach unten bewegen + int blockiert(); + public: + int spiel_laeuft; // Indikator, dass das Spiel laeuft + ultris(){ srand( GetTickCount()); initialisieren(); vorbelegung = 0; vorschau = 1;} + int get_vorbelegung() { return vorbelegung;} + void set_vorbelegung( int v) {if( v < 0) v = 0; if( v > 20) v = 20; vorbelegung = v;} + int get_vorschau() { return vorschau;} + void set_vorschau( int v) {if( v < 0) v = 0; if(v > 5) v = 5; vorschau = v;} + void start(); + void display(); + int step(); + void down(); + void reset_timer(){time = timeGetTime();} + void schneller() { speed += 50;} + void langsamer() { if( speed > 50) speed -= 50;} + void bewegen( int dir); // -1 eins nach links +1 eins nach rechts + void drehen(int dir); // -1 eins nach links +1 eins nach rechts + }; + +void ultris::initialisieren() + { + int z, s; + + for( z = 0; z < 20; z++) + { + fuellstand[z] = 0; + for( s = 0; s < 10; s++) + spielfeld[z][s] = 0; + } + spiel_laeuft = 0; + zeige_dyn = 0; + punktestand = 0; + } + +void ultris::vorbelegen() + { + int z, s, i; + + for( i = 0; i < vorbelegung*5; i++) + { + z = 19-rand()%vorbelegung; + s = rand()%10; + if( !spielfeld[z][s]) + { + spielfeld[z][s] = 1; + fuellstand[z]++; + } + } + punktestand = vorbelegung * 2500; + } + +void ultris::start() + { + ultris_sounds.play( sound_start); + initialisieren(); + vorbelegen(); + spiel_laeuft = 1; + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + neue_form(); + zeige_dyn = 1; + reset_timer(); + speed = 100; + } + +void ultris::display_spielfeld() + { + int z, s; + + for( z = 0; z < 20; z++) + { + for( s = 0; s < 10; s++) + { + if( spielfeld[z][s]) + ultris_display.feldstein( z, s); + } + } + } + +void ultris::display_punktestand() + { + int i, z, p; + + for( i = 5, p = punktestand; i >= 0; i--, p/= 10) + { + z = p % 10; + ultris_display.ziffer( i, z); + } + } + +void ultris::display() + { + ultris_display.hintergrund(); + display_spielfeld(); + if( zeige_dyn) + { + display_vorschau(); + display_form(); + } + ultris_display.abdeckung(); + display_punktestand(); + ultris_display.present(); + } + +void ultris::naechste_form() + { + int z, i, ix; + + for( i = 0; i < 5; i++) + formen[i] = formen[i+1]; + + z = rand()%anz_aktive_formen+1; + for( ix = -1; z; z--) + { + while( !aktive_formen[++ix]) + ; + } + formen[5].ix = ix; + formen[5].dv = rand()%4; + } + +void ultris::neue_form() + { + naechste_form(); + zeile = -aktuelle_form()->h; + spalte = 5-(aktuelle_form()->b)/2; + offset = 0; + sichtbar = 0; + punktestand += formwert[formen[0].ix]; + } + +void ultris::display_vorschau() + { + int z, s, p, y; + const form *f; + + if( !sichtbar) + sichtbar = (zeile >= 0); + + for( y = 0, p = sichtbar; y < vorschau; p++, y++) + { + f = ultris_form[formen[p].ix][formen[p].dv]; + for( z = 0; z < f->h; z++) + { + for( s = 0; s < f->b; s++) + { + if( f->data[z][s]) + ultris_display.prevstein(y, z, s, f->b, f->h); + } + } + } + } + +void ultris::display_form() + { + int z, s; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + ultris_display.fallstein( zeile+z, spalte+s, offset); + } + } + } + } + +void ultris::down() + { + while( onestep()) + ; + } + +int ultris::step() + { + DWORD now; + int pixel; + int diff; + + now = timeGetTime(); + diff = (now-time)*speed; + pixel = diff/5000; + if( !pixel) + return 0; + time = now - diff%5000/speed; + for( ; pixel && onestep(); pixel--) + ; + return 1; + } + +int ultris::blockiert() + { + int z, s, zz; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + zz = zeile + z + 1; + if( (zz >= 20) || ((zz >= 0) &&(spielfeld[zz][spalte+s]))) + return 1; + } + } + } + return 0; + } + +int ultris::onestep() + { + if( offset) + { + if( offset < 20) + offset++; + else + { + offset = 0; + zeile++; + } + return 1; + } + else + { + if( blockiert()) + { + ultris_sounds.play( sound_down); // vorlaeufig + neue_form(); // vorlaeufig + return 0; + } + offset++; + return 1; + } + } + +// V10 Beginn + +void ultris::bewegen( int dir) // -1 eins nach links +1 eins nach rechts + { + int z, s, neue_spalte; + const form *f; + + f = aktuelle_form(); + neue_spalte = spalte + dir; + if( neue_spalte < 0) + return; + if( neue_spalte + f->b > 10) + return; + for( z = 0; z < f->h; z++) + { + if( zeile+z < 0) + continue; + for( s = 0; s < f->b; s++) + { + if( f->data[z][s]) + { + if( (offset < 16) && spielfeld[zeile+z][neue_spalte+s]) + return; + if( (offset > 0) && spielfeld[zeile+z+1][neue_spalte+s]) + return; + } + } + } + spalte = neue_spalte; + ultris_sounds.play( sound_move); + } + + + +void ultris::drehen(int dir) + { + int sv, sp, zl; + int b1, b2, h1, h2, db, dh; + int maxb, maxh, minz, mins; + int i, j; + + sv = (formen[0].dv + 4 - dir)%4; + + b1 = aktuelle_form()->b; + b2 = ultris_form[formen[0].ix][sv]->b; + h1 = aktuelle_form()->h; + h2 = ultris_form[formen[0].ix][sv]->h; + + db = (b1-b2)/2; + dh = (h1-h2)/2; + sp = spalte+db; + zl = zeile+dh; + + if( sp < 0) + sp = 0; + if( sp+b2 >= 10) + sp = 10-b2; + if( zl+h2 >= 20) + return; + + mins = spalte < sp ? spalte : sp; + minz = zeile < zl ? zeile : zl; + maxb = b1 > b2 ? b1 : b2; + maxh = h1 > h2 ? h1 : h2; + if( offset) + maxh++; + + for( i = minz; i < minz+maxh; i++) + { + for( j = mins; j < mins+maxb; j++) + { + if( (i>=0)&&(i<20)&&(j>=0)&&(j<10)&&spielfeld[i][j]) + return; + } + } + formen[0].dv = sv; + spalte = sp; + zeile = zl; + ultris_sounds.play( sound_dreh); + } + +// V10 Ende + +ultris mein_spiel; + + +BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if( wParam == IDC_WEITERE_INFO) + { + ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); + return TRUE; + } + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK konfigurationsdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int i; + + switch (uMsg) + { + case WM_INITDIALOG: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, aktive_formen[i] ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, mein_spiel.get_vorbelegung(), FALSE); + SetDlgItemInt( hwndDlg, IDC_VORSCHAU, mein_spiel.get_vorschau(), FALSE); + return TRUE; + case WM_COMMAND: + if(wParam == IDOK) + { + for( i = 0, anz_aktive_formen = 0; i < anzahl_formen; i++) + { + aktive_formen[i] = 0; + if(IsDlgButtonChecked( hwndDlg, 5000+i) == BST_CHECKED) + { + aktive_formen[i] = 1; + anz_aktive_formen++; + } + } + if( anz_aktive_formen == 0) + { + aktive_formen[0] = 1; + anz_aktive_formen = 1; + } + mein_spiel.set_vorbelegung( GetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, NULL, FALSE)); + mein_spiel.set_vorschau( GetDlgItemInt( hwndDlg, IDC_VORSCHAU, NULL, FALSE)); + EndDialog(hwndDlg, wParam); + return TRUE; + } + if(wParam == IDCANCEL) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + if (HIWORD(wParam) == BN_CLICKED) + { + switch( LOWORD(wParam)) + { + case IDC_LOESCHEN: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_UNCHECKED); + return TRUE; + case IDC_ALLE: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_CHECKED); + return TRUE; + case IDC_STANDARD: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, i < 7 ? BST_CHECKED:BST_UNCHECKED); + return TRUE; + } + } + } + return FALSE; + } + +/* +** ultris_windowhandler +*/ + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case ID_INFO_HILFE: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); + mein_spiel.reset_timer(); + return 0; + case ID_INFO_ULTRIS: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); + mein_spiel.reset_timer(); + return 0; + case ID_EINSTELLUNGEN_KONFIGURATION: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_KONFIGURATION), ultris_window, konfigurationsdialog); + mein_spiel.reset_timer(); + return 0; + case ID_ULTRIS_NEUESSPIEL: + mein_spiel.start(); + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, MF_UNCHECKED); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + case ID_ULTRIS_PAUSE: + mein_spiel.spiel_laeuft = !mein_spiel.spiel_laeuft; + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, mein_spiel.spiel_laeuft ? MF_UNCHECKED:MF_CHECKED); + return 0; + case IDM_DOWN: + if( mein_spiel.spiel_laeuft) + mein_spiel.down(); + return 0; + case IDM_SCHNELLER: + mein_spiel.schneller(); + return 0; + case IDM_LANGSAMER: + mein_spiel.langsamer(); + return 0; +// V10 Beginn + case IDM_DREHRECHTS: + mein_spiel.drehen(1); + return 0; + case IDM_DREHLINKS: + mein_spiel.drehen(-1); + return 0; + case IDM_RECHTS: + mein_spiel.bewegen(1); + return 0; + case IDM_LINKS: + mein_spiel.bewegen(-1); + return 0; +// V10 Ende + case IDM_TEST: // Testcode + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; + case WM_EXITMENULOOP: + case WM_EXITSIZEMOVE: + mein_spiel.reset_timer(); + break; + case WM_PAINT: + mein_spiel.display(); + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + if( mein_spiel.spiel_laeuft) + { + if( mein_spiel.step()) + mein_spiel.display(); + } + else + { + WaitMessage(); + mein_spiel.reset_timer(); // Spieluhr laeuft nicht + } + } + } + } + } + + + diff --git a/V10/Demo.h b/V10/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V10/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V10/Demo.ncb b/V10/Demo.ncb new file mode 100644 index 0000000..f901cda Binary files /dev/null and b/V10/Demo.ncb differ diff --git a/V10/Demo.plg b/V10/Demo.plg new file mode 100644 index 0000000..1d113d4 --- /dev/null +++ b/V10/Demo.plg @@ -0,0 +1,45 @@ + + +
+

Erstellungsprotokoll

+

+--------------------Konfiguration: Demo - Win32 Debug-------------------- +

+

Befehlszeilen

+Creating command line "rc.exe /l 0x407 /fo"Debug/Demo.res" /d "_DEBUG" "C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V10\Demo.rc"" +Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSP5.tmp" mit Inhalten +[ +/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V10\Demo.cpp" +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V10\ddutil.cpp" +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V10\dsutil.cpp" +"C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V10\dxutil.cpp" +] +Creating command line "cl.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSP5.tmp" +Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSP6.tmp" mit Inhalten +[ +winmm.lib dxguid.lib dxerr8.lib ddraw.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib dsound.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/Ultris.pdb" /debug /machine:I386 /out:"Debug/Ultris.exe" /pdbtype:sept +.\Debug\Demo.obj +.\Debug\ddutil.obj +.\Debug\dsutil.obj +.\Debug\dxutil.obj +.\Debug\Demo.res +] +Erstellen der Befehlzeile "link.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSP6.tmp" +

Ausgabefenster

+Ressourcen werden kompiliert... +Kompilierung läuft... +Demo.cpp +ddutil.cpp +dsutil.cpp +dxutil.cpp +Generieren von Code... +Linker-Vorgang läuft... + + + +

Ergebnisse

+Ultris.exe - 0 Fehler, 0 Warnung(en) +
+ + diff --git a/V10/Demo.rc b/V10/Demo.rc new file mode 100644 index 0000000..69ce038 --- /dev/null +++ b/V10/Demo.rc @@ -0,0 +1,699 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END + POPUP "Einstellungen" + BEGIN + MENUITEM "Konfiguration", ID_EINSTELLUNGEN_KONFIGURATION + + END + POPUP "Info" + BEGIN + MENUITEM "Hilfe", ID_INFO_HILFE + MENUITEM "Highscores", ID_INFO_HIGHSCORES + MENUITEM "Ultris", ID_INFO_ULTRIS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "I", IDM_DREHRECHTS, VIRTKEY, NOINVERT + "J", IDM_LINKS, VIRTKEY, NOINVERT + "K", IDM_DREHLINKS, VIRTKEY, NOINVERT + "L", IDM_RECHTS, VIRTKEY, NOINVERT + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_DOWN, IDM_DREHLINKS, VIRTKEY, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F1, ID_ULTRIS_NEUESSPIEL, VIRTKEY, NOINVERT + VK_F2, ID_ULTRIS_PAUSE, VIRTKEY, NOINVERT + VK_F3, IDM_SCHNELLER, VIRTKEY, NOINVERT + VK_F4, IDM_LANGSAMER, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT + VK_LEFT, IDM_LINKS, VIRTKEY, NOINVERT + VK_RIGHT, IDM_RECHTS, VIRTKEY, NOINVERT + VK_SPACE, IDM_DOWN, VIRTKEY, NOINVERT + VK_UP, IDM_DREHRECHTS, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_HILFE DIALOG DISCARDABLE 0, 0, 302, 107 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Hilfe" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,245,90,50,14 + LTEXT "F1: Neues Spiel",IDC_STATIC,15,22,130,8 + LTEXT "F2: Pause (ein/aus)",IDC_STATIC,15,34,130,8 + LTEXT "F3: Schneller",IDC_STATIC,15,46,130,8 + LTEXT "F4: Langsamer",IDC_STATIC,15,58,130,8 + LTEXT "F5: Sound (ein/aus)",IDC_STATIC,15,70,130,8 + GROUPBOX "Steuerung des Spiels",IDC_STATIC,7,7,142,78 + GROUPBOX "Steuerung der Steine",IDC_STATIC,153,7,142,78 + LTEXT "J oder Cursor left: Links",IDC_STATIC,159,22,131,8 + LTEXT "L oder Cursor right: Rechts",IDC_STATIC,159,34,131,8 + LTEXT "K oder Cursor down: Linksdrehung",IDC_STATIC,159,46,131, + 8 + LTEXT "I oder Cursor up: Rechtsdrehung",IDC_STATIC,159,58,131, + 8 + LTEXT "Space: Stein fallen lassen",IDC_STATIC,159,70,126,8 +END + +IDD_ULTRIS DIALOG DISCARDABLE 0, 0, 204, 142 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Über Ultris" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,125,50,14 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_BORDER,7,7,190,78 + CTEXT "Demoprogramm\rzur Vorlesung\rGrafik und Spieleprogrammierung", + IDC_STATIC,7,92,195,28 + PUSHBUTTON "Weitere Informationen",IDC_WEITERE_INFO,5,125,140,14 +END + +IDD_KONFIGURATION DIALOGEX 0, 0, 289, 297 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Einstellungen" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,235,280,50,14 + PUSHBUTTON "Abbrechen",IDCANCEL,180,280,50,14 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,50,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,70,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,30,10,10 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,40,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,10,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,105,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,25,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,55,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,65,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,210,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,15,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,160,10,10 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 43,8,8 + CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 43,8,8 + CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 43,8,8 + CONTROL "10",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 154,43,8,8 + CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 43,8,8 + CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 43,8,8 + CONTROL "6",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 43,8,8 + CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 93,8,8 + CONTROL "",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 93,8,8 + CONTROL "",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 93,8,8 + CONTROL "",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 93,8,8 + CONTROL "",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 93,8,8 + CONTROL "",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 93,8,8 + CONTROL "20",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 274,93,8,8 + CONTROL "",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 143,8,8 + CONTROL "",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 143,8,8 + CONTROL "",IDC_CHECK17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 143,8,8 + CONTROL "",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 143,8,8 + CONTROL "",IDC_CHECK19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 143,8,8 + CONTROL "",IDC_CHECK20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 143,8,8 + CONTROL "",IDC_CHECK21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 143,8,8 + CONTROL "",IDC_CHECK22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 193,8,8 + CONTROL "",IDC_CHECK23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 193,8,8 + CONTROL "",IDC_CHECK24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 193,8,8 + CONTROL "",IDC_CHECK25,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 193,8,8 + CONTROL "",IDC_CHECK26,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 193,8,8 + CONTROL "",IDC_CHECK27,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 193,8,8 + CONTROL "",IDC_CHECK28,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 193,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,210,10,10 + CONTROL "",IDC_CHECK29,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 243,8,8 + CONTROL "",IDC_CHECK30,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 243,8,8 + CONTROL "",IDC_CHECK31,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 243,8,8 + CONTROL "",IDC_CHECK32,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 243,8,8 + CONTROL "",IDC_CHECK33,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 243,8,8 + CONTROL "",IDC_CHECK34,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 243,8,8 + CONTROL "",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 243,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,205,40,50, + WS_EX_DLGMODALFRAME + PUSHBUTTON "Alle auswählen",IDC_ALLE,235,260,50,14 + PUSHBUTTON "Standard",IDC_STANDARD,180,260,50,14 + PUSHBUTTON "Alle Löschen",IDC_LOESCHEN,125,260,50,14 + EDITTEXT IDC_VORBELEGUNG,105,260,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Vorbelegte Zeilen bei Spielstart:",IDC_STATIC,5,260,95, + 13,SS_CENTERIMAGE + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,210,10,10 + LTEXT "1",IDC_STATIC,11,143,8,8 + LTEXT "2",IDC_STATIC,10,193,8,8 + LTEXT "4",IDC_STATIC,50,193,8,8 + LTEXT "6",IDC_STATIC,250,43,8,8 + LTEXT "8",IDC_STATIC,10,43,8,8 + LTEXT "10",IDC_STATIC,130,43,8,8 + LTEXT "10",IDC_STATIC,170,43,8,8 + LTEXT "12",IDC_STATIC,50,43,8,8 + LTEXT "12",IDC_STATIC,90,43,8,8 + LTEXT "10",IDC_STATIC,210,43,8,8 + LTEXT "25",IDC_STATIC,10,93,8,8 + LTEXT "25",IDC_STATIC,50,93,8,8 + LTEXT "4",IDC_STATIC,90,93,8,8 + LTEXT "20",IDC_STATIC,130,93,8,8 + LTEXT "10",IDC_STATIC,170,93,8,8 + LTEXT "10",IDC_STATIC,210,93,8,8 + LTEXT "20",IDC_STATIC,250,93,8,8 + LTEXT "8",IDC_STATIC,50,143,8,8 + LTEXT "25",IDC_STATIC,90,143,8,8 + LTEXT "40",IDC_STATIC,130,143,8,8 + LTEXT "15",IDC_STATIC,170,143,8,8 + LTEXT "25",IDC_STATIC,210,143,8,8 + LTEXT "35",IDC_STATIC,250,143,8,8 + LTEXT "10",IDC_STATIC,90,193,8,8 + LTEXT "10",IDC_STATIC,130,193,8,8 + LTEXT "20",IDC_STATIC,170,193,8,8 + LTEXT "20",IDC_STATIC,210,193,8,8 + LTEXT "25",IDC_STATIC,250,193,8,8 + LTEXT "25",IDC_STATIC,10,243,8,8 + LTEXT "30",IDC_STATIC,50,243,8,8 + LTEXT "25",IDC_STATIC,90,243,8,8 + LTEXT "25",IDC_STATIC,130,243,8,8 + LTEXT "10",IDC_STATIC,170,243,8,8 + LTEXT "15",IDC_STATIC,210,243,8,8 + LTEXT "25",IDC_STATIC,250,243,8,8 + EDITTEXT IDC_VORSCHAU,105,280,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Steine in der Vorschau:",IDC_STATIC,5,280,95,13, + SS_CENTERIMAGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_HILFE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_ULTRIS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 197 + TOPMARGIN, 7 + BOTTOMMARGIN, 135 + END + + IDD_KONFIGURATION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 282 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ULTRIS BITMAP DISCARDABLE "bmp00001.bmp" +IDB_STEIN BITMAP DISCARDABLE "bmp00002.bmp" +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V10/Demo.sln b/V10/Demo.sln new file mode 100644 index 0000000..794f5fc --- /dev/null +++ b/V10/Demo.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{D93304A2-7779-4CAE-9715-87278B9B3CBD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {D93304A2-7779-4CAE-9715-87278B9B3CBD}.Debug.ActiveCfg = Debug|Win32 + {D93304A2-7779-4CAE-9715-87278B9B3CBD}.Debug.Build.0 = Debug|Win32 + {D93304A2-7779-4CAE-9715-87278B9B3CBD}.Release.ActiveCfg = Release|Win32 + {D93304A2-7779-4CAE-9715-87278B9B3CBD}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V10/Demo.suo b/V10/Demo.suo new file mode 100644 index 0000000..2bafd43 Binary files /dev/null and b/V10/Demo.suo differ diff --git a/V10/Demo.vcproj b/V10/Demo.vcproj new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V10/Demo.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V10/Icon.ico b/V10/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V10/Icon.ico differ diff --git a/V10/bmp00001.bmp b/V10/bmp00001.bmp new file mode 100644 index 0000000..12d2027 Binary files /dev/null and b/V10/bmp00001.bmp differ diff --git a/V10/bmp00002.bmp b/V10/bmp00002.bmp new file mode 100644 index 0000000..92b8396 Binary files /dev/null and b/V10/bmp00002.bmp differ diff --git a/V10/ddutil.cpp b/V10/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V10/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V10/ddutil.h b/V10/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V10/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V10/dsutil.cpp b/V10/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V10/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V10/dsutil.h b/V10/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V10/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V10/resource.h b/V10/resource.h new file mode 100644 index 0000000..995c558 --- /dev/null +++ b/V10/resource.h @@ -0,0 +1,81 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDD_HILFE 124 +#define IDD_KONFIGURATION 125 +#define IDB_STEIN 126 +#define IDD_ULTRIS 129 +#define IDB_ULTRIS 130 +#define IDM_EXIT 1001 +#define IDC_ALLE 1005 +#define IDC_STANDARD 1006 +#define IDC_LOESCHEN 1007 +#define IDC_VORBELEGUNG 1008 +#define IDC_VORSCHAU 1009 +#define IDC_WEITERE_INFO 1018 +#define IDC_CHECK1 5000 +#define IDC_CHECK2 5001 +#define IDC_CHECK3 5002 +#define IDC_CHECK4 5003 +#define IDC_CHECK5 5004 +#define IDC_CHECK6 5005 +#define IDC_CHECK7 5006 +#define IDC_CHECK8 5007 +#define IDC_CHECK9 5008 +#define IDC_CHECK10 5009 +#define IDC_CHECK11 5010 +#define IDC_CHECK12 5011 +#define IDC_CHECK13 5012 +#define IDC_CHECK14 5013 +#define IDC_CHECK15 5014 +#define IDC_CHECK16 5015 +#define IDC_CHECK17 5016 +#define IDC_CHECK18 5017 +#define IDC_CHECK19 5018 +#define IDC_CHECK20 5019 +#define IDC_CHECK21 5020 +#define IDC_CHECK22 5021 +#define IDC_CHECK23 5022 +#define IDC_CHECK24 5023 +#define IDC_CHECK25 5024 +#define IDC_CHECK26 5025 +#define IDC_CHECK27 5026 +#define IDC_CHECK28 5027 +#define IDC_CHECK29 5028 +#define IDC_CHECK30 5029 +#define IDC_CHECK31 5030 +#define IDC_CHECK32 5031 +#define IDC_CHECK33 5032 +#define IDC_CHECK34 5033 +#define IDC_CHECK35 5034 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define ID_EINSTELLUNGEN_KONFIGURATION 40028 +#define ID_INFO_HILFE 40029 +#define ID_INFO_HIGHSCORES 40030 +#define ID_INFO_ULTRIS 40031 +#define IDM_DOWN 40033 +#define IDM_SCHNELLER 40034 +#define IDM_LANGSAMER 40035 +#define IDM_DREHRECHTS 40036 +#define IDM_DREHLINKS 40037 +#define IDM_LINKS 40038 +#define IDM_RECHTS 40039 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40040 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V10/ul_adeck.bmp b/V10/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V10/ul_adeck.bmp differ diff --git a/V10/ul_down.wav b/V10/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V10/ul_down.wav differ diff --git a/V10/ul_dreh.WAV b/V10/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V10/ul_dreh.WAV differ diff --git a/V10/ul_ende.WAV b/V10/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V10/ul_ende.WAV differ diff --git a/V10/ul_feld.bmp b/V10/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V10/ul_feld.bmp differ diff --git a/V10/ul_hgrnd.bmp b/V10/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V10/ul_hgrnd.bmp differ diff --git a/V10/ul_move.WAV b/V10/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V10/ul_move.WAV differ diff --git a/V10/ul_prev.bmp b/V10/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V10/ul_prev.bmp differ diff --git a/V10/ul_row1.WAV b/V10/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V10/ul_row1.WAV differ diff --git a/V10/ul_row2.WAV b/V10/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V10/ul_row2.WAV differ diff --git a/V10/ul_start.WAV b/V10/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V10/ul_start.WAV differ diff --git a/V10/ul_stein.bmp b/V10/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V10/ul_stein.bmp differ diff --git a/V10/ul_win.wav b/V10/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V10/ul_win.wav differ diff --git a/V10/ul_z0.bmp b/V10/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V10/ul_z0.bmp differ diff --git a/V10/ul_z1.bmp b/V10/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V10/ul_z1.bmp differ diff --git a/V10/ul_z2.bmp b/V10/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V10/ul_z2.bmp differ diff --git a/V10/ul_z3.bmp b/V10/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V10/ul_z3.bmp differ diff --git a/V10/ul_z4.bmp b/V10/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V10/ul_z4.bmp differ diff --git a/V10/ul_z5.bmp b/V10/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V10/ul_z5.bmp differ diff --git a/V10/ul_z6.bmp b/V10/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V10/ul_z6.bmp differ diff --git a/V10/ul_z7.bmp b/V10/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V10/ul_z7.bmp differ diff --git a/V10/ul_z8.bmp b/V10/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V10/ul_z8.bmp differ diff --git a/V10/ul_z9.bmp b/V10/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V10/ul_z9.bmp differ diff --git a/V11/Demo.cpp b/V11/Demo.cpp new file mode 100644 index 0000000..8f9adb3 --- /dev/null +++ b/V11/Demo.cpp @@ -0,0 +1,1402 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + MessageBox( ultris_window, "Surfaces restauriert", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + + +// Array mit den aktuell im Spiel aktivierten Steinformen +// Zu Programmstart sind dies die ueblichen Tetris Spielsteine (0-6) +char aktive_formen[anzahl_formen] = + { + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 + }; + +// Anzahl der aktuell aktivierten Steinformen +int anz_aktive_formen = 7; + +// Punktwerte aller Steinformen +const int formwert[anzahl_formen] = + { + 8,12,12,10,10,10, 6, + 25,25, 4,20,10,10,20, + 1, 8,25,40,15,25,35, + 2, 4,10,10,20,20,25, + 25,30,25,25,10,15,25 + }; + +class ultris + { + struct formwahl + { + int ix; // Index der Form + int dv; // Drehvariante der Form + }; + private: + int vorbelegung; // Anzahl der bei Spielbeginn vorzubelegenden Zeilen + int vorschau; // Anzahl der Formen in der Vorschau + int spielfeld[20][10]; // Das Spielfeld + int fuellstand[20]; // Der Fuellstand einer Reihe (= Anzahl Segmente in der Reihe) + int punktestand; // Der aktuelle Punktestand + formwahl formen[6]; // 0 aktuelle Form, 1-5 Vorschau + int zeile; // Zeile der aktuellen Form + int spalte; // Spalte der aktuellen Form + int offset; // Offset zur Zeile + int sichtbar; // Form war bereits sichtbar + int zeige_dyn; // Zeige den dynamischen Anteil + DWORD time; // Zeitreferenz + int speed; // Geschwindigkeit + void initialisieren(); + void vorbelegen(); + void display_spielfeld(); + void display_punktestand(); + void display_vorschau(); + void display_form(); + void naechste_form(); + void neue_form(); + const form *aktuelle_form() {return ultris_form[formen[0].ix][formen[0].dv];} + int onestep(); // Stein um ein Pixel nach unten bewegen + int blockiert(); + void aufloesen(); + void aufruecken(); + public: + int spiel_laeuft; // Indikator, dass das Spiel laeuft + ultris(){ srand( GetTickCount()); initialisieren(); vorbelegung = 0; vorschau = 1;} + int get_vorbelegung() { return vorbelegung;} + void set_vorbelegung( int v) {if( v < 0) v = 0; if( v > 20) v = 20; vorbelegung = v;} + int get_vorschau() { return vorschau;} + void set_vorschau( int v) {if( v < 0) v = 0; if(v > 5) v = 5; vorschau = v;} + void start(); + void display(); + int step(); + void down(); + void reset_timer(){time = timeGetTime();} + void schneller() { speed += 50;} + void langsamer() { if( speed > 50) speed -= 50;} + void bewegen( int dir); // -1 eins nach links +1 eins nach rechts + void drehen(int dir); // -1 eins nach links +1 eins nach rechts + }; + +void ultris::initialisieren() + { + int z, s; + + for( z = 0; z < 20; z++) + { + fuellstand[z] = 0; + for( s = 0; s < 10; s++) + spielfeld[z][s] = 0; + } + spiel_laeuft = 0; + zeige_dyn = 0; + punktestand = 0; + } + +void ultris::vorbelegen() + { + int z, s, i; + + for( i = 0; i < vorbelegung*5; i++) + { + z = 19-rand()%vorbelegung; + s = rand()%10; + if( !spielfeld[z][s]) + { + spielfeld[z][s] = 1; + fuellstand[z]++; + } + } + punktestand = vorbelegung * 2500; + } + +void ultris::start() + { + ultris_sounds.play( sound_start); + initialisieren(); + vorbelegen(); + spiel_laeuft = 1; + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + neue_form(); + zeige_dyn = 1; + reset_timer(); + speed = 100; + } + +void ultris::display_spielfeld() + { + int z, s; + + for( z = 0; z < 20; z++) + { + for( s = 0; s < 10; s++) + { + if( spielfeld[z][s]) + ultris_display.feldstein( z, s); + } + } + } + +void ultris::display_punktestand() + { + int i, z, p; + + for( i = 5, p = punktestand; i >= 0; i--, p/= 10) + { + z = p % 10; + ultris_display.ziffer( i, z); + } + } + +void ultris::display() + { + ultris_display.hintergrund(); + display_spielfeld(); + if( zeige_dyn) + { + display_vorschau(); + display_form(); + } + ultris_display.abdeckung(); + display_punktestand(); + ultris_display.present(); + } + +void ultris::naechste_form() + { + int z, i, ix; + + for( i = 0; i < 5; i++) + formen[i] = formen[i+1]; + + z = rand()%anz_aktive_formen+1; + for( ix = -1; z; z--) + { + while( !aktive_formen[++ix]) + ; + } + formen[5].ix = ix; + formen[5].dv = rand()%4; + } + +void ultris::neue_form() + { + naechste_form(); + zeile = -aktuelle_form()->h; + spalte = 5-(aktuelle_form()->b)/2; + offset = 0; + sichtbar = 0; + punktestand += formwert[formen[0].ix]; + } + +void ultris::display_vorschau() + { + int z, s, p, y; + const form *f; + + if( !sichtbar) + sichtbar = (zeile >= 0); + + for( y = 0, p = sichtbar; y < vorschau; p++, y++) + { + f = ultris_form[formen[p].ix][formen[p].dv]; + for( z = 0; z < f->h; z++) + { + for( s = 0; s < f->b; s++) + { + if( f->data[z][s]) + ultris_display.prevstein(y, z, s, f->b, f->h); + } + } + } + } + +void ultris::display_form() + { + int z, s; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + ultris_display.fallstein( zeile+z, spalte+s, offset); + } + } + } + } + +void ultris::down() + { + while( onestep()) + ; + } + +int ultris::step() + { + DWORD now; + int pixel; + int diff; + + now = timeGetTime(); + diff = (now-time)*speed; + pixel = diff/5000; + if( !pixel) + return 0; + time = now - diff%5000/speed; + for( ; pixel && onestep(); pixel--) + ; + return 1; + } + +int ultris::blockiert() + { + int z, s, zz; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + zz = zeile + z + 1; + if( (zz >= 20) || ((zz >= 0) &&(spielfeld[zz][spalte+s]))) + return 1; + } + } + } + return 0; + } + +int ultris::onestep() + { + if( offset) + { + if( offset < 20) + offset++; + else + { + offset = 0; + zeile++; + } + return 1; + } + else + { + if( blockiert()) + { +// V11 Beginn + aufloesen(); + aufruecken(); + spiel_laeuft = (zeile >= 0); + if( spiel_laeuft) + neue_form(); + else + { + zeige_dyn = 0; + display(); + ultris_sounds.play( sound_ende); + } + return 0; +// V11 Ende + } + offset++; + return 1; + } + } + + + +void ultris::bewegen( int dir) // -1 eins nach links +1 eins nach rechts + { + int z, s, neue_spalte; + const form *f; + + f = aktuelle_form(); + neue_spalte = spalte + dir; + if( neue_spalte < 0) + return; + if( neue_spalte + f->b > 10) + return; + for( z = 0; z < f->h; z++) + { + if( zeile+z < 0) + continue; + for( s = 0; s < f->b; s++) + { + if( f->data[z][s]) + { + if( (offset < 16) && spielfeld[zeile+z][neue_spalte+s]) + return; + if( (offset > 0) && spielfeld[zeile+z+1][neue_spalte+s]) + return; + } + } + } + spalte = neue_spalte; + ultris_sounds.play( sound_move); + } + + + +void ultris::drehen(int dir) + { + int sv, sp, zl; + int b1, b2, h1, h2, db, dh; + int maxb, maxh, minz, mins; + int i, j; + + sv = (formen[0].dv + 4 - dir)%4; + + b1 = aktuelle_form()->b; + b2 = ultris_form[formen[0].ix][sv]->b; + h1 = aktuelle_form()->h; + h2 = ultris_form[formen[0].ix][sv]->h; + + db = (b1-b2)/2; + dh = (h1-h2)/2; + sp = spalte+db; + zl = zeile+dh; + + if( sp < 0) + sp = 0; + if( sp+b2 >= 10) + sp = 10-b2; + if( zl+h2 >= 20) + return; + + mins = spalte < sp ? spalte : sp; + minz = zeile < zl ? zeile : zl; + maxb = b1 > b2 ? b1 : b2; + maxh = h1 > h2 ? h1 : h2; + if( offset) + maxh++; + + for( i = minz; i < minz+maxh; i++) + { + for( j = mins; j < mins+maxb; j++) + { + if( (i>=0)&&(i<20)&&(j>=0)&&(j<10)&&spielfeld[i][j]) + return; + } + } + formen[0].dv = sv; + spalte = sp; + zeile = zl; + ultris_sounds.play( sound_dreh); + } + +// V11 Beginn +void ultris::aufloesen() + { + int z, s; + int zz, ss; + + for( z = 0; z < aktuelle_form()->h; z++) + { + zz = zeile+z; + if((zz >=0) && (zz<20)) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + ss = spalte + s; + if( aktuelle_form()->data[z][s] && (ss>=0) && (ss<10)) + { + spielfeld[zz][ss] = 1; + fuellstand[zz]++; + } + } + } + } + } + +void ultris::aufruecken() + { + int zz, z, s; + int a; + + for( z = 19, a = 0; z >= 0; ) + { + if( fuellstand[z] == 10) + { + a++; + punktestand += speed; + speed += 5; + for( zz = z-1; zz >= 0; zz--) + { + for( s = 0; s < 10; s++) + spielfeld[zz+1][s] = spielfeld[zz][s]; + fuellstand[zz+1] = fuellstand[zz]; + } + for( s = 0; s < 10; s++) + spielfeld[0][s] = 0; + fuellstand[0] = 0; + } + else + z--; + } + if( a == 0) + ultris_sounds.play( sound_down); + else if( a == 1) + ultris_sounds.play( sound_row1); + else + ultris_sounds.play( sound_row2); + } + + +// V11 Ende + +ultris mein_spiel; + +BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if( wParam == IDC_WEITERE_INFO) + { + ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); + return TRUE; + } + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK konfigurationsdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int i; + + switch (uMsg) + { + case WM_INITDIALOG: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, aktive_formen[i] ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, mein_spiel.get_vorbelegung(), FALSE); + SetDlgItemInt( hwndDlg, IDC_VORSCHAU, mein_spiel.get_vorschau(), FALSE); + return TRUE; + case WM_COMMAND: + if(wParam == IDOK) + { + for( i = 0, anz_aktive_formen = 0; i < anzahl_formen; i++) + { + aktive_formen[i] = 0; + if(IsDlgButtonChecked( hwndDlg, 5000+i) == BST_CHECKED) + { + aktive_formen[i] = 1; + anz_aktive_formen++; + } + } + if( anz_aktive_formen == 0) + { + aktive_formen[0] = 1; + anz_aktive_formen = 1; + } + mein_spiel.set_vorbelegung( GetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, NULL, FALSE)); + mein_spiel.set_vorschau( GetDlgItemInt( hwndDlg, IDC_VORSCHAU, NULL, FALSE)); + EndDialog(hwndDlg, wParam); + return TRUE; + } + if(wParam == IDCANCEL) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + if (HIWORD(wParam) == BN_CLICKED) + { + switch( LOWORD(wParam)) + { + case IDC_LOESCHEN: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_UNCHECKED); + return TRUE; + case IDC_ALLE: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_CHECKED); + return TRUE; + case IDC_STANDARD: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, i < 7 ? BST_CHECKED:BST_UNCHECKED); + return TRUE; + } + } + } + return FALSE; + } + +/* +** ultris_windowhandler +*/ + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case ID_INFO_HILFE: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); + mein_spiel.reset_timer(); + return 0; + case ID_INFO_ULTRIS: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); + mein_spiel.reset_timer(); + return 0; + case ID_EINSTELLUNGEN_KONFIGURATION: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_KONFIGURATION), ultris_window, konfigurationsdialog); + mein_spiel.reset_timer(); + return 0; + case ID_ULTRIS_NEUESSPIEL: + mein_spiel.start(); + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, MF_UNCHECKED); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + case ID_ULTRIS_PAUSE: + mein_spiel.spiel_laeuft = !mein_spiel.spiel_laeuft; + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, mein_spiel.spiel_laeuft ? MF_UNCHECKED:MF_CHECKED); + return 0; + case IDM_DOWN: + if( mein_spiel.spiel_laeuft) + mein_spiel.down(); + return 0; + case IDM_SCHNELLER: + mein_spiel.schneller(); + return 0; + case IDM_LANGSAMER: + mein_spiel.langsamer(); + return 0; + case IDM_DREHRECHTS: + mein_spiel.drehen(1); + return 0; + case IDM_DREHLINKS: + mein_spiel.drehen(-1); + return 0; + case IDM_RECHTS: + mein_spiel.bewegen(1); + return 0; + case IDM_LINKS: + mein_spiel.bewegen(-1); + return 0; + case IDM_TEST: // Testcode + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; + case WM_EXITMENULOOP: + case WM_EXITSIZEMOVE: + mein_spiel.reset_timer(); + break; + case WM_PAINT: + mein_spiel.display(); + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + if( mein_spiel.spiel_laeuft) + { + if( mein_spiel.step()) + mein_spiel.display(); + } + else + { + WaitMessage(); + mein_spiel.reset_timer(); // Spieluhr laeuft nicht + } + } + } + } + } + + + diff --git a/V11/Demo.h b/V11/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V11/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V11/Demo.ncb b/V11/Demo.ncb new file mode 100644 index 0000000..e394c18 Binary files /dev/null and b/V11/Demo.ncb differ diff --git a/V11/Demo.plg b/V11/Demo.plg new file mode 100644 index 0000000..084841a --- /dev/null +++ b/V11/Demo.plg @@ -0,0 +1,30 @@ + + +
+

Erstellungsprotokoll

+

+--------------------Konfiguration: Demo - Win32 Debug-------------------- +

+

Befehlszeilen

+Creating command line "rc.exe /l 0x407 /fo"Debug/Demo.res" /d "_DEBUG" "C:\uk\FHG\Vorlesungen\GSP\Programme\Ultris\V11\Demo.rc"" +Erstellen der temporären Datei "C:\DOKUME~1\uk\LOKALE~1\Temp\RSPC7.tmp" mit Inhalten +[ +winmm.lib dxguid.lib dxerr8.lib ddraw.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib dsound.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/Ultris.pdb" /debug /machine:I386 /out:"Debug/Ultris.exe" /pdbtype:sept +.\Debug\Demo.obj +.\Debug\ddutil.obj +.\Debug\dsutil.obj +.\Debug\dxutil.obj +.\Debug\Demo.res +] +Erstellen der Befehlzeile "link.exe @C:\DOKUME~1\uk\LOKALE~1\Temp\RSPC7.tmp" +

Ausgabefenster

+Ressourcen werden kompiliert... +Linker-Vorgang läuft... + + + +

Ergebnisse

+Ultris.exe - 0 Fehler, 0 Warnung(en) +
+ + diff --git a/V11/Demo.rc b/V11/Demo.rc new file mode 100644 index 0000000..a1267c3 --- /dev/null +++ b/V11/Demo.rc @@ -0,0 +1,699 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END + POPUP "Einstellungen" + BEGIN + MENUITEM "Konfiguration", ID_EINSTELLUNGEN_KONFIGURATION + + END + POPUP "Info" + BEGIN + MENUITEM "Hilfe", ID_INFO_HILFE + MENUITEM "Highscores", ID_INFO_HIGHSCORES + MENUITEM "Ultris", ID_INFO_ULTRIS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "I", IDM_DREHRECHTS, VIRTKEY, NOINVERT + "J", IDM_LINKS, VIRTKEY, NOINVERT + "K", IDM_DREHLINKS, VIRTKEY, NOINVERT + "L", IDM_RECHTS, VIRTKEY, NOINVERT + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_DOWN, IDM_DREHLINKS, VIRTKEY, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F1, ID_ULTRIS_NEUESSPIEL, VIRTKEY, NOINVERT + VK_F2, ID_ULTRIS_PAUSE, VIRTKEY, NOINVERT + VK_F3, IDM_SCHNELLER, VIRTKEY, NOINVERT + VK_F4, IDM_LANGSAMER, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT + VK_LEFT, IDM_LINKS, VIRTKEY, NOINVERT + VK_RIGHT, IDM_RECHTS, VIRTKEY, NOINVERT + VK_SPACE, IDM_DOWN, VIRTKEY, NOINVERT + VK_UP, IDM_DREHRECHTS, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ULTRIS DIALOG DISCARDABLE 0, 0, 204, 142 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Über Ultris" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,125,50,14 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_BORDER,7,7,190,78 + CTEXT "Demoprogramm\rzur Vorlesung\rGrafik und Spieleprogrammierung", + IDC_STATIC,7,92,195,28 + PUSHBUTTON "Weitere Informationen",IDC_WEITERE_INFO,5,125,140,14 +END + +IDD_KONFIGURATION DIALOGEX 0, 0, 289, 297 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Einstellungen" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,235,280,50,14 + PUSHBUTTON "Abbrechen",IDCANCEL,180,280,50,14 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,50,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,70,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,30,10,10 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,40,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,10,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,105,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,25,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,55,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,65,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,210,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,15,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,160,10,10 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 43,8,8 + CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 43,8,8 + CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 43,8,8 + CONTROL "10",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 154,43,8,8 + CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 43,8,8 + CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 43,8,8 + CONTROL "6",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 43,8,8 + CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 93,8,8 + CONTROL "",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 93,8,8 + CONTROL "",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 93,8,8 + CONTROL "",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 93,8,8 + CONTROL "",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 93,8,8 + CONTROL "",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 93,8,8 + CONTROL "20",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 274,93,8,8 + CONTROL "",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 143,8,8 + CONTROL "",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 143,8,8 + CONTROL "",IDC_CHECK17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 143,8,8 + CONTROL "",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 143,8,8 + CONTROL "",IDC_CHECK19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 143,8,8 + CONTROL "",IDC_CHECK20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 143,8,8 + CONTROL "",IDC_CHECK21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 143,8,8 + CONTROL "",IDC_CHECK22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 193,8,8 + CONTROL "",IDC_CHECK23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 193,8,8 + CONTROL "",IDC_CHECK24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 193,8,8 + CONTROL "",IDC_CHECK25,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 193,8,8 + CONTROL "",IDC_CHECK26,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 193,8,8 + CONTROL "",IDC_CHECK27,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 193,8,8 + CONTROL "",IDC_CHECK28,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 193,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,210,10,10 + CONTROL "",IDC_CHECK29,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 243,8,8 + CONTROL "",IDC_CHECK30,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 243,8,8 + CONTROL "",IDC_CHECK31,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 243,8,8 + CONTROL "",IDC_CHECK32,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 243,8,8 + CONTROL "",IDC_CHECK33,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 243,8,8 + CONTROL "",IDC_CHECK34,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 243,8,8 + CONTROL "",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 243,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,205,40,50, + WS_EX_DLGMODALFRAME + PUSHBUTTON "Alle auswählen",IDC_ALLE,235,260,50,14 + PUSHBUTTON "Standard",IDC_STANDARD,180,260,50,14 + PUSHBUTTON "Alle Löschen",IDC_LOESCHEN,125,260,50,14 + EDITTEXT IDC_VORBELEGUNG,105,260,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Vorbelegte Zeilen bei Spielstart:",IDC_STATIC,5,260,95, + 13,SS_CENTERIMAGE + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,210,10,10 + LTEXT "1",IDC_STATIC,11,143,8,8 + LTEXT "2",IDC_STATIC,10,193,8,8 + LTEXT "4",IDC_STATIC,50,193,8,8 + LTEXT "6",IDC_STATIC,250,43,8,8 + LTEXT "8",IDC_STATIC,10,43,8,8 + LTEXT "10",IDC_STATIC,130,43,8,8 + LTEXT "10",IDC_STATIC,170,43,8,8 + LTEXT "12",IDC_STATIC,50,43,8,8 + LTEXT "12",IDC_STATIC,90,43,8,8 + LTEXT "10",IDC_STATIC,210,43,8,8 + LTEXT "25",IDC_STATIC,10,93,8,8 + LTEXT "25",IDC_STATIC,50,93,8,8 + LTEXT "4",IDC_STATIC,90,93,8,8 + LTEXT "20",IDC_STATIC,130,93,8,8 + LTEXT "10",IDC_STATIC,170,93,8,8 + LTEXT "10",IDC_STATIC,210,93,8,8 + LTEXT "20",IDC_STATIC,250,93,8,8 + LTEXT "8",IDC_STATIC,50,143,8,8 + LTEXT "25",IDC_STATIC,90,143,8,8 + LTEXT "40",IDC_STATIC,130,143,8,8 + LTEXT "15",IDC_STATIC,170,143,8,8 + LTEXT "25",IDC_STATIC,210,143,8,8 + LTEXT "35",IDC_STATIC,250,143,8,8 + LTEXT "10",IDC_STATIC,90,193,8,8 + LTEXT "10",IDC_STATIC,130,193,8,8 + LTEXT "20",IDC_STATIC,170,193,8,8 + LTEXT "20",IDC_STATIC,210,193,8,8 + LTEXT "25",IDC_STATIC,250,193,8,8 + LTEXT "25",IDC_STATIC,10,243,8,8 + LTEXT "30",IDC_STATIC,50,243,8,8 + LTEXT "25",IDC_STATIC,90,243,8,8 + LTEXT "25",IDC_STATIC,130,243,8,8 + LTEXT "10",IDC_STATIC,170,243,8,8 + LTEXT "15",IDC_STATIC,210,243,8,8 + LTEXT "25",IDC_STATIC,250,243,8,8 + EDITTEXT IDC_VORSCHAU,105,280,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Steine in der Vorschau:",IDC_STATIC,5,280,95,13, + SS_CENTERIMAGE +END + +IDD_HILFE DIALOG DISCARDABLE 0, 0, 302, 107 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Hilfe" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,245,90,50,14 + LTEXT "F1: Neues Spiel",IDC_STATIC,15,22,130,8 + LTEXT "F2: Pause (ein/aus)",IDC_STATIC,15,34,130,8 + LTEXT "F3: Schneller",IDC_STATIC,15,46,130,8 + LTEXT "F4: Langsamer",IDC_STATIC,15,58,130,8 + LTEXT "F5: Sound (ein/aus)",IDC_STATIC,15,70,130,8 + GROUPBOX "Steuerung des Spiels",IDC_STATIC,7,7,142,78 + GROUPBOX "Steuerung der Steine",IDC_STATIC,153,7,142,78 + LTEXT "J oder Cursor left: Links",IDC_STATIC,159,22,131,8 + LTEXT "L oder Cursor right: Rechts",IDC_STATIC,159,34,131,8 + LTEXT "K oder Cursor down: Linksdrehung",IDC_STATIC,159,46,131, + 8 + LTEXT "I oder Cursor up: Rechtsdrehung",IDC_STATIC,159,58,131, + 8 + LTEXT "Space: Stein fallen lassen",IDC_STATIC,159,70,126,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ULTRIS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 197 + TOPMARGIN, 7 + BOTTOMMARGIN, 135 + END + + IDD_KONFIGURATION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 282 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END + + IDD_HILFE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ULTRIS BITMAP DISCARDABLE "bmp00001.bmp" +IDB_STEIN BITMAP DISCARDABLE "bmp00002.bmp" +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V11/Demo.sln b/V11/Demo.sln new file mode 100644 index 0000000..2524b72 --- /dev/null +++ b/V11/Demo.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{BE467961-88E1-41FF-98B0-3BB15D1DA76A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BE467961-88E1-41FF-98B0-3BB15D1DA76A}.Debug.ActiveCfg = Debug|Win32 + {BE467961-88E1-41FF-98B0-3BB15D1DA76A}.Debug.Build.0 = Debug|Win32 + {BE467961-88E1-41FF-98B0-3BB15D1DA76A}.Release.ActiveCfg = Release|Win32 + {BE467961-88E1-41FF-98B0-3BB15D1DA76A}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/V11/Demo.suo b/V11/Demo.suo new file mode 100644 index 0000000..09bef20 Binary files /dev/null and b/V11/Demo.suo differ diff --git a/V11/Demo.vcproj b/V11/Demo.vcproj new file mode 100644 index 0000000..98ce341 --- /dev/null +++ b/V11/Demo.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V11/Icon.ico b/V11/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V11/Icon.ico differ diff --git a/V11/bmp00001.bmp b/V11/bmp00001.bmp new file mode 100644 index 0000000..12d2027 Binary files /dev/null and b/V11/bmp00001.bmp differ diff --git a/V11/bmp00002.bmp b/V11/bmp00002.bmp new file mode 100644 index 0000000..92b8396 Binary files /dev/null and b/V11/bmp00002.bmp differ diff --git a/V11/ddutil.cpp b/V11/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V11/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V11/ddutil.h b/V11/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V11/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V11/dsutil.cpp b/V11/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V11/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V11/dsutil.h b/V11/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V11/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V11/resource.h b/V11/resource.h new file mode 100644 index 0000000..995c558 --- /dev/null +++ b/V11/resource.h @@ -0,0 +1,81 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDD_HILFE 124 +#define IDD_KONFIGURATION 125 +#define IDB_STEIN 126 +#define IDD_ULTRIS 129 +#define IDB_ULTRIS 130 +#define IDM_EXIT 1001 +#define IDC_ALLE 1005 +#define IDC_STANDARD 1006 +#define IDC_LOESCHEN 1007 +#define IDC_VORBELEGUNG 1008 +#define IDC_VORSCHAU 1009 +#define IDC_WEITERE_INFO 1018 +#define IDC_CHECK1 5000 +#define IDC_CHECK2 5001 +#define IDC_CHECK3 5002 +#define IDC_CHECK4 5003 +#define IDC_CHECK5 5004 +#define IDC_CHECK6 5005 +#define IDC_CHECK7 5006 +#define IDC_CHECK8 5007 +#define IDC_CHECK9 5008 +#define IDC_CHECK10 5009 +#define IDC_CHECK11 5010 +#define IDC_CHECK12 5011 +#define IDC_CHECK13 5012 +#define IDC_CHECK14 5013 +#define IDC_CHECK15 5014 +#define IDC_CHECK16 5015 +#define IDC_CHECK17 5016 +#define IDC_CHECK18 5017 +#define IDC_CHECK19 5018 +#define IDC_CHECK20 5019 +#define IDC_CHECK21 5020 +#define IDC_CHECK22 5021 +#define IDC_CHECK23 5022 +#define IDC_CHECK24 5023 +#define IDC_CHECK25 5024 +#define IDC_CHECK26 5025 +#define IDC_CHECK27 5026 +#define IDC_CHECK28 5027 +#define IDC_CHECK29 5028 +#define IDC_CHECK30 5029 +#define IDC_CHECK31 5030 +#define IDC_CHECK32 5031 +#define IDC_CHECK33 5032 +#define IDC_CHECK34 5033 +#define IDC_CHECK35 5034 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define ID_EINSTELLUNGEN_KONFIGURATION 40028 +#define ID_INFO_HILFE 40029 +#define ID_INFO_HIGHSCORES 40030 +#define ID_INFO_ULTRIS 40031 +#define IDM_DOWN 40033 +#define IDM_SCHNELLER 40034 +#define IDM_LANGSAMER 40035 +#define IDM_DREHRECHTS 40036 +#define IDM_DREHLINKS 40037 +#define IDM_LINKS 40038 +#define IDM_RECHTS 40039 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40040 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V11/ul_adeck.bmp b/V11/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V11/ul_adeck.bmp differ diff --git a/V11/ul_down.wav b/V11/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V11/ul_down.wav differ diff --git a/V11/ul_dreh.WAV b/V11/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V11/ul_dreh.WAV differ diff --git a/V11/ul_ende.WAV b/V11/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V11/ul_ende.WAV differ diff --git a/V11/ul_feld.bmp b/V11/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V11/ul_feld.bmp differ diff --git a/V11/ul_hgrnd.bmp b/V11/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V11/ul_hgrnd.bmp differ diff --git a/V11/ul_move.WAV b/V11/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V11/ul_move.WAV differ diff --git a/V11/ul_prev.bmp b/V11/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V11/ul_prev.bmp differ diff --git a/V11/ul_row1.WAV b/V11/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V11/ul_row1.WAV differ diff --git a/V11/ul_row2.WAV b/V11/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V11/ul_row2.WAV differ diff --git a/V11/ul_start.WAV b/V11/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V11/ul_start.WAV differ diff --git a/V11/ul_stein.bmp b/V11/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V11/ul_stein.bmp differ diff --git a/V11/ul_win.wav b/V11/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V11/ul_win.wav differ diff --git a/V11/ul_z0.bmp b/V11/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V11/ul_z0.bmp differ diff --git a/V11/ul_z1.bmp b/V11/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V11/ul_z1.bmp differ diff --git a/V11/ul_z2.bmp b/V11/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V11/ul_z2.bmp differ diff --git a/V11/ul_z3.bmp b/V11/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V11/ul_z3.bmp differ diff --git a/V11/ul_z4.bmp b/V11/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V11/ul_z4.bmp differ diff --git a/V11/ul_z5.bmp b/V11/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V11/ul_z5.bmp differ diff --git a/V11/ul_z6.bmp b/V11/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V11/ul_z6.bmp differ diff --git a/V11/ul_z7.bmp b/V11/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V11/ul_z7.bmp differ diff --git a/V11/ul_z8.bmp b/V11/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V11/ul_z8.bmp differ diff --git a/V11/ul_z9.bmp b/V11/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V11/ul_z9.bmp differ diff --git a/V12/Debug/BuildLog.htm b/V12/Debug/BuildLog.htm new file mode 100644 index 0000000..b464a53 Binary files /dev/null and b/V12/Debug/BuildLog.htm differ diff --git a/V12/Debug/Demo.obj b/V12/Debug/Demo.obj new file mode 100644 index 0000000..44a5220 Binary files /dev/null and b/V12/Debug/Demo.obj differ diff --git a/V12/Debug/Demo.res b/V12/Debug/Demo.res new file mode 100644 index 0000000..35405a2 Binary files /dev/null and b/V12/Debug/Demo.res differ diff --git a/V12/Debug/Ultris.exe b/V12/Debug/Ultris.exe new file mode 100644 index 0000000..b03f6a1 Binary files /dev/null and b/V12/Debug/Ultris.exe differ diff --git a/V12/Debug/Ultris.exe.intermediate.manifest b/V12/Debug/Ultris.exe.intermediate.manifest new file mode 100644 index 0000000..1c06b61 --- /dev/null +++ b/V12/Debug/Ultris.exe.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/V12/Debug/Ultris.pdb b/V12/Debug/Ultris.pdb new file mode 100644 index 0000000..858a590 Binary files /dev/null and b/V12/Debug/Ultris.pdb differ diff --git a/V12/Debug/ddutil.obj b/V12/Debug/ddutil.obj new file mode 100644 index 0000000..9a47b75 Binary files /dev/null and b/V12/Debug/ddutil.obj differ diff --git a/V12/Debug/dsutil.obj b/V12/Debug/dsutil.obj new file mode 100644 index 0000000..a2ef95c Binary files /dev/null and b/V12/Debug/dsutil.obj differ diff --git a/V12/Debug/mt.dep b/V12/Debug/mt.dep new file mode 100644 index 0000000..d7d0d87 --- /dev/null +++ b/V12/Debug/mt.dep @@ -0,0 +1 @@ + die Manifestressource wurde zuletzt um 8:27:59,71 am 18.02.2010 aktualisiert diff --git a/V12/Debug/ul_high.dat b/V12/Debug/ul_high.dat new file mode 100644 index 0000000..5bccaab --- /dev/null +++ b/V12/Debug/ul_high.dat @@ -0,0 +1,5 @@ +0, +0, +0, +0, +0, diff --git a/V12/Debug/vc90.idb b/V12/Debug/vc90.idb new file mode 100644 index 0000000..1a20e84 Binary files /dev/null and b/V12/Debug/vc90.idb differ diff --git a/V12/Debug/vc90.pdb b/V12/Debug/vc90.pdb new file mode 100644 index 0000000..29e6587 Binary files /dev/null and b/V12/Debug/vc90.pdb differ diff --git a/V12/Demo.aps b/V12/Demo.aps new file mode 100644 index 0000000..19be997 Binary files /dev/null and b/V12/Demo.aps differ diff --git a/V12/Demo.cpp b/V12/Demo.cpp new file mode 100644 index 0000000..0cfe020 --- /dev/null +++ b/V12/Demo.cpp @@ -0,0 +1,1534 @@ +# include +# include +# include +# include +# include "ddutil.h" +# include "dsutil.h" +# include "resource.h" + +const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters +const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters +int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) +int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) + +HINSTANCE ultris_instance; // Instanz der Ultris Applikation +HWND ultris_window; // Das Hauptfenster von Ultris +HMENU ultris_menu; // Das Menu von Ultris + +const int sound_start = 0; // Sound fuer neues Spiel +const int sound_dreh = 1; // Sound bei Drehung +const int sound_move = 2; // Sound bei rechts/links Bewegung +const int sound_down = 3; // Sound bei Aufprall +const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe +const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen +const int sound_ende = 6; // Sound bei Spielende +const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle +const int anzahl_sounds = 8; // Anzahl Sounds + +char *soundfiles[anzahl_sounds] = + { + "ul_start.wav", + "ul_dreh.wav", + "ul_move.wav", + "ul_down.wav", + "ul_row1.wav", + "ul_row2.wav", + "ul_ende.wav", + "ul_win.wav" + }; + +class sounds + { + private: + CSoundManager smgr; + CSound *snd[anzahl_sounds]; + public: + int on; + sounds(); + int init( HWND wnd); + void play( int snr); + ~sounds(); + }; + +sounds::sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + snd[i] = 0; + on = 1; + } + +int sounds::init( HWND wnd) + { + HRESULT ret; + int i; + + ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); + if( ret < 0) + return ret; + + for( i = 0; i < anzahl_sounds; i++) + { + ret = smgr.Create( snd+i, soundfiles[i]); + if( ret < 0) + return ret; + } + return S_OK; + } + +sounds::~sounds() + { + int i; + + for( i = 0; i < anzahl_sounds; i++) + { + if( snd[i]) + delete snd[i]; + } + } + +void sounds::play( int i) + { + if( !on) + return; + if( snd[i]->IsSoundPlaying()) + { + snd[i]->Stop(); + snd[i]->Reset(); + } + snd[i]->Play(0,0); + } + +sounds ultris_sounds; + +class display + { + private: + CDisplay dsply; + CSurface *hgrnd; + CSurface *fldst; + CSurface *fllst; + CSurface *prvst; + CSurface *deckel; + CSurface *ziff[10]; + public: + display(); + void free_all(); + ~display() {free_all();} + HRESULT init( HWND wnd); + void hintergrund() { dsply.Blt( 0, 0, hgrnd);} + void abdeckung() { dsply.Blt( 60, 0, deckel);} + void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} + void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} + void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} + void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} + void update(){ dsply.UpdateBounds();} + HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} + HRESULT restore(); + HRESULT present(); + }; + +display::display() + { + int i; + + hgrnd = 0; + fldst = 0; + fllst = 0; + prvst = 0; + deckel = 0; + for( i = 0; i < 10; i++) + ziff[i] = 0; + } + +void display::free_all() + { + int i; + + if( hgrnd) + delete hgrnd; + if( fldst) + delete fldst; + if( fllst) + delete fllst; + if( prvst) + delete prvst; + if( deckel) + delete deckel; + for( i = 0; i < 10; i++) + { + if( ziff[i]) + delete ziff[i]; + } + } + +HRESULT display::init( HWND wnd) + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); + if( hr < 0) + return hr; + } + return S_OK; + } + +HRESULT display::restore() + { + HRESULT hr; + int i; + char fname[20]; + + hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); + if( hr < 0) + return hr; + hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); + if( hr < 0) + return hr; + hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); + if( hr < 0) + return hr; + hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); + if( hr < 0) + return hr; + hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); + if( hr < 0) + return hr; + hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); + if( hr < 0) + return hr; + + for( i = 0; i < 10; i++) + { + sprintf( fname, "ul_z%d.bmp", i); + hr = ziff[i]->DrawBitmap( fname, 20, 40); + if( hr < 0) + return hr; + } + MessageBox( ultris_window, "Surfaces restauriert", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return S_OK; + } + +HRESULT display::present() + { + HRESULT hr; + + hr = dsply.Present(); + if( hr == DDERR_SURFACELOST ) + return restore(); + return hr; + } + +display ultris_display; + +// V12 Beginn + +BOOL CALLBACK siegerehrung( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + static char *parameter; + + switch (uMsg) + { + case WM_INITDIALOG: + parameter = (char *)lParam; + SetDlgItemText( hwndDlg, IDC_SIEGERTEXT, parameter); + return TRUE; + case WM_COMMAND: + if(wParam == IDOK) + { + GetDlgItemText( hwndDlg, IDC_NAME, parameter, 256); + EndDialog(hwndDlg, wParam); + } + break; + } + return FALSE; + } + + +class highscore + { + struct score + { + int punkte; + char name[40]; + }; + private: + score high[5]; + public: + highscore(); + int get_score( int i){ return high[i].punkte;} + const char *get_name( int i){ return high[i].name;} + void newscore( int pkt); + ~highscore(); + }; + + +highscore::highscore() + { + int i; + FILE *pf; + + for( i = 0; i < 5; i++) + { + high[i].punkte = 0; + *(high[i].name) = 0; + } + pf = fopen( "ul_high.dat", "r"); + if( !pf) + return; + + for( i = 0; i < 5; i++) + { + fscanf( pf, "%d,", &high[i].punkte); + fgets( high[i].name, 40, pf); + high[i].name[ strlen(high[i].name)-1] = 0; + } + fclose( pf); + } + +highscore::~highscore() + { + int i; + FILE *pf; + + pf = fopen( "ul_high.dat", "w"); + for( i = 0; i < 5; i++) + fprintf( pf, "%d,%s\n", high[i].punkte, high[i].name); + fclose( pf); + } + +void highscore::newscore( int pkt) + { + int pos, i; + char buf[256]; + + for( pos = 5; pos && (high[pos-1].punkte < pkt); pos--) + ; + if( pos < 5) + { + for( i = 4; i > pos; i--) + high[i] = high[i-1]; + high[pos].punkte = pkt; + *(high[i].name) = 0; + ultris_sounds.play( sound_win); + sprintf( buf, "Glückwunsch, du hast mit %d Punkten den %d. Platz erreicht!", pkt, pos+1); + DialogBoxParam( ultris_instance, MAKEINTRESOURCE( IDD_SIEGEREHRUNG), ultris_window, siegerehrung, (LPARAM)buf); + buf[38] = 0; + strcpy( high[pos].name, buf); + PostMessage( ultris_window, WM_COMMAND, ID_INFO_HIGHSCORES, 0); + } + } + + highscore ultris_highscores; + +// V12 Ende + +const int anzahl_formen = 35; // Anzahl der Formen + +// +// Datenstruktur für die Formen +// +struct form + { + char h; // Hoehe + char b; // Breite + char data[4][4]; // Vorhandene Segmente + }; + +// Form 1 in allen Drehvarianten +// +// *** * * * +// * ** *** ** +// * * +const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; +const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; +const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; +const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; + +// Form 2 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; +const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; +const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; + +// Form 3 in allen Drehvarianten +// +// ** * ** * +// ** ** ** ** +// * * +const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; +const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; +const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; + +// Form 4 in allen Drehvarianten +// +// *** ** * * +// * * *** * +// * ** +const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; +const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; +const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; +const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; + +// Form 5 in allen Drehvarianten +// +// * ** *** * +// *** * * * +// * ** +const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; +const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; +const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; +const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; + +// Form 6 in allen Drehvarianten +// +// ** ** ** ** +// ** ** ** ** +// +const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; +const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; + +// Form 7 in allen Drehvarianten +// +// **** * **** * +// * * +// * * +// * * +const form s_07_1 = {1, 4, {{1,1,1,1}}}; +const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; +const form s_07_3 = {1, 4, {{1,1,1,1}}}; +const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; + +// Form 8 in allen Drehvarianten +// +// *** ** * * ** +// * * * *** * +// ** ** +const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; +const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; +const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; +const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; + +// Form 9 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; +const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; +const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; + +// Form 10 in allen Drehvarianten +// +// ** ** * * +// * * ** ** +// +const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; +const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; +const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; +const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; + +// Form 11 in allen Drehvarianten +// +// * * * * +// *** *** *** *** +// * * * * +const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; +const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; + +// Form 12 in allen Drehvarianten +// +// ** ** * *** +// ** *** ** ** +// * ** +const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; +const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; +const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; +const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; + +// Form 13 in allen Drehvarianten +// +// ** *** * ** +// ** ** ** *** +// * ** +const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; +const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; +const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; +const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; + +// Form 14 in allen Drehvarianten +// +// *** * * *** +// * * * * +// * *** *** * +const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; +const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; +const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; +const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; + +// Form 15 in allen Drehvarianten +// +// * * * * +const form s_15_1 = {1, 1, {{1}}}; +const form s_15_2 = {1, 1, {{1}}}; +const form s_15_3 = {1, 1, {{1}}}; +const form s_15_4 = {1, 1, {{1}}}; + +// Form 16 in allen Drehvarianten +// +// * * * * +// * * * * +const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; +const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; +const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; + +// Form 17 in allen Drehvarianten +// +// * * * * +// * * * * +// * * * * +const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; +const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; +const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; + +// Form 18 in allen Drehvarianten +// +// * * * * +// * * * * * * * * +// * * * * +const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; +const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; + +// Form 19 in allen Drehvarianten +// +// * * * * * +// * * * * * +// * * +const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; +const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; +const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; +const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; + +// Form 20 in allen Drehvarianten +// +// *** * * * +// * *** * *** +// * * *** * +const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; +const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; +const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; +const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; + +// Form 21 in allen Drehvarianten +// +// * * * * * +// * ** * ** +// * * * * * +const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; +const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; +const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; +const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; + +// Form 22 in allen Drehvarianten +// +// ** * ** * +// * * +// +const form s_22_1 = {1, 2, {{1,1}}}; +const form s_22_2 = {2, 1, {{1},{1}}}; +const form s_22_3 = {1, 2, {{1,1}}}; +const form s_22_4 = {2, 1, {{1},{1}}}; + +// Form 23 in allen Drehvarianten +// +// *** * *** * +// * * +// * * +const form s_23_1 = {1, 3, {{1,1,1}}}; +const form s_23_2 = {3, 1, {{1},{1},{1}}}; +const form s_23_3 = {1, 3, {{1,1,1}}}; +const form s_23_4 = {3, 1, {{1},{1},{1}}}; + +// Form 24 in allen Drehvarianten +// +// ** * * * +// * * ** * +// * * +const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; +const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; +const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; +const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; + +// Form 25 in allen Drehvarianten +// +// * * ** * +// ** * * * +// * * +const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; +const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; +const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; +const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; + +// Form 26 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; +const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; +const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; + +// Form 27 in allen Drehvarianten +// +// ** * ** * +// ** * ** * +// * * +// * * +const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; +const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; +const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; + +// Form 28 in allen Drehvarianten +// +// * * * ** * +// ** * * * * +// * * +// * * +const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; +const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; +const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; +const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; + +// Form 29 in allen Drehvarianten +// +// ** * * ** +// * * * * +// * ** ** * +const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; +const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; +const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; +const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; + +// Form 30 in allen Drehvarianten +// +// * ** * * ** +// * * * * * * +// * * ** * ** +const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; +const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; +const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; +const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; + +// Form 31 in allen Drehvarianten +// +// *** * * * +// * * *** * +// * * +// * * +const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; +const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; +const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; +const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; + +// Form 32 in allen Drehvarianten +// +// * * *** * +// *** * * * +// * * +// * * +const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; +const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; +const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; +const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; + +// Form 33 in allen Drehvarianten +// +// ** *** ** *** +// ** *** ** *** +// ** ** +const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; +const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; +const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; + +// Form 34 in allen Drehvarianten +// +// **** * ** * +// ** ** **** ** +// ** ** +// * * +const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; +const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; +const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; +const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; + +// Form 35 in allen Drehvarianten +// +// ** * ** * +// * *** * *** +// ** * ** * +const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; +const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; +const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; + +// Array mit allen Steinformen in allen Drehvarianten +// Zugriff in der Form +// +// ultris_form[ steinform][ drehvariante] +// +// mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 + +const form *ultris_form[anzahl_formen][4] = + { + { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, + { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, + { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, + { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, + { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, + { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, + { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, + { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, + { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, + { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, + { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, + { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, + { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, + { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, + { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, + { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, + { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, + { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, + { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, + { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, + { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, + { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, + { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, + { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, + { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, + { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, + { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, + { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, + { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, + { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, + { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, + { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, + { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, + { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, + { &s_35_1, &s_35_2, &s_35_3, &s_35_4} + }; + + +// Array mit den aktuell im Spiel aktivierten Steinformen +// Zu Programmstart sind dies die ueblichen Tetris Spielsteine (0-6) +char aktive_formen[anzahl_formen] = + { + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0 + }; + +// Anzahl der aktuell aktivierten Steinformen +int anz_aktive_formen = 7; + +// Punktwerte aller Steinformen +const int formwert[anzahl_formen] = + { + 8,12,12,10,10,10, 6, + 25,25, 4,20,10,10,20, + 1, 8,25,40,15,25,35, + 2, 4,10,10,20,20,25, + 25,30,25,25,10,15,25 + }; + +class ultris + { + struct formwahl + { + int ix; // Index der Form + int dv; // Drehvariante der Form + }; + private: + int vorbelegung; // Anzahl der bei Spielbeginn vorzubelegenden Zeilen + int vorschau; // Anzahl der Formen in der Vorschau + int spielfeld[20][10]; // Das Spielfeld + int fuellstand[20]; // Der Fuellstand einer Reihe (= Anzahl Segmente in der Reihe) + int punktestand; // Der aktuelle Punktestand + formwahl formen[6]; // 0 aktuelle Form, 1-5 Vorschau + int zeile; // Zeile der aktuellen Form + int spalte; // Spalte der aktuellen Form + int offset; // Offset zur Zeile + int sichtbar; // Form war bereits sichtbar + int zeige_dyn; // Zeige den dynamischen Anteil + DWORD time; // Zeitreferenz + int speed; // Geschwindigkeit + void initialisieren(); + void vorbelegen(); + void display_spielfeld(); + void display_punktestand(); + void display_vorschau(); + void display_form(); + void naechste_form(); + void neue_form(); + const form *aktuelle_form() {return ultris_form[formen[0].ix][formen[0].dv];} + int onestep(); // Stein um ein Pixel nach unten bewegen + int blockiert(); + void aufloesen(); + void aufruecken(); + public: + int spiel_laeuft; // Indikator, dass das Spiel laeuft + ultris(){ srand( GetTickCount()); initialisieren(); vorbelegung = 0; vorschau = 1;} + int get_vorbelegung() { return vorbelegung;} + void set_vorbelegung( int v) {if( v < 0) v = 0; if( v > 20) v = 20; vorbelegung = v;} + int get_vorschau() { return vorschau;} + void set_vorschau( int v) {if( v < 0) v = 0; if(v > 5) v = 5; vorschau = v;} + void start(); + void display(); + int step(); + void down(); + void reset_timer(){time = timeGetTime();} + void schneller() { speed += 50;} + void langsamer() { if( speed > 50) speed -= 50;} + void bewegen( int dir); // -1 eins nach links +1 eins nach rechts + void drehen(int dir); // -1 eins nach links +1 eins nach rechts + }; + +void ultris::initialisieren() + { + int z, s; + + for( z = 0; z < 20; z++) + { + fuellstand[z] = 0; + for( s = 0; s < 10; s++) + spielfeld[z][s] = 0; + } + spiel_laeuft = 0; + zeige_dyn = 0; + punktestand = 0; + } + +void ultris::vorbelegen() + { + int z, s, i; + + for( i = 0; i < vorbelegung*5; i++) + { + z = 19-rand()%vorbelegung; + s = rand()%10; + if( !spielfeld[z][s]) + { + spielfeld[z][s] = 1; + fuellstand[z]++; + } + } + punktestand = vorbelegung * 2500; + } + +void ultris::start() + { + ultris_sounds.play( sound_start); + initialisieren(); + vorbelegen(); + spiel_laeuft = 1; + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + naechste_form(); + neue_form(); + zeige_dyn = 1; + reset_timer(); + speed = 100; + } + +void ultris::display_spielfeld() + { + int z, s; + + for( z = 0; z < 20; z++) + { + for( s = 0; s < 10; s++) + { + if( spielfeld[z][s]) + ultris_display.feldstein( z, s); + } + } + } + +void ultris::display_punktestand() + { + int i, z, p; + + for( i = 5, p = punktestand; i >= 0; i--, p/= 10) + { + z = p % 10; + ultris_display.ziffer( i, z); + } + } + +void ultris::display() + { + ultris_display.hintergrund(); + display_spielfeld(); + if( zeige_dyn) + { + display_vorschau(); + display_form(); + } + ultris_display.abdeckung(); + display_punktestand(); + ultris_display.present(); + } + +void ultris::naechste_form() + { + int z, i, ix; + + for( i = 0; i < 5; i++) + formen[i] = formen[i+1]; + + z = rand()%anz_aktive_formen+1; + for( ix = -1; z; z--) + { + while( !aktive_formen[++ix]) + ; + } + formen[5].ix = ix; + formen[5].dv = rand()%4; + } + +void ultris::neue_form() + { + naechste_form(); + zeile = -aktuelle_form()->h; + spalte = 5-(aktuelle_form()->b)/2; + offset = 0; + sichtbar = 0; + punktestand += formwert[formen[0].ix]; + } + +void ultris::display_vorschau() + { + int z, s, p, y; + const form *f; + + if( !sichtbar) + sichtbar = (zeile >= 0); + + for( y = 0, p = sichtbar; y < vorschau; p++, y++) + { + f = ultris_form[formen[p].ix][formen[p].dv]; + for( z = 0; z < f->h; z++) + { + for( s = 0; s < f->b; s++) + { + if( f->data[z][s]) + ultris_display.prevstein(y, z, s, f->b, f->h); + } + } + } + } + +void ultris::display_form() + { + int z, s; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + ultris_display.fallstein( zeile+z, spalte+s, offset); + } + } + } + } + +void ultris::down() + { + while( onestep()) + ; + } + +int ultris::step() + { + DWORD now; + int pixel; + int diff; + + now = timeGetTime(); + diff = (now-time)*speed; + pixel = diff/5000; + if( !pixel) + return 0; + time = now - diff%5000/speed; + for( ; pixel && onestep(); pixel--) + ; + return 1; + } + +int ultris::blockiert() + { + int z, s, zz; + + for( z = 0; z < aktuelle_form()->h; z++) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + if( aktuelle_form()->data[z][s]) + { + zz = zeile + z + 1; + if( (zz >= 20) || ((zz >= 0) &&(spielfeld[zz][spalte+s]))) + return 1; + } + } + } + return 0; + } + +int ultris::onestep() + { + if( offset) + { + if( offset < 20) + offset++; + else + { + offset = 0; + zeile++; + } + return 1; + } + else + { + if( blockiert()) + { + aufloesen(); + aufruecken(); + spiel_laeuft = (zeile >= 0); + if( spiel_laeuft) + neue_form(); + else + { + zeige_dyn = 0; + display(); + ultris_sounds.play( sound_ende); +// V12 Beginn + ultris_highscores.newscore( punktestand); +// V12 Ende + } + return 0; + } + offset++; + return 1; + } + } + + + +void ultris::bewegen( int dir) // -1 eins nach links +1 eins nach rechts + { + int z, s, neue_spalte; + const form *f; + + f = aktuelle_form(); + neue_spalte = spalte + dir; + if( neue_spalte < 0) + return; + if( neue_spalte + f->b > 10) + return; + for( z = 0; z < f->h; z++) + { + if( zeile+z < 0) + continue; + for( s = 0; s < f->b; s++) + { + if( f->data[z][s]) + { + if( (offset < 16) && spielfeld[zeile+z][neue_spalte+s]) + return; + if( (offset > 0) && spielfeld[zeile+z+1][neue_spalte+s]) + return; + } + } + } + spalte = neue_spalte; + ultris_sounds.play( sound_move); + } + + + +void ultris::drehen(int dir) + { + int sv, sp, zl; + int b1, b2, h1, h2, db, dh; + int maxb, maxh, minz, mins; + int i, j; + + sv = (formen[0].dv + 4 - dir)%4; + + b1 = aktuelle_form()->b; + b2 = ultris_form[formen[0].ix][sv]->b; + h1 = aktuelle_form()->h; + h2 = ultris_form[formen[0].ix][sv]->h; + + db = (b1-b2)/2; + dh = (h1-h2)/2; + sp = spalte+db; + zl = zeile+dh; + + if( sp < 0) + sp = 0; + if( sp+b2 >= 10) + sp = 10-b2; + if( zl+h2 >= 20) + return; + + mins = spalte < sp ? spalte : sp; + minz = zeile < zl ? zeile : zl; + maxb = b1 > b2 ? b1 : b2; + maxh = h1 > h2 ? h1 : h2; + if( offset) + maxh++; + + for( i = minz; i < minz+maxh; i++) + { + for( j = mins; j < mins+maxb; j++) + { + if( (i>=0)&&(i<20)&&(j>=0)&&(j<10)&&spielfeld[i][j]) + return; + } + } + formen[0].dv = sv; + spalte = sp; + zeile = zl; + ultris_sounds.play( sound_dreh); + } + +void ultris::aufloesen() + { + int z, s; + int zz, ss; + + for( z = 0; z < aktuelle_form()->h; z++) + { + zz = zeile+z; + if((zz >=0) && (zz<20)) + { + for( s = 0; s < aktuelle_form()->b; s++) + { + ss = spalte + s; + if( aktuelle_form()->data[z][s] && (ss>=0) && (ss<10)) + { + spielfeld[zz][ss] = 1; + fuellstand[zz]++; + } + } + } + } + } + +void ultris::aufruecken() + { + int zz, z, s; + int a; + + for( z = 19, a = 0; z >= 0; ) + { + if( fuellstand[z] == 10) + { + a++; + punktestand += speed; + speed += 5; + for( zz = z-1; zz >= 0; zz--) + { + for( s = 0; s < 10; s++) + spielfeld[zz+1][s] = spielfeld[zz][s]; + fuellstand[zz+1] = fuellstand[zz]; + } + for( s = 0; s < 10; s++) + spielfeld[0][s] = 0; + fuellstand[0] = 0; + } + else + z--; + } + if( a == 0) + ultris_sounds.play( sound_down); + else if( a == 1) + ultris_sounds.play( sound_row1); + else + ultris_sounds.play( sound_row2); + } + +ultris mein_spiel; + +BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + if( wParam == IDC_WEITERE_INFO) + { + ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); + return TRUE; + } + if((wParam == IDOK)||(wParam == IDCANCEL)) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + } + return FALSE; + } + +BOOL CALLBACK konfigurationsdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + int i; + + switch (uMsg) + { + case WM_INITDIALOG: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, aktive_formen[i] ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, mein_spiel.get_vorbelegung(), FALSE); + SetDlgItemInt( hwndDlg, IDC_VORSCHAU, mein_spiel.get_vorschau(), FALSE); + return TRUE; + case WM_COMMAND: + if(wParam == IDOK) + { + for( i = 0, anz_aktive_formen = 0; i < anzahl_formen; i++) + { + aktive_formen[i] = 0; + if(IsDlgButtonChecked( hwndDlg, 5000+i) == BST_CHECKED) + { + aktive_formen[i] = 1; + anz_aktive_formen++; + } + } + if( anz_aktive_formen == 0) + { + aktive_formen[0] = 1; + anz_aktive_formen = 1; + } + mein_spiel.set_vorbelegung( GetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, NULL, FALSE)); + mein_spiel.set_vorschau( GetDlgItemInt( hwndDlg, IDC_VORSCHAU, NULL, FALSE)); + EndDialog(hwndDlg, wParam); + return TRUE; + } + if(wParam == IDCANCEL) + { + EndDialog(hwndDlg, wParam); + return TRUE; + } + if (HIWORD(wParam) == BN_CLICKED) + { + switch( LOWORD(wParam)) + { + case IDC_LOESCHEN: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_UNCHECKED); + return TRUE; + case IDC_ALLE: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, BST_CHECKED); + return TRUE; + case IDC_STANDARD: + for( i = 0; i < anzahl_formen; i++) + CheckDlgButton( hwndDlg, 5000+i, i < 7 ? BST_CHECKED:BST_UNCHECKED); + return TRUE; + } + } + } + return FALSE; + } + +// V12 Beginn +BOOL CALLBACK highscoredialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_INITDIALOG: + SetDlgItemInt( hwndDlg, IDC_SCORE1, ultris_highscores.get_score(0), FALSE); + SetDlgItemInt( hwndDlg, IDC_SCORE2, ultris_highscores.get_score(1), FALSE); + SetDlgItemInt( hwndDlg, IDC_SCORE3, ultris_highscores.get_score(2), FALSE); + SetDlgItemInt( hwndDlg, IDC_SCORE4, ultris_highscores.get_score(3), FALSE); + SetDlgItemInt( hwndDlg, IDC_SCORE5, ultris_highscores.get_score(4), FALSE); + SetDlgItemText( hwndDlg, IDC_NAME1, ultris_highscores.get_name(0)); + SetDlgItemText( hwndDlg, IDC_NAME2, ultris_highscores.get_name(1)); + SetDlgItemText( hwndDlg, IDC_NAME3, ultris_highscores.get_name(2)); + SetDlgItemText( hwndDlg, IDC_NAME4, ultris_highscores.get_name(3)); + SetDlgItemText( hwndDlg, IDC_NAME5, ultris_highscores.get_name(4)); + return TRUE; + case WM_COMMAND: + if((wParam == IDOK)||(wParam == IDCANCEL)) + EndDialog(hwndDlg, wParam); + break; + } + return FALSE; + } + +// V12 Ende + +/* +** ultris_windowhandler +*/ + +LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch(msg) + { + case WM_COMMAND: + switch( LOWORD( wParam)) + { + case IDM_EXIT: + PostMessage( hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_ULTRIS_SOUND: + ultris_sounds.on = !ultris_sounds.on; + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + return 0; + case ID_INFO_HILFE: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); + mein_spiel.reset_timer(); + return 0; + case ID_INFO_ULTRIS: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); + mein_spiel.reset_timer(); + return 0; + case ID_EINSTELLUNGEN_KONFIGURATION: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_KONFIGURATION), ultris_window, konfigurationsdialog); + mein_spiel.reset_timer(); + return 0; +// V12 Beginn + case ID_INFO_HIGHSCORES: + DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HIGHSCORE), ultris_window, highscoredialog); + mein_spiel.reset_timer(); + return 0; +// V12 Ende + case ID_ULTRIS_NEUESSPIEL: + mein_spiel.start(); + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, MF_UNCHECKED); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + case ID_ULTRIS_PAUSE: + mein_spiel.spiel_laeuft = !mein_spiel.spiel_laeuft; + CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, mein_spiel.spiel_laeuft ? MF_UNCHECKED:MF_CHECKED); + return 0; + case IDM_DOWN: + if( mein_spiel.spiel_laeuft) + mein_spiel.down(); + return 0; + case IDM_SCHNELLER: + mein_spiel.schneller(); + return 0; + case IDM_LANGSAMER: + mein_spiel.langsamer(); + return 0; + case IDM_DREHRECHTS: + mein_spiel.drehen(1); + return 0; + case IDM_DREHLINKS: + mein_spiel.drehen(-1); + return 0; + case IDM_RECHTS: + mein_spiel.bewegen(1); + return 0; + case IDM_LINKS: + mein_spiel.bewegen(-1); + return 0; + case IDM_TEST: // Testcode + return 0; + } + break; + case WM_GETMINMAXINFO: + ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; + ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; + return 0; + case WM_DESTROY: + PostQuitMessage( 0); + return 0; + case WM_MOVE: + ultris_display.update(); + return 0; + case WM_EXITMENULOOP: + case WM_EXITSIZEMOVE: + mein_spiel.reset_timer(); + break; + case WM_PAINT: + mein_spiel.display(); + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + +/* +** WinMain +*/ +int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) + { + MSG msg; + HACCEL acc; + WNDCLASSEX wcx; + + ultris_instance = hInst; + + wcx.cbSize = sizeof( wcx); + wcx.lpszClassName = TEXT( "Ultris"); + wcx.lpfnWndProc = ultris_windowhandler; + wcx.style = CS_VREDRAW | CS_HREDRAW; + wcx.hInstance = hInst; + wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); + wcx.hCursor = LoadCursor( NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + + if( !RegisterClassEx( &wcx)) + return 0; + + acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); + + ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + + GetSystemMetrics( SM_CYMENU) + + GetSystemMetrics( SM_CYCAPTION); + ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); + + ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); + if( !ultris_window) + return 0; + + ultris_menu = GetMenu( ultris_window); + + if( ultris_sounds.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); + + if( ultris_display.init( ultris_window) < 0) + { + MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + return 0; + } + + MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, + (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, + ultris_bruttobreite, ultris_bruttohoehe, TRUE); + + ShowWindow( ultris_window, nCmdShow); + + while( TRUE) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) + { + if( GetMessage( &msg, NULL, 0, 0 ) == 0) + return 0; // Message ist WM_QUIT + + if( TranslateAccelerator( ultris_window, acc, &msg) == 0) + { + TranslateMessage( &msg); + DispatchMessage( &msg); + } + } + else + { + HRESULT hr; + hr = ultris_display.cooperative(); + if( hr < 0) + { + switch( hr ) + { + case DDERR_EXCLUSIVEMODEALREADYSET: + Sleep(10); + break; + case DDERR_WRONGMODE: + ultris_display.free_all(); + ultris_display.init( ultris_window); + PostMessage( ultris_window, WM_PAINT, 0, 0); + break; + } + } + else + { + if( mein_spiel.spiel_laeuft) + { + if( mein_spiel.step()) + mein_spiel.display(); + } + else + { + WaitMessage(); + mein_spiel.reset_timer(); // Spieluhr laeuft nicht + } + } + } + } + } + + + diff --git a/V12/Demo.h b/V12/Demo.h new file mode 100644 index 0000000..a19fa69 --- /dev/null +++ b/V12/Demo.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) +#define AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_DEMO_H__6F0BC346_A022_4D9B_B04C_63C781695029__INCLUDED_) diff --git a/V12/Demo.ncb b/V12/Demo.ncb new file mode 100644 index 0000000..880cb8f Binary files /dev/null and b/V12/Demo.ncb differ diff --git a/V12/Demo.rc b/V12/Demo.rc new file mode 100644 index 0000000..d26d5dd --- /dev/null +++ b/V12/Demo.rc @@ -0,0 +1,750 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Ultris" + BEGIN + MENUITEM "Neues Spiel", ID_ULTRIS_NEUESSPIEL + MENUITEM "Pause", ID_ULTRIS_PAUSE + MENUITEM "Sound", ID_ULTRIS_SOUND + MENUITEM SEPARATOR + MENUITEM "Ende", IDM_EXIT + END + POPUP "Einstellungen" + BEGIN + MENUITEM "Konfiguration", ID_EINSTELLUNGEN_KONFIGURATION + + END + POPUP "Info" + BEGIN + MENUITEM "Hilfe", ID_INFO_HILFE + MENUITEM "Highscores", ID_INFO_HIGHSCORES + MENUITEM "Ultris", ID_INFO_ULTRIS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN ICON DISCARDABLE "Icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "I", IDM_DREHRECHTS, VIRTKEY, NOINVERT + "J", IDM_LINKS, VIRTKEY, NOINVERT + "K", IDM_DREHLINKS, VIRTKEY, NOINVERT + "L", IDM_RECHTS, VIRTKEY, NOINVERT + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + VK_DOWN, IDM_DREHLINKS, VIRTKEY, NOINVERT + VK_ESCAPE, IDM_EXIT, VIRTKEY, NOINVERT + VK_F1, ID_ULTRIS_NEUESSPIEL, VIRTKEY, NOINVERT + VK_F2, ID_ULTRIS_PAUSE, VIRTKEY, NOINVERT + VK_F3, IDM_SCHNELLER, VIRTKEY, NOINVERT + VK_F4, IDM_LANGSAMER, VIRTKEY, NOINVERT + VK_F5, ID_ULTRIS_SOUND, VIRTKEY, NOINVERT + VK_LEFT, IDM_LINKS, VIRTKEY, NOINVERT + VK_RIGHT, IDM_RECHTS, VIRTKEY, NOINVERT + VK_SPACE, IDM_DOWN, VIRTKEY, NOINVERT + VK_UP, IDM_DREHRECHTS, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_HILFE DIALOG DISCARDABLE 0, 0, 302, 107 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Hilfe" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,245,90,50,14 + LTEXT "F1: Neues Spiel",IDC_STATIC,15,22,130,8 + LTEXT "F2: Pause (ein/aus)",IDC_STATIC,15,34,130,8 + LTEXT "F3: Schneller",IDC_STATIC,15,46,130,8 + LTEXT "F4: Langsamer",IDC_STATIC,15,58,130,8 + LTEXT "F5: Sound (ein/aus)",IDC_STATIC,15,70,130,8 + GROUPBOX "Steuerung des Spiels",IDC_STATIC,7,7,142,78 + GROUPBOX "Steuerung der Steine",IDC_STATIC,153,7,142,78 + LTEXT "J oder Cursor left: Links",IDC_STATIC,159,22,131,8 + LTEXT "L oder Cursor right: Rechts",IDC_STATIC,159,34,131,8 + LTEXT "K oder Cursor down: Linksdrehung",IDC_STATIC,159,46,131, + 8 + LTEXT "I oder Cursor up: Rechtsdrehung",IDC_STATIC,159,58,131, + 8 + LTEXT "Space: Stein fallen lassen",IDC_STATIC,159,70,126,8 +END + +IDD_ULTRIS DIALOG DISCARDABLE 0, 0, 204, 142 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Über Ultris" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,125,50,14 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_BORDER,7,7,190,78 + CTEXT "Demoprogramm\rzur Vorlesung\rGrafik und Spieleprogrammierung", + IDC_STATIC,7,92,195,28 + PUSHBUTTON "Weitere Informationen",IDC_WEITERE_INFO,5,125,140,14 +END + +IDD_KONFIGURATION DIALOGEX 0, 0, 289, 297 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Einstellungen" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,235,280,50,14 + PUSHBUTTON "Abbrechen",IDCANCEL,180,280,50,14 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,50,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,60,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE | WS_BORDER,70,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,30,10,10 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,40,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,30,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,20,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,10,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,105,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,95,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,65,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,75,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,25,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,215,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,225,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,55,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,65,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,60,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,80,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,70,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,115,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,190,125,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,210,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,130,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,120,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,110,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,90,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,15,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,150,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,180,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,170,160,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,180,190,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,170,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,160,10,10 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 43,8,8 + CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 43,8,8 + CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 43,8,8 + CONTROL "10",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 154,43,8,8 + CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 43,8,8 + CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 43,8,8 + CONTROL "6",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 43,8,8 + CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 93,8,8 + CONTROL "",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 93,8,8 + CONTROL "",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 93,8,8 + CONTROL "",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 93,8,8 + CONTROL "",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 93,8,8 + CONTROL "",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 93,8,8 + CONTROL "20",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 274,93,8,8 + CONTROL "",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 143,8,8 + CONTROL "",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 143,8,8 + CONTROL "",IDC_CHECK17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 143,8,8 + CONTROL "",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 143,8,8 + CONTROL "",IDC_CHECK19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 143,8,8 + CONTROL "",IDC_CHECK20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 143,8,8 + CONTROL "",IDC_CHECK21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 143,8,8 + CONTROL "",IDC_CHECK22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 193,8,8 + CONTROL "",IDC_CHECK23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 193,8,8 + CONTROL "",IDC_CHECK24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 193,8,8 + CONTROL "",IDC_CHECK25,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 193,8,8 + CONTROL "",IDC_CHECK26,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 193,8,8 + CONTROL "",IDC_CHECK27,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 193,8,8 + CONTROL "",IDC_CHECK28,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 193,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,5,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,55,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,105,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,155,40,50, + WS_EX_DLGMODALFRAME + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,30,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,10,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,110,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,50,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,70,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,20,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,100,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,185,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,130,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,140,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,175,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,210,10,10 + CONTROL "",IDC_CHECK29,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34, + 243,8,8 + CONTROL "",IDC_CHECK30,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,74, + 243,8,8 + CONTROL "",IDC_CHECK31,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114, + 243,8,8 + CONTROL "",IDC_CHECK32,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154, + 243,8,8 + CONTROL "",IDC_CHECK33,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194, + 243,8,8 + CONTROL "",IDC_CHECK34,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,234, + 243,8,8 + CONTROL "",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274, + 243,8,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,5,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,45,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,85,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,125,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,165,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,205,205,40,50, + WS_EX_DLGMODALFRAME + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,245,205,40,50, + WS_EX_DLGMODALFRAME + PUSHBUTTON "Alle auswählen",IDC_ALLE,235,260,50,14 + PUSHBUTTON "Standard",IDC_STANDARD,180,260,50,14 + PUSHBUTTON "Alle Löschen",IDC_LOESCHEN,125,260,50,14 + EDITTEXT IDC_VORBELEGUNG,105,260,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Vorbelegte Zeilen bei Spielstart:",IDC_STATIC,5,260,95, + 13,SS_CENTERIMAGE + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,220,240,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,230,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,210,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,250,230,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,260,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,270,220,10,10 + CONTROL 126,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE | + WS_BORDER,60,210,10,10 + LTEXT "1",IDC_STATIC,11,143,8,8 + LTEXT "2",IDC_STATIC,10,193,8,8 + LTEXT "4",IDC_STATIC,50,193,8,8 + LTEXT "6",IDC_STATIC,250,43,8,8 + LTEXT "8",IDC_STATIC,10,43,8,8 + LTEXT "10",IDC_STATIC,130,43,8,8 + LTEXT "10",IDC_STATIC,170,43,8,8 + LTEXT "12",IDC_STATIC,50,43,8,8 + LTEXT "12",IDC_STATIC,90,43,8,8 + LTEXT "10",IDC_STATIC,210,43,8,8 + LTEXT "25",IDC_STATIC,10,93,8,8 + LTEXT "25",IDC_STATIC,50,93,8,8 + LTEXT "4",IDC_STATIC,90,93,8,8 + LTEXT "20",IDC_STATIC,130,93,8,8 + LTEXT "10",IDC_STATIC,170,93,8,8 + LTEXT "10",IDC_STATIC,210,93,8,8 + LTEXT "20",IDC_STATIC,250,93,8,8 + LTEXT "8",IDC_STATIC,50,143,8,8 + LTEXT "25",IDC_STATIC,90,143,8,8 + LTEXT "40",IDC_STATIC,130,143,8,8 + LTEXT "15",IDC_STATIC,170,143,8,8 + LTEXT "25",IDC_STATIC,210,143,8,8 + LTEXT "35",IDC_STATIC,250,143,8,8 + LTEXT "10",IDC_STATIC,90,193,8,8 + LTEXT "10",IDC_STATIC,130,193,8,8 + LTEXT "20",IDC_STATIC,170,193,8,8 + LTEXT "20",IDC_STATIC,210,193,8,8 + LTEXT "25",IDC_STATIC,250,193,8,8 + LTEXT "25",IDC_STATIC,10,243,8,8 + LTEXT "30",IDC_STATIC,50,243,8,8 + LTEXT "25",IDC_STATIC,90,243,8,8 + LTEXT "25",IDC_STATIC,130,243,8,8 + LTEXT "10",IDC_STATIC,170,243,8,8 + LTEXT "15",IDC_STATIC,210,243,8,8 + LTEXT "25",IDC_STATIC,250,243,8,8 + EDITTEXT IDC_VORSCHAU,105,280,15,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + LTEXT "Steine in der Vorschau:",IDC_STATIC,5,280,95,13, + SS_CENTERIMAGE +END + +IDD_HIGHSCORE DIALOG DISCARDABLE 0, 0, 174, 127 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Highscores" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,120,110,50,14 + PUSHBUTTON "Abbrechen",IDCANCEL,65,110,50,14 + EDITTEXT IDC_SCORE1,5,10,30,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_READONLY | ES_NUMBER + EDITTEXT IDC_SCORE2,5,30,30,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_READONLY | ES_NUMBER + EDITTEXT IDC_SCORE3,5,50,30,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_READONLY | ES_NUMBER + EDITTEXT IDC_SCORE4,5,70,30,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_READONLY | ES_NUMBER + EDITTEXT IDC_SCORE5,5,90,30,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_READONLY | ES_NUMBER + EDITTEXT IDC_NAME1,40,10,130,14,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_NAME2,40,30,130,14,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_NAME3,40,50,130,14,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_NAME4,40,70,130,14,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_NAME5,40,90,130,14,ES_AUTOHSCROLL | ES_READONLY +END + +IDD_SIEGEREHRUNG DIALOG DISCARDABLE 0, 0, 224, 57 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION +CAPTION "Siegerehrung" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_NAME,95,20,125,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,170,40,50,14 + LTEXT "Static",IDC_SIEGERTEXT,5,5,215,8 + LTEXT "Gib bitte deinen Namen ein:",IDC_STATIC,5,20,85,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_HILFE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 295 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_ULTRIS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 197 + TOPMARGIN, 7 + BOTTOMMARGIN, 135 + END + + IDD_KONFIGURATION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 282 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END + + IDD_HIGHSCORE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 167 + TOPMARGIN, 7 + BOTTOMMARGIN, 120 + END + + IDD_SIEGEREHRUNG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 217 + TOPMARGIN, 7 + BOTTOMMARGIN, 50 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ULTRIS BITMAP DISCARDABLE "bmp00001.bmp" +IDB_STEIN BITMAP DISCARDABLE "bmp00002.bmp" +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/V12/Demo.sln b/V12/Demo.sln new file mode 100644 index 0000000..72d86bb --- /dev/null +++ b/V12/Demo.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo.vcproj", "{70C56FBC-EDDD-4EFD-81BC-31150C979AD5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {70C56FBC-EDDD-4EFD-81BC-31150C979AD5}.Debug|Win32.ActiveCfg = Debug|Win32 + {70C56FBC-EDDD-4EFD-81BC-31150C979AD5}.Debug|Win32.Build.0 = Debug|Win32 + {70C56FBC-EDDD-4EFD-81BC-31150C979AD5}.Release|Win32.ActiveCfg = Release|Win32 + {70C56FBC-EDDD-4EFD-81BC-31150C979AD5}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/V12/Demo.suo b/V12/Demo.suo new file mode 100644 index 0000000..060875e Binary files /dev/null and b/V12/Demo.suo differ diff --git a/V12/Demo.vcproj b/V12/Demo.vcproj new file mode 100644 index 0000000..bb74557 --- /dev/null +++ b/V12/Demo.vcproj @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V12/Demo.vcproj.SASCHA.Sasch.user b/V12/Demo.vcproj.SASCHA.Sasch.user new file mode 100644 index 0000000..86f2a09 --- /dev/null +++ b/V12/Demo.vcproj.SASCHA.Sasch.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/V12/Icon.ico b/V12/Icon.ico new file mode 100644 index 0000000..7a53f63 Binary files /dev/null and b/V12/Icon.ico differ diff --git a/V12/Kopie von ul_high.dat b/V12/Kopie von ul_high.dat new file mode 100644 index 0000000..31fb4a9 --- /dev/null +++ b/V12/Kopie von ul_high.dat @@ -0,0 +1,5 @@ +567890,Phil Marlowe +456789,Sam Spade +345678,Lew Archer +234567,Inspector Columbo +123456,Ulrich Kaiser diff --git a/V12/Ultris.exe b/V12/Ultris.exe new file mode 100644 index 0000000..b03f6a1 Binary files /dev/null and b/V12/Ultris.exe differ diff --git a/V12/UpgradeLog.XML b/V12/UpgradeLog.XML new file mode 100644 index 0000000..9562bef --- /dev/null +++ b/V12/UpgradeLog.XML @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/V12/_UpgradeReport_Files/UpgradeReport.css b/V12/_UpgradeReport_Files/UpgradeReport.css new file mode 100644 index 0000000..3411f63 --- /dev/null +++ b/V12/_UpgradeReport_Files/UpgradeReport.css @@ -0,0 +1,207 @@ +BODY +{ + BACKGROUND-COLOR: white; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px +} +P +{ + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 70%; + LINE-HEIGHT: 12pt; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 10px +} +.note +{ + BACKGROUND-COLOR: #ffffff; + COLOR: #336699; + FONT-FAMILY: "Verdana", sans-serif; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 0px; + MARGIN-LEFT: 0px; + MARGIN-TOP: 0px; + PADDING-RIGHT: 10px +} +.infotable +{ + BACKGROUND-COLOR: #f0f0e0; + BORDER-BOTTOM: #ffffff 0px solid; + BORDER-COLLAPSE: collapse; + BORDER-LEFT: #ffffff 0px solid; + BORDER-RIGHT: #ffffff 0px solid; + BORDER-TOP: #ffffff 0px solid; + FONT-SIZE: 70%; + MARGIN-LEFT: 10px +} +.issuetable +{ + BACKGROUND-COLOR: #ffffe8; + BORDER-COLLAPSE: collapse; + COLOR: #000000; + FONT-SIZE: 100%; + MARGIN-BOTTOM: 10px; + MARGIN-LEFT: 13px; + MARGIN-TOP: 0px +} +.issuetitle +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px; + COLOR: #003366; + FONT-WEIGHT: normal +} +.header +{ + BACKGROUND-COLOR: #cecf9c; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + COLOR: #000000; + FONT-WEIGHT: bold +} +.issuehdr +{ + BACKGROUND-COLOR: #E0EBF5; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + COLOR: #000000; + FONT-WEIGHT: normal +} +.issuenone +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: 0px; + BORDER-LEFT: 0px; + BORDER-RIGHT: 0px; + BORDER-TOP: 0px; + COLOR: #000000; + FONT-WEIGHT: normal +} +.content +{ + BACKGROUND-COLOR: #e7e7ce; + BORDER-BOTTOM: #ffffff 1px solid; + BORDER-LEFT: #ffffff 1px solid; + BORDER-RIGHT: #ffffff 1px solid; + BORDER-TOP: #ffffff 1px solid; + PADDING-LEFT: 3px +} +.issuecontent +{ + BACKGROUND-COLOR: #ffffff; + BORDER-BOTTOM: #dcdcdc 1px solid; + BORDER-TOP: #dcdcdc 1px solid; + PADDING-LEFT: 3px +} +A:link +{ + COLOR: #cc6633; + TEXT-DECORATION: underline +} +A:visited +{ + COLOR: #cc6633; +} +A:active +{ + COLOR: #cc6633; +} +A:hover +{ + COLOR: #cc3300; + TEXT-DECORATION: underline +} +H1 +{ + BACKGROUND-COLOR: #003366; + BORDER-BOTTOM: #336699 6px solid; + COLOR: #ffffff; + FONT-SIZE: 130%; + FONT-WEIGHT: normal; + MARGIN: 0em 0em 0em -20px; + PADDING-BOTTOM: 8px; + PADDING-LEFT: 30px; + PADDING-TOP: 16px +} +H2 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 3px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px; + PADDING-LEFT: 0px +} +H3 +{ + COLOR: #000000; + FONT-SIZE: 80%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: -5px; + MARGIN-LEFT: 10px; + MARGIN-TOP: 20px +} +H4 +{ + COLOR: #000000; + FONT-SIZE: 70%; + FONT-WEIGHT: bold; + MARGIN-BOTTOM: 0px; + MARGIN-TOP: 15px; + PADDING-BOTTOM: 0px +} +UL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +OL +{ + COLOR: #000000; + FONT-SIZE: 70%; + LIST-STYLE: square; + MARGIN-BOTTOM: 0pt; + MARGIN-TOP: 0pt +} +LI +{ + LIST-STYLE: square; + MARGIN-LEFT: 0px +} +.expandable +{ + CURSOR: hand +} +.expanded +{ + color: black +} +.collapsed +{ + DISPLAY: none +} +.foot +{ +BACKGROUND-COLOR: #ffffff; +BORDER-BOTTOM: #cecf9c 1px solid; +BORDER-TOP: #cecf9c 2px solid +} +.settings +{ +MARGIN-LEFT: 25PX; +} +.help +{ +TEXT-ALIGN: right; +margin-right: 10px; +} diff --git a/V12/_UpgradeReport_Files/UpgradeReport.xslt b/V12/_UpgradeReport_Files/UpgradeReport.xslt new file mode 100644 index 0000000..6fb44ed --- /dev/null +++ b/V12/_UpgradeReport_Files/UpgradeReport.xslt @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Projektmappe: + Projekt: + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + src + + + + + + + + + + + + +
DateinameStatusFehlerWarnungen
+ javascript:document.images[''].click()src + + + + Konvertiert + + + + Konvertiert + +
+ + Dateien + + + 1 Datei + + + Konvertiert:
+ Nicht konvertiert: +
+
+
+ + + + : + + + + + + + + + Konvertierungsbericht + <xsl:if test="Properties/Property[@Name='LogNumber']"> + <xsl:value-of select="Properties/Property[@Name='LogNumber']/@Value"/> + </xsl:if> + + + + +

Konvertierungsbericht -

+ +

+ Konvertierungsdauer:
+

+ + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + +
+ Konvertierungseinstellungen +

+ + +
+
diff --git a/V12/_UpgradeReport_Files/UpgradeReport_Minus.gif b/V12/_UpgradeReport_Files/UpgradeReport_Minus.gif new file mode 100644 index 0000000..17751cb Binary files /dev/null and b/V12/_UpgradeReport_Files/UpgradeReport_Minus.gif differ diff --git a/V12/_UpgradeReport_Files/UpgradeReport_Plus.gif b/V12/_UpgradeReport_Files/UpgradeReport_Plus.gif new file mode 100644 index 0000000..f6009ca Binary files /dev/null and b/V12/_UpgradeReport_Files/UpgradeReport_Plus.gif differ diff --git a/V12/bmp00001.bmp b/V12/bmp00001.bmp new file mode 100644 index 0000000..12d2027 Binary files /dev/null and b/V12/bmp00001.bmp differ diff --git a/V12/bmp00002.bmp b/V12/bmp00002.bmp new file mode 100644 index 0000000..92b8396 Binary files /dev/null and b/V12/bmp00002.bmp differ diff --git a/V12/ddutil.cpp b/V12/ddutil.cpp new file mode 100644 index 0000000..faccc24 --- /dev/null +++ b/V12/ddutil.cpp @@ -0,0 +1,1035 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: DirectDraw framewark classes. Feel free to use this class as a +// starting point for adding extra functionality. +// +// +// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include "ddutil.h" +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::CDisplay() +{ + m_pDD = NULL; + m_pddsFrontBuffer = NULL; + m_pddsBackBuffer = NULL; + m_pddsBackBufferLeft = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CDisplay() +// Desc: +//----------------------------------------------------------------------------- +CDisplay::~CDisplay() +{ + DestroyObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::DestroyObjects() +{ + SAFE_RELEASE( m_pddsBackBufferLeft ); + SAFE_RELEASE( m_pddsBackBuffer ); + SAFE_RELEASE( m_pddsFrontBuffer ); + + if( m_pDD ) + m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); + + SAFE_RELEASE( m_pDD ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateFullScreenDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, + DWORD dwHeight, DWORD dwBPP ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); + if( FAILED(hr) ) + return E_FAIL; + + // Set the display mode + if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) + return E_FAIL; + + // Create primary surface (with backbuffer attached) + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | + DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; + ddsd.dwBackBufferCount = 1; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, + NULL ) ) ) + return E_FAIL; + + // Get a pointer to the back buffer + DDSCAPS2 ddscaps; + ZeroMemory( &ddscaps, sizeof( ddscaps ) ); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + + if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, + &m_pddsBackBuffer ) ) ) + return E_FAIL; + + m_pddsBackBuffer->AddRef(); + + m_hWnd = hWnd; + m_bWindowed = FALSE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CreateWindowedDisplay() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) +{ + HRESULT hr; + + // Cleanup anything from a previous call + DestroyObjects(); + + // DDraw stuff begins here + if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, + IID_IDirectDraw7, NULL ) ) ) + return E_FAIL; + + // Set cooperative level + hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); + if( FAILED(hr) ) + return E_FAIL; + + RECT rcWork; + RECT rc; + DWORD dwStyle; + + // If we are still a WS_POPUP window we should convert to a normal app + // window so we look like a windows app. + dwStyle = GetWindowStyle( hWnd ); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + + // Aet window size + SetRect( &rc, 0, 0, dwWidth, dwHeight ); + + AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, + GetWindowExStyle(hWnd) ); + + SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + + // Make sure our window does not hang outside of the work area + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); + GetWindowRect( hWnd, &rc ); + if( rc.left < rcWork.left ) rc.left = rcWork.left; + if( rc.top < rcWork.top ) rc.top = rcWork.top; + SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); + + LPDIRECTDRAWCLIPPER pcClipper; + + // Create the primary surface + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) + return E_FAIL; + + // Create the backbuffer surface + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) + return E_FAIL; + + if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) + { + pcClipper->Release(); + return E_FAIL; + } + + // Done with clipper + pcClipper->Release(); + + m_hWnd = hWnd; + m_bWindowed = TRUE; + UpdateBounds(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurface( CSurface** ppSurface, + DWORD dwWidth, DWORD dwHeight ) +{ + if( NULL == m_pDD ) + return E_POINTER; + if( NULL == ppSurface ) + return E_INVALIDARG; + + HRESULT hr; + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof( ddsd ) ); + ddsd.dwSize = sizeof( ddsd ); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = dwWidth; + ddsd.dwHeight = dwHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromBitmap() +// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. +// Use MAKEINTRESOURCE() to pass a constant into strBMP. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, + TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ) +{ + HRESULT hr; + HBITMAP hBMP = NULL; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + + if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = bmp.bmWidth; + ddsd.dwHeight = bmp.bmHeight; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + // Draw the bitmap on this surface + if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::CreateSurfaceFromText() +// Desc: Creates a DirectDrawSurface from a text string using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, + HFONT hFont, TCHAR* strText, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + LPDIRECTDRAWSURFACE7 pDDS = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + SIZE sizeText; + + if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) + return E_INVALIDARG; + + *ppSurface = NULL; + + hDC = GetDC( NULL ); + + if( hFont ) + SelectObject( hDC, hFont ); + + GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); + ReleaseDC( NULL, hDC ); + + // Create a DirectDrawSurface for this bitmap + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = sizeText.cx; + ddsd.dwHeight = sizeText.cy; + + (*ppSurface) = new CSurface(); + if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) + { + delete (*ppSurface); + return hr; + } + + if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, + crBackground, crForeground ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Present() +{ + HRESULT hr; + + if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) + return E_POINTER; + + while( 1 ) + { + if( m_bWindowed ) + hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, + NULL, DDBLT_WAIT, NULL ); + else + hr = m_pddsFrontBuffer->Flip( NULL, 0 ); + + if( hr == DDERR_SURFACELOST ) + { + m_pddsFrontBuffer->Restore(); + m_pddsBackBuffer->Restore(); + } + + if( hr != DDERR_WASSTILLDRAWING ) + return hr; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Set the palette before loading the bitmap + if( pPalette ) + m_pddsFrontBuffer->SetPalette( pPalette ); + + CSurface backBuffer; + backBuffer.Create( m_pddsBackBuffer ); + + if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) + return E_FAIL; + + return Present(); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, + DWORD dwFlags ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) +{ + if( NULL == pSurface ) + return E_INVALIDARG; + + if( pSurface->IsColorKeyed() ) + return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); + else + return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::Clear( DWORD dwColor ) +{ + if( NULL == m_pddsBackBuffer ) + return E_POINTER; + + // Erase the background + DDBLTFX ddbltfx; + ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); + ddbltfx.dwSize = sizeof(ddbltfx); + ddbltfx.dwFillColor = dwColor; + + return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) +{ + if( NULL == m_pddsFrontBuffer ) + return E_POINTER; + + return m_pddsFrontBuffer->SetPalette( pPalette ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, + const TCHAR* strBMP ) +{ + HRSRC hResource = NULL; + RGBQUAD* pRGB = NULL; + BITMAPINFOHEADER* pbi = NULL; + PALETTEENTRY aPalette[256]; + HANDLE hFile = NULL; + DWORD iColor; + DWORD dwColors; + BITMAPFILEHEADER bf; + BITMAPINFOHEADER bi; + DWORD dwBytesRead; + + if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) + return E_INVALIDARG; + + *ppPalette = NULL; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hResource = FindResource( NULL, strBMP, RT_BITMAP ); + if( hResource ) + { + pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); + if( NULL == pbi ) + return E_FAIL; + + pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); + + // Figure out how many colors there are + if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if( pbi->biBitCount > 8 ) + dwColors = 0; + else if( pbi->biClrUsed == 0 ) + dwColors = 1 << pbi->biBitCount; + else + dwColors = pbi->biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around. + for( iColor = 0; iColor < dwColors; iColor++ ) + { + aPalette[iColor].peRed = pRGB[iColor].rgbRed; + aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; + aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; + aPalette[iColor].peFlags = 0; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); + } + + // Attempt to load bitmap as a file + hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if( NULL == hFile ) + return E_FAIL; + + // Read the BITMAPFILEHEADER + ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bf) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the BITMAPINFOHEADER + ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(bi) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + // Read the PALETTEENTRY + ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); + if( dwBytesRead != sizeof(aPalette) ) + { + CloseHandle( hFile ); + return E_FAIL; + } + + CloseHandle( hFile ); + + // Figure out how many colors there are + if( bi.biSize != sizeof(BITMAPINFOHEADER) ) + dwColors = 0; + else if (bi.biBitCount > 8) + dwColors = 0; + else if (bi.biClrUsed == 0) + dwColors = 1 << bi.biBitCount; + else + dwColors = bi.biClrUsed; + + // A DIB color table has its colors stored BGR not RGB + // so flip them around since DirectDraw uses RGB + for( iColor = 0; iColor < dwColors; iColor++ ) + { + BYTE r = aPalette[iColor].peRed; + aPalette[iColor].peRed = aPalette[iColor].peBlue; + aPalette[iColor].peBlue = r; + } + + return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::UpdateBounds() +{ + if( m_bWindowed ) + { + GetClientRect( m_hWnd, &m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); + ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); + } + else + { + SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN) ); + } + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CDisplay::InitClipper +// Desc: +//----------------------------------------------------------------------------- +HRESULT CDisplay::InitClipper() +{ + LPDIRECTDRAWCLIPPER pClipper; + HRESULT hr; + + // Create a clipper when using GDI to draw on the primary surface + if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) + return hr; + + pClipper->SetHWnd( 0, m_hWnd ); + + if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) + return hr; + + // We can release the clipper now since g_pDDSPrimary + // now maintains a ref count on the clipper + SAFE_RELEASE( pClipper ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::CSurface() +{ + m_pdds = NULL; + m_bColorKeyed = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +CSurface::~CSurface() +{ + SAFE_RELEASE( m_pdds ); +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) +{ + m_pdds = pdds; + + if( m_pdds ) + { + m_pdds->AddRef(); + + // Get the DDSURFACEDESC structure for this surface + m_ddsd.dwSize = sizeof(m_ddsd); + m_pdds->GetSurfaceDesc( &m_ddsd ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) +{ + HRESULT hr; + + // Create the DDraw surface + if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) + return hr; + + // Prepare the DDSURFACEDESC structure + m_ddsd.dwSize = sizeof(m_ddsd); + + // Get the DDSURFACEDESC structure for this surface + m_pdds->GetSurfaceDesc( &m_ddsd ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::Destroy() +{ + SAFE_RELEASE( m_pdds ); + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawBitmap() +// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the +// bitmap if nessasary +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( HBITMAP hBMP, + DWORD dwBMPOriginX, DWORD dwBMPOriginY, + DWORD dwBMPWidth, DWORD dwBMPHeight ) +{ + HDC hDCImage; + HDC hDC; + BITMAP bmp; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + if( hBMP == NULL || m_pdds == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + // Get the surface.description + ddsd.dwSize = sizeof(ddsd); + m_pdds->GetSurfaceDesc( &ddsd ); + + if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) + return E_NOTIMPL; + + // Select bitmap into a memoryDC so we can use it. + hDCImage = CreateCompatibleDC( NULL ); + if( NULL == hDCImage ) + return E_FAIL; + + SelectObject( hDCImage, hBMP ); + + // Get size of the bitmap + GetObject( hBMP, sizeof(bmp), &bmp ); + + // Use the passed size, unless zero + dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; + dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; + + // Stretch the bitmap to cover this surface + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + StretchBlt( hDC, 0, 0, + ddsd.dwWidth, ddsd.dwHeight, + hDCImage, dwBMPOriginX, dwBMPOriginY, + dwBMPWidth, dwBMPHeight, SRCCOPY ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + DeleteDC( hDCImage ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::DrawText() +// Desc: Draws a text string on a DirectDraw surface using hFont or the default +// GDI font if hFont is NULL. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, + DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ) +{ + HDC hDC = NULL; + HRESULT hr; + + if( m_pdds == NULL || strText == NULL ) + return E_INVALIDARG; + + // Make sure this surface is restored. + if( FAILED( hr = m_pdds->Restore() ) ) + return hr; + + if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) + return hr; + + // Set the background and foreground color + SetBkColor( hDC, crBackground ); + SetTextColor( hDC, crForeground ); + + if( hFont ) + SelectObject( hDC, hFont ); + + // Use GDI to draw the text on the surface + TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); + + if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) + return hr; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ReDrawBitmapOnSurface() +// Desc: Load a bitmap from a file or resource into a DirectDraw surface. +// normaly used to re-load a surface after a restore. +//----------------------------------------------------------------------------- +HRESULT CSurface::DrawBitmap( TCHAR* strBMP, + DWORD dwDesiredWidth, DWORD dwDesiredHeight ) +{ + HBITMAP hBMP; + HRESULT hr; + + if( m_pdds == NULL || strBMP == NULL ) + return E_INVALIDARG; + + // Try to load the bitmap as a resource, if that fails, try it as a file + hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, + IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, + LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + { + hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, + dwDesiredWidth, dwDesiredHeight, + LR_LOADFROMFILE | LR_CREATEDIBSECTION ); + if( hBMP == NULL ) + return E_FAIL; + } + + // Draw the bitmap on this surface + if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) + { + DeleteObject( hBMP ); + return hr; + } + + DeleteObject( hBMP ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSurface::SetColorKey( DWORD dwColorKey ) +{ + if( NULL == m_pdds ) + return E_POINTER; + + m_bColorKeyed = TRUE; + + DDCOLORKEY ddck; + ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); + ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); + + return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::ConvertGDIColor() +// Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a +// DirectDrawSurface using its pixel format. +//----------------------------------------------------------------------------- +DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) +{ + if( m_pdds == NULL ) + return 0x00000000; + + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hr; + + // Use GDI SetPixel to color match for us + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) + { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, dwGDIColor); // Set our value + m_pdds->ReleaseDC(hdc); + } + + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); + if( hr == DD_OK) + { + dw = *(DWORD *) ddsd.lpSurface; + if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp + dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; + m_pdds->Unlock(NULL); + } + + // Now put the color that was there back. + if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) + { + SetPixel( hdc, 0, 0, rgbT ); + m_pdds->ReleaseDC(hdc); + } + + return dw; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSurface::GetBitMaskInfo() +// Desc: Returns the number of bits and the shift in the bit mask +//----------------------------------------------------------------------------- +HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) +{ + DWORD dwShift = 0; + DWORD dwBits = 0; + + if( pdwShift == NULL || pdwBits == NULL ) + return E_INVALIDARG; + + if( dwBitMask ) + { + while( (dwBitMask & 1) == 0 ) + { + dwShift++; + dwBitMask >>= 1; + } + } + + while( (dwBitMask & 1) != 0 ) + { + dwBits++; + dwBitMask >>= 1; + } + + *pdwShift = dwShift; + *pdwBits = dwBits; + + return S_OK; +} + + + + diff --git a/V12/ddutil.h b/V12/ddutil.h new file mode 100644 index 0000000..61fb0be --- /dev/null +++ b/V12/ddutil.h @@ -0,0 +1,140 @@ +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +// front and back buffers, creating offscreen surfaces and palettes, +// and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: + LPDIRECTDRAW7 m_pDD; + LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; + LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + + HWND m_hWnd; + RECT m_rcWindow; + BOOL m_bWindowed; + BOOL m_bStereo; + +public: + CDisplay(); + ~CDisplay(); + + // Access functions + HWND GetHWnd() { return m_hWnd; } + LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; } + LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; } + LPDIRECTDRAWSURFACE7 GetBackBufferLEft() { return m_pddsBackBufferLeft; } + + // Status functions + BOOL IsWindowed() { return m_bWindowed; } + BOOL IsStereo() { return m_bStereo; } + + // Creation/destruction methods + HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, + DWORD dwBPP ); + HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); + HRESULT InitClipper(); + HRESULT UpdateBounds(); + virtual HRESULT DestroyObjects(); + + // Methods to create child objects + HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, + DWORD dwHeight ); + HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, + DWORD dwDesiredWidth, + DWORD dwDesiredHeight ); + HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, + TCHAR* strText, + COLORREF crBackground, + COLORREF crForeground ); + HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + + // Display methods + HRESULT Clear( DWORD dwColor = 0L ); + HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc = NULL ); + HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, + RECT* prc=NULL, DWORD dwFlags=0 ); + HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); + HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); + HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); + HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ + LPDIRECTDRAWSURFACE7 m_pdds; + DDSURFACEDESC2 m_ddsd; + BOOL m_bColorKeyed; + +public: + LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } + BOOL IsColorKeyed() { return m_bColorKeyed; } + + HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0, + DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); + HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); + HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, + COLORREF crBackground, COLORREF crForeground ); + + HRESULT SetColorKey( DWORD dwColorKey ); + DWORD ConvertGDIColor( COLORREF dwGDIColor ); + static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + + HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); + HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); + HRESULT Destroy(); + + CSurface(); + ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/V12/dsutil.cpp b/V12/dsutil.cpp new file mode 100644 index 0000000..83c1512 --- /dev/null +++ b/V12/dsutil.cpp @@ -0,0 +1,1546 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.cpp +// +// Desc: DirectSound framework classes for reading and writing wav files and +// playing them in DirectSound buffers. Feel free to use this class +// as a starting point for adding extra functionality. +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "DSUtil.h" + +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel, + DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); + + // Set primary buffer format + SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = (WORD) dwPrimaryChannels; + wfx.nSamplesPerSec = dwPrimaryFreq; + wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) + return DXTRACE_ERR( TEXT("SetFormat"), hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + (VOID**)ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED(hr) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN (100ms) and the buffer is created + // with DSBCAPS_CTRLFX. + if( hr != DSERR_BUFFERTOOSMALL ) + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + goto LFail; + } + + for( i=1; iDuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); + goto LFail; + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile ); + + SAFE_DELETE( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE( apDSBuffer ); + return hr; +} + + + + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPTSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); + + return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + (VOID**)&pDSNotify ) ) ) + { + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("QueryInterface"), hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile ) +{ + DWORD i; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + for( i=0; iSetCurrentPosition(0); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i=0; iLock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED(hr) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXTRACE_ERR( TEXT("GetStatus"), hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } + while( hr = pDSB->Restore() ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + BOOL bIsPlaying = FALSE; + DWORD i; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( i=0; iGetStatus( &dwStatus ); + if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + (VOID**)ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + + // Make DirectSound do pre-processing on sound effects + Reset(); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iStop(); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i=0; iSetCurrentPosition( 0 ); + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i=0; iGetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) + : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tell us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXTRACE_ERR( TEXT("Lock"), hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXTRACE_ERR( TEXT("Read"), hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // passed the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("FindResource"), E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) + return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); + + CHAR* pData = new CHAR[ dwSize ]; + memcpy( pData, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = (CHAR*) pData; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( TEXT("ResetFile"), hr ); + } + + return hr; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Check to make sure this is a valid wave file + if( (m_ckRiff.ckid != FOURCC_RIFF) || + (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) + return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) + return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, + sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + + m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( TEXT("new"), E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), + SEEK_SET ) ) + return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( (BYTE*)(m_pbDataCur + dwSizeToRead) > + (BYTE*)(m_pbData + m_ulDataSize) ) + { + dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); + } + + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); + } + + // Actual copy. + *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + if( pdwSizeRead != NULL ) + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); + + m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = (DWORD)-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); + m_ck.cksize = sizeof(PCMWAVEFORMAT); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + else + { + // Write the variable length size. + if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, + sizeof(*pwfxDest) + pwfxDest->cbSize ) != + ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); + + if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != + sizeof(dwFactChunk) ) + return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); + } + + *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); + (BYTE*)m_mmioinfoOut.pchNext++; + + (*pnSizeWrote)++; + } + + return S_OK; +} + + + + diff --git a/V12/dsutil.h b/V12/dsutil.h new file mode 100644 index 0000000..57d26df --- /dev/null +++ b/V12/dsutil.h @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// File: DSUtil.h +// +// Desc: +// +// Copyright (c) 1999-2000 Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DSUTIL_H +#define DSUTIL_H + +#include +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +#define DSUtil_StopSound(s) { if(s) s->Stop(); } +#define DSUtil_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DSUtil_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + LPDIRECTSOUND8 m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + inline LPDIRECTSOUND GetDirectSound() { return m_pDS; } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, CWaveFile* pWaveFile ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority, DWORD dwFlags ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() { return m_pwfx; }; +}; + + + + +#endif // DSUTIL_H diff --git a/V12/resource.h b/V12/resource.h new file mode 100644 index 0000000..dd8c0cb --- /dev/null +++ b/V12/resource.h @@ -0,0 +1,95 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Demo.rc +// +#define IDI_MAIN 101 +#define IDR_MENU 102 +#define IDR_ACCEL 103 +#define IDD_HILFE 124 +#define IDD_KONFIGURATION 125 +#define IDB_STEIN 126 +#define IDD_HIGHSCORE 127 +#define IDD_SIEGEREHRUNG 128 +#define IDD_ULTRIS 129 +#define IDB_ULTRIS 130 +#define IDM_EXIT 1001 +#define IDC_ALLE 1005 +#define IDC_STANDARD 1006 +#define IDC_LOESCHEN 1007 +#define IDC_VORBELEGUNG 1008 +#define IDC_VORSCHAU 1009 +#define IDC_SCORE1 1010 +#define IDC_SCORE2 1011 +#define IDC_SCORE3 1012 +#define IDC_SCORE4 1013 +#define IDC_SCORE5 1014 +#define IDC_NAME1 1015 +#define IDC_NAME2 1016 +#define IDC_NAME 1016 +#define IDC_NAME3 1017 +#define IDC_SIEGERTEXT 1017 +#define IDC_WEITERE_INFO 1018 +#define IDC_NAME4 1018 +#define IDC_NAME5 1019 +#define IDC_CHECK1 5000 +#define IDC_CHECK2 5001 +#define IDC_CHECK3 5002 +#define IDC_CHECK4 5003 +#define IDC_CHECK5 5004 +#define IDC_CHECK6 5005 +#define IDC_CHECK7 5006 +#define IDC_CHECK8 5007 +#define IDC_CHECK9 5008 +#define IDC_CHECK10 5009 +#define IDC_CHECK11 5010 +#define IDC_CHECK12 5011 +#define IDC_CHECK13 5012 +#define IDC_CHECK14 5013 +#define IDC_CHECK15 5014 +#define IDC_CHECK16 5015 +#define IDC_CHECK17 5016 +#define IDC_CHECK18 5017 +#define IDC_CHECK19 5018 +#define IDC_CHECK20 5019 +#define IDC_CHECK21 5020 +#define IDC_CHECK22 5021 +#define IDC_CHECK23 5022 +#define IDC_CHECK24 5023 +#define IDC_CHECK25 5024 +#define IDC_CHECK26 5025 +#define IDC_CHECK27 5026 +#define IDC_CHECK28 5027 +#define IDC_CHECK29 5028 +#define IDC_CHECK30 5029 +#define IDC_CHECK31 5030 +#define IDC_CHECK32 5031 +#define IDC_CHECK33 5032 +#define IDC_CHECK34 5033 +#define IDC_CHECK35 5034 +#define IDM_TEST 40024 +#define ID_ULTRIS_NEUESSPIEL 40025 +#define ID_ULTRIS_PAUSE 40026 +#define ID_ULTRIS_SOUND 40027 +#define ID_EINSTELLUNGEN_KONFIGURATION 40028 +#define ID_INFO_HILFE 40029 +#define ID_INFO_HIGHSCORES 40030 +#define ID_INFO_ULTRIS 40031 +#define IDM_DOWN 40033 +#define IDM_SCHNELLER 40034 +#define IDM_LANGSAMER 40035 +#define IDM_DREHRECHTS 40036 +#define IDM_DREHLINKS 40037 +#define IDM_LINKS 40038 +#define IDM_RECHTS 40039 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 133 +#define _APS_NEXT_COMMAND_VALUE 40040 +#define _APS_NEXT_CONTROL_VALUE 1019 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/V12/ul_adeck.bmp b/V12/ul_adeck.bmp new file mode 100644 index 0000000..5f3b867 Binary files /dev/null and b/V12/ul_adeck.bmp differ diff --git a/V12/ul_down.wav b/V12/ul_down.wav new file mode 100644 index 0000000..84cf9e1 Binary files /dev/null and b/V12/ul_down.wav differ diff --git a/V12/ul_dreh.WAV b/V12/ul_dreh.WAV new file mode 100644 index 0000000..790ef8c Binary files /dev/null and b/V12/ul_dreh.WAV differ diff --git a/V12/ul_ende.WAV b/V12/ul_ende.WAV new file mode 100644 index 0000000..43c73f0 Binary files /dev/null and b/V12/ul_ende.WAV differ diff --git a/V12/ul_feld.bmp b/V12/ul_feld.bmp new file mode 100644 index 0000000..3225b6b Binary files /dev/null and b/V12/ul_feld.bmp differ diff --git a/V12/ul_hgrnd.bmp b/V12/ul_hgrnd.bmp new file mode 100644 index 0000000..c33b077 Binary files /dev/null and b/V12/ul_hgrnd.bmp differ diff --git a/V12/ul_high.dat b/V12/ul_high.dat new file mode 100644 index 0000000..335d7ac --- /dev/null +++ b/V12/ul_high.dat @@ -0,0 +1,5 @@ +230,asd +86,Ulrich Kaiser +84, +82, +0,Glückwunsch, du hast mit 112 Punkten d diff --git a/V12/ul_move.WAV b/V12/ul_move.WAV new file mode 100644 index 0000000..22b2a99 Binary files /dev/null and b/V12/ul_move.WAV differ diff --git a/V12/ul_prev.bmp b/V12/ul_prev.bmp new file mode 100644 index 0000000..c791074 Binary files /dev/null and b/V12/ul_prev.bmp differ diff --git a/V12/ul_row1.WAV b/V12/ul_row1.WAV new file mode 100644 index 0000000..ab5bfca Binary files /dev/null and b/V12/ul_row1.WAV differ diff --git a/V12/ul_row2.WAV b/V12/ul_row2.WAV new file mode 100644 index 0000000..671fc71 Binary files /dev/null and b/V12/ul_row2.WAV differ diff --git a/V12/ul_start.WAV b/V12/ul_start.WAV new file mode 100644 index 0000000..f66bfef Binary files /dev/null and b/V12/ul_start.WAV differ diff --git a/V12/ul_stein.bmp b/V12/ul_stein.bmp new file mode 100644 index 0000000..dadb7a0 Binary files /dev/null and b/V12/ul_stein.bmp differ diff --git a/V12/ul_win.wav b/V12/ul_win.wav new file mode 100644 index 0000000..e11c880 Binary files /dev/null and b/V12/ul_win.wav differ diff --git a/V12/ul_z0.bmp b/V12/ul_z0.bmp new file mode 100644 index 0000000..10fe8a6 Binary files /dev/null and b/V12/ul_z0.bmp differ diff --git a/V12/ul_z1.bmp b/V12/ul_z1.bmp new file mode 100644 index 0000000..1ce2939 Binary files /dev/null and b/V12/ul_z1.bmp differ diff --git a/V12/ul_z2.bmp b/V12/ul_z2.bmp new file mode 100644 index 0000000..9006084 Binary files /dev/null and b/V12/ul_z2.bmp differ diff --git a/V12/ul_z3.bmp b/V12/ul_z3.bmp new file mode 100644 index 0000000..5710c67 Binary files /dev/null and b/V12/ul_z3.bmp differ diff --git a/V12/ul_z4.bmp b/V12/ul_z4.bmp new file mode 100644 index 0000000..11306ed Binary files /dev/null and b/V12/ul_z4.bmp differ diff --git a/V12/ul_z5.bmp b/V12/ul_z5.bmp new file mode 100644 index 0000000..b4a22b5 Binary files /dev/null and b/V12/ul_z5.bmp differ diff --git a/V12/ul_z6.bmp b/V12/ul_z6.bmp new file mode 100644 index 0000000..62616d4 Binary files /dev/null and b/V12/ul_z6.bmp differ diff --git a/V12/ul_z7.bmp b/V12/ul_z7.bmp new file mode 100644 index 0000000..d9178df Binary files /dev/null and b/V12/ul_z7.bmp differ diff --git a/V12/ul_z8.bmp b/V12/ul_z8.bmp new file mode 100644 index 0000000..98e1a18 Binary files /dev/null and b/V12/ul_z8.bmp differ diff --git a/V12/ul_z9.bmp b/V12/ul_z9.bmp new file mode 100644 index 0000000..e6245a3 Binary files /dev/null and b/V12/ul_z9.bmp differ