Initial commit.

This commit is contained in:
Jim Gray
2013-04-04 14:32:05 -07:00
parent ba5c81da32
commit d71d53e8ec
2180 changed files with 1393544 additions and 1 deletions

79
code/win32/AutoVersion.h Normal file
View File

@@ -0,0 +1,79 @@
#ifndef __AUTO_VERSION_HEADER
#define __AUTO_VERSION_HEADER
#define VERSION_MAJOR_RELEASE 1
#define VERSION_MINOR_RELEASE 0
#define VERSION_EXTERNAL_BUILD 0
#define VERSION_INTERNAL_BUILD 0
#define VERSION_STRING "1, 0, 0, 0"
#define VERSION_STRING_DOTTED "1.0.0.0"
#define VERSION_BUILD_NUMBER 73
// BEGIN COMMENTS
// 1.0.0.0 07/21/2003 16:09:23 jmonroe going gold
// 0.0.12.0 07/20/2003 19:04:44 jmonroe build 0.12 for qa
// 0.0.11.0 07/19/2003 15:30:08 jmonroe stuff
// 0.0.11.0 07/17/2003 17:08:09 jmonroe build 0.11 for qa
// 0.0.10.1 07/16/2003 17:33:28 mgummelt General Update With Latest Code
// 0.0.10.0 07/16/2003 10:28:51 jmonroe new product id, remove outcast.roq at end, menu ignoreescape, eax looping sounds support chan_less_atten
// 0.0.10.0 07/14/2003 19:04:42 jmonroe build 0.10 for qa
// 0.0.9.0 07/12/2003 13:05:57 jmonroe increase numsnapshot ents
// 0.0.9.0 07/11/2003 17:48:40 jmonroe buil 0.09 for qa
// 0.0.8.4 07/11/2003 15:47:55 jmonroe weatherzone caching
// 0.0.8.3 07/11/2003 12:05:44 mgummelt Lava & Acid fixes
// 0.0.8.2 07/10/2003 17:26:42 mgummelt General Update with today's bug fixes
// 0.0.8.1 07/09/2003 19:24:19 jmonroe eax voice stomp fix, increased weather zones, ...
// 0.0.8.0 07/08/2003 17:28:27 jmonroe build 0.08 for qa
// 0.0.7.2 07/07/2003 16:28:40 mgummelt Blaster Pistol alt-fire returns, Rancor spawnflags corrected
// 0.0.7.1 07/07/2003 10:48:29 jmonroe load menu fixes, darkside autoload fix,...
// 0.0.7.0 07/02/2003 19:31:37 jmonroe buil 7 for qa
// 0.0.6.5 07/02/2003 18:17:17 mgummelt Boss balancing
// 0.0.6.3 07/02/2003 01:34:48 jmonroe saber in moves menu
// 0.0.6.2 06/30/2003 15:33:37 mgummelt Force Sight change (designers readme)
// 0.0.6.1 06/29/2003 19:00:17 jmonroe vv merged, aev_soundchan
// 0.0.6.0 06/28/2003 16:38:27 jmonroe eax update, force sight on key dudes
// 0.0.6.0 06/26/2003 16:45:26 jmonroe qa build
// 0.0.5.6 06/25/2003 21:22:38 mgummelt "redcrosshair" field on misc_model_breakables and func_breakables
// 0.0.5.5 06/25/2003 18:31:52 mgummelt Force Visible on all applicable ents
// 0.0.5.4 06/25/2003 10:45:12 jmonroe EAX 4.0
// 0.0.5.3 06/24/2003 22:59:31 mgummelt Reborn tweaks
// 0.0.5.2 06/24/2003 18:53:55 mgummelt New Reborn Master
// 0.0.5.1 06/23/2003 20:47:44 jmonroe fix NULL NPC usage
// 0.0.5.0 06/21/2003 13:04:27 jmonroe fix eweb crash
// 0.0.4.2 06/18/2003 14:24:35 jmonroe script cmd SET_WEAPON now precaches weapon, gil's optimized dlights
// 0.0.4.1 06/17/2003 19:04:28 mgummelt Various Force Power, saber move & Enemy Jedi tweaks
// 0.0.4.0 06/16/2003 19:41:54 jmonroe bug stuff
// 0.0.4.0 06/13/2003 23:52:36 jmonroe inc version to match qa beta
// 0.0.2.6 06/12/2003 13:11:21 creed new z-far cull
// 0.0.2.5 06/10/2003 17:02:17 creed targetJump & other navigation
// 0.0.2.4 06/10/2003 11:18:58 jmonroe footstep sounds in per material
// 0.0.2.3 06/10/2003 01:37:10 mgummelt helping with entity limit at spawntime
// 0.0.2.2 06/09/2003 14:10:32 scork fix for asian languages being bust by bad font
// 0.0.2.1 06/08/2003 17:57:11 mgummelt Area portal fix
// 0.0.2.0 06/08/2003 14:02:03 mgummelt Force sight change
// 0.0.2.0 06/08/2003 00:03:58 jmonroe CGEN_LIGHTING_DIFFUSE_ENTITY merges lightingdiffuse and entity color
// 0.0.1.25 06/05/2003 20:51:30 mgummelt Saber pull-attacks done
// 0.0.1.24 06/05/2003 18:11:06 mgummelt Both saber control schemes implemented
// 0.0.1.23 05/30/2003 17:12:34 mgummelt Fixed Noghri and Sand Creature
// 0.0.1.22 05/30/2003 12:15:37 mgummelt Saboteur change, new cultist
// 0.0.1.21 05/29/2003 16:02:48 creed Fixes For Assassin, ST AI changes
// 0.0.1.20 05/29/2003 12:00:18 mgummelt Navigation changes
// 0.0.1.19 05/29/2003 11:08:06 mgummelt various tweaks
// 0.0.1.18 05/28/2003 22:08:16 creed Boba Fett ++
// 0.0.1.17 05/28/2003 20:38:33 mgummelt force grip and force sense changes
// 0.0.1.15 05/28/2003 17:07:26 mgummelt tweaks of force drain, protect and absorb
// 0.0.1.14 05/28/2003 14:48:57 mgummelt various saber & AI fixes
// 0.0.1.13 05/27/2003 17:26:30 areis Ported Glow stuff from MP (with support for nVidia and ATI cards). Added solid flag for roffs (in behaved) and made tie-bombers explode with effect.
// 0.0.1.12 05/27/2003 13:06:03 mgummelt Noghri stick weapon shoots a projectile, E-Web uses proper sounds
// 0.0.1.7 05/19/2003 15:00:10 mgummelt adding random jedi, elder prisoners, jedi master
// 0.0.1.6 05/19/2003 09:22:18 creed Weather Effects & Haz Trooper
// 0.0.1.5 05/16/2003 18:55:10 creed New Wind Spawn Flags For Dusty Fog & 1/2 way through Haz Trooper Fixins
// 0.0.1.4 05/15/2003 14:29:35 jmonroe misc_model_static stay around after a vid_start
// 0.0.1.3 05/14/2003 17:53:44 mgummelt testing misc_model_breakable scaling
// 0.0.1.2 05/13/2003 20:48:35 jmonroe vv post merge
// 0.0.1.1 05/13/2003 14:17:20 scork ste test comment
// END COMMENTS
#endif // __AUTO_VERSION_HEADER

View File

@@ -0,0 +1,247 @@
/**********************************************************************
Copyright (c) 1999 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FEELitIFR.h
PURPOSE: Input/Output for IFR Files, FEELit version
STARTED:
NOTES/REVISIONS:
**********************************************************************/
#if !defined( _FEELIT2_H_)
#define _FEELIT2_H_
#ifndef __FEELITAPI_INCLUDED__
#error include 'dinput.h' before including this file for structures.
#endif /* !__DINPUT_INCLUDED__ */
#define IFRAPI __stdcall
#if !defined(_FFCDLL_)
#define DLLAPI __declspec(dllimport)
#else
#define DLLAPI __declspec(dllexport)
#endif
#if defined __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
** CONSTANTS
*/
/*
** RT_FEELIT - Resource type for IFR projects stored as resources.
** This is the resource type looked for by IFLoadProjectResource().
*/
#define RT_FEELIT ((LPCSTR)"FEELIT")
/*
** TYPES/STRUCTURES
*/
/*
** HIFRPROJECT - used to identify a loaded project as a whole.
** individual objects within a project are uniquely referenced by name.
** Created by the IFLoadProject*() functions and released by IFReleaseProject().
*/
typedef LPVOID HIFRPROJECT;
/*
** IFREffect - contains the information needed to create a DI effect
** using IDirectInputEffect::CreateEffect(). An array of pointers to these
** structures is allocated and returned by IFCreateEffectStructs().
*/
typedef struct {
GUID guid;
LPFEELIT_EFFECT lpDIEffect;
} IFREffect;
/*
** FUNCTION DECLARATIONS
*/
/*
** IFLoadProjectResource() - Load a project from a resource.
** hRsrcModule - handle of the module containing the project definition resource.
** pRsrcName - name or MAKEINTRESOURCE(id) identifier of resource to load.
** pDevice - device for which the project is being loaded. If NULL,
** effects will be created generically, and IFCreateEffects() will fail.
** Returns an identifier for the loaded project, or NULL if unsuccessful.
*/
DLLAPI
HIFRPROJECT
IFRAPI
IFRLoadProjectResource(
HMODULE hRsrcModule,
LPCSTR pRsrcName,
LPIFEELIT_DEVICE pDevice );
/*
** IFLoadProjectPointer() - Load a project from a pointer.
** pProject - points to a project definition.
** pDevice - device for which the project is being loaded. If NULL,
** effects will be created generically, and IFCreateEffects() will fail.
** Returns an identifier for the loaded project, or NULL if unsuccessful.
*/
DLLAPI
HIFRPROJECT
IFRAPI
IFRLoadProjectPointer(
LPVOID pProject,
LPIFEELIT_DEVICE pDevice );
/*
** IFLoadProjectFile() - Load a project from a file.
** pProjectFileName - points to a project file name.
** pDevice - device for which the project is being loaded. If NULL,
** effects will be created generically, and IFCreateEffects() will fail.
** Returns an identifier for the loaded project, or NULL if unsuccessful.
*/
DLLAPI
HIFRPROJECT
IFRAPI
IFRLoadProjectFile(
LPCSTR pProjectFileName,
LPIFEELIT_DEVICE pDevice );
/*
** IFLoadProjectObjectPointer() - Load a project from a pointer to a single
** object definition (usually used only by the editor).
** pObject - points to an object definition.
** pDevice - device for which the project is being loaded. If NULL,
** effects will be created generically, and IFCreateEffects() will fail.
** Returns an identifier for the loaded project, or NULL if unsuccessful.
*/
DLLAPI
HIFRPROJECT
IFRAPI
IFRLoadProjectObjectPointer(
LPVOID pObject,
LPIFEELIT_DEVICE pDevice );
/*
** IFReleaseProject() - Release a loaded project.
** hProject - identifies the project to be released.
** Returns TRUE if the project is released, FALSE if it is an invalid project.
*/
DLLAPI
BOOL
IFRAPI
IFRReleaseProject(
HIFRPROJECT hProject );
/*
** IFCreateEffectStructs() - Create IFREffects for a named effect.
** hProject - identifies the project containing the object.
** pObjectName - name of the object for which to create structures.
** pNumEffects - if not NULL will be set to a count of the IFREffect
** structures in the array (not including the terminating NULL pointer.)
** Returns a pointer to the allocated array of pointers to IFREffect
** structures. The array is terminated with a NULL pointer. If the
** function fails, a NULL pointer is returned.
*/
DLLAPI
IFREffect **
IFRAPI
IFRCreateEffectStructs(
HIFRPROJECT hProject,
LPCSTR pObjectName,
int *pNumEffects );
DLLAPI
IFREffect **
IFRAPI
IFRCreateEffectStructsByIndex(
HIFRPROJECT hProject,
int nObjectIndex,
int *pNumEffects );
DLLAPI
LPCSTR
IFRAPI
IFRGetObjectNameByIndex(
HIFRPROJECT hProject,
int nObjectIndex );
/*
** IFReleaseEffectStructs() - Release an array of IFREffects.
** hProject - identifies the project for which the effects were created.
** pEffects - points to the array of IFREffect pointers to be released.
** Returns TRUE if the array is released, FALSE if it is an invalid array.
*/
DLLAPI
BOOL
IFRAPI
IFRReleaseEffectStructs(
HIFRPROJECT hProject,
IFREffect **pEffects );
/*
** IFCreateEffects() - Creates the DirectInput effects using
** IDirectInput::CreateEffect().
** hProject - identifies the project containing the object.
** pObjectName - name of the object for which to create effects.
** pNumEffects - if not NULL will be set to a count of the IDirectInputEffect
** pointers in the array (not including the terminating NULL pointer.)
** Returns a pointer to the allocated array of pointers to IDirectInputEffects.
** The array is terminated with a NULL pointer. If the function fails,
** a NULL pointer is returned.
*/
DLLAPI
LPIFEELIT_EFFECT *
IFRAPI
IFRCreateEffects(
HIFRPROJECT hProject,
LPCSTR pObjectName,
int *pNumEffects );
/*
** IFReleaseEffects() - Releases an array of IDirectInputEffect structures.
** hProject - identifies the project for which the effects were created.
** pEffects - points to the array if IDirectInputEffect pointers to be released.
** Returns TRUE if the array is released, FALSE if it is an invalid array.
*/
DLLAPI
BOOL
IFRAPI
IFRReleaseEffects(
HIFRPROJECT hProject,
LPIFEELIT_EFFECT *pEffects );
DLLAPI
BOOL
IFRAPI
DllMain(
HINSTANCE hInstDLL,
DWORD fdwReason,
LPVOID lpvReserved );
#if defined __cplusplus
}
#endif /* __cplusplus */
#endif /* !IForce2_h */

78
code/win32/FeelIt/FFC.h Normal file
View File

@@ -0,0 +1,78 @@
/**********************************************************************
Copyright (c) 1997,8,9 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FFC.h
PURPOSE: Class Types for the Force Foundation Classes
STARTED: 10/29/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
**********************************************************************/
#if !defined(AFX_FFC_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FFC_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include "FeelBox.h"
#include "FeelCondition.h"
#include "FeelConstant.h"
#include "FeelDamper.h"
#include "FeelDevice.h"
#include "FeelDXDevice.h"
#include "FeelEffect.h"
#include "FeelEllipse.h"
#include "FeelEnclosure.h"
#include "FeelMouse.h"
#include "FeelFriction.h"
#include "FeelGrid.h"
#include "FeelInertia.h"
#include "FeelPeriodic.h"
#include "FeelProjects.h"
#include "FeelRamp.h"
#include "FeelSpring.h"
#include "FeelTexture.h"
#include "FFCErrors.h"
#endif // !defined(AFX_FFC_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

BIN
code/win32/FeelIt/FFC10.dll Normal file

Binary file not shown.

BIN
code/win32/FeelIt/FFC10.lib Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,171 @@
/**********************************************************************
Copyright (c) 1999 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FFCErrors.h
PURPOSE: Error codes returned in FFC; Error handling in FFC
STARTED: 2/28/99 by Jeff Mallett
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/6/99 jrm: Added user error handling control
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(FFCERRORS_H__INCLUDED_)
#define FFCERRORS_H__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include <winerror.h>
#include "FeelBaseTypes.h"
/****************************************************************************
*
* Error Codes
*
****************************************************************************/
typedef enum {
FFC_ERR_OK = 0,
FFC_ERR_UNKNOWN_ERROR = 1,
FFC_ERR_ALLOCATION_FAILED = 2,
FFC_ERR_INVALID_PARAMETER = 3,
FFC_ERR_NULL_PARAMETER = 4,
FFC_ERR_WRONG_FORM = 5,
FFC_ERR_DEVICE_IS_NULL = 6,
FFC_ERR_INVALID_GUID = 7,
FFC_ERR_EFFECT_NOT_INITIALIZED = 8,
FFC_ERR_CANT_INITIALIZE_DEVICE = 9,
FFC_ERR_CANT_CREATE_EFFECT = 10,
FFC_ERR_CANT_CREATE_EFFECT_FROM_IFR = 11,
FFC_ERR_NO_EFFECTS_FOUND = 12,
FFC_ERR_EFFECT_IS_COMPOUND = 13,
FFC_ERR_PROJECT_ALREADY_OPEN = 14,
FFC_ERR_PROJECT_NOT_OPEN = 15
} FFC_ERROR_CODE;
typedef enum {
FFC_OUTPUT_ERR_TO_DEBUG = 0x0001,
FFC_OUTPUT_ERR_TO_DIALOG = 0x0002
} FFC_ERROR_HANDLING_FLAGS;
/****************************************************************************
*
* Macros
*
****************************************************************************/
//
// ------ PUBLIC MACROS ------
//
#define FFC_GET_LAST_ERROR CFFCErrors::GetLastErrorCode()
#define FFC_SET_ERROR_HANDLING CFFCErrors::SetErrorHandling
//
// ------ PRIVATE MACROS ------
//
#if (FFC_VERSION >= 0x0110)
#define FFC_SET_ERROR(err) CFFCErrors::SetErrorCode(err, __FILE__, __LINE__)
#else
#define FFC_SET_ERROR(err) CFFCErrors::SetErrorCode(err)
#endif
#define FFC_CLEAR_ERROR FFC_SET_ERROR(FFC_ERR_OK)
/****************************************************************************
*
* CFFCErrors
*
****************************************************************************/
// All members are static. Don't bother instantiating an object of this class.
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFFCErrors
{
//
// ATTRIBUTES
//
public:
static HRESULT
GetLastErrorCode()
{ return m_Err; }
static void
SetErrorHandling(unsigned long dwFlags)
{ m_dwErrHandlingFlags = dwFlags; }
//
// ------ PRIVATE INTERFACE ------
//
// Internally used by FFC classes
static void
SetErrorCode(
HRESULT err
#if (FFC_VERSION >= 0x0110)
, const char *sFile, int nLine
#endif
);
//
// HELPERS
//
protected:
//
// INTERNAL DATA
//
private:
static HRESULT m_Err;
static unsigned long m_dwErrHandlingFlags;
};
#endif // FFCERRORS_H__INCLUDED_

View File

@@ -0,0 +1,265 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelBaseTypes.h
PURPOSE: Base Types for Feelit API Foundation Classes
STARTED: 10/29/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
**********************************************************************/
#if !defined(AFX_FEELBASETYPES_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELBASETYPES_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
//#include <windows.h>
#include "FeelitApi.h"
#ifndef FFC_VERSION
#define FFC_VERSION 0x0100
#endif
#if (FFC_VERSION >= 0x0110)
#define FFC_START_DELAY
#define FFC_EFFECT_CACHING
#endif
// These are defined in FEELitAPI.h
//
// #define FEELIT_DEVICETYPE_DEVICE 1
// #define FEELIT_DEVICETYPE_MOUSE 2
// #define FEELIT_DEVICETYPE_HID 0x00010000
//
// Add define for DirectInput Device emulating FEELit Device
#define FEELIT_DEVICETYPE_DIRECTINPUT 3
//================================================================
// TYPE WRAPPERS
//================================================================
//
// FEEL --> FEELIT Wrappers
//
#define FEEL_DEVICETYPE_DEVICE FEELIT_DEVICETYPE_DEVICE
#define FEEL_DEVICETYPE_MOUSE FEELIT_DEVICETYPE_MOUSE
#define FEEL_DEVICETYPE_DIRECTINPUT FEELIT_DEVICETYPE_DIRECTINPUT
#define FEEL_EFFECT FEELIT_EFFECT
#define LPFEEL_EFFECT LPFEELIT_EFFECT
#define LPCFEEL_EFFECT LPCFEELIT_EFFECT
#define FEEL_CONDITION FEELIT_CONDITION
#define LPFEEL_CONDITION LPFEELIT_CONDITION
#define LPCFEEL_CONDITION LPCFEELIT_CONDITION
#define FEEL_TEXTURE FEELIT_TEXTURE
#define LPFEEL_TEXTURE LPFEELIT_TEXTURE
#define LPCFEEL_TEXTURE LPCFEELIT_TEXTURE
#define FEEL_PERIODIC FEELIT_PERIODIC
#define LPFEEL_PERIODIC LPFEELIT_PERIODIC
#define LPCFEEL_PERIODIC LPCFEELIT_PERIODIC
#define FEEL_CONSTANTFORCE FEELIT_CONSTANTFORCE
#define LPFEEL_CONSTANTFORCE LPFEELIT_CONSTANTFORCE
#define LPCFEEL_CONSTANTFORCE LPCFEELIT_CONSTANTFORCE
#define FEEL_RAMPFORCE FEELIT_RAMPFORCE
#define LPFEEL_RAMPFORCE LPFEELIT_RAMPFORCE
#define LPCFEEL_RAMPFORCE LPCFEELIT_RAMPFORCE
#define FEEL_ENVELOPE FEELIT_ENVELOPE
#define LPFEEL_ENVELOPE LPFEELIT_ENVELOPE
#define LPCFEEL_ENVELOPE LPCFEELIT_ENVELOPE
#define LPIFEEL_API LPIFEELIT
#define LPIFEEL_EFFECT LPIFEELIT_EFFECT
#define LPIFEEL_DEVICE LPIFEELIT_DEVICE
#define LPFEEL_DEVICEINSTANCE LPFEELIT_DEVICEINSTANCE
#define LPCFEEL_DEVICEOBJECTINSTANCE LPCFEELIT_DEVICEOBJECTINSTANCE
#define LPCFEEL_EFFECTINFO LPCFEELIT_EFFECTINFO
#define FEEL_FPARAM_DURATION FEELIT_FPARAM_DURATION
#define FEEL_FPARAM_SAMPLEPERIOD FEELIT_FPARAM_SAMPLEPERIOD
#define FEEL_FPARAM_GAIN FEELIT_FPARAM_GAIN
#define FEEL_FPARAM_TRIGGERBUTTON FEELIT_FPARAM_TRIGGERBUTTON
#define FEEL_FPARAM_TRIGGERREPEATINTERVAL FEELIT_FPARAM_TRIGGERREPEATINTERVAL
#define FEEL_FPARAM_AXES FEELIT_FPARAM_AXES
#define FEEL_FPARAM_DIRECTION FEELIT_FPARAM_DIRECTION
#define FEEL_FPARAM_ENVELOPE FEELIT_FPARAM_ENVELOPE
#define FEEL_FPARAM_TYPESPECIFICPARAMS FEELIT_FPARAM_TYPESPECIFICPARAMS
#define FEEL_FPARAM_ALLPARAMS FEELIT_FPARAM_ALLPARAMS
#define FEEL_FPARAM_START FEELIT_FPARAM_START
#define FEEL_FPARAM_NORESTART FEELIT_FPARAM_NORESTART
#define FEEL_FPARAM_NODOWNLOAD FEELIT_FPARAM_NODOWNLOAD
#define FEEL_FEFFECT_OBJECTIDS FEELIT_FEFFECT_OBJECTIDS
#define FEEL_FEFFECT_OBJECTOFFSETS FEELIT_FEFFECT_OBJECTOFFSETS
#define FEEL_FEFFECT_CARTESIAN FEELIT_FEFFECT_CARTESIAN
#define FEEL_FEFFECT_POLAR FEELIT_FEFFECT_POLAR
#define FEEL_FEFFECT_SPHERICAL FEELIT_FEFFECT_SPHERICAL
#define FEEL_PARAM_NOTRIGGER FEELIT_PARAM_NOTRIGGER
#define FEEL_MOUSEOFFSET_XAXIS FEELIT_MOUSEOFFSET_XAXIS
#define FEEL_MOUSEOFFSET_YAXIS FEELIT_MOUSEOFFSET_YAXIS
#define FEEL_MOUSEOFFSET_ZAXIS FEELIT_MOUSEOFFSET_ZAXIS
//
// FORCE --> FEELIT Wrappers
//
#define FORCE_EFFECT FEELIT_EFFECT
#define LPFORCE_EFFECT LPFEELIT_EFFECT
#define LPCFORCE_EFFECT LPCFEELIT_EFFECT
#define FORCE_CONDITION FEELIT_CONDITION
#define LPFORCE_CONDITION LPFEELIT_CONDITION
#define LPCFORCE_CONDITION LPCFEELIT_CONDITION
#define FORCE_TEXTURE FEELIT_TEXTURE
#define LPFORCE_TEXTURE LPFEELIT_TEXTURE
#define LPCFORCE_TEXTURE LPCFEELIT_TEXTURE
#define FORCE_PERIODIC FEELIT_PERIODIC
#define LPFORCE_PERIODIC LPFEELIT_PERIODIC
#define LPCFORCE_PERIODIC LPCFEELIT_PERIODIC
#define FORCE_CONSTANTFORCE FEELIT_CONSTANTFORCE
#define LPFORCE_CONSTANTFORCE LPFEELIT_CONSTANTFORCE
#define LPCFORCE_CONSTANTFORCE LPCFEELIT_CONSTANTFORCE
#define FORCE_RAMPFORCE FEELIT_RAMPFORCE
#define LPFORCE_RAMPFORCE LPFEELIT_RAMPFORCE
#define LPCFORCE_RAMPFORCE LPCFEELIT_RAMPFORCE
#define FORCE_ENVELOPE FEELIT_ENVELOPE
#define LPFORCE_ENVELOPE LPFEELIT_ENVELOPE
#define LPCFORCE_ENVELOPE LPCFEELIT_ENVELOPE
#define LPIFORCE_API LPIFEELIT
#define LPIFORCE_EFFECT LPIFEELIT_EFFECT
#define LPIFORCE_DEVICE LPIFEELIT_DEVICE
#define LPFORCE_DEVICEINSTANCE LPFEELIT_DEVICEINSTANCE
#define LPCFORCE_DEVICEOBJECTINSTANCE LPCFEELIT_DEVICEOBJECTINSTANCE
#define LPCFORCE_EFFECTINFO LPCFEELIT_EFFECTINFO
#define FORCE_FPARAM_DURATION FEELIT_FPARAM_DURATION
#define FORCE_FPARAM_SAMPLEPERIOD FEELIT_FPARAM_SAMPLEPERIOD
#define FORCE_FPARAM_GAIN FEELIT_FPARAM_GAIN
#define FORCE_FPARAM_TRIGGERBUTTON FEELIT_FPARAM_TRIGGERBUTTON
#define FORCE_FPARAM_TRIGGERREPEATINTERVAL FEELIT_FPARAM_TRIGGERREPEATINTERVAL
#define FORCE_FPARAM_AXES FEELIT_FPARAM_AXES
#define FORCE_FPARAM_DIRECTION FEELIT_FPARAM_DIRECTION
#define FORCE_FPARAM_ENVELOPE FEELIT_FPARAM_ENVELOPE
#define FORCE_FPARAM_TYPESPECIFICPARAMS FEELIT_FPARAM_TYPESPECIFICPARAMS
#define FORCE_FPARAM_ALLPARAMS FEELIT_FPARAM_ALLPARAMS
#define FORCE_FPARAM_START FEELIT_FPARAM_START
#define FORCE_FPARAM_NORESTART FEELIT_FPARAM_NORESTART
#define FORCE_FPARAM_NODOWNLOAD FEELIT_FPARAM_NODOWNLOAD
#define FORCE_FEFFECT_OBJECTIDS FEELIT_FEFFECT_OBJECTIDS
#define FORCE_FEFFECT_OBJECTOFFSETS FEELIT_FEFFECT_OBJECTOFFSETS
#define FORCE_FEFFECT_CARTESIAN FEELIT_FEFFECT_CARTESIAN
#define FORCE_FEFFECT_POLAR FEELIT_FEFFECT_POLAR
#define FORCE_FEFFECT_SPHERICAL FEELIT_FEFFECT_SPHERICAL
#define FORCE_PARAM_NOTRIGGER FEELIT_PARAM_NOTRIGGER
#define FORCE_MOUSEOFFSET_XAXIS FEELIT_MOUSEOFFSET_XAXIS
#define FORCE_MOUSEOFFSET_YAXIS FEELIT_MOUSEOFFSET_YAXIS
#define FORCE_MOUSEOFFSET_ZAXIS FEELIT_MOUSEOFFSET_ZAXIS
//================================================================
// GUID WRAPPERS
//================================================================
//
// Feel --> Feelit Wrappers
//
#define GUID_Feel_ConstantForce GUID_Feelit_ConstantForce
#define GUID_Feel_RampForce GUID_Feelit_RampForce
#define GUID_Feel_Square GUID_Feelit_Square
#define GUID_Feel_Sine GUID_Feelit_Sine
#define GUID_Feel_Triangle GUID_Feelit_Triangle
#define GUID_Feel_SawtoothUp GUID_Feelit_SawtoothUp
#define GUID_Feel_SawtoothDown GUID_Feelit_SawtoothDown
#define GUID_Feel_Spring GUID_Feelit_Spring
#define GUID_Feel_DeviceSpring GUID_Feelit_DeviceSpring
#define GUID_Feel_Damper GUID_Feelit_Damper
#define GUID_Feel_Inertia GUID_Feelit_Inertia
#define GUID_Feel_Friction GUID_Feelit_Friction
#define GUID_Feel_Texture GUID_Feelit_Texture
#define GUID_Feel_Grid GUID_Feelit_Grid
#define GUID_Feel_Enclosure GUID_Feelit_Enclosure
#define GUID_Feel_Ellipse GUID_Feelit_Ellipse
#define GUID_Feel_CustomForce GUID_Feelit_CustomForce
//
// Force --> Feelit Wrappers
//
#define GUID_Force_ConstantForce GUID_Feelit_ConstantForce
#define GUID_Force_RampForce GUID_Feelit_RampForce
#define GUID_Force_Square GUID_Feelit_Square
#define GUID_Force_Sine GUID_Feelit_Sine
#define GUID_Force_Triangle GUID_Feelit_Triangle
#define GUID_Force_SawtoothUp GUID_Feelit_SawtoothUp
#define GUID_Force_SawtoothDown GUID_Feelit_SawtoothDown
#define GUID_Force_Spring GUID_Feelit_Spring
#define GUID_Force_Damper GUID_Feelit_Damper
#define GUID_Force_Inertia GUID_Feelit_Inertia
#define GUID_Force_Friction GUID_Feelit_Friction
#define GUID_Force_Texture GUID_Feelit_Texture
#define GUID_Force_Grid GUID_Feelit_Grid
#define GUID_Force_Enclosure GUID_Feelit_Enclosure
#define GUID_Force_Ellipse GUID_Feelit_Ellipse
#define GUID_Force_CustomForce GUID_Feelit_CustomForce
#endif // !defined(AFX_FEELBASETYPES_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

178
code/win32/FeelIt/FeelBox.h Normal file
View File

@@ -0,0 +1,178 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelBox.h
PURPOSE: Box Class for Feelit API Foundation Classes
STARTED: 11/04/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELBOX_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELBOX_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
#include "FeelEnclosure.h"
//================================================================
// Constants
//================================================================
const POINT FEEL_BOX_MOUSE_POS_AT_START = { MAXLONG, MAXLONG };
#define FEEL_BOX_DEFAULT_STIFFNESS 5000
#define FEEL_BOX_DEFAULT_WIDTH 10
#define FEEL_BOX_DEFAULT_HEIGHT FEEL_ENCLOSURE_HEIGHT_AUTO
#define FEEL_BOX_DEFAULT_WALL_WIDTH FEEL_ENCLOSURE_WALL_WIDTH_AUTO
#define FEEL_BOX_DEFAULT_CENTER_POINT FEEL_BOX_MOUSE_POS_AT_START
//
// FORCE --> FEEL Wrappers
//
#define FORCE_BOX_MOUSE_POS_AT_START FEEL_BOX_DEFAULT_STIFFNESS
#define FORCE_BOX_DEFAULT_STIFFNESS FEEL_BOX_DEFAULT_STIFFNESS
#define FORCE_BOX_DEFAULT_WIDTH FEEL_BOX_DEFAULT_WIDTH
#define FORCE_BOX_DEFAULT_HEIGHT FEEL_BOX_DEFAULT_HEIGHT
#define FORCE_BOX_DEFAULT_WALL_WIDTH FEEL_BOX_DEFAULT_WALL_WIDTH
#define FORCE_BOX_DEFAULT_CENTER_POINT FEEL_BOX_DEFAULT_CENTER_POINT
//================================================================
// CFeelBox
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelBox : public CFeelEnclosure
{
//
// CONSTRUCTOR/DESCTRUCTOR
//
public:
// Constructor
CFeelBox();
// Destructor
virtual
~CFeelBox();
//
// ATTRIBUTES
//
public:
BOOL
ChangeParameters(
POINT pntCenter,
LONG lStiffness = FEEL_EFFECT_DONT_CHANGE,
DWORD dwWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwHeight = FEEL_EFFECT_DONT_CHANGE,
DWORD dwWallWidth = FEEL_EFFECT_DONT_CHANGE,
CFeelEffect* pInsideEffect = (CFeelEffect*) FEEL_EFFECT_DONT_CHANGE
);
BOOL
ChangeParameters(
LPCRECT pRectOutside,
LONG lStiffness = FEEL_EFFECT_DONT_CHANGE,
DWORD dwWallWidth = FEEL_EFFECT_DONT_CHANGE,
CFeelEffect* pInsideEffect = (CFeelEffect*) FEEL_EFFECT_DONT_CHANGE
);
//
// OPERATIONS
//
public:
BOOL
Initialize(
CFeelDevice* pDevice,
DWORD dwWidth = FEEL_ENCLOSURE_DEFAULT_WIDTH,
DWORD dwHeight = FEEL_ENCLOSURE_DEFAULT_HEIGHT,
LONG lStiffness = FEEL_BOX_DEFAULT_STIFFNESS,
DWORD dwWallWidth = FEEL_BOX_DEFAULT_WALL_WIDTH,
POINT pntCenter = FEEL_BOX_DEFAULT_CENTER_POINT,
CFeelEffect* pInsideEffect = NULL
);
BOOL
Initialize(
CFeelDevice* pDevice,
LPCRECT pRectOutside,
LONG lStiffness = FEEL_BOX_DEFAULT_STIFFNESS,
DWORD dwWallWidth = FEEL_BOX_DEFAULT_WALL_WIDTH,
CFeelEffect* pInsideEffect = NULL
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
//
// INTERNAL DATA
//
protected:
};
#endif // !defined(AFX_FEELBOX_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,184 @@
/**********************************************************************
Copyright (c) 1999 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelCompoundEffect.h
PURPOSE: Manages Compound Effects for Force Foundation Classes
STARTED: 2/24/99 by Jeff Mallett
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(__FEELCOMPOUNDEFFECT_H)
#define __FEELCOMPOUNDEFFECT_H
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
#include "FeelitIFR.h"
//================================================================
// CFeelCompoundEffect
//================================================================
// Represents a compound effect, such as might be created in
// I-FORCE Studio. Contains an array of effect objects.
// Methods iterate over component effects, passing the message
// to each one.
// Also, has stuff for being used by CFeelProject:
// * next pointer so can be put on a linked list
// * force name
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelCompoundEffect
{
//
// CONSTRUCTOR/DESTRUCTOR
//
protected:
// Constructs a CFeelCompoundEffect
// Don't try to construct a CFeelCompoundEffect yourself.
// Instead let CFeelProject construct it for you.
CFeelCompoundEffect(
IFREffect **hEffects,
long nEffects
);
public:
~CFeelCompoundEffect();
//
// ATTRIBUTES
//
public:
long
GetNumberOfContainedEffects() const
{ return m_nEffects; }
const char *
GetName() const
{ return m_lpszName; }
GENERIC_EFFECT_PTR
GetContainedEffect(
long index
);
//
// OPERATIONS
//
public:
// Start all the contained effects
BOOL Start(
DWORD dwIterations = 1,
DWORD dwFlags = 0
);
// Stop all the contained effects
BOOL Stop();
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
BOOL initialize(
CFeelDevice* pDevice,
IFREffect **hEffects
);
BOOL
set_contained_effect(
GENERIC_EFFECT_PTR pObject,
int index = 0
);
BOOL
set_name(
const char *lpszName
);
void
set_next(
CFeelCompoundEffect *pNext
)
{ m_pNext = pNext; }
CFeelCompoundEffect *
get_next() const
{ return m_pNext; }
//
// FRIENDS
//
public:
friend class CFeelProject;
//
// INTERNAL DATA
//
protected:
GENERIC_EFFECT_PTR *m_paEffects; // Array of force class object pointers
long m_nEffects; // Number of effects in m_paEffects
private:
char *m_lpszName; // Name of the compound effect
CFeelCompoundEffect *m_pNext; // Next compound effect in the project
};
#endif

View File

@@ -0,0 +1,345 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelCondition.h
PURPOSE: Base Condition Class for Feelit API Foundation Classes
STARTED: 10/10/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELCONDITION_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELCONDITION_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
//================================================================
// Constants
//================================================================
const POINT FEEL_CONDITION_PT_NULL = { 0, 0 };
#define FEEL_CONDITION_DEFAULT_COEFFICIENT 2500
#define FEEL_CONDITION_DEFAULT_SATURATION 10000
#define FEEL_CONDITION_DEFAULT_DEADBAND 100
#define FEEL_CONDITION_DEFAULT_CENTER_POINT FEEL_EFFECT_MOUSE_POS_AT_START
#define FEEL_CONDITION_DEFAULT_DURATION INFINITE
typedef enum {
FC_NULL = 0,
FC_POSITIVE_COEFFICIENT,
FC_NEGATIVE_COEFFICIENT,
FC_POSITIVE_SATURATION,
FC_NEGATIVE_SATURATION,
FC_DEAD_BAND,
FC_AXIS,
FC_CENTER,
FC_DIRECTION_X,
FC_DIRECTION_Y,
FC_ANGLE,
FC_CONDITION_X,
FC_CONDITION_Y
} FC_ArgumentType;
#define FC_CONDITION FC_CONDITION_X
//
// FORCE --> FEEL Wrappers
//
#define FORCE_CONDITION_PT_NULL FEEL_CONDITION_PT_NULL
#define FORCE_CONDITION_DEFAULT_COEFFICIENT FEEL_CONDITION_DEFAULT_COEFFICIENT
#define FORCE_CONDITION_DEFAULT_SATURATION FEEL_CONDITION_DEFAULT_SATURATION
#define FORCE_CONDITION_DEFAULT_DEADBAND FEEL_CONDITION_DEFAULT_DEADBAND
#define FORCE_CONDITION_DEFAULT_CENTER_POINT FEEL_CONDITION_DEFAULT_CENTER_POINT
#define FORCE_CONDITION_DEFAULT_DURATION FEEL_CONDITION_DEFAULT_DURATION
//================================================================
// CFeelCondition
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelCondition : public CFeelEffect
{
//
// CONSTRUCTOR/DESCTRUCTOR
//
public:
// Constructor
CFeelCondition(
const GUID& rguidEffect
);
// Destructor
virtual
~CFeelCondition();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
// Use this form for single-axis and dual-axis effects
BOOL
ChangeConditionParams(
LPCFEELIT_CONDITION pConditionX,
LPCFEELIT_CONDITION pConditionY
);
// Use this form for directional effects
BOOL
ChangeConditionParams(
LPCFEELIT_CONDITION pCondition,
LONG lDirectionX,
LONG lDirectionY
);
// Use this form for directional effects
BOOL
ChangeConditionParamsPolar(
LPCFEELIT_CONDITION pCondition,
LONG lAngle
);
// Use this form for single-axis, dual-axis symetrical, or directional effects
BOOL
ChangeConditionParams(
LONG lPositiveCoefficient,
LONG lNegativeCoefficient = FEEL_EFFECT_DONT_CHANGE,
DWORD dwPositiveSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwNegativeSaturation = FEEL_EFFECT_DONT_CHANGE,
LONG lDeadBand = FEEL_EFFECT_DONT_CHANGE,
POINT pntCenter = FEEL_EFFECT_DONT_CHANGE_POINT,
LONG lDirectionX = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionY = FEEL_EFFECT_DONT_CHANGE
);
// Use this form for single-axis, dual-axis symetrical, or directional effects
BOOL
ChangeConditionParamsPolar(
LONG lPositiveCoefficient,
LONG lNegativeCoefficient,
DWORD dwPositiveSaturation,
DWORD dwNegativeSaturation,
LONG lDeadBand,
POINT pntCenter,
LONG lAngle
);
BOOL
SetCenter(
POINT pntCenter
);
BOOL
ChangeConditionParams2(
FC_ArgumentType type,
...
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
const FEEL_EFFECT &effect
);
// Use this form for single-axis and dual-axis effects
BOOL
InitCondition(
CFeelDevice* pDevice,
LPCFEELIT_CONDITION pConditionX,
LPCFEELIT_CONDITION pConditionY,
BOOL bUseDeviceCoordinates = FALSE
);
// Use this form for directional effects
BOOL
InitCondition(
CFeelDevice* pDevice,
LPCFEELIT_CONDITION pCondition,
LONG lDirectionX,
LONG lDirectionY,
BOOL bUseDeviceCoordinates = FALSE
);
// Use this form for directional effects
BOOL
InitConditionPolar(
CFeelDevice* pDevice,
LPCFEELIT_CONDITION pCondition,
LONG lAngle,
BOOL bUseDeviceCoordinates = FALSE
);
// Use this form for single-axis, dual-axis symetrical, or directional effects
BOOL
InitCondition(
CFeelDevice* pDevice,
LONG lPositiveCoefficient = FEEL_CONDITION_DEFAULT_COEFFICIENT,
LONG lNegativeCoefficient = FEEL_CONDITION_DEFAULT_COEFFICIENT,
DWORD dwPositiveSaturation = FEEL_CONDITION_DEFAULT_SATURATION,
DWORD dwNegativeSaturation = FEEL_CONDITION_DEFAULT_SATURATION,
LONG lDeadBand = FEEL_CONDITION_DEFAULT_DEADBAND,
DWORD dwfAxis = FEEL_EFFECT_AXIS_BOTH,
POINT pntCenter = FEEL_CONDITION_DEFAULT_CENTER_POINT,
LONG lDirectionX = FEEL_EFFECT_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_EFFECT_DEFAULT_DIRECTION_Y,
BOOL bUseDeviceCoordinates = FALSE
);
// Use this form for directional effects
BOOL
InitConditionPolar(
CFeelDevice* pDevice,
LONG lPositiveCoefficient = FEEL_CONDITION_DEFAULT_COEFFICIENT,
LONG lNegativeCoefficient = FEEL_CONDITION_DEFAULT_COEFFICIENT,
DWORD dwPositiveSaturation = FEEL_CONDITION_DEFAULT_SATURATION,
DWORD dwNegativeSaturation = FEEL_CONDITION_DEFAULT_SATURATION,
LONG lDeadBand = FEEL_CONDITION_DEFAULT_DEADBAND,
POINT pntCenter = FEEL_CONDITION_DEFAULT_CENTER_POINT,
LONG lAngle = FEEL_EFFECT_DEFAULT_ANGLE,
BOOL bUseDeviceCoordinates = FALSE
);
virtual BOOL
#ifdef FFC_START_DELAY
StartNow(
#else
Start(
#endif
DWORD dwIterations = 1,
DWORD dwFlags = 0
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
void
convert_line_point_to_offset(
POINT pntOnLine
);
BOOL
set_parameters(
DWORD dwfAxis,
DWORD dwfCoordinates,
LONG lDirection0,
LONG lDirection1,
LPCFEELIT_CONDITION pConditionX,
LPCFEELIT_CONDITION pConditionY
);
BOOL
set_parameters(
DWORD dwfAxis,
DWORD dwfCoordinates,
LONG lDirection0,
LONG lDirection1,
LONG lPositiveCoefficient,
LONG lNegativeCoefficient,
DWORD dwPositiveSaturation,
DWORD dwNegativeSaturation,
LONG lDeadBand,
POINT pntCenter
);
//
// INTERNAL DATA
//
FEEL_CONDITION m_aCondition[2];
DWORD m_dwfAxis;
BOOL m_bUseMousePosAtStart;
protected:
BOOL m_bUseDeviceCoordinates;
};
//
// INLINES
//
inline BOOL
CFeelCondition::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Spring) ||
IsEqualGUID(guid, GUID_Feel_DeviceSpring) ||
IsEqualGUID(guid, GUID_Feel_Damper) ||
IsEqualGUID(guid, GUID_Feel_Inertia) ||
IsEqualGUID(guid, GUID_Feel_Friction) ||
IsEqualGUID(guid, GUID_Feel_Texture) ||
IsEqualGUID(guid, GUID_Feel_Grid);
}
#endif // !defined(AFX_FEELCONDITION_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,193 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelConstant.h
PURPOSE: Base Constant Class for Feelit API Foundation Classes
STARTED: 11/03/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELCONSTANT_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELCONSTANT_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
//================================================================
// Constants
//================================================================
const POINT FEEL_CONSTANT_DEFAULT_DIRECTION = { 1, 0 };
#define FEEL_CONSTANT_DEFAULT_DURATION 1000 // Milliseconds
#define FEEL_CONSTANT_DEFAULT_MAGNITUDE 5000
//
// FORCE --> FEEL Wrappers
//
#define FORCE_CONSTANT_DEFAULT_DIRECTION FEEL_CONSTANT_DEFAULT_DIRECTION
#define FORCE_CONSTANT_DEFAULT_DURATION FEEL_CONSTANT_DEFAULT_DURATION
#define FORCE_CONSTANT_DEFAULT_MAGNITUDE FEEL_CONSTANT_DEFAULT_MAGNITUDE
//================================================================
// CFeelConstant
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelConstant : public CFeelEffect
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelConstant();
// Destructor
virtual
~CFeelConstant();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
LONG lDirectionX,
LONG lDirectionY,
DWORD dwDuration = FEEL_EFFECT_DONT_CHANGE,
LONG lMagnitude = FEEL_EFFECT_DONT_CHANGE,
LPFEEL_ENVELOPE pEnvelope = (LPFEEL_ENVELOPE) FEEL_EFFECT_DONT_CHANGE_PTR
);
BOOL
ChangeParametersPolar(
LONG lAngle,
DWORD dwDuration = FEEL_EFFECT_DONT_CHANGE,
LONG lMagnitude = FEEL_EFFECT_DONT_CHANGE,
LPFEEL_ENVELOPE pEnvelope = (LPFEEL_ENVELOPE) FEEL_EFFECT_DONT_CHANGE_PTR
);
//
// OPERATIONS
//
public:
virtual
BOOL
Initialize(
CFeelDevice* pDevice,
LONG lDirectionX = FEEL_EFFECT_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_EFFECT_DEFAULT_DIRECTION_Y,
DWORD dwDuration = FEEL_CONSTANT_DEFAULT_DURATION,
LONG lMagnitude = FEEL_CONSTANT_DEFAULT_MAGNITUDE,
LPFEEL_ENVELOPE pEnvelope = NULL
);
virtual
BOOL
InitializePolar(
CFeelDevice* pDevice,
LONG lArray = FEEL_EFFECT_DEFAULT_ANGLE,
DWORD dwDuration = FEEL_CONSTANT_DEFAULT_DURATION,
LONG lMagnitude = FEEL_CONSTANT_DEFAULT_MAGNITUDE,
LPFEEL_ENVELOPE pEnvelope = NULL
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
BOOL
set_parameters(
DWORD dwfCoordinates,
LONG lDirection0,
LONG lDirection1,
DWORD dwDuration,
LONG lMagnitude,
LPFEEL_ENVELOPE pEnvelope
);
//
// INTERNAL DATA
//
FEEL_CONSTANTFORCE m_ConstantForce;
protected:
};
//
// INLINES
//
inline BOOL
CFeelConstant::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_ConstantForce);
}
#endif // !defined(AFX_FEELCONSTANT_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,126 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelDXDevice.h
PURPOSE: Abstraction of DirectX Force Feedback device
STARTED: 10/10/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#ifndef FeelDXDevice_h
#define FeelDXDevice_h
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelDevice.h"
//================================================================
// CFeelDXDevice
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelDXDevice : public CFeelDevice
{
//
// CONSTRUCTOR/DESCTRUCTOR
//
public:
// Constructor
CFeelDXDevice();
// Destructor
virtual
~CFeelDXDevice();
//
// ATTRIBUTES
//
public:
virtual LPIFEEL_API
GetAPI()
{ return (LPIFEEL_API) m_piApi; } // actually LPDIRECTINPUT
virtual LPIFEEL_DEVICE
GetDevice()
{ return (LPIFEEL_DEVICE) m_piDevice; } // actually LPDIRECTINPUTDEVICE2
//
// OPERATIONS
//
public:
BOOL
Initialize(
HANDLE hinstApp,
HANDLE hwndApp,
LPDIRECTINPUT pDI = NULL,
LPDIRECTINPUTDEVICE2 piDevice = NULL
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
virtual void
reset();
//
// INTERNAL DATA
//
protected:
BOOL m_bpDIPreExist;
BOOL m_bpDIDevicePreExist;
LPDIRECTINPUT m_piApi;
LPDIRECTINPUTDEVICE2 m_piDevice;
};
#endif // ForceDXDevice_h

View File

@@ -0,0 +1,177 @@
/**********************************************************************
Copyright (c) 1997,8,9 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelDamper.h
PURPOSE: Feelit API Damper Effect Class
STARTED: 10/14/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELDamper_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELDamper_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include <windows.h>
#include "FeelCondition.h"
//================================================================
// Constants
//================================================================
#define FEEL_DAMPER_DEFAULT_VISCOSITY 2500
#define FEEL_DAMPER_DEFAULT_SATURATION 10000
#define FEEL_DAMPER_DEFAULT_MIN_VELOCITY 0
//
// FORCE --> FEEL Wrappers
//
#define FORCE_DAMPER_DEFAULT_VISCOSITY FEEL_DAMPER_DEFAULT_VISCOSITY
#define FORCE_DAMPER_DEFAULT_SATURATION FEEL_DAMPER_DEFAULT_SATURATION
#define FORCE_DAMPER_DEFAULT_MIN_VELOCITY FEEL_DAMPER_DEFAULT_MIN_VELOCITY
//================================================================
// CFeelDamper
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelDamper : public CFeelCondition
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelDamper();
// Destructor
virtual ~CFeelDamper();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
DWORD dwViscosity,
DWORD dwSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwMinVelocity = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionX = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionY = FEEL_EFFECT_DONT_CHANGE
);
BOOL
ChangeParametersPolar(
DWORD dwViscosity,
DWORD dwSaturation,
DWORD dwMinVelocity,
LONG lAngle
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
DWORD dwViscosity = FEEL_DAMPER_DEFAULT_VISCOSITY,
DWORD dwSaturation = FEEL_DAMPER_DEFAULT_SATURATION,
DWORD dwMinVelocity = FEEL_DAMPER_DEFAULT_MIN_VELOCITY,
DWORD dwfAxis = FEEL_EFFECT_AXIS_BOTH,
LONG lDirectionX = FEEL_EFFECT_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_EFFECT_DEFAULT_DIRECTION_Y
);
virtual BOOL
InitializePolar(
CFeelDevice* pDevice,
DWORD dwViscosity,
DWORD dwSaturation,
DWORD dwMinVelocity,
LONG lAngle
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
//
// INTERNAL DATA
//
protected:
};
//
// INLINES
//
inline BOOL
CFeelDamper::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Damper);
}
#endif // !defined(AFX_FEELDamper_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,196 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelDevice.h
PURPOSE: Abstract Base Device Class for Force Foundation Classes
STARTED: 10/10/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
3/16/99 jrm: Made abstract. Moved functionality to CFeelMouse/CFeelDXDevice
**********************************************************************/
#if !defined(AFX_FORCEDEVICE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FORCEDEVICE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#define DIRECTINPUT_VERSION 0x0800 //[ 0x0300 | 0x0500 | 0x0700 | 0x0800 ]
#include "dinput.h"
#include "FeelBaseTypes.h"
#ifdef FFC_EFFECT_CACHING
#include "FeelEffectSuite.h"
#endif
//================================================================
// CFeelDevice
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelDevice
{
//
// CONSTRUCTOR/DESCTRUCTOR
//
public:
// Constructor
CFeelDevice();
// Destructor
virtual
~CFeelDevice();
//
// ATTRIBUTES
//
public:
virtual LPIFEEL_API
GetAPI()
= 0; // pure virtual function
virtual LPIFEEL_DEVICE // Will actually return LPDIRECTINPUTDEVICE2 if non-FEELit
GetDevice()
= 0; // pure virtual function
DWORD
GetDeviceType() const
{ return m_dwDeviceType; }
//
// OPERATIONS
//
public:
static CFeelDevice *
CreateDevice(HINSTANCE hinstApp, HWND hwndApp);
virtual BOOL
ChangeScreenResolution(
BOOL bAutoSet,
DWORD dwXScreenSize = 0,
DWORD dwYScreenSize = 0
);
// The default state is using standard Win32 Mouse messages (e.g., WM_MOUSEMOVE)
// and functions (e.g, GetCursorPos). Call only to switch to relative mode
// if not using standard Win32 Mouse services (e.g., DirectInput) for mouse
// input.
BOOL
UsesWin32MouseServices(
BOOL bWin32MouseServ
);
// Another syntax for SwitchToAbsoluteMode.
// The default is Absolute mode. Call only to switch to Relative mode or
// to switch back to Absolute mode.
virtual BOOL
SwitchToAbsoluteMode(
BOOL bAbsMode
);
//
// ------ PRIVATE INTERFACE ------
//
//
// CACHING
//
#ifdef FFC_EFFECT_CACHING
public:
void Cache_AddEffect(CFeelEffect *pFeelEffect);
void Cache_RemoveEffect(const CFeelEffect *pFeelEffect);
void Cache_SwapOutEffect();
protected:
void Cache_LoadEffectSuite(CFeelEffectSuite *pSuite, BOOL bCreateOnDevice);
void Cache_UnloadEffectSuite(CFeelEffectSuite *pSuite, BOOL bUnloadFromDevice);
CEffectList m_Cache; // List of all effects created on device
#endif
//
// HELPERS
//
protected:
// Performs device preparation by setting the device's parameters
virtual BOOL
prepare_device();
virtual void
reset()
= 0; // pure virtual function
static BOOL CALLBACK
enum_didevices_proc(
LPDIDEVICEINSTANCE pForceDevInst,
LPVOID pv
);
static BOOL CALLBACK
enum_devices_proc(
LPFORCE_DEVICEINSTANCE pForceDevInst,
LPVOID pv
);
//
// INTERNAL DATA
//
protected:
BOOL m_bInitialized;
DWORD m_dwDeviceType;
GUID m_guidDevice;
BOOL m_bGuidValid;
};
#endif // !defined(AFX_FORCEDEVICE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,344 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelEffect.h
PURPOSE: Base Effect Class for Feelit API Foundation Classes
STARTED: 10/10/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID and feel_to_DI_GUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELEFFECT_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELEFFECT_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelDevice.h"
class CFeelProject;
//================================================================
// Constants
//================================================================
#define FEEL_EFFECT_AXIS_X 1
#define FEEL_EFFECT_AXIS_Y 2
#define FEEL_EFFECT_AXIS_BOTH 3
#define FEEL_EFFECT_AXIS_DIRECTIONAL 4
#define FEEL_EFFECT_DONT_CHANGE MINLONG
#define FEEL_EFFECT_DONT_CHANGE_PTR MAXDWORD
const POINT FEEL_EFFECT_DONT_CHANGE_POINT = { 0xFFFFFFFF, 0xFFFFFFFF };
const POINT FEEL_EFFECT_MOUSE_POS_AT_START = { MAXLONG, MAXLONG };
#define FEEL_EFFECT_DEFAULT_ENVELOPE NULL
#define FEEL_EFFECT_DEFAULT_DIRECTION_X 1
#define FEEL_EFFECT_DEFAULT_DIRECTION_Y 1
#define FEEL_EFFECT_DEFAULT_ANGLE 0
//
// FORCE --> FEEL Wrappers
//
#define FORCE_EFFECT_AXIS_X FEEL_EFFECT_AXIS_X
#define FORCE_EFFECT_AXIS_Y FEEL_EFFECT_AXIS_Y
#define FORCE_EFFECT_AXIS_BOTH FEEL_EFFECT_AXIS_BOTH
#define FORCE_EFFECT_AXIS_DIRECTIONAL FEEL_EFFECT_AXIS_DIRECTIONAL
#define FORCE_EFFECT_DONT_CHANGE FEEL_EFFECT_DONT_CHANGE
#define FORCE_EFFECT_DONT_CHANGE_PTR FEEL_EFFECT_DONT_CHANGE_PTR
#define FORCE_EFFECT_DONT_CHANGE_POINT FEEL_EFFECT_DONT_CHANGE_POINT
#define FORCE_EFFECT_MOUSE_POS_AT_START FEEL_EFFECT_MOUSE_POS_AT_START
#define FORCE_EFFECT_DEFAULT_ENVELOPE FEEL_EFFECT_DEFAULT_ENVELOPE
#define FORCE_EFFECT_DEFAULT_DIRECTION_X FEEL_EFFECT_DEFAULT_DIRECTION_X
#define FORCE_EFFECT_DEFAULT_DIRECTION_Y FEEL_EFFECT_DEFAULT_DIRECTION_Y
#define FORCE_EFFECT_DEFAULT_ANGLE FEEL_EFFECT_DEFAULT_ANGLE
// GENERIC_EFFECT_PTR
// This is really a pointer to a child of CFeelEffect.
typedef class CFeelEffect * GENERIC_EFFECT_PTR;
//================================================================
// CFeelEffect
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelEffect
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelEffect(
const GUID& rguidEffect
);
// Destructor
virtual
~CFeelEffect();
//
// ATTRIBUTES
//
public:
LPIFEEL_EFFECT
GetEffect()
{ return m_piFeelitEffect; }
BOOL
GetStatus(
DWORD* pdwStatus
)
#if (FFC_VERSION >= 0x0110) || defined(FFC_EFFECT_CACHING)
const
#endif
;
GUID
GetGUID()
{ return m_guidEffect; }
virtual BOOL
GetIsCompatibleGUID(
GUID & /* guid */
)
{ return true; }
// Allocates an object of the correct FFC class from the given GUID
static GENERIC_EFFECT_PTR
NewObjectFromGUID(
GUID &guid
);
BOOL
ChangeBaseParams(
LONG lDirectionX,
LONG lDirectionY,
DWORD dwDuration = FEEL_EFFECT_DONT_CHANGE,
LPFEEL_ENVELOPE pEnvelope = (LPFEEL_ENVELOPE) FEEL_EFFECT_DONT_CHANGE_PTR,
DWORD dwSamplePeriod = FEEL_EFFECT_DONT_CHANGE,
DWORD dwGain = FEEL_EFFECT_DONT_CHANGE,
DWORD dwTriggerButton = FEEL_EFFECT_DONT_CHANGE,
DWORD dwTriggerRepeatInterval = FEEL_EFFECT_DONT_CHANGE
#ifdef FFC_START_DELAY
,DWORD dwStartDelay = FEEL_EFFECT_DONT_CHANGE
#endif
);
BOOL
ChangeBaseParamsPolar(
LONG lAngle,
DWORD dwDuration = FEEL_EFFECT_DONT_CHANGE,
LPFEEL_ENVELOPE pEnvelope = (LPFEEL_ENVELOPE) FEEL_EFFECT_DONT_CHANGE_PTR,
DWORD dwSamplePeriod = FEEL_EFFECT_DONT_CHANGE,
DWORD dwGain = FEEL_EFFECT_DONT_CHANGE,
DWORD dwTriggerButton = FEEL_EFFECT_DONT_CHANGE,
DWORD dwTriggerRepeatInterval = FEEL_EFFECT_DONT_CHANGE
#ifdef FFC_START_DELAY
,DWORD dwStartDelay = FEEL_EFFECT_DONT_CHANGE
#endif
);
BOOL
ChangeDirection(
LONG lDirectionX,
LONG lDirectionY
);
BOOL
ChangeDirection(
LONG lAngle
);
BOOL
SetEnvelope(
DWORD dwAttackLevel,
DWORD dwAttackTime,
DWORD dwFadeLevel,
DWORD dwFadeTime
);
BOOL
SetEnvelope(
LPFEEL_ENVELOPE pEnvelope
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
const FEEL_EFFECT &effect
);
virtual BOOL
InitializeFromProject(
CFeelProject &project,
LPCSTR lpszEffectName,
CFeelDevice* pDevice = NULL
);
virtual BOOL
Start(
DWORD dwIterations = 1,
DWORD dwFlags = 0
);
#ifdef FFC_START_DELAY
virtual BOOL
StartNow(
DWORD dwIterations = 1,
DWORD dwFlags = 0
);
#endif
virtual BOOL
Stop();
//
// ------ PRIVATE INTERFACE ------
//
//
// CACHING
//
#ifdef FFC_EFFECT_CACHING
public:
BOOL GetIsPlaying() const;
BOOL GetIsTriggered() const;
short GetPriority() const { return m_Priority; }
void SetPriority(short priority) { m_Priority = priority; }
HRESULT Unload();
void Reload();
public:
ECacheState m_CacheState; // effect's status in the cache
BOOL m_bInCurrentSuite; // is the effect in the currently loaded suite?
short m_Priority; // Priority within suite: higher number is higher priority
DWORD m_dwLastStarted; // when last started (0 = never) or when param change made on device
DWORD m_dwLastStopped; // when last stopped (0 = not since last start)
DWORD m_dwLastLoaded; // when last loaded with CFeelEffectSuite::Load or Create
protected:
CFeelDevice *m_pFeelDevice; // ### Use instead of m_piFeelitDevice
#endif
//
// HELPERS
//
protected:
#ifdef FFC_EFFECT_CACHING
public: // initalize needs to be called by CFeelDevice
#endif
BOOL
initialize(
CFeelDevice* pDevice
);
#ifdef FFC_EFFECT_CACHING
protected:
#endif
HRESULT
set_parameters_on_device(
DWORD dwFlags
);
void
feel_to_DI_GUID(
GUID &guid
);
void
reset();
void
reset_effect_struct();
//
// INTERNAL DATA
//
protected:
FEEL_EFFECT m_Effect;
DWORD m_dwaAxes[2];
LONG m_laDirections[2];
GUID m_guidEffect;
BOOL m_bIsPlaying;
DWORD m_dwDeviceType;
LPIFEEL_DEVICE m_piFeelitDevice; // Might also be holding LPDIRECTINPUTDEVICE2
LPIFEEL_EFFECT m_piFeelitEffect;
DWORD m_cAxes; // Number of axes
#ifdef FFC_START_DELAY
public:
// Prevents access to dangling pointer when this is deleted
// All relevent code may be removed when all hardware and drivers support start delay
CFeelEffect **m_ppTimerRef; // pointer to pointer to this.
#endif
};
#if (DIRECTINPUT_VERSION >= 0x0700)
#define DIRECT_INPUT_STARTDELAY_SUPPORTED TRUE
#else
#define DIRECT_INPUT_STARTDELAY_SUPPORTED FALSE
#endif /* DIRECTINPUT_VERSION >= 0x0700 */
#endif // !defined(AFX_FEELEFFECT_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,253 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelEllipse.h
PURPOSE: Base Ellipse Class for Feelit API Foundation Classes
STARTED: 10/29/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELELLIPSE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELELLIPSE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
//================================================================
// Constants
//================================================================
#define FEEL_ELLIPSE_DEFAULT_STIFFNESS 5000
#define FEEL_ELLIPSE_DEFAULT_SATURATION 10000
#define FEEL_ELLIPSE_DEFAULT_WIDTH 10
#define FEEL_ELLIPSE_HEIGHT_AUTO MAXDWORD
#define FEEL_ELLIPSE_DEFAULT_HEIGHT FEEL_ELLIPSE_HEIGHT_AUTO
#define FEEL_ELLIPSE_WALL_WIDTH_AUTO MAXDWORD
#define FEEL_ELLIPSE_DEFAULT_WALL_WIDTH FEEL_ELLIPSE_WALL_WIDTH_AUTO
#define FEEL_ELLIPSE_DEFAULT_STIFFNESS_MASK FEELIT_FSTIFF_ANYWALL
#define FEEL_ELLIPSE_DEFAULT_CLIPPING_MASK FEELIT_FCLIP_NONE
#define FEEL_ELLIPSE_DEFAULT_CENTER_POINT FEEL_EFFECT_MOUSE_POS_AT_START
//
// FEEL --> FORCE Wrappers
//
#define FORCE_ELLIPSE_DEFAULT_STIFFNESS FEEL_ELLIPSE_DEFAULT_STIFFNESS
#define FORCE_ELLIPSE_DEFAULT_SATURATION FEEL_ELLIPSE_DEFAULT_SATURATION
#define FORCE_ELLIPSE_DEFAULT_WIDTH FEEL_ELLIPSE_DEFAULT_WIDTH
#define FORCE_ELLIPSE_HEIGHT_AUTO FEEL_ELLIPSE_HEIGHT_AUTO
#define FORCE_ELLIPSE_DEFAULT_HEIGHT FEEL_ELLIPSE_DEFAULT_HEIGHT
#define FORCE_ELLIPSE_WALL_WIDTH_AUTO FEEL_ELLIPSE_WALL_WIDTH_AUTO
#define FORCE_ELLIPSE_DEFAULT_WALL_WIDTH FEEL_ELLIPSE_DEFAULT_WALL_WIDTH
#define FORCE_ELLIPSE_DEFAULT_STIFFNESS_MASK FEEL_ELLIPSE_DEFAULT_STIFFNESS_MASK
#define FORCE_ELLIPSE_DEFAULT_CLIPPING_MASK FEEL_ELLIPSE_DEFAULT_CLIPPING_MASK
#define FORCE_ELLIPSE_DEFAULT_CENTER_POINT FEEL_ELLIPSE_DEFAULT_CENTER_POINT
//================================================================
// CFeelEllipse
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelEllipse : public CFeelEffect
{
//
// CONSTRUCTOR/DESCTRUCTOR
//
public:
// Constructor
CFeelEllipse();
// Destructor
virtual
~CFeelEllipse();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
POINT pntCenter,
DWORD dwWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwHeight = FEEL_EFFECT_DONT_CHANGE,
LONG lStiffness = FEEL_EFFECT_DONT_CHANGE,
DWORD dwWallWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwStiffnessMask = FEEL_EFFECT_DONT_CHANGE,
DWORD dwClippingMask = FEEL_EFFECT_DONT_CHANGE,
CFeelEffect* pInsideEffect = (CFeelEffect*) FEEL_EFFECT_DONT_CHANGE
);
BOOL
ChangeParameters(
LPCRECT pRectOutside,
LONG lStiffness = FEEL_EFFECT_DONT_CHANGE,
DWORD dwWallWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwStiffnessMask = FEEL_EFFECT_DONT_CHANGE,
DWORD dwClippingMask = FEEL_EFFECT_DONT_CHANGE,
CFeelEffect* pInsideEffect = (CFeelEffect*) FEEL_EFFECT_DONT_CHANGE
);
BOOL
SetRect(
LPCRECT pRect
);
BOOL
SetCenter(
POINT pntCenter
);
BOOL
SetCenter(
LONG x,
LONG y
);
//
// OPERATIONS
//
public:
BOOL
Initialize(
CFeelDevice* pDevice,
DWORD dwWidth = FEEL_ELLIPSE_DEFAULT_WIDTH,
DWORD dwHeight = FEEL_ELLIPSE_DEFAULT_HEIGHT,
LONG lStiffness = FEEL_ELLIPSE_DEFAULT_STIFFNESS,
DWORD dwWallWidth = FEEL_ELLIPSE_DEFAULT_WALL_WIDTH,
DWORD dwSaturation = FEEL_ELLIPSE_DEFAULT_SATURATION,
DWORD dwStiffnessMask = FEEL_ELLIPSE_DEFAULT_STIFFNESS_MASK,
DWORD dwClippingMask = FEEL_ELLIPSE_DEFAULT_CLIPPING_MASK,
POINT pntCenter = FEEL_ELLIPSE_DEFAULT_CENTER_POINT,
CFeelEffect* pInsideEffect = NULL
);
BOOL
Initialize(
CFeelDevice* pDevice,
LPCRECT pRectOutside,
LONG lStiffness = FEEL_ELLIPSE_DEFAULT_STIFFNESS,
DWORD dwWallWidth = FEEL_ELLIPSE_DEFAULT_WALL_WIDTH,
DWORD dwSaturation = FEEL_ELLIPSE_DEFAULT_SATURATION,
DWORD dwStiffnessMask = FEEL_ELLIPSE_DEFAULT_STIFFNESS_MASK,
DWORD dwClippingMask = FEEL_ELLIPSE_DEFAULT_CLIPPING_MASK,
CFeelEffect* pInsideEffect = NULL
);
virtual BOOL
#ifdef FFC_START_DELAY
StartNow(
#else
Start(
#endif
DWORD dwFlags = 0
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
BOOL
set_parameters(
LPCRECT pRectOutside,
LONG lStiffness,
DWORD dwWallWidth,
DWORD dwSaturation,
DWORD dwStiffnessMask,
DWORD dwClippingMask,
CFeelEffect* pInsideEffect
);
//
// INTERNAL DATA
//
protected:
FEELIT_ELLIPSE m_ellipse;
BOOL m_bUseMousePosAtStart;
};
//
// INLINES
//
inline BOOL
CFeelEllipse::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Ellipse);
}
#endif // !defined(AFX_FEELELLIPSE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,268 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelEnclosure.h
PURPOSE: Base Enclosure Class for Feelit API Foundation Classes
STARTED: 10/29/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELENCLOSURE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELENCLOSURE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
//================================================================
// Constants
//================================================================
#define FEEL_ENCLOSURE_DEFAULT_STIFFNESS 5000
#define FEEL_ENCLOSURE_DEFAULT_SATURATION 10000
#define FEEL_ENCLOSURE_DEFAULT_WIDTH 10
#define FEEL_ENCLOSURE_HEIGHT_AUTO MAXDWORD
#define FEEL_ENCLOSURE_DEFAULT_HEIGHT FEEL_ENCLOSURE_HEIGHT_AUTO
#define FEEL_ENCLOSURE_WALL_WIDTH_AUTO MAXDWORD
#define FEEL_ENCLOSURE_DEFAULT_WALL_WIDTH FEEL_ENCLOSURE_WALL_WIDTH_AUTO
#define FEEL_ENCLOSURE_DEFAULT_STIFFNESS_MASK FEELIT_FSTIFF_ANYWALL
#define FEEL_ENCLOSURE_DEFAULT_CLIPPING_MASK FEELIT_FCLIP_NONE
#define FEEL_ENCLOSURE_DEFAULT_CENTER_POINT FEEL_EFFECT_MOUSE_POS_AT_START
//
// FORCE --> FEEL Wrappers
//
#define FORCE_ENCLOSURE_DEFAULT_STIFFNESS FEEL_ENCLOSURE_DEFAULT_STIFFNESS
#define FORCE_ENCLOSURE_DEFAULT_SATURATION FEEL_ENCLOSURE_DEFAULT_SATURATION
#define FORCE_ENCLOSURE_DEFAULT_WIDTH FEEL_ENCLOSURE_DEFAULT_WIDTH
#define FORCE_ENCLOSURE_HEIGHT_AUTO FEEL_ENCLOSURE_HEIGHT_AUTO
#define FORCE_ENCLOSURE_DEFAULT_HEIGHT FEEL_ENCLOSURE_DEFAULT_HEIGHT
#define FORCE_ENCLOSURE_WALL_WIDTH_AUTO FEEL_ENCLOSURE_WALL_WIDTH_AUTO
#define FORCE_ENCLOSURE_DEFAULT_WALL_WIDTH FEEL_ENCLOSURE_DEFAULT_WALL_WIDTH
#define FORCE_ENCLOSURE_DEFAULT_STIFFNESS_MASK FEEL_ENCLOSURE_DEFAULT_STIFFNESS_MASK
#define FORCE_ENCLOSURE_DEFAULT_CLIPPING_MASK FEEL_ENCLOSURE_DEFAULT_CLIPPING_MASK
#define FORCE_ENCLOSURE_DEFAULT_CENTER_POINT FEEL_ENCLOSURE_DEFAULT_CENTER_POINT
//================================================================
// CFeelEnclosure
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelEnclosure : public CFeelEffect
{
//
// CONSTRUCTOR/DESCTRUCTOR
//
public:
// Constructor
CFeelEnclosure();
// Destructor
virtual
~CFeelEnclosure();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
POINT pntCenter,
DWORD dwWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwHeight = FEEL_EFFECT_DONT_CHANGE,
LONG lTopAndBottomWallStiffness = FEEL_EFFECT_DONT_CHANGE,
LONG lLeftAndRightWallStiffness = FEEL_EFFECT_DONT_CHANGE,
DWORD dwTopAndBottomWallWallWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwLeftAndRightWallWallWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwTopAndBottomWallSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwLeftAndRightWallSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwStiffnessMask = FEEL_EFFECT_DONT_CHANGE,
DWORD dwClippingMask = FEEL_EFFECT_DONT_CHANGE,
CFeelEffect* pInsideEffect = (CFeelEffect*) FEEL_EFFECT_DONT_CHANGE
);
BOOL
ChangeParameters(
LPCRECT pRectOutside,
LONG lTopAndBottomWallStiffness = FEEL_EFFECT_DONT_CHANGE,
LONG lLeftAndRightWallStiffness = FEEL_EFFECT_DONT_CHANGE,
DWORD dwTopAndBottomWallWallWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwLeftAndRightWallWallWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwTopAndBottomWallSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwLeftAndRightWallSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwStiffnessMask = FEEL_EFFECT_DONT_CHANGE,
DWORD dwClippingMask = FEEL_EFFECT_DONT_CHANGE,
CFeelEffect* pInsideEffect = (CFeelEffect*) FEEL_EFFECT_DONT_CHANGE
);
BOOL
SetRect(
LPCRECT pRect
);
BOOL
SetCenter(
POINT pntCenter
);
BOOL
SetCenter(
LONG x,
LONG y
);
//
// OPERATIONS
//
public:
BOOL
Initialize(
CFeelDevice* pDevice,
DWORD dwWidth = FEEL_ENCLOSURE_DEFAULT_WIDTH,
DWORD dwHeight = FEEL_ENCLOSURE_DEFAULT_HEIGHT,
LONG lTopAndBottomWallStiffness = FEEL_ENCLOSURE_DEFAULT_STIFFNESS,
LONG lLeftAndRightWallStiffness = FEEL_ENCLOSURE_DEFAULT_STIFFNESS,
DWORD dwTopAndBottomWallWallWidth = FEEL_ENCLOSURE_DEFAULT_WALL_WIDTH,
DWORD dwLeftAndRightWallWallWidth = FEEL_ENCLOSURE_DEFAULT_WALL_WIDTH,
DWORD dwTopAndBottomWallSaturation = FEEL_ENCLOSURE_DEFAULT_SATURATION,
DWORD dwLeftAndRightWallSaturation = FEEL_ENCLOSURE_DEFAULT_SATURATION,
DWORD dwStiffnessMask = FEEL_ENCLOSURE_DEFAULT_STIFFNESS_MASK,
DWORD dwClippingMask = FEEL_ENCLOSURE_DEFAULT_CLIPPING_MASK,
POINT pntCenter = FEEL_ENCLOSURE_DEFAULT_CENTER_POINT,
CFeelEffect* pInsideEffect = NULL
);
BOOL
Initialize(
CFeelDevice* pDevice,
LPCRECT pRectOutside,
LONG lTopAndBottomWallStiffness = FEEL_ENCLOSURE_DEFAULT_STIFFNESS,
LONG lLeftAndRightWallStiffness = FEEL_ENCLOSURE_DEFAULT_STIFFNESS,
DWORD dwTopAndBottomWallWallWidth = FEEL_ENCLOSURE_DEFAULT_WALL_WIDTH,
DWORD dwLeftAndRightWallWallWidth = FEEL_ENCLOSURE_DEFAULT_WALL_WIDTH,
DWORD dwTopAndBottomWallSaturation = FEEL_ENCLOSURE_DEFAULT_SATURATION,
DWORD dwLeftAndRightWallSaturation = FEEL_ENCLOSURE_DEFAULT_SATURATION,
DWORD dwStiffnessMask = FEEL_ENCLOSURE_DEFAULT_STIFFNESS_MASK,
DWORD dwClippingMask = FEEL_ENCLOSURE_DEFAULT_CLIPPING_MASK,
CFeelEffect* pInsideEffect = NULL
);
virtual BOOL
#ifdef FFC_START_DELAY
StartNow(
#else
Start(
#endif
DWORD dwFlags = 0
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
BOOL
set_parameters(
LPCRECT pRectOutside,
LONG lTopAndBottomWallStiffness,
LONG lLeftAndRightWallStiffness,
DWORD dwTopAndBottomWallWallWidth,
DWORD dwLeftAndRightWallWallWidth,
DWORD dwTopAndBottomWallSaturation,
DWORD dwLeftAndRightWallSaturation,
DWORD dwStiffnessMask,
DWORD dwClippingMask,
CFeelEffect* pInsideEffect
);
//
// INTERNAL DATA
//
protected:
FEELIT_ENCLOSURE m_enclosure;
BOOL m_bUseMousePosAtStart;
};
//
// INLINES
//
inline BOOL
CFeelEnclosure::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Enclosure);
}
#endif // !defined(AFX_FEELENCLOSURE_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,172 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelFriction.h
PURPOSE: Feelit API Friction Effect Class
STARTED: 12/29/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELFriction_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELFriction_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include <windows.h>
#include "FeelCondition.h"
//================================================================
// Constants
//================================================================
#define FEEL_FRICTION_DEFAULT_COEFFICIENT 2500
#define FEEL_FRICTION_DEFAULT_MIN_VELOCITY 0
//
// FORCE --> FEEL Wrappers
//
#define FORCE_FRICTION_DEFAULT_COEFFICIENT FEEL_FRICTION_DEFAULT_COEFFICIENT
#define FORCE_FRICTION_DEFAULT_MIN_VELOCITY FEEL_FRICTION_DEFAULT_MIN_VELOCITY
//================================================================
// CFeelFriction
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelFriction : public CFeelCondition
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelFriction();
// Destructor
virtual
~CFeelFriction();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
DWORD dwCoefficient,
DWORD dwMinVelocity = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionX = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionY = FEEL_EFFECT_DONT_CHANGE
);
BOOL
ChangeParametersPolar(
DWORD dwCoefficient,
DWORD dwMinVelocity,
LONG lAngle
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
DWORD dwCoefficient = FEEL_FRICTION_DEFAULT_COEFFICIENT,
DWORD dwMinVelocity = FEEL_FRICTION_DEFAULT_MIN_VELOCITY,
DWORD dwfAxis = FEEL_EFFECT_AXIS_BOTH,
LONG lDirectionX = FEEL_EFFECT_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_EFFECT_DEFAULT_DIRECTION_Y
);
virtual BOOL
InitializePolar(
CFeelDevice* pDevice,
DWORD dwCoefficient,
DWORD dwMinVelocity,
LONG lAngle
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
//
// INTERNAL DATA
//
protected:
};
//
// INLINES
//
inline BOOL
CFeelFriction::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Friction);
}
#endif // !defined(AFX_FEELFriction_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,171 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelGrid.h
PURPOSE: Feelit API Grid Effect Class
STARTED: 12/11/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELGrid_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELGrid_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include <windows.h>
#include "FeelCondition.h"
//================================================================
// Constants
//================================================================
#define FEEL_GRID_DEFAULT_HORIZ_OFFSET 0
#define FEEL_GRID_DEFAULT_VERT_OFFSET 0
#define FEEL_GRID_DEFAULT_HORIZ_SPACING 100
#define FEEL_GRID_DEFAULT_VERT_SPACING 100
#define FEEL_GRID_DEFAULT_NODE_STRENGTH 5000
#define FEEL_GRID_DEFAULT_NODE_SATURATION 10000
//
// FORCE --> FEEL Wrappers
//
#define FORCE_GRID_DEFAULT_HORIZ_OFFSET FEEL_GRID_DEFAULT_HORIZ_OFFSET
#define FORCE_GRID_DEFAULT_VERT_OFFSET FEEL_GRID_DEFAULT_VERT_OFFSET
#define FORCE_GRID_DEFAULT_HORIZ_SPACING FEEL_GRID_DEFAULT_HORIZ_SPACING
#define FORCE_GRID_DEFAULT_VERT_SPACING FEEL_GRID_DEFAULT_VERT_SPACING
#define FORCE_GRID_DEFAULT_NODE_STRENGTH FEEL_GRID_DEFAULT_NODE_STRENGTH
#define FORCE_GRID_DEFAULT_NODE_SATURATION FEEL_GRID_DEFAULT_NODE_SATURATION
//================================================================
// CFeelGrid
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelGrid : public CFeelCondition
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelGrid();
// Destructor
virtual
~CFeelGrid();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
DWORD dwHorizSpacing,
DWORD dwVertSpacing,
LONG lHorizNodeStrength = FEEL_EFFECT_DONT_CHANGE,
LONG lVertNodeStrength = FEEL_EFFECT_DONT_CHANGE,
DWORD dwHorizOffset = FEEL_EFFECT_DONT_CHANGE,
DWORD dwVertOffset = FEEL_EFFECT_DONT_CHANGE,
DWORD dwHorizNodeSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwVertNodeSaturation = FEEL_EFFECT_DONT_CHANGE
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
DWORD dwHorizSpacing = FEEL_GRID_DEFAULT_HORIZ_SPACING,
DWORD dwVertSpacing = FEEL_GRID_DEFAULT_VERT_SPACING,
LONG lHorizNodeStrength = FEEL_GRID_DEFAULT_NODE_STRENGTH,
LONG lVertNodeStrength = FEEL_GRID_DEFAULT_NODE_STRENGTH,
DWORD dwHorizOffset = FEEL_GRID_DEFAULT_HORIZ_OFFSET,
DWORD dwVertOffset = FEEL_GRID_DEFAULT_VERT_OFFSET,
DWORD dwHorizNodeSaturation = FEEL_GRID_DEFAULT_NODE_SATURATION,
DWORD dwVertNodeSaturation = FEEL_GRID_DEFAULT_NODE_SATURATION
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
//
// INTERNAL DATA
//
protected:
};
//
// INLINES
//
inline BOOL
CFeelGrid::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Grid);
}
#endif // !defined(AFX_FEELGrid_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,178 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelInertia.h
PURPOSE: Feelit API Inertia Effect Class
STARTED: 12/29/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELInertia_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELInertia_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include <windows.h>
#include "FeelCondition.h"
//================================================================
// Constants
//================================================================
#define FEEL_INERTIA_DEFAULT_COEFFICIENT 2500
#define FEEL_INERTIA_DEFAULT_SATURATION 10000
#define FEEL_INERTIA_DEFAULT_MIN_ACCELERATION 0
//
// FORCE --> FEEL Wrappers
//
#define FORCE_INERTIA_DEFAULT_COEFFICIENT FEEL_INERTIA_DEFAULT_COEFFICIENT
#define FORCE_INERTIA_DEFAULT_SATURATION FEEL_INERTIA_DEFAULT_SATURATION
#define FORCE_INERTIA_DEFAULT_MIN_ACCELERATION FEEL_INERTIA_DEFAULT_MIN_ACCELERATION
//================================================================
// CFeelInertia
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelInertia : public CFeelCondition
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelInertia();
// Destructor
virtual
~CFeelInertia();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
DWORD dwCoefficient,
DWORD dwSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwMinAcceleration = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionX = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionY = FEEL_EFFECT_DONT_CHANGE
);
BOOL
ChangeParametersPolar(
DWORD dwCoefficient,
DWORD dwSaturation,
DWORD dwMinAcceleration,
LONG lAngle
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
DWORD dwCoefficient = FEEL_INERTIA_DEFAULT_COEFFICIENT,
DWORD dwSaturation = FEEL_INERTIA_DEFAULT_SATURATION,
DWORD dwMinAcceleration = FEEL_INERTIA_DEFAULT_MIN_ACCELERATION,
DWORD dwfAxis = FEEL_EFFECT_AXIS_BOTH,
LONG lDirectionX = FEEL_EFFECT_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_EFFECT_DEFAULT_DIRECTION_Y
);
virtual BOOL
InitializePolar(
CFeelDevice* pDevice,
DWORD dwCoefficient,
DWORD dwSaturation,
DWORD dwMinAcceleration,
LONG lAngle
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
//
// INTERNAL DATA
//
protected:
};
//
// INLINES
//
inline BOOL
CFeelInertia::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Inertia);
}
#endif // !defined(AFX_FEELInertia_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,143 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelMouse.h
PURPOSE: Abstraction of Feelit mouse device
STARTED: 10/10/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#ifndef FeelMouse_h
#define FeelMouse_h
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelDevice.h"
//================================================================
// CFeelMouse
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelMouse : public CFeelDevice
{
//
// CONSTRUCTOR/DESCTRUCTOR
//
public:
// Constructor
CFeelMouse();
// Destructor
virtual
~CFeelMouse();
//
// ATTRIBUTES
//
public:
virtual LPIFEEL_API
GetAPI()
{ return m_piApi; }
virtual LPIFEEL_DEVICE
GetDevice()
{ return m_piDevice; }
BOOL
HaveForceFeelitMouse()
{ return m_piDevice != NULL; }
//
// OPERATIONS
//
public:
BOOL
Initialize(
HANDLE hinstApp,
HANDLE hwndApp,
DWORD dwCooperativeFlag = FEELIT_FCOOPLEVEL_FOREGROUND
);
virtual BOOL
ChangeScreenResolution(
BOOL bAutoSet,
DWORD dwXScreenSize = 0,
DWORD dwYScreenSize = 0
);
// Another syntax for SwitchToAbsoluteMode.
// The default is Absolute mode. Call only to switch to Relative mode or
// to switch back to Absolute mode.
virtual BOOL
SwitchToAbsoluteMode(
BOOL bAbsMode
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
virtual void
reset();
virtual BOOL
prepare_device();
//
// INTERNAL DATA
//
protected:
LPIFEEL_API m_piApi;
LPIFEEL_DEVICE m_piDevice;
};
#endif // ForceFeelitMouse_h

View File

@@ -0,0 +1,227 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelPeriodic.h
PURPOSE: Base Periodic Class for Feelit API Foundation Classes
STARTED: 11/03/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELPERIODIC_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELPERIODIC_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
//================================================================
// Constants
//================================================================
#define FEEL_PERIODIC_DEFAULT_DURATION 1000 // Milliseconds
#define FEEL_PERIODIC_DEFAULT_MAGNITUDE 5000
#define FEEL_PERIODIC_DEFAULT_PERIOD 100 // Milliseconds
#define FEEL_PERIODIC_DEFAULT_OFFSET 0
#define FEEL_PERIODIC_DEFAULT_PHASE 0 // Degrees
#define FEEL_PERIODIC_DEFAULT_DIRECTION_X 1 // Pixels
#define FEEL_PERIODIC_DEFAULT_DIRECTION_Y 0 // Pixels
#define FEEL_PERIODIC_DEFAULT_ANGLE 9000 // 100ths of degrees
//
// FORCE --> FEEL Wrappers
//
#define FORCE_PERIODIC_DEFAULT_DURATION FEEL_PERIODIC_DEFAULT_DURATION
#define FORCE_PERIODIC_DEFAULT_MAGNITUDE FEEL_PERIODIC_DEFAULT_MAGNITUDE
#define FORCE_PERIODIC_DEFAULT_PERIOD FEEL_PERIODIC_DEFAULT_PERIOD
#define FORCE_PERIODIC_DEFAULT_OFFSET FEEL_PERIODIC_DEFAULT_OFFSET
#define FORCE_PERIODIC_DEFAULT_PHASE FEEL_PERIODIC_DEFAULT_PHASE
#define FORCE_PERIODIC_DEFAULT_DIRECTION_X FEEL_PERIODIC_DEFAULT_DIRECTION_X
#define FORCE_PERIODIC_DEFAULT_DIRECTION_Y FEEL_PERIODIC_DEFAULT_DIRECTION_Y
#define FORCE_PERIODIC_DEFAULT_ANGLE FEEL_PERIODIC_DEFAULT_ANGLE
//================================================================
// CFeelPeriodic
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelPeriodic : public CFeelEffect
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructors
// You may use this form if you will immediately initialize it
// from an IFR file...
CFeelPeriodic();
// Otherwise use this form...
CFeelPeriodic(
const GUID& rguidEffect
);
// Destructor
virtual
~CFeelPeriodic();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
DWORD dwMagnitude,
DWORD dwPeriod = FEEL_EFFECT_DONT_CHANGE,
DWORD dwDuration = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionX = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionY = FEEL_EFFECT_DONT_CHANGE,
LONG lOffset = FEEL_EFFECT_DONT_CHANGE,
DWORD dwPhase = FEEL_EFFECT_DONT_CHANGE,
LPFEEL_ENVELOPE pEnvelope = (LPFEEL_ENVELOPE) FEEL_EFFECT_DONT_CHANGE_PTR
);
BOOL
ChangeParametersPolar(
DWORD dwMagnitude,
DWORD dwPeriod = FEEL_EFFECT_DONT_CHANGE,
DWORD dwDuration = FEEL_EFFECT_DONT_CHANGE,
LONG lAngle = FEEL_EFFECT_DONT_CHANGE,
LONG lOffset = FEEL_EFFECT_DONT_CHANGE,
DWORD dwPhase = FEEL_EFFECT_DONT_CHANGE,
LPFEEL_ENVELOPE pEnvelope = (LPFEEL_ENVELOPE) FEEL_EFFECT_DONT_CHANGE_PTR
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
DWORD dwMagnitude = FEEL_PERIODIC_DEFAULT_MAGNITUDE,
DWORD dwPeriod = FEEL_PERIODIC_DEFAULT_PERIOD,
DWORD dwDuration = FEEL_PERIODIC_DEFAULT_DURATION,
LONG lDirectionX = FEEL_PERIODIC_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_PERIODIC_DEFAULT_DIRECTION_Y,
LONG lOffset = FEEL_PERIODIC_DEFAULT_OFFSET,
DWORD dwPhase = FEEL_PERIODIC_DEFAULT_PHASE,
LPFEEL_ENVELOPE pEnvelope = NULL
);
virtual BOOL
InitializePolar(
CFeelDevice* pDevice,
DWORD dwMagnitude = FEEL_PERIODIC_DEFAULT_MAGNITUDE,
DWORD dwPeriod = FEEL_PERIODIC_DEFAULT_PERIOD,
DWORD dwDuration = FEEL_PERIODIC_DEFAULT_DURATION,
LONG lAngle = FEEL_PERIODIC_DEFAULT_ANGLE,
LONG lOffset = FEEL_PERIODIC_DEFAULT_OFFSET,
DWORD dwPhase = FEEL_PERIODIC_DEFAULT_PHASE,
LPFEEL_ENVELOPE pEnvelope = NULL
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
BOOL
set_parameters(
DWORD dwfCoordinates,
LONG lDirection0,
LONG lDirection1,
DWORD dwDuration,
DWORD dwMagnitude,
DWORD dwPeriod,
LONG lOffset,
DWORD dwPhase,
LPFEEL_ENVELOPE pEnvelope
);
//
// INTERNAL DATA
//
protected:
FEEL_PERIODIC m_Periodic;
};
//
// INLINES
//
inline BOOL
CFeelPeriodic::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Sine) ||
IsEqualGUID(guid, GUID_Feel_Square) ||
IsEqualGUID(guid, GUID_Feel_Triangle) ||
IsEqualGUID(guid, GUID_Feel_SawtoothUp) ||
IsEqualGUID(guid, GUID_Feel_SawtoothDown);
}
#endif // !defined(AFX_FEELPERIODIC_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,302 @@
/**********************************************************************
Copyright (c) 1999 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelProjects.h
PURPOSE: CFeelProject
Manages a set of forces in a project.
There will be a project for each opened IFR file.
CFeelProjects
Manages a set of projects
STARTED: 2/22/99 by Jeff Mallett
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#ifndef __FEEL_PROJECTS_H
#define __FEEL_PROJECTS_H
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FFCErrors.h"
#include "FeelBaseTypes.h"
#include "FeelDevice.h"
#include "FeelCompoundEffect.h"
class CFeelProjects;
//================================================================
// CFeelProject
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelProject
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
CFeelProject() :
m_hProj(NULL), m_pCreatedEffects(NULL),
m_pNext(NULL), m_pDevice(NULL)
{ }
~CFeelProject();
void
Close();
//
// ATTRIBUTES
//
public:
CFeelDevice*
GetDevice() const
{ return m_pDevice; }
BOOL
GetIsOpen() const
{ return m_hProj != NULL; }
CFeelCompoundEffect *
GetCreatedEffect(
LPCSTR lpszEffectName
);
//
// OPERATIONS
//
public:
BOOL
Start(
LPCSTR lpszEffectName = NULL,
DWORD dwIterations = 1,
DWORD dwFlags = 0,
CFeelDevice* pDevice = NULL
);
BOOL
Stop(
LPCSTR lpszEffectName = NULL
);
BOOL
OpenFile(
LPCSTR lpszFilePath,
CFeelDevice *pDevice
);
LoadProjectObjectPointer(
BYTE *pMem,
CFeelDevice *pDevice
);
CFeelCompoundEffect *
CreateEffect(
LPCSTR lpszEffectName,
CFeelDevice* pDevice = NULL
);
CFeelCompoundEffect *
CreateEffectByIndex(
int nEffectIndex,
CFeelDevice* pDevice = NULL
);
CFeelCompoundEffect *
AddEffect(
LPCSTR lpszEffectName,
GENERIC_EFFECT_PTR pObject
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
void
set_next(
CFeelProject *pNext
)
{ m_pNext = pNext; }
CFeelProject *
get_next() const
{ return m_pNext; }
void
append_effect_to_list(
CFeelCompoundEffect* pEffect
);
IFREffect **
create_effect_structs(
LPCSTR lpszEffectName,
int &nEff
);
IFREffect **
create_effect_structs_by_index(
int nEffectIndex,
int &nEff
);
BOOL
release_effect_structs(
IFREffect **hEffects
);
//
// FRIENDS
//
public:
friend BOOL
CFeelEffect::InitializeFromProject(
CFeelProject &project,
LPCSTR lpszEffectName,
CFeelDevice* pDevice /* = NULL */
);
friend class CFeelProjects;
//
// INTERNAL DATA
//
protected:
HIFRPROJECT m_hProj;
CFeelCompoundEffect* m_pCreatedEffects;
CFeelDevice* m_pDevice;
private:
CFeelProject* m_pNext;
};
//================================================================
// CFeelProjects
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelProjects
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
CFeelProjects() : m_pProjects(NULL) { }
~CFeelProjects();
void
Close();
//
// ATTRIBUTES
//
public:
CFeelProject *
GetProject(
int index = 0
);
//
// OPERATIONS
//
public:
BOOL
Stop();
long
OpenFile(
LPCSTR lpszFilePath,
CFeelDevice *pDevice
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
//
// INTERNAL DATA
//
protected:
CFeelProject *m_pProjects;
};
#endif // __FEEL_PROJECTS_H

View File

@@ -0,0 +1,194 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelRamp.h
PURPOSE: Base Ramp Force Class for Feelit API Foundation Classes
STARTED: 12/11/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELRAMP_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELRAMP_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
//================================================================
// Constants
//================================================================
#define FEEL_RAMP_DEFAULT_DURATION 1000 // Milliseconds
#define FEEL_RAMP_DEFAULT_MAGNITUDE_START 0
#define FEEL_RAMP_DEFAULT_MAGNITUDE_END 10000
//
// FORCE --> FEEL Wrappers
//
#define FORCE_RAMP_DEFAULT_DURATION FEEL_RAMP_DEFAULT_DURATION
#define FORCE_RAMP_DEFAULT_MAGNITUDE_START FEEL_RAMP_DEFAULT_MAGNITUDE_START
#define FORCE_RAMP_DEFAULT_MAGNITUDE_END FEEL_RAMP_DEFAULT_MAGNITUDE_END
//================================================================
// CFeelRamp
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelRamp : public CFeelEffect
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelRamp();
// Destructor
virtual
~CFeelRamp();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
LONG lDirectionX,
LONG lDirectionY,
DWORD dwDuration = FEEL_EFFECT_DONT_CHANGE,
LONG lMagStart = FEEL_EFFECT_DONT_CHANGE,
LONG lMagEnd = FEEL_EFFECT_DONT_CHANGE,
LPFEEL_ENVELOPE pEnvelope = (LPFEEL_ENVELOPE) FEEL_EFFECT_DONT_CHANGE_PTR
);
BOOL
ChangeParametersPolar(
LONG lAngle,
DWORD dwDuration = FEEL_EFFECT_DONT_CHANGE,
LONG lMagStart = FEEL_EFFECT_DONT_CHANGE,
LONG lMagEnd = FEEL_EFFECT_DONT_CHANGE,
LPFEEL_ENVELOPE pEnvelope = (LPFEEL_ENVELOPE) FEEL_EFFECT_DONT_CHANGE_PTR
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
LONG lDirectionX = FEEL_EFFECT_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_EFFECT_DEFAULT_DIRECTION_Y,
DWORD dwDuration = FEEL_RAMP_DEFAULT_DURATION,
LONG lMagStart = FEEL_RAMP_DEFAULT_MAGNITUDE_START,
LONG lMagEnd = FEEL_RAMP_DEFAULT_MAGNITUDE_END,
LPFEEL_ENVELOPE pEnvelope = NULL
);
virtual BOOL
InitializePolar(
CFeelDevice* pDevice,
LONG lAngle = FEEL_EFFECT_DEFAULT_ANGLE,
DWORD dwDuration = FEEL_RAMP_DEFAULT_DURATION,
LONG lMagStart = FEEL_RAMP_DEFAULT_MAGNITUDE_START,
LONG lMagEnd = FEEL_RAMP_DEFAULT_MAGNITUDE_END,
LPFEEL_ENVELOPE pEnvelope = NULL
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
BOOL
set_parameters(
DWORD dwfCoordinates,
LONG lDirection0,
LONG lDirection1,
DWORD dwDuration,
LONG lMagStart,
LONG lMagEnd,
LPFEEL_ENVELOPE pEnvelope
);
//
// INTERNAL DATA
//
protected:
FEEL_RAMPFORCE m_RampForce;
};
//
// INLINES
//
inline BOOL
CFeelRamp::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_RampForce);
}
#endif // !defined(AFX_FEELRAMP_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,191 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelSpring.h
PURPOSE: Feelit API Spring Class
STARTED: 10/10/97
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FEELSPRING_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FEELSPRING_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include <windows.h>
#include "FeelCondition.h"
//================================================================
// Constants
//================================================================
#define FEEL_SPRING_DEFAULT_STIFFNESS 2500
#define FEEL_SPRING_DEFAULT_SATURATION 10000
#define FEEL_SPRING_DEFAULT_DEADBAND 100
#define FEEL_SPRING_DEFAULT_CENTER_POINT FEEL_EFFECT_MOUSE_POS_AT_START
#define FEEL_SPRING_DEFAULT_DIRECTION_X 1
#define FEEL_SPRING_DEFAULT_DIRECTION_Y 0
#define FEEL_SPRING_DEFAULT_ANGLE 0
//
// FORCE --> FEEL Wrappers
//
#define FORCE_SPRING_DEFAULT_STIFFNESS FEEL_SPRING_DEFAULT_STIFFNESS
#define FORCE_SPRING_DEFAULT_SATURATION FEEL_SPRING_DEFAULT_SATURATION
#define FORCE_SPRING_DEFAULT_DEADBAND FEEL_SPRING_DEFAULT_DEADBAND
#define FORCE_SPRING_DEFAULT_CENTER_POINT FEEL_SPRING_DEFAULT_CENTER_POINT
#define FORCE_SPRING_DEFAULT_DIRECTION_X FEEL_SPRING_DEFAULT_DIRECTION_X
#define FORCE_SPRING_DEFAULT_DIRECTION_Y FEEL_SPRING_DEFAULT_DIRECTION_Y
#define FORCE_SPRING_DEFAULT_ANGLE FEEL_SPRING_DEFAULT_ANGLE
//================================================================
// CFeelSpring
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelSpring : public CFeelCondition
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelSpring();
// Destructor
virtual
~CFeelSpring();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
BOOL
ChangeParameters(
POINT pntCenter,
LONG lStiffness = FEEL_EFFECT_DONT_CHANGE,
DWORD dwSaturation = FEEL_EFFECT_DONT_CHANGE,
DWORD dwDeadband = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionX = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionY = FEEL_EFFECT_DONT_CHANGE
);
BOOL
ChangeParametersPolar(
POINT pntCenter,
LONG lStiffness,
DWORD dwSaturation,
DWORD dwDeadband,
LONG lAngle
);
//
// OPERATIONS
//
public:
virtual BOOL
Initialize(
CFeelDevice* pDevice,
LONG lStiffness = FEEL_SPRING_DEFAULT_STIFFNESS,
DWORD dwSaturation = FEEL_SPRING_DEFAULT_SATURATION,
DWORD dwDeadband = FEEL_SPRING_DEFAULT_DEADBAND,
DWORD dwfAxis = FEEL_EFFECT_AXIS_BOTH,
POINT pntCenter = FEEL_SPRING_DEFAULT_CENTER_POINT,
LONG lDirectionX = FEEL_SPRING_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_SPRING_DEFAULT_DIRECTION_Y,
BOOL bUseDeviceCoordinates = FALSE
);
virtual BOOL
InitializePolar(
CFeelDevice* pDevice,
LONG lStiffness,
DWORD dwSaturation,
DWORD dwDeadband,
POINT pntCenter,
LONG lAngle,
BOOL bUseDeviceCoordinates = FALSE
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
//
// INTERNAL DATA
//
protected:
};
//
// INLINES
//
inline BOOL
CFeelSpring::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Spring);
}
#endif // !defined(AFX_FEELSPRING_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

View File

@@ -0,0 +1,287 @@
/**********************************************************************
Copyright (c) 1997 Immersion Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation may be granted without fee;
interested parties are encouraged to request permission from
Immersion Corporation
2158 Paragon Drive
San Jose, CA 95131
408-467-1900
IMMERSION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL IMMERSION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
FILE: FeelTexture.h
PURPOSE: Texture Class for Feelit API Foundation Classes
STARTED: 2/27/98
NOTES/REVISIONS:
3/2/99 jrm (Jeff Mallett): Force-->Feel renaming
3/2/99 jrm: Added GetIsCompatibleGUID
3/15/99 jrm: __declspec(dllimport/dllexport) the whole class
**********************************************************************/
#if !defined(AFX_FeelTexture_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)
#define AFX_FeelTexture_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _FFCDLL_
#define DLLFFC __declspec(dllimport)
#else
#define DLLFFC __declspec(dllexport)
#endif
#include <windows.h>
#include "FeelBaseTypes.h"
#include "FeelEffect.h"
//================================================================
// Constants
//================================================================
const POINT FEEL_TEXTURE_PT_NULL = { 0, 0 };
const POINT FEEL_TEXTURE_DEFAULT_OFFSET_POINT = { 0, 0};
#define FEEL_TEXTURE_DEFAULT_MAGNITUDE 5000
#define FEEL_TEXTURE_DEFAULT_WIDTH 10
#define FEEL_TEXTURE_DEFAULT_SPACING 20
//
// FORCE --> FEEL Wrappers
//
#define FORCE_TEXTURE_PT_NULL FEEL_TEXTURE_PT_NULL
#define FORCE_TEXTURE_DEFAULT_OFFSET_POINT FEEL_TEXTURE_DEFAULT_OFFSET_POINT
#define FORCE_TEXTURE_DEFAULT_MAGNITUDE FEEL_TEXTURE_DEFAULT_MAGNITUDE
#define FORCE_TEXTURE_DEFAULT_WIDTH FEEL_TEXTURE_DEFAULT_WIDTH
#define FORCE_TEXTURE_DEFAULT_SPACING FEEL_TEXTURE_DEFAULT_SPACING
//================================================================
// CFeelTexture
//================================================================
//
// ------ PUBLIC INTERFACE ------
//
class DLLFFC CFeelTexture : public CFeelEffect
{
//
// CONSTRUCTOR/DESTRUCTOR
//
public:
// Constructor
CFeelTexture();
// Destructor
virtual
~CFeelTexture();
//
// ATTRIBUTES
//
public:
virtual BOOL
GetIsCompatibleGUID(
GUID &guid
);
// Use this form for single-axis and dual-axis effects
BOOL
ChangeTextureParams(
LPCFEELIT_TEXTURE pTextureX,
LPCFEELIT_TEXTURE pTextureY
);
// Use this form for directional effects
BOOL
ChangeTextureParams(
LPCFEELIT_TEXTURE pTexture,
LONG lDirectionX,
LONG lDirectionY
);
// Use this form for directional effects
BOOL
ChangeTextureParamsPolar(
LPCFEELIT_TEXTURE pTexture,
LONG lAngle
);
// Use this form for single-axis, dual-axis symetrical, or directional effects
BOOL
ChangeTextureParams(
LONG lPosBumpMag = FEEL_EFFECT_DONT_CHANGE,
DWORD dwPosBumpWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwPosBumpSpacing = FEEL_EFFECT_DONT_CHANGE,
LONG lNegBumpMag = FEEL_EFFECT_DONT_CHANGE,
DWORD dwNegBumpWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwNegBumpSpacing = FEEL_EFFECT_DONT_CHANGE,
POINT pntOffset = FEEL_EFFECT_DONT_CHANGE_POINT,
LONG lDirectionX = FEEL_EFFECT_DONT_CHANGE,
LONG lDirectionY = FEEL_EFFECT_DONT_CHANGE
);
// Use this form for single-axis, dual-axis symetrical, or directional effects
BOOL
ChangeTextureParamsPolar(
LONG lPosBumpMag = FEEL_EFFECT_DONT_CHANGE,
DWORD dwPosBumpWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwPosBumpSpacing = FEEL_EFFECT_DONT_CHANGE,
LONG lNegBumpMag = FEEL_EFFECT_DONT_CHANGE,
DWORD dwNegBumpWidth = FEEL_EFFECT_DONT_CHANGE,
DWORD dwNegBumpSpacing = FEEL_EFFECT_DONT_CHANGE,
POINT pntOffset = FEEL_EFFECT_DONT_CHANGE_POINT,
LONG lAngle = FEEL_EFFECT_DONT_CHANGE
);
BOOL
SetOffset(
POINT pntOffset
);
//
// OPERATIONS
//
public:
// Use this form for single-axis and dual-axis effects
BOOL
InitTexture(
CFeelDevice* pDevice,
LPCFEELIT_TEXTURE pTextureX,
LPCFEELIT_TEXTURE pTextureY
);
// Use this form for directional effects
BOOL
InitTexture(
CFeelDevice* pDevice,
LPCFEELIT_TEXTURE pTexture,
LONG lDirectionX,
LONG lDirectionY
);
// Use this form for directional effects
BOOL
InitTexturePolar(
CFeelDevice* pDevice,
LPCFEELIT_TEXTURE pTexture,
LONG lAngle
);
// Use this form for single-axis, dual-axis symetrical, or directional effects
BOOL
InitTexture(
CFeelDevice* pDevice,
LONG lPosBumpMag = FEEL_TEXTURE_DEFAULT_MAGNITUDE,
DWORD dwPosBumpWidth = FEEL_TEXTURE_DEFAULT_WIDTH,
DWORD dwPosBumpSpacing = FEEL_TEXTURE_DEFAULT_SPACING,
LONG lNegBumpMag = FEEL_TEXTURE_DEFAULT_MAGNITUDE,
DWORD dwNegBumpWidth = FEEL_TEXTURE_DEFAULT_WIDTH,
DWORD dwNegBumpSpacing = FEEL_TEXTURE_DEFAULT_SPACING,
DWORD dwfAxis = FEEL_EFFECT_AXIS_BOTH,
POINT pntOffset = FEEL_TEXTURE_DEFAULT_OFFSET_POINT,
LONG lDirectionX = FEEL_EFFECT_DEFAULT_DIRECTION_X,
LONG lDirectionY = FEEL_EFFECT_DEFAULT_DIRECTION_Y
);
// Use this form for directional effects
BOOL
InitTexturePolar(
CFeelDevice* pDevice,
LONG lPosBumpMag = FEEL_TEXTURE_DEFAULT_MAGNITUDE,
DWORD dwPosBumpWidth = FEEL_TEXTURE_DEFAULT_WIDTH,
DWORD dwPosBumpSpacing = FEEL_TEXTURE_DEFAULT_SPACING,
LONG lNegBumpMag = FEEL_TEXTURE_DEFAULT_MAGNITUDE,
DWORD dwNegBumpWidth = FEEL_TEXTURE_DEFAULT_WIDTH,
DWORD dwNegBumpSpacing = FEEL_TEXTURE_DEFAULT_SPACING,
POINT pntOffset = FEEL_TEXTURE_DEFAULT_OFFSET_POINT,
LONG lAngle = FEEL_EFFECT_DEFAULT_ANGLE
);
//
// ------ PRIVATE INTERFACE ------
//
//
// HELPERS
//
protected:
BOOL
set_parameters(
DWORD dwfAxis,
DWORD dwfCoordinates,
LONG lDirection0,
LONG lDirection1,
LPCFEELIT_TEXTURE pTextureX,
LPCFEELIT_TEXTURE pTextureY
);
BOOL
set_parameters(
DWORD dwfAxis,
DWORD dwfCoordinates,
LONG lDirection0,
LONG lDirection1,
LONG lPosBumpMag,
DWORD dwPosBumpWidth,
DWORD dwPosBumpSpacing,
LONG lNegBumpMag,
DWORD dwNegBumpWidth,
DWORD dwNegBumpSpacing,
POINT pntOffset
);
//
// INTERNAL DATA
//
FEEL_TEXTURE m_aTexture[2];
DWORD m_dwfAxis;
protected:
};
//
// INLINES
//
inline BOOL
CFeelTexture::GetIsCompatibleGUID(GUID &guid)
{
return IsEqualGUID(guid, GUID_Feel_Texture);
}
#endif // !defined(AFX_FeelTexture_H__135B88C4_4175_11D1_B049_0020AF30269A__INCLUDED_)

File diff suppressed because it is too large Load Diff

680
code/win32/FeelIt/fffx.cpp Normal file
View File

@@ -0,0 +1,680 @@
// Filename:- fffx.cpp (Force-Feedback FX)
//
// (Function names with "_FF_" beginnings are my internal stuff only, "FF_" beginnings are for external stuff)
//
#define INITGUID // this will need removing if already defined in someone else's module. Only one must exist in whole game
#include "../../client/client.h"
#include "../win_local.h"
#include "ffc.h"
#include "fffx_feel.h"
// these now MUST default to NULL...
//
CFeelDevice *g_pFeelDevice=NULL;
CFeelProject *g_pFeelProject=NULL;
CFeelSpring *g_pFeelSpring=NULL;
ffFX_e ffFXLoaded[MAX_CONCURRENT_FFFXs];
//extern HINSTANCE global_hInstance;
//extern HWND cl_hwnd;
extern WinVars_t g_wv;
extern cvar_t *in_joystick;
cvar_t *use_ff;
cvar_t *ff_defaultTension;
void _FF_ClearUsageArray(void);
void _FF_ClearFXSlot(int i);
void _FF_ClearCreatePlayFXSlot(int iSlotNum, ffFX_e fffx);
void _FF_CreatePlayFXSlot(int iSlotNum, ffFX_e fffx);
void _FF_PlayFXSlot(int iSlotNum);
// externally accessed
qboolean FF_IsAvailable(void)
{
return g_pFeelDevice?TRUE:FALSE;
}
qboolean FF_IsMouse(void)
{
if (g_pFeelDevice && (g_pFeelDevice->GetDeviceType() == FEEL_DEVICETYPE_MOUSE))
return TRUE;
return FALSE;
}
// 4 semi-useful CMD functions...
void CMD_FF_UseMouse(void)
{
FF_Init(TRUE);
}
void CMD_FF_UseJoy(void)
{
FF_Init(FALSE);
}
// arg = 0..3
//
void CMD_FF_Tension(void)
{
if (Cmd_Argc() != 2)
{
Com_Printf ("ff_tension <tension [0..3]> (default = 1)\n");
return;
}
int iTension = atoi(Cmd_Argv(1));
if (iTension<0 || iTension>3)
{
Com_Printf ("ff_tension <tension [0..3]>\n");
return;
}
if (g_pFeelSpring)
{
Com_Printf(va("Setting tension %d\n",iTension));
Cvar_Set(ff_defaultTension->name,va("%d",iTension));
FF_SetTension(iTension);
}
else
{
Com_Printf("No spring device\n");
}
}
typedef struct
{
char* psName;
ffFX_e eFXNum;
}FFFX_LOOKUP;
#define FFFX_ENTRY(blah) {#blah,(ffFX_e)fffx_ ## blah}
FFFX_LOOKUP FFFX_Lookup[fffx_NUMBEROF]=
{
FFFX_ENTRY( RandomNoise ),
FFFX_ENTRY( AircraftCarrierTakeOff ), // this one is pointless / dumb
FFFX_ENTRY( BasketballDribble ),
FFFX_ENTRY( CarEngineIdle ),
FFFX_ENTRY( ChainsawIdle ),
FFFX_ENTRY( ChainsawInAction ),
FFFX_ENTRY( DieselEngineIdle ),
FFFX_ENTRY( Jump ),
FFFX_ENTRY( Land ),
FFFX_ENTRY( MachineGun ),
FFFX_ENTRY( Punched ),
FFFX_ENTRY( RocketLaunch ),
FFFX_ENTRY( SecretDoor ),
FFFX_ENTRY( SwitchClick ),
FFFX_ENTRY( WindGust ),
FFFX_ENTRY( WindShear ), // also pretty crap
FFFX_ENTRY( Pistol ),
FFFX_ENTRY( Shotgun ),
FFFX_ENTRY( Laser1 ),
FFFX_ENTRY( Laser2 ),
FFFX_ENTRY( Laser3 ),
FFFX_ENTRY( Laser4 ),
FFFX_ENTRY( Laser5 ),
FFFX_ENTRY( Laser6 ),
FFFX_ENTRY( OutOfAmmo ),
FFFX_ENTRY( LightningGun ),
FFFX_ENTRY( Missile ),
FFFX_ENTRY( GatlingGun ),
FFFX_ENTRY( ShortPlasma ),
FFFX_ENTRY( PlasmaCannon1 ),
FFFX_ENTRY( PlasmaCannon2 ),
FFFX_ENTRY( Cannon )
};
void CMD_FF_Play(void)
{
if (Cmd_Argc() != 2 && Cmd_Argc() != 3)
{
Com_Printf ("ff_play <n> (where n = 0..%d) || ff_play name \"fxname\"\n",fffx_NUMBEROF-1);
return;
}
ffFX_e eFX = fffx_NULL;
if (!Q_stricmp(Cmd_Argv(1),"name"))
{
if (Cmd_Argc() != 3)
{
Com_Printf ("ff_play <n> (where n = 0..%d) || ff_play name \"fxname\"\n",0,fffx_NUMBEROF-1);
return;
}
for (int i=0; i<fffx_NUMBEROF; i++)
{
if (!Q_stricmp(FFFX_Lookup[i].psName,Cmd_Argv(2)))
{
eFX = FFFX_Lookup[i].eFXNum;
break;
}
}
}
else
{
eFX = (ffFX_e) atoi(Cmd_Argv(1));
}
if (eFX>=0 && eFX<fffx_NUMBEROF)
{
Com_Printf ("Playing FFFX # %d...(%s)\n",eFX,FFFX_Lookup[eFX].psName);
FF_Play(eFX);
}
}
// arg 0..n..10000
void CMD_FF_Spring(void)
{
if (Cmd_Argc() != 2)
{
Com_Printf ("ff_spring <0..10000>\n");
return;
}
long lSpring = atoi(Cmd_Argv(1));
if (lSpring<0 || lSpring>10000)
{
Com_Printf ("ff_spring <0..10000>\n");
return;
}
if (g_pFeelSpring)
{
Com_Printf(va("Setting spring to %d\n",lSpring));
FF_SetSpring(lSpring);
}
else
{
Com_Printf("No spring device\n");
}
}
// Called once only during .exe lifetime...
//
void FF_Init(qboolean bTryMouseFirst)
{
FF_Shutdown();
Cmd_AddCommand ("ff_usemouse", CMD_FF_UseMouse);
Cmd_AddCommand ("ff_usejoy", CMD_FF_UseJoy);
Cmd_AddCommand ("ff_tension", CMD_FF_Tension);
Cmd_AddCommand ("ff_spring", CMD_FF_Spring);
Cmd_AddCommand ("ff_play", CMD_FF_Play);
// ====================================
Com_Printf("\n" S_COLOR_CYAN "------- Force Feedback Initialization -------\n");
// for the moment default to OFF until usage tables are in...
use_ff = Cvar_Get ("use_ff", "0", CVAR_ARCHIVE);
ff_defaultTension = Cvar_Get ("ff_defaultTension", "1", CVAR_ARCHIVE);
// don't bother initializing if user specifically turned off force feedback...
//
if (!use_ff->value)
{
Com_Printf("...inhibited, not initializing\n\n");
return;
}
Com_Printf("Creating feedback device:\n");
if ( bTryMouseFirst )
{
CFeelMouse* m_pFeelMouse = new CFeelMouse;
if (m_pFeelMouse)
{
if (m_pFeelMouse->Initialize( g_wv.hInstance, g_wv.hWnd))
{
g_pFeelDevice = m_pFeelMouse;
}
else
{
delete m_pFeelMouse;
m_pFeelMouse = NULL;
}
}
}
if (!g_pFeelDevice)
{
// try a general DI FF device...
//
CFeelDXDevice* m_pFeelDXDevice = new CFeelDXDevice;
if (m_pFeelDXDevice)
{
if (m_pFeelDXDevice->Initialize( g_wv.hInstance, g_wv.hWnd))
{
g_pFeelDevice = m_pFeelDXDevice;
}
else
{
delete m_pFeelDXDevice;
m_pFeelDXDevice = NULL;
}
}
}
// g_pFeelDevice = CFeelDevice::CreateDevice(g_wv.hInstance, g_wv.hWnd);
if (!g_pFeelDevice)
{
Com_Printf("...no feedback devices found\n");
return;
}
else
{
_FeelInitEffects();
for (int _i=0; _i<MAX_CONCURRENT_FFFXs; _i++)
{
ffFXLoaded[_i] = fffx_NULL;
}
if (g_pFeelDevice->GetDeviceType() == FEEL_DEVICETYPE_MOUSE)
{
Com_Printf("...found FEELit Mouse\n");
g_pFeelDevice->UsesWin32MouseServices(FALSE);
}
else if (g_pFeelDevice->GetDeviceType() == FEEL_DEVICETYPE_DIRECTINPUT)
{
Com_Printf("...found feedback device\n");
g_pFeelSpring = new CFeelSpring;
if (!g_pFeelSpring->Initialize( g_pFeelDevice,
2000, //10000, // LONG lStiffness = FEEL_SPRING_DEFAULT_STIFFNESS
10000, //5000, // DWORD dwSaturation = FEEL_SPRING_DEFAULT_SATURATION
1000, //0, // DWORD dwDeadband = FEEL_SPRING_DEFAULT_DEADBAND // must be 0..n..10000
FEEL_EFFECT_AXIS_BOTH, // DWORD dwfAxis = FEEL_EFFECT_AXIS_BOTH
FEEL_SPRING_DEFAULT_CENTER_POINT, // POINT pntCenter = FEEL_SPRING_DEFAULT_CENTER_POINT
FEEL_EFFECT_DEFAULT_DIRECTION_X, // LONG lDirectionX = FEEL_EFFECT_DEFAULT_DIRECTION_X
FEEL_EFFECT_DEFAULT_DIRECTION_Y, // LONG lDirectionY = FEEL_EFFECT_DEFAULT_DIRECTION_Y
TRUE // TRUE = rel coords, else screen coords // BOOL bUseDeviceCoordinates = FALSE
)
)
{
Com_Printf("...(no device return spring)\n");
delete g_pFeelSpring;
g_pFeelSpring = NULL;
}
else
{
Com_Printf("...device return spring ok\n");
FF_SetTension(ff_defaultTension->integer); // 0..3
}
}// if (g_pFeelDevice->GetDeviceType() == FEEL_DEVICETYPE_DIRECTINPUT)
}
}
// call this at app shutdown... (or when switching controllers)
//
// (also called by FF_Init in case you're switching controllers so do everything
// as if-protected)
//
void FF_Shutdown(void)
{
// note the check first before print, since this is called from the init code
// as well, and it'd be weird to see the sutdown string first...
//
if (g_pFeelSpring || g_pFeelDevice)
{
Com_Printf("\n" S_COLOR_CYAN "------- Force Feedback Shutdown -------\n");
}
if (g_pFeelSpring)
{
Com_Printf("...closing return spring\n");
delete g_pFeelSpring;
g_pFeelSpring = NULL;
}
if (g_pFeelDevice)
{
Com_Printf("...closing feedback device\n");
_FF_ClearUsageArray();
delete g_pFeelDevice;
g_pFeelDevice = NULL;
}
Cmd_RemoveCommand ("ff_usemouse");
Cmd_RemoveCommand ("ff_usejoy");
Cmd_RemoveCommand ("ff_tension");
Cmd_RemoveCommand ("ff_spring");
Cmd_RemoveCommand ("ff_play");
}
void FF_EnsurePlaying(ffFX_e fffx)
{
if (fffx<0 || fffx>=fffx_NUMBEROF)
return;
// if user has specifically turned off force feedback at command line,
// or is not using the joystick as current input method (though this can be ignored because stick has a hands-on sensor),
// then forget it...
//
if (!use_ff->value)
return;
if (FF_IsAvailable())
{
// Have we already got this FF FX loaded?
//
for (int i=0; i<MAX_CONCURRENT_FFFXs; i++)
{
if (ffFXLoaded[i]==fffx)
{
// yes, is it playing now?
//
if (_FeelEffectPlaying(i))
return;
_FF_PlayFXSlot(i);
return;
}
}
// if we got this far then it ain't even loaded, so...
//
FF_Play(fffx);
}// if (FF_IsAvailable())
}// void FF_EnsurePlaying(ffFX_e fffx)
// strictly speaking I suppose I should check that the current player is actually using a
// joystick as his current input method before sending an FF FX to it, but considering the stick
// will only move if he's holding it then he's daft to hold it and still use the keyboard or
// something, so for now I'll just leave it in to avoid yet another IF statement...
//
// Since the joystick appears to run out of FX ram very quickly I'll have to use a sort of rolling
// buffer principle I think...
//
// (watch the mid-func returns if you put anything at the end!)
//
void _FF_Play(ffFX_e fffx)
{
int i;
if (fffx<0 || fffx>=fffx_NUMBEROF)
return;
// if user has specifically turned off force feedback at command line,
// or is not using the joystick as current input method (though this can be ignored because stick has a hands-on sensor),
// then forget it...
//
if (!use_ff->value)
return;
if (FF_IsAvailable())
{
// first, search for an instance of this FF FX that's already loaded, if found, start it off again...
//
for (i=0; i<MAX_CONCURRENT_FFFXs; i++)
{
if (ffFXLoaded[i]==fffx)
{
_FF_PlayFXSlot(i);
return;
}
}
// ok, so we didn't find one of these already here, so search for any FF FX that's loaded but
// finished playing...
//
// (note that I prefer to re-use an existing one before looking for an empty slot so
// there's less chance of the create call failing because of lack of j/s ram)
//
for (i=0; i<MAX_CONCURRENT_FFFXs; i++)
{
if (ffFXLoaded[i] != fffx_NULL)
{
// slot has an effect, has it finished?
//
if (!_FeelEffectPlaying(i))
{
_FF_ClearCreatePlayFXSlot(i,fffx);
return;
}
}// if (lpDIEffectsCreated[i])
}// for (i=0; i<MAX_CONCURRENT_FFFXs; i++)
// At this point we haven't found an existing one to re-start, and there are no dead ones to reclaim, so
// we just look for an empty slot...
//
for (i=0; i<MAX_CONCURRENT_FFFXs; i++)
{
if (ffFXLoaded[i] == fffx_NULL)
{
_FF_CreatePlayFXSlot(i,fffx);
return;
}
}
// Hmmm, we seem to have several FF FX's playing at once and we need another. Let's just trash one of the slots
// and take it over anyway. I'll use the second slot in case the first is some sort of permanent engine throb
// or similar...
//
_FF_ClearCreatePlayFXSlot(1,fffx);
}// if (FF_IsAvailable())
}// void FF_Play(ffFX_e fffx)
// hack-wrapper around original play() function because the stick keeps going slack!
//
void FF_Play(ffFX_e fffx)
{
if (FF_IsAvailable())
{
_FF_Play(fffx);
FF_SetTension(ff_defaultTension->integer);
}
}
void _FF_ClearUsageArray(void)
{
int i;
for (i=0; i<MAX_CONCURRENT_FFFXs; i++)
{
_FF_ClearFXSlot(i);
}
}
// called from more than one place, subroutinised to avoid bugs if method changes...
//
void _FF_ClearFXSlot(int i)
{
if (ffFXLoaded[i] != fffx_NULL)
{
_FeelClearEffect(i);
}
ffFXLoaded [i]=fffx_NULL;
}
void _FF_ClearCreatePlayFXSlot(int iSlotNum, ffFX_e fffx)
{
// if this slot has a FF FX, zap it...
//
if (ffFXLoaded[iSlotNum] != fffx_NULL)
{
// if playing, stop it...
//
if (_FeelEffectPlaying(iSlotNum))
{
if (!_FeelStopEffect(iSlotNum))
{
return;
}
}
}
_FF_ClearFXSlot(iSlotNum); // so slot is left clear if err creating next ffFX_e
_FF_CreatePlayFXSlot(iSlotNum,fffx);
}
void _FF_CreatePlayFXSlot(int iSlotNum, ffFX_e fffx)
{
if (!_FeelCreateEffect(iSlotNum, fffx, g_pFeelDevice))
{
return;
}
// effect created ok, so record it's type...
//
ffFXLoaded[iSlotNum]=fffx;
//
// ... and start it playing...
//
_FF_PlayFXSlot(iSlotNum);
}
void _FF_PlayFXSlot(int iSlotNum)
{
#define FFFX_DURATION 1 // 1 = duration (repeat count?) (could be 'INFINITE')
#define FFFX_FLAGS 0 // 0 = special flags
if (!_FeelStartEffect(iSlotNum, FFFX_DURATION, FFFX_FLAGS))
{
return;
}
}
void FF_StopAll(void)
{
if (FF_IsAvailable())
{
for (int i=0; i<MAX_CONCURRENT_FFFXs; i++)
{
if (ffFXLoaded[i] != fffx_NULL)
{
/*BOOL bRes = */_FeelStopEffect(i);
}
}
}
}
void FF_Stop(ffFX_e fffx)
{
if (fffx<0 || fffx>=fffx_NUMBEROF)
return;
if (FF_IsAvailable())
{
for (int i=0; i<MAX_CONCURRENT_FFFXs; i++)
{
if (ffFXLoaded[i] == fffx)
{
/*BOOL bRes = */_FeelStopEffect(i);
}
}
}
}
// 0..n..10000
//
qboolean FF_SetSpring(long lSpring)
{
static qboolean bFXPlaying = FALSE;
if (FF_IsAvailable())
{
// this plays a spring effect, and set the tension accordingly. Tension of 0 results in an effect-stop call
//
if (g_pFeelSpring)
{
if (lSpring)
{
if (!bFXPlaying && !g_pFeelSpring->Start())
{
return FALSE;
}
bFXPlaying = TRUE;
static POINT p={0,0};
g_pFeelSpring->ChangeParameters(p, lSpring);
}
else
{
if (bFXPlaying && !g_pFeelSpring->Stop())
{
return FALSE;
}
bFXPlaying = FALSE;
}
return TRUE;
}
}
return FALSE;
}
// tension is 0 (none) to 3 (max)...
//
qboolean FF_SetTension(int iTension)
{
static long lSpringValues[4] = {0, 1000, 5000, 10000};
if (iTension>3)
iTension=3;
if (iTension<0)
iTension=0;
return FF_SetSpring(lSpringValues[iTension]);
}
///////////////////////// eof //////////////////////////////

View File

@@ -0,0 +1,689 @@
// Filename:- fffx_Feel.cpp (Force-Feedback FX)
#include "../../client/client.h"
//#include "stdafx.h"
//#include "resource.h"
#include "fffx_feel.h"
extern cvar_t* js_ffmult;
#define MAX_EFFECTS_IN_COMPOUND 3 // This needs to be at least 3 for now. I can add array bounds checking later
CFeelEffect* g_pEffects[MAX_CONCURRENT_FFFXs][MAX_EFFECTS_IN_COMPOUND];
void _FeelInitEffects()
{
for (int i = 0; i < MAX_CONCURRENT_FFFXs; i++)
{
for (int j = 0; j < MAX_EFFECTS_IN_COMPOUND; j++)
{
g_pEffects[i][j] = NULL;
}
}
}
BOOL _FeelCreateEffect(int iSlotNum, ffFX_e fffx, CFeelDevice* pFeelDevice)
{
BOOL success = TRUE;
FEELIT_ENVELOPE envelope;
envelope.dwSize = sizeof(FEELIT_ENVELOPE);
switch (fffx)
{
case fffx_RandomNoise:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
7500 * js_ffmult->value, // magnitude
95, // period
10000, // duration
0, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
g_pEffects[iSlotNum][1] = new CFeelPeriodic(GUID_Feel_SawtoothDown);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
8300 * js_ffmult->value, // magnitude
160, // period
10000, // duration
9000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
g_pEffects[iSlotNum][2] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][2]))->InitializePolar(pFeelDevice,
8300 * js_ffmult->value, // magnitude
34, // period
10000, // duration
31000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_AircraftCarrierTakeOff:
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 600000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 750000;
g_pEffects[iSlotNum][0] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
0, // angle
2500, // duration
10000 * js_ffmult->value, // magnitude
&envelope))// envelope
success = FALSE;
break;
case fffx_BasketballDribble:
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 40000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 30000;
g_pEffects[iSlotNum][0] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
18000, // angle
150, // duration
5000 * js_ffmult->value, // magnitude
&envelope))// envelope
success = FALSE;
break;
case fffx_CarEngineIdle:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
2500 * js_ffmult->value, // magnitude
50, // period
10000, // duration
0, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_ChainsawIdle:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
3600 * js_ffmult->value, // magnitude
60, // period
1000, // duration
9000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
g_pEffects[iSlotNum][1] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
4000 * js_ffmult->value, // magnitude
100, // period
1000, // duration
18000, // angle
4000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_ChainsawInAction:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
6700 * js_ffmult->value, // magnitude
60, // period
1000, // duration
9000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
g_pEffects[iSlotNum][1] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
5000 * js_ffmult->value, // magnitude
100, // period
1000, // duration
18000, // angle
5000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
g_pEffects[iSlotNum][2] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][2]))->InitializePolar(pFeelDevice,
10000 * js_ffmult->value, // magnitude
340, // period
1000, // duration
18000, // angle
4000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_DieselEngineIdle:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_SawtoothDown);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
2000 * js_ffmult->value, // magnitude
250, // period
10000, // duration
18000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
g_pEffects[iSlotNum][1] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
4000 * js_ffmult->value, // magnitude
125, // period
10000, // duration
18000, // angle
1500, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Jump:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
5000 * js_ffmult->value, // magnitude
500, // period
300, // duration
18000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Land:
envelope.dwAttackLevel = 6000;
envelope.dwAttackTime = 200000;
envelope.dwFadeLevel = 3000;
envelope.dwFadeTime = 50000;
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
1000 * js_ffmult->value, // magnitude
750, // period
250, // duration
0, // angle
0, // offset
0, // phase
&envelope)) // envelope
success = FALSE;
break;
case fffx_MachineGun:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
3500 * js_ffmult->value, // magnitude
70, // period
1000, // duration
0, // angle
2500, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Punched:
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 0;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 50000;
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
8000 * js_ffmult->value, // magnitude
130, // period
70, // duration
0, // angle
0, // offset
0, // phase
&envelope)) // envelope
success = FALSE;
break;
case fffx_RocketLaunch:
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 200000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 0;
g_pEffects[iSlotNum][1] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
18000, // angle
400, // duration
10000 * js_ffmult->value, // magnitude
&envelope))// envelope
success = FALSE;
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 300000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 100000;
g_pEffects[iSlotNum][0] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
0, // angle
1000, // duration
10000 * js_ffmult->value, // magnitude
&envelope))// envelope
success = FALSE;
break;
case fffx_SecretDoor:
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 400000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 0;
g_pEffects[iSlotNum][0] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
0, // angle
400, // duration
10000 * js_ffmult->value, // magnitude
&envelope))// envelope
success = FALSE;
break;
case fffx_SwitchClick:
g_pEffects[iSlotNum][0] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
18000, // angle
50, // duration
7000 * js_ffmult->value, // magnitude
NULL))// envelope
success = FALSE;
break;
case fffx_WindGust:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
6000 * js_ffmult->value, // magnitude
1000, // period
500, // duration
18000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_WindShear:
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 1500000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 500000;
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_SawtoothDown);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
10000 * js_ffmult->value, // magnitude
80, // period
2000, // duration
0, // angle
0, // offset
0, // phase
&envelope)) // envelope
success = FALSE;
break;
case fffx_Pistol:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
8500 * js_ffmult->value, // magnitude
130, // period
50, // duration
0, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Shotgun:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
6000 * js_ffmult->value, // magnitude
100, // period
100, // duration
18000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 100000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 100000;
g_pEffects[iSlotNum][1] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
0, // angle
300, // duration
7000 * js_ffmult->value, // magnitude
&envelope))// envelope
success = FALSE;
break;
case fffx_Laser1:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
6000 * js_ffmult->value, // magnitude
25, // period
1000, // duration
18000, // angle
2000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Laser2:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
5000 * js_ffmult->value, // magnitude
25, // period
1000, // duration
0, // angle
3000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Laser3:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
5000 * js_ffmult->value, // magnitude
25, // period
1000, // duration
9000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Laser4:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
7000 * js_ffmult->value, // magnitude
25, // period
1000, // duration
9000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Laser5:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
5000 * js_ffmult->value, // magnitude
25, // period
1000, // duration
0, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Laser6:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
5000 * js_ffmult->value, // magnitude
25, // period
1000, // duration
0, // angle
2000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_OutOfAmmo:
g_pEffects[iSlotNum][0] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
18000, // angle
10, // duration
6000 * js_ffmult->value, // magnitude
NULL))// envelope
success = FALSE;
break;
case fffx_LightningGun:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
1500 * js_ffmult->value, // magnitude
250, // period
1000, // duration
18000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
g_pEffects[iSlotNum][1] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
6000 * js_ffmult->value, // magnitude
50, // period
1000, // duration
0, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_Missile:
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 500000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 200000;
g_pEffects[iSlotNum][0] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
0, // angle
250, // duration
10000 * js_ffmult->value, // magnitude
&envelope))// envelope
success = FALSE;
break;
case fffx_GatlingGun:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_SawtoothDown);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
6000 * js_ffmult->value, // magnitude
100, // period
1000, // duration
0, // angle
1000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
break;
case fffx_ShortPlasma:
envelope.dwAttackLevel = 7000;
envelope.dwAttackTime = 250000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 0;
g_pEffects[iSlotNum][0] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
0, // angle
250, // duration
0, // magnitude
&envelope))// envelope
success = FALSE;
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 0;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 250000;
g_pEffects[iSlotNum][1] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
5000 * js_ffmult->value, // magnitude
30, // period
250, // duration
0, // angle
0, // offset
0, // phase
&envelope)) // envelope
success = FALSE;
break;
case fffx_PlasmaCannon1:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
5000 * js_ffmult->value, // magnitude
500, // period
400, // duration
18000, // angle
-5000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 250000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 0;
g_pEffects[iSlotNum][1] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
6000 * js_ffmult->value, // magnitude
30, // period
250, // duration
0, // angle
0, // offset
0, // phase
&envelope)) // envelope
success = FALSE;
break;
case fffx_PlasmaCannon2:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
4000 * js_ffmult->value, // magnitude
1000, // period
800, // duration
18000, // angle
-4000, // offset
0, // phase
NULL)) // envelope
success = FALSE;
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 500000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 0;
g_pEffects[iSlotNum][1] = new CFeelPeriodic(GUID_Feel_Sine);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
8000 * js_ffmult->value, // magnitude
35, // period
500, // duration
0, // angle
0, // offset
0, // phase
&envelope)) // envelope
success = FALSE;
break;
case fffx_Cannon:
g_pEffects[iSlotNum][0] = new CFeelPeriodic(GUID_Feel_Square);
if (!((CFeelPeriodic*)(g_pEffects[iSlotNum][0]))->InitializePolar(pFeelDevice,
8000 * js_ffmult->value, // magnitude
100, // period
100, // duration
18000, // angle
0, // offset
0, // phase
NULL)) // envelope
success = FALSE;
envelope.dwAttackLevel = 0;
envelope.dwAttackTime = 100000;
envelope.dwFadeLevel = 0;
envelope.dwFadeTime = 100000;
g_pEffects[iSlotNum][1] = new CFeelConstant;
if (!((CFeelConstant*)(g_pEffects[iSlotNum][1]))->InitializePolar(pFeelDevice,
0, // angle
300, // duration
10000 * js_ffmult->value, // magnitude
&envelope))// envelope
success = FALSE;
break;
}// switch (fffx)
// if any effect in the compound failed to initialize, dump the lot
if (!success)
{
for (int i = 0; i < MAX_EFFECTS_IN_COMPOUND; i++)
{
if (g_pEffects[iSlotNum][i])
{
delete g_pEffects[iSlotNum][i];
g_pEffects[iSlotNum][i] = NULL;
}
}
}
return success;
}
BOOL _FeelStartEffect(int iSlotNum, DWORD dwIterations, DWORD dwFlags)
{
BOOL success = TRUE;
for (int i = 0; i < MAX_EFFECTS_IN_COMPOUND; i++)
{
if (g_pEffects[iSlotNum][i])
{
if (!g_pEffects[iSlotNum][i]->Start(dwIterations, dwFlags))
success = FALSE;
}
}
return success;
}
BOOL _FeelEffectPlaying(int iSlotNum)
{
DWORD dwFlags;
dwFlags = 0;
// check to see if any effect within the compound is still playing
for (int i = 0; i < MAX_EFFECTS_IN_COMPOUND; i++)
{
if (g_pEffects[iSlotNum][i])
{
g_pEffects[iSlotNum][i]->GetStatus(&dwFlags);
if (dwFlags & FEELIT_FSTATUS_PLAYING)
return TRUE;
}
}
return FALSE;
}
BOOL _FeelStopEffect(int iSlotNum)
{
BOOL success = TRUE;
for (int i = 0; i < MAX_EFFECTS_IN_COMPOUND; i++)
{
if (g_pEffects[iSlotNum][i])
{
if (!g_pEffects[iSlotNum][i]->Stop())
success = FALSE;
}
}
return success;
}
BOOL _FeelClearEffect(int iSlotNum)
{
for (int i = 0; i < MAX_EFFECTS_IN_COMPOUND; i++)
{
if (g_pEffects[iSlotNum][i])
{
delete g_pEffects[iSlotNum][i];
g_pEffects[iSlotNum][i] = NULL;
}
}
return TRUE;
}

View File

@@ -0,0 +1,29 @@
// Filename:- fffx_Feel.h (Force-Feedback FX)
// ADDED BY IMMRESION
#ifndef FFFX_FEEL_H
#define FFFX_FEEL_H
#include "../../client/fffx.h"
#include "ffc.h"
/////////////////////////////////////////////////////////////////////////
/* These functions were created to make the code a little easier to read.
* _FeelCreateEffect is quite long since it needs to create different
* kinds of effects. When playing effects, the number of iterations
* may not act as expected. I can't use CFeelCompound effects since I
* don't have a Project (which requires an ifr file at this point). So,
* I simulate compound effects with arrays. If an effect has multiple
* CFeelEffect in it, each CFeelEffect will be started individually with
* that number of iterations. The only case where this will act strange
* is when the CFeelEffects have different durations.
*/
/////////////////////////////////////////////////////////////////////////
void _FeelInitEffects();
BOOL _FeelCreateEffect(int iSlotNum, ffFX_e fffx, CFeelDevice* pFeelDevice);
BOOL _FeelStartEffect(int iSlotNum, DWORD dwIterations, DWORD dwFlags);
BOOL _FeelEffectPlaying(int iSlotNum);
BOOL _FeelStopEffect(int iSlotNum);
BOOL _FeelClearEffect(int iSlotNum);
#endif // #ifndef FFFX_FEEL_H

BIN
code/win32/background.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

620
code/win32/bink.h Normal file
View File

@@ -0,0 +1,620 @@
#ifndef BINKH
#define BINKH
#define BINKVERSION "1.0p"
#define BINKDATE "2000-06-26"
#ifndef __RADRES__
#include "rad.h"
RADDEFSTART
typedef struct BINK PTR4* HBINK;
typedef s32 (RADLINK PTR4* BINKIOOPEN) (struct BINKIO PTR4* Bnkio, const char PTR4 *name, u32 flags);
typedef u32 (RADLINK PTR4* BINKIOREADHEADER) (struct BINKIO PTR4* Bnkio, s32 Offset, void PTR4* Dest,u32 Size);
typedef u32 (RADLINK PTR4* BINKIOREADFRAME) (struct BINKIO PTR4* Bnkio, u32 Framenum,s32 origofs,void PTR4* dest,u32 size);
typedef u32 (RADLINK PTR4* BINKIOGETBUFFERSIZE)(struct BINKIO PTR4* Bnkio, u32 Size);
typedef void (RADLINK PTR4* BINKIOSETINFO) (struct BINKIO PTR4* Bnkio, void PTR4* Buf,u32 Size,u32 FileSize,u32 simulate);
typedef u32 (RADLINK PTR4* BINKIOIDLE) (struct BINKIO PTR4* Bnkio);
typedef void (RADLINK PTR4* BINKIOCLOSE) (struct BINKIO PTR4* Bnkio);
typedef struct BINKIO {
BINKIOREADHEADER ReadHeader;
BINKIOREADFRAME ReadFrame;
BINKIOGETBUFFERSIZE GetBufferSize;
BINKIOSETINFO SetInfo;
BINKIOIDLE Idle;
BINKIOCLOSE Close;
HBINK bink;
volatile u32 ReadError;
volatile u32 DoingARead;
volatile u32 BytesRead;
volatile u32 Working;
volatile u32 TotalTime;
volatile u32 ForegroundTime;
volatile u32 IdleTime;
volatile u32 ThreadTime;
volatile u32 BufSize;
volatile u32 BufHighUsed;
volatile u32 CurBufSize;
volatile u32 CurBufUsed;
volatile u8 iodata[128];
} BINKIO;
typedef s32 (RADLINK PTR4* BINKSNDOPEN) (struct BINKSND PTR4* BnkSnd, u32 freq, s32 bits, s32 chans, u32 flags, HBINK bink);
typedef s32 (RADLINK PTR4* BINKSNDREADY) (struct BINKSND PTR4* BnkSnd);
typedef s32 (RADLINK PTR4* BINKSNDLOCK) (struct BINKSND PTR4* BnkSnd, u8 PTR4* PTR4* addr, u32 PTR4* len);
typedef s32 (RADLINK PTR4* BINKSNDUNLOCK) (struct BINKSND PTR4* BnkSnd, u32 filled);
typedef void (RADLINK PTR4* BINKSNDVOLUME) (struct BINKSND PTR4* BnkSnd, s32 volume);
typedef void (RADLINK PTR4* BINKSNDPAN) (struct BINKSND PTR4* BnkSnd, s32 pan);
typedef s32 (RADLINK PTR4* BINKSNDONOFF) (struct BINKSND PTR4* BnkSnd, s32 status);
typedef s32 (RADLINK PTR4* BINKSNDPAUSE) (struct BINKSND PTR4* BnkSnd, s32 status);
typedef void (RADLINK PTR4* BINKSNDCLOSE) (struct BINKSND PTR4* BnkSnd);
typedef BINKSNDOPEN (RADLINK PTR4* BINKSNDSYSOPEN) (u32 param);
typedef struct BINKSND {
BINKSNDREADY Ready;
BINKSNDLOCK Lock;
BINKSNDUNLOCK Unlock;
BINKSNDVOLUME Volume;
BINKSNDPAN Pan;
BINKSNDPAUSE Pause;
BINKSNDONOFF SetOnOff;
BINKSNDCLOSE Close;
u32 BestSizeIn16;
u32 SoundDroppedOut;
s32 OnOff;
u32 Latency;
u32 freq;
s32 bits,chans;
u8 snddata[128];
} BINKSND;
typedef struct BINKRECT {
s32 Left,Top,Width,Height;
} BINKRECT;
#define BINKMAXDIRTYRECTS 8
typedef struct BUNDLEPOINTERS {
void* typeptr;
void* type16ptr;
void* colorptr;
void* bits2ptr;
void* motionXptr;
void* motionYptr;
void* dctptr;
void* mdctptr;
void* patptr;
} BUNDLEPOINTERS;
typedef struct BINK {
u32 Width; // Width (1 based, 640 for example)
u32 Height; // Height (1 based, 480 for example)
u32 Frames; // Number of frames (1 based, 100 = 100 frames)
u32 FrameNum; // Frame to *be* displayed (1 based)
u32 LastFrameNum; // Last frame decompressed or skipped (1 based)
u32 FrameRate; // Frame Rate Numerator
u32 FrameRateDiv; // Frame Rate Divisor (frame rate=numerator/divisor)
u32 ReadError; // Non-zero if a read error has ocurred
u32 OpenFlags; // flags used on open
u32 BinkType; // Bink flags
u32 Size; // size of file
u32 FrameSize; // The current frame's size in bytes
u32 SndSize; // The current frame sound tracks' size in bytes
BINKRECT FrameRects[BINKMAXDIRTYRECTS];// Dirty rects from BinkGetRects
s32 NumRects;
u32 PlaneNum; // which set of planes is current
void PTR4* YPlane[2]; // pointer to the uncompressed Y (Cr and Cr follow)
void PTR4* APlane[2]; // decompressed alpha plane (if present)
u32 YWidth; // widths and heights of the video planes
u32 YHeight;
u32 UVWidth;
u32 UVHeight;
void PTR4* MaskPlane; // pointer to the mask plane (Ywidth/16*Yheight/16)
u32 MaskPitch; // Mask Pitch
u32 MaskLength; // total length of the mask plane
u32 LargestFrameSize; // Largest frame size
u32 InternalFrames; // how many frames were potentially compressed
s32 NumTracks; // how many tracks
u32 Highest1SecRate; // Highest 1 sec data rate
u32 Highest1SecFrame; // Highest 1 sec data rate starting frame
s32 Paused; // is the bink movie paused?
u32 BackgroundThread; // handle to background thread
// everything below is for internal Bink use
void PTR4* compframe; // compressed frame data
void PTR4* preloadptr; // preloaded compressed frame data
u32* frameoffsets; // offsets of each of the frames
BINKIO bio; // IO structure
u8 PTR4* ioptr; // io buffer ptr
u32 iosize; // io buffer size
u32 decompwidth; // width not include scaling
u32 decompheight; // height not include scaling
s32 trackindex; // track index
u32 PTR4* tracksizes; // largest single frame of track
u32 PTR4* tracktypes; // type of each sound track
s32 PTR4* trackIDs; // external track numbers
u32 numrects; // number of rects from BinkGetRects
u32 playedframes; // how many frames have we played
u32 firstframetime; // very first frame start
u32 startframetime; // start frame start
u32 startblittime; // start of blit period
u32 startsynctime; // start of synched time
u32 startsyncframe; // frame of startsynctime
u32 twoframestime; // two frames worth of time
u32 entireframetime; // entire frame time
u32 slowestframetime; // slowest frame in ms
u32 slowestframe; // slowest frame number
u32 slowest2frametime; // second slowest frame in ms
u32 slowest2frame; // second slowest frame
u32 soundon; // sound turned on?
u32 videoon; // video turned on?
u32 totalmem; // total memory used
u32 timevdecomp; // total time decompressing video
u32 timeadecomp; // total time decompressing audio
u32 timeblit; // total time blitting
u32 timeopen; // total open time
u32 fileframerate; // frame rate originally in the file
u32 fileframeratediv;
volatile u32 threadcontrol; // controls the background reading thread
u32 runtimeframes; // max frames for runtime analysis
u32 runtimemoveamt; // bytes to move each frame
u32 PTR4* rtframetimes; // start times for runtime frames
u32 PTR4* rtadecomptimes; // decompress times for runtime frames
u32 PTR4* rtvdecomptimes; // decompress times for runtime frames
u32 PTR4* rtblittimes; // blit times for runtime frames
u32 PTR4* rtreadtimes; // read times for runtime frames
u32 PTR4* rtidlereadtimes; // idle read times for runtime frames
u32 PTR4* rtthreadreadtimes;// thread read times for runtime frames
u32 lastblitflags; // flags used on last blit
u32 lastdecompframe; // last frame number decompressed
u32 sndbufsize; // sound buffer size
u8 PTR4* sndbuf; // sound buffer
u8 PTR4* sndend; // end of the sound buffer
u8 PTR4* sndwritepos; // current write position
u8 PTR4* sndreadpos; // current read position
u32 sndcomp; // sound compression handle
u32 sndamt; // amount of sound currently in the buffer
volatile u32 sndreenter; // re-entrancy check on the sound
u32 sndconvert8; // convert back to 8-bit sound at runtime
BINKSND bsnd; // SND structure
u32 skippedlastblit; // skipped last frame?
u32 skippedblits; // how many blits were skipped
u32 soundskips; // number of sound stops
u32 sndendframe; // frame number that the sound ends on
u32 sndprime; // amount of data to prime the playahead
u32 sndpad; // padded this much audio
BUNDLEPOINTERS bunp; // pointers to internal temporary memory
} BINK;
typedef struct BINKSUMMARY {
u32 Width; // Width of frames
u32 Height; // Height of frames
u32 TotalTime; // total time (ms)
u32 FileFrameRate; // frame rate
u32 FileFrameRateDiv; // frame rate divisor
u32 FrameRate; // frame rate
u32 FrameRateDiv; // frame rate divisor
u32 TotalOpenTime; // Time to open and prepare for decompression
u32 TotalFrames; // Total Frames
u32 TotalPlayedFrames; // Total Frames played
u32 SkippedFrames; // Total number of skipped frames
u32 SkippedBlits; // Total number of skipped blits
u32 SoundSkips; // Total number of sound skips
u32 TotalBlitTime; // Total time spent blitting
u32 TotalReadTime; // Total time spent reading
u32 TotalVideoDecompTime; // Total time spent decompressing video
u32 TotalAudioDecompTime; // Total time spent decompressing audio
u32 TotalIdleReadTime; // Total time spent reading while idle
u32 TotalBackReadTime; // Total time spent reading in background
u32 TotalReadSpeed; // Total io speed (bytes/second)
u32 SlowestFrameTime; // Slowest single frame time (ms)
u32 Slowest2FrameTime; // Second slowest single frame time (ms)
u32 SlowestFrameNum; // Slowest single frame number
u32 Slowest2FrameNum; // Second slowest single frame number
u32 AverageDataRate; // Average data rate of the movie
u32 AverageFrameSize; // Average size of the frame
u32 HighestMemAmount; // Highest amount of memory allocated
u32 TotalIOMemory; // Total extra memory allocated
u32 HighestIOUsed; // Highest extra memory actually used
u32 Highest1SecRate; // Highest 1 second rate
u32 Highest1SecFrame; // Highest 1 second start frame
} BINKSUMMARY;
typedef struct BINKREALTIME {
u32 FrameNum; // Current frame number
u32 FrameRate; // frame rate
u32 FrameRateDiv; // frame rate divisor
u32 Frames; // frames in this sample period
u32 FramesTime; // time is ms for these frames
u32 FramesVideoDecompTime; // time decompressing these frames
u32 FramesAudioDecompTime; // time decompressing these frames
u32 FramesReadTime; // time reading these frames
u32 FramesIdleReadTime; // time reading these frames at idle
u32 FramesThreadReadTime; // time reading these frames in background
u32 FramesBlitTime; // time blitting these frames
u32 ReadBufferSize; // size of read buffer
u32 ReadBufferUsed; // amount of read buffer currently used
u32 FramesDataRate; // data rate for these frames
} BINKREALTIME;
#define BINKMARKER1 'fKIB'
#define BINKMARKER2 'gKIB' // new Bink files use this tag
#define BINKMARKER3 'hKIB' // newer Bink files use this tag
#define BINKMARKER4 'iKIB' // even newer Bink files use this tag
typedef struct BINKHDR {
u32 Marker; // Bink marker
u32 Size; // size of the file-8
u32 Frames; // Number of frames (1 based, 100 = 100 frames)
u32 LargestFrameSize; // Size in bytes of largest frame
u32 InternalFrames; // Number of internal frames
u32 Width; // Width (1 based, 640 for example)
u32 Height; // Height (1 based, 480 for example)
u32 FrameRate; // frame rate
u32 FrameRateDiv; // frame rate divisor (framerate/frameratediv=fps)
u32 Flags; // height compression options
u32 NumTracks; // number of tracks
} BINKHDR;
//=======================================================================
#define BINKFRAMERATE 0x00001000L // Override fr (call BinkFrameRate first)
#define BINKPRELOADALL 0x00002000L // Preload the entire animation
#define BINKSNDTRACK 0x00004000L // Set the track number to play
#define BINKOLDFRAMEFORMAT 0x00008000L // using the old Bink frame format (internal use only)
#define BINKRBINVERT 0x00010000L // use reversed R and B planes (internal use only)
#define BINKGRAYSCALE 0x00020000L // Force Bink to use grayscale
#define BINKNOMMX 0x00040000L // Don't use MMX
#define BINKNOSKIP 0x00080000L // Don't skip frames if falling behind
#define BINKALPHA 0x00100000L // Decompress alpha plane (if present)
#define BINKNOFILLIOBUF 0x00200000L // Fill the IO buffer in SmackOpen
#define BINKSIMULATE 0x00400000L // Simulate the speed (call BinkSim first)
#define BINKFILEHANDLE 0x00800000L // Use when passing in a file handle
#define BINKIOSIZE 0x01000000L // Set an io size (call BinkIOSize first)
#define BINKIOPROCESSOR 0x02000000L // Set an io processor (call BinkIO first)
#define BINKFROMMEMORY 0x04000000L // Use when passing in a pointer to the file
#define BINKNOTHREADEDIO 0x08000000L // Don't use a background thread for IO
#define BINKSURFACEFAST 0x00000000L
#define BINKSURFACESLOW 0x08000000L
#define BINKSURFACEDIRECT 0x04000000L
#define BINKCOPYALL 0x80000000L // copy all pixels (not just changed)
#define BINKCOPY2XH 0x10000000L // Force doubling height scaling
#define BINKCOPY2XHI 0x20000000L // Force interleaving height scaling
#define BINKCOPY2XW 0x30000000L // copy the width zoomed by two
#define BINKCOPY2XWH 0x40000000L // copy the width and height zoomed by two
#define BINKCOPY2XWHI 0x50000000L // copy the width and height zoomed by two
#define BINKCOPY1XI 0x60000000L // copy the width and height zoomed by two
#define BINKCOPYNOSCALING 0x70000000L // Force scaling off
//#define BINKALPHA 0x00100000L // Decompress alpha plane (if present)
//#define BINKNOSKIP 0x00080000L // don't skip the blit if behind in sound
//#define BINKNOMMX 0x00040000L // Don't skip frames if falling behind
//#define BINKGRAYSCALE 0x00020000L // force Bink to use grayscale
//#define BINKRBINVERT 0x00010000L // use reversed R and B planes
#define BINKSURFACE8P 0
#define BINKSURFACE24 1
#define BINKSURFACE24R 2
#define BINKSURFACE32 3
#define BINKSURFACE32R 4
#define BINKSURFACE32A 5
#define BINKSURFACE32RA 6
#define BINKSURFACE4444 7
#define BINKSURFACE5551 8
#define BINKSURFACE555 9
#define BINKSURFACE565 10
#define BINKSURFACE655 11
#define BINKSURFACE664 12
#define BINKSURFACEYUY2 13
#define BINKSURFACEUYVY 14
#define BINKSURFACEYV12 15
#define BINKSURFACEMASK 15
#define BINKGOTOQUICK 1
#define BINKGETKEYPREVIOUS 0
#define BINKGETKEYNEXT 1
#define BINKGETKEYCLOSEST 2
#define BINKGETKEYNOTEQUAL 128
//=======================================================================
#ifdef __RADMAC__
#include <files.h>
#pragma export on
RADEXPFUNC HBINK RADEXPLINK BinkMacOpen(FSSpec* fsp,u32 flags);
#endif
RADEXPFUNC void PTR4* RADEXPLINK BinkLogoAddress(void);
RADEXPFUNC void RADEXPLINK BinkSetError(const char PTR4* err);
RADEXPFUNC char PTR4* RADEXPLINK BinkGetError(void);
RADEXPFUNC HBINK RADEXPLINK BinkOpen(const char PTR4* name,u32 flags);
RADEXPFUNC s32 RADEXPLINK BinkDoFrame(HBINK bnk);
RADEXPFUNC void RADEXPLINK BinkNextFrame(HBINK bnk);
RADEXPFUNC s32 RADEXPLINK BinkWait(HBINK bnk);
RADEXPFUNC void RADEXPLINK BinkClose(HBINK bnk);
RADEXPFUNC s32 RADEXPLINK BinkPause(HBINK bnk,s32 pause);
RADEXPFUNC s32 RADEXPLINK BinkCopyToBuffer(HBINK bnk,void* dest,s32 destpitch,u32 destheight,u32 destx,u32 desty,u32 flags);
RADEXPFUNC s32 RADEXPLINK BinkGetRects(HBINK bnk,u32 flags);
RADEXPFUNC void RADEXPLINK BinkGoto(HBINK bnk,u32 frame,s32 flags); // use 1 for the first frame
RADEXPFUNC u32 RADEXPLINK BinkGetKeyFrame(HBINK bnk,u32 frame,s32 flags);
RADEXPFUNC s32 RADEXPLINK BinkSetVideoOnOff(HBINK bnk,s32 onoff);
RADEXPFUNC s32 RADEXPLINK BinkSetSoundOnOff(HBINK bnk,s32 onoff);
RADEXPFUNC void RADEXPLINK BinkSetVolume(HBINK bnk,s32 volume);
RADEXPFUNC void RADEXPLINK BinkSetPan(HBINK bnk,s32 pan);
RADEXPFUNC void RADEXPLINK BinkService(HBINK bink);
typedef struct BINKTRACK PTR4* HBINKTRACK;
typedef struct BINKTRACK
{
u32 Frequency;
u32 Bits;
u32 Channels;
u32 MaxSize;
HBINK bink;
u32 sndcomp;
s32 trackindex;
} BINKTRACK;
RADEXPFUNC HBINKTRACK RADEXPLINK BinkOpenTrack(HBINK bnk,u32 trackindex);
RADEXPFUNC void RADEXPLINK BinkCloseTrack(HBINKTRACK bnkt);
RADEXPFUNC u32 RADEXPLINK BinkGetTrackData(HBINKTRACK bnkt,void PTR4* dest);
RADEXPFUNC u32 RADEXPLINK BinkGetTrackType(HBINK bnk,u32 trackindex);
RADEXPFUNC u32 RADEXPLINK BinkGetTrackMaxSize(HBINK bnk,u32 trackindex);
RADEXPFUNC u32 RADEXPLINK BinkGetTrackID(HBINK bnk,u32 trackindex);
RADEXPFUNC u32 RADEXPLINK BinkGetTrackLargest(HBINK bnk,u32 trackindex);
RADEXPFUNC void RADEXPLINK BinkGetSummary(HBINK bnk,BINKSUMMARY PTR4* sum);
RADEXPFUNC void RADEXPLINK BinkGetRealtime(HBINK bink,BINKREALTIME PTR4* run,u32 frames);
#define BINKNOSOUND 0xffffffff
RADEXPFUNC void RADEXPLINK BinkSetSoundTrack(u32 track);
RADEXPFUNC void RADEXPLINK BinkSetIO(BINKIOOPEN io);
RADEXPFUNC void RADEXPLINK BinkSetFrameRate(u32 forcerate,u32 forceratediv);
RADEXPFUNC void RADEXPLINK BinkSetSimulate(u32 sim);
RADEXPFUNC void RADEXPLINK BinkSetIOSize(u32 iosize);
RADEXPFUNC s32 RADEXPLINK BinkSetSoundSystem(BINKSNDSYSOPEN open, u32 param);
#ifdef __RADWIN__
RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenDirectSound(u32 param); // don't call directly
#define BinkSoundUseDirectSound(lpDS) BinkSetSoundSystem(BinkOpenDirectSound,(u32)lpDS)
RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenWaveOut(u32 param); // don't call directly
#define BinkSoundUseWaveOut() BinkSetSoundSystem(BinkOpenWaveOut,0)
#define INCLUDE_MMSYSTEM_H
#include "windows.h"
#include "windowsx.h"
#ifdef __RADNT__ // to combat WIN32_LEAN_AND_MEAN
#include "mmsystem.h"
#endif
#endif
#ifndef __RADMAC__
RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenMiles(u32 param); // don't call directly
#define BinkSoundUseMiles(hdigdriver) BinkSetSoundSystem(BinkOpenMiles,(u32)hdigdriver)
#endif
#ifdef __RADMAC__
RADEXPFUNC BINKSNDOPEN RADEXPLINK BinkOpenSoundManager(u32 param); // don't call directly
#define BinkSoundUseSoundManager() BinkSetSoundSystem(BinkOpenSoundManager,0)
#endif
// The BinkBuffer API isn't currently implemented on DOS
#if !defined(__RADDOS__)
//=========================================================================
typedef struct BINKBUFFER * HBINKBUFFER;
#define BINKBUFFERSTRETCHXINT 0x80000000
#define BINKBUFFERSTRETCHX 0x40000000
#define BINKBUFFERSHRINKXINT 0x20000000
#define BINKBUFFERSHRINKX 0x10000000
#define BINKBUFFERSTRETCHYINT 0x08000000
#define BINKBUFFERSTRETCHY 0x04000000
#define BINKBUFFERSHRINKYINT 0x02000000
#define BINKBUFFERSHRINKY 0x01000000
#define BINKBUFFERSCALES 0xff000000
#define BINKBUFFERRESOLUTION 0x00800000
#ifdef __RADMAC__
#include <windows.h>
#include <palettes.h>
#include <qdoffscreen.h>
typedef struct BINKBUFFER {
u32 Width;
u32 Height;
u32 WindowWidth;
u32 WindowHeight;
u32 SurfaceType;
void* Buffer;
s32 BufferPitch;
u32 ScreenWidth;
u32 ScreenHeight;
u32 ScreenDepth;
u32 ScaleFlags;
s32 destx,desty;
s32 wndx,wndy;
u32 wnd;
s32 noclipping;
u32 type;
s32 issoftcur;
u32 cursorcount;
} BINKBUFFER;
#define BINKBUFFERAUTO 0
#define BINKBUFFERDIRECT 1
#define BINKBUFFERGWORLD 2
#define BINKBUFFERTYPEMASK 31
RADEXPFUNC HBINKBUFFER RADEXPLINK BinkBufferOpen( WindowPtr wnd, u32 width, u32 height, u32 bufferflags);
RADEXPFUNC s32 RADEXPLINK BinkGDSurfaceType( GDHandle gd );
RADEXPFUNC s32 RADEXPLINK BinkIsSoftwareCursor(GDHandle gd);
RADEXPFUNC s32 RADEXPLINK BinkCheckCursor(WindowPtr wp,s32 x,s32 y,s32 w,s32 h);
#else
typedef struct BINKBUFFER {
u32 Width;
u32 Height;
u32 WindowWidth;
u32 WindowHeight;
u32 SurfaceType;
void* Buffer;
s32 BufferPitch;
s32 ClientOffsetX;
s32 ClientOffsetY;
u32 ScreenWidth;
u32 ScreenHeight;
u32 ScreenDepth;
u32 ExtraWindowWidth;
u32 ExtraWindowHeight;
u32 ScaleFlags;
u32 StretchWidth;
u32 StretchHeight;
s32 surface;
void* ddsurface;
void* ddclipper;
s32 destx,desty;
s32 wndx,wndy;
u32 wnd;
s32 ddoverlay;
s32 ddoffscreen;
s32 lastovershow;
s32 issoftcur;
u32 cursorcount;
void* buffertop;
u32 type;
s32 noclipping;
s32 loadeddd;
s32 loadedwin;
void* dibh;
void* dibbuffer;
s32 dibpitch;
void* dibinfo;
u32 dibdc;
u32 diboldbitmap;
} BINKBUFFER;
#define BINKBUFFERAUTO 0
#define BINKBUFFERPRIMARY 1
#define BINKBUFFERDIBSECTION 2
#define BINKBUFFERYV12OVERLAY 3
#define BINKBUFFERYUY2OVERLAY 4
#define BINKBUFFERUYVYOVERLAY 5
#define BINKBUFFERYV12OFFSCREEN 6
#define BINKBUFFERYUY2OFFSCREEN 7
#define BINKBUFFERUYVYOFFSCREEN 8
#define BINKBUFFERRGBOFFSCREENVIDEO 9
#define BINKBUFFERRGBOFFSCREENSYSTEM 10
#define BINKBUFFERLAST 10
#define BINKBUFFERTYPEMASK 31
RADEXPFUNC HBINKBUFFER RADEXPLINK BinkBufferOpen( HWND wnd, u32 width, u32 height, u32 bufferflags);
RADEXPFUNC s32 RADEXPLINK BinkBufferSetHWND( HBINKBUFFER buf, HWND newwnd);
RADEXPFUNC s32 RADEXPLINK BinkDDSurfaceType(void PTR4* lpDDS);
RADEXPFUNC s32 RADEXPLINK BinkIsSoftwareCursor(void PTR4* lpDDSP,HCURSOR cur);
RADEXPFUNC s32 RADEXPLINK BinkCheckCursor(HWND wnd,s32 x,s32 y,s32 w,s32 h);
RADEXPFUNC s32 RADEXPLINK BinkBufferSetDirectDraw(void PTR4* lpDirectDraw, void PTR4* lpPrimary);
#endif
RADEXPFUNC void RADEXPLINK BinkBufferClose( HBINKBUFFER buf);
RADEXPFUNC s32 RADEXPLINK BinkBufferLock( HBINKBUFFER buf);
RADEXPFUNC s32 RADEXPLINK BinkBufferUnlock( HBINKBUFFER buf);
RADEXPFUNC void RADEXPLINK BinkBufferSetResolution( s32 w, s32 h, s32 bits);
RADEXPFUNC void RADEXPLINK BinkBufferCheckWinPos( HBINKBUFFER buf, s32 PTR4* NewWindowX, s32 PTR4* NewWindowY);
RADEXPFUNC s32 RADEXPLINK BinkBufferSetOffset( HBINKBUFFER buf, s32 destx, s32 desty);
RADEXPFUNC void RADEXPLINK BinkBufferBlit( HBINKBUFFER buf, BINKRECT PTR4* rects, u32 numrects );
RADEXPFUNC s32 RADEXPLINK BinkBufferSetScale( HBINKBUFFER buf, u32 w, u32 h);
RADEXPFUNC char PTR4* RADEXPLINK BinkBufferGetDescription( HBINKBUFFER buf);
RADEXPFUNC char PTR4* RADEXPLINK BinkBufferGetError();
RADEXPFUNC s32 RADEXPLINK BinkBufferClear(HBINKBUFFER buf, u32 RGB);
RADEXPFUNC void RADEXPLINK BinkRestoreCursor(s32 checkcount);
#endif
#ifdef __RADMAC__
#pragma export off
#endif
RADDEFEND
#endif
#endif

BIN
code/win32/binkw32.lib Normal file

Binary file not shown.

BIN
code/win32/clear.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,172 @@
//-----------------------------------------------------------------------------
// File: dbg_console_xbox.cpp
//
// Desc: Listens for string commands sent from a debug console on a
// remote dev machine, and forwards them to the Q3 engine.
//
// Commands are sent from the remote debug console through the debug
// channel to the debug monitor on the Xbox machine. The Xbox machine
// receives the commands on a separate thread through a
// registered command processor callback function. The callback
// function will store commands in a buffer, and the app should
// poll this buffer once per frame and then decipher and handle
// the commands.
//
// Hist: 02.05.01 - Initial creation for March XDK release
// 08.21.02 - Revision and code cleanup
// 04.10.02 - Buthcered by BTO for use in JK3:JA
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include <xtl.h>
#include <xbdm.h>
#include <stdio.h>
#include "dbg_console_xbox.h"
#include "../client/client.h"
#include "../qcommon/qcommon.h"
// Command prefix for things sent across the dubg channel
static const CHAR g_strDebugConsoleCommandPrefix[] = "XCMD";
// Global buffer to receive remote commands from the debug console. Note that
// since this data is accessed by the app's main thread, and the debug monitor
// thread, we need to protect access with a critical section
static CHAR g_strRemoteBuf[MAXRCMDLENGTH];
// The critical section used to protect data that is shared between threads
static CRITICAL_SECTION g_CriticalSection;
// Temporary replacement for CRT string funcs, since
// we can't call CRT functions on the debug monitor
// thread right now.
//-----------------------------------------------------------------------------
// Name: dbgtolower()
// Desc: Returns lowercase of char
//-----------------------------------------------------------------------------
inline CHAR dbgtolower( CHAR ch )
{
if( ch >= 'A' && ch <= 'Z' )
return ch - ( 'A' - 'a' );
else
return ch;
}
//-----------------------------------------------------------------------------
// Name: dbgstrnicmp()
// Desc: Critical section safe string compare.
//-----------------------------------------------------------------------------
BOOL dbgstrnicmp( const CHAR* str1, const CHAR* str2, int n )
{
while( ( dbgtolower( *str1 ) == dbgtolower( *str2 ) ) && *str1 && n > 0 )
{
--n;
++str1;
++str2;
}
return( n == 0 || dbgtolower( *str1 ) == dbgtolower( *str2 ) );
}
//-----------------------------------------------------------------------------
// Name: dbgstrcpy()
// Desc: Critical section safe string copy
//-----------------------------------------------------------------------------
VOID dbgstrcpy( CHAR* strDest, const CHAR* strSrc )
{
while( ( *strDest++ = *strSrc++ ) != 0 );
}
//-----------------------------------------------------------------------------
// Name: DebugConsoleCmdProcessor()
// Desc: Command notification proc that is called by the Xbox debug monitor to
// have us process a command. What we'll actually attempt to do is tell
// it to make calls to us on a separate thread, so that we can just block
// until we're able to process a command.
//
// Note: Do NOT include newlines in the response string! To do so will confuse
// the internal WinSock networking code used by the debug monitor API.
//-----------------------------------------------------------------------------
HRESULT __stdcall DebugConsoleCmdProcessor( const CHAR* strCommand,
CHAR* strResponse, DWORD dwResponseLen,
PDM_CMDCONT pdmcc )
{
// Skip over the command prefix and the exclamation mark
strCommand += strlen(g_strDebugConsoleCommandPrefix) + 1;
// Check if this is the initial connect signal
if( dbgstrnicmp( strCommand, "__connect__", 11 ) )
{
// If so, respond that we're connected
lstrcpynA( strResponse, "Connected.", dwResponseLen );
return XBDM_NOERR;
}
// g_strRemoteBuf needs to be protected by the critical section
EnterCriticalSection( &g_CriticalSection );
if( g_strRemoteBuf[0] )
{
// This means the application has probably stopped polling for debug commands
dbgstrcpy( strResponse, "Cannot execute - previous command still pending" );
}
else
{
dbgstrcpy( g_strRemoteBuf, strCommand );
}
LeaveCriticalSection( &g_CriticalSection );
return XBDM_NOERR;
}
//-----------------------------------------------------------------------------
// Name: DebugConsoleHandleCommands()
// Desc: Poll routine called periodically (typically every frame) by the Xbox
// app to see if there is a command waiting to be executed, and if so,
// execute it.
//-----------------------------------------------------------------------------
BOOL DebugConsoleHandleCommands()
{
static BOOL bInitialized = FALSE;
CHAR strLocalBuf[MAXRCMDLENGTH+1]; // local copy of command
// Initialize ourselves when we're first called.
if( !bInitialized )
{
// Register our command handler with the debug monitor
HRESULT hr = DmRegisterCommandProcessor( g_strDebugConsoleCommandPrefix,
DebugConsoleCmdProcessor );
if( FAILED(hr) )
return FALSE;
// We'll also need a critical section to protect access to g_strRemoteBuf
InitializeCriticalSection( &g_CriticalSection );
bInitialized = TRUE;
}
// If there's nothing waiting, return.
if( !g_strRemoteBuf[0] )
return FALSE;
// Grab a local copy of the command received in the remote buffer
EnterCriticalSection( &g_CriticalSection );
lstrcpyA( strLocalBuf, g_strRemoteBuf );
g_strRemoteBuf[0] = 0;
LeaveCriticalSection( &g_CriticalSection );
Cbuf_ExecuteText( EXEC_APPEND, va("%s\n", strLocalBuf) );
return TRUE;
}

View File

@@ -0,0 +1,34 @@
//-----------------------------------------------------------------------------
// File: dbg_console_xbox.h
//
// Desc: Header file for communicating with a remote debug console. Please read
// the comments in the dbg_console_xbox.cpp file for more info
// on the API.
//
// This header defines the following arrays:
//
// g_RemoteCommands - This is the list of commands your application provides.
// Note that "help" and "set" are provided automatically
// This is implemented in DebugCmd.cpp
//
// g_RemoteVariables - This is a list of variables that your application
// exposes. They can be examined and modified by the
// remote debug console with the "set" command.
// This is implemented in DebugChannel.cpp
//
// Hist: 02.05.01 - Initial creation for March XDK release
// 08.21.02 - Revision and code cleanup
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#ifndef DEBUGCMD_H
#define DEBUGCMD_H
#define MAXRCMDLENGTH 256 // Size of the remote cmd buffer
// Handle any remote commands that have been sent - this should be called
// periodically by the application
BOOL DebugConsoleHandleCommands();
#endif // DEBUGCMD_H

104
code/win32/game.rc Normal file
View File

@@ -0,0 +1,104 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) 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
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "AutoVersion.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
PRODUCTVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "Raven Software"
VALUE "CompanyName", "Activision Inc"
VALUE "FileDescription", "Jedi Academy Game DLL"
VALUE "FileVersion", VERSION_STRING
VALUE "InternalName", "ja game.dll"
VALUE "LegalCopyright", "Copyright (C) 2003"
VALUE "OriginalFilename", "jagamex86.dll"
VALUE "ProductName", "Jedi Knight®: Jedi Academy"
VALUE "ProductVersion", VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

30
code/win32/glw_win.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef _WIN32
# error You should not be including this file on this platform
#endif
#ifndef __GLW_WIN_H__
#define __GLW_WIN_H__
typedef struct
{
WNDPROC wndproc;
HDC hDC; // handle to device context
HGLRC hGLRC; // handle to GL rendering context
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
qboolean allowdisplaydepthchange;
qboolean pixelFormatSet;
int desktopBitsPixel;
int desktopWidth, desktopHeight;
qboolean cdsFullscreen;
FILE *log_fp;
} glwstate_t;
extern glwstate_t glw_state;
#endif

184
code/win32/glw_win_dx8.h Normal file
View File

@@ -0,0 +1,184 @@
/*
* UNPUBLISHED -- Rights reserved under the copyright laws of the
* United States. Use of a copyright notice is precautionary only and
* does not imply publication or disclosure.
*
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
*/
#ifndef __GLW_WIN_H__
#define __GLW_WIN_H__
#include <map>
#include <d3d9.h>
#ifdef _WIN32
#include <d3dx9.h>
#endif
#include "../renderer/qgl_console.h"
#include "../game/q_shared.h"
#include "../qcommon/qfiles.h"
#define GLW_MAX_TEXTURE_STAGES 2
#define GLW_MAX_STRIPS 2048
struct glwstate_t
{
// Interface to DX
IDirect3DDevice9* device;
// Matrix stuff
enum MatrixMode
{
MatrixMode_Model = 0,
MatrixMode_Projection = 1,
MatrixMode_Texture0 = 2,
MatrixMode_Texture1 = 3,
MatrixMode_Texture2 = 4,
MatrixMode_Texture3 = 5,
Num_MatrixModes
};
ID3DXMatrixStack* matrixStack[Num_MatrixModes];
MatrixMode matrixMode;
// Current primitive mode (triangles/quads/strips)
D3DPRIMITIVETYPE primitiveMode;
// Are we in a glBegin/glEnd block? (Used for sanity checks.)
bool inDrawBlock;
// Texturing
bool textureStageDirty[GLW_MAX_TEXTURE_STAGES];
bool textureStageEnable[GLW_MAX_TEXTURE_STAGES];
GLuint currentTexture[GLW_MAX_TEXTURE_STAGES];
D3DTEXTUREOP textureEnv[GLW_MAX_TEXTURE_STAGES];
struct TextureInfo
{
IDirect3DTexture9* mipmap;
D3DTEXTUREFILTERTYPE minFilter, mipFilter, magFilter;
D3DTEXTUREADDRESS wrapU, wrapV;
float anisotropy;
// I only need this for ONE texture, but it's easier than adding more hacks:
void *data;
};
typedef std::map<GLuint, TextureInfo> texturexlat_t;
texturexlat_t textureXlat;
GLuint textureBindNum;
GLuint serverTU, clientTU;
// Pointers to various draw buffers
const void* vertexPointer;
const void* normalPointer;
const void* texCoordPointer[GLW_MAX_TEXTURE_STAGES];
const void* colorPointer;
#ifdef _WINDOWS
// Temporary storage used when rendering quads
const void* vertexPointerBack;
const void* normalPointerBack;
const void* texCoordPointerBack[GLW_MAX_TEXTURE_STAGES];
const void* colorPointerBack;
#endif
// State of draw buffers
bool colorArrayState;
bool texCoordArrayState[GLW_MAX_TEXTURE_STAGES];
bool vertexArrayState;
bool normalArrayState;
// Stride of various draw buffers
int vertexStride;
int texCoordStride[GLW_MAX_TEXTURE_STAGES];
int colorStride;
int normalStride;
// Current number of verts in this packet
int numVertices;
// Max verts allowed in this packet
int maxVertices;
// Total verts to draw (may take multiple packets)
int totalVertices;
// Current number of indices in this packet
int numIndices;
// Max indices allowed in this packet
int maxIndices;
// Total indices to draw
int totalIndices;
// Culling
bool cullEnable;
D3DCULL cullMode;
// Viewport
D3DVIEWPORT9 viewport;
// Clearing info
D3DCOLOR clearColor;
float clearDepth;
int clearStencil;
// Widescreen mode
bool isWidescreen;
// Global color
D3DCOLOR currentColor;
// Scissoring
bool scissorEnable;
D3DRECT scissorBox;
// Directional Light
D3DLIGHT9 dirLight;
D3DMATERIAL9 mtrl;
// Description of current shader
DWORD shaderMask;
// Should we reset matrices on next draw?
bool matricesDirty[Num_MatrixModes];
// Render commands go here
DWORD* drawArray;
DWORD drawStride;
// This is designed to be an optimization for triangle strips
// as well as making life easier for the flare effect
GLushort strip_dest[SHADER_MAX_INDEXES];
GLuint strip_lengths[GLW_MAX_STRIPS];
GLsizei num_strip_lengths;
#ifdef _XBOX
// class FlareEffect* flareEffect;
class LightEffects* lightEffects;
#endif
};
extern glwstate_t *glw_state;
void renderObject_HACK();
void renderObject_Light( int numIndexes, const unsigned short *indexes );
void renderObject_Shadow( int primType, int numIndexes, const unsigned short *indexes );
void renderObject_Env();
void renderObject_Bump();
bool CreateVertexShader( const CHAR* strFilename, const DWORD* pdwVertexDecl, DWORD* pdwVertexShader );
bool CreatePixelShader( const CHAR* strFilename, DWORD* pdwPixelShader );
#endif

962
code/win32/rad.h Normal file
View File

@@ -0,0 +1,962 @@
#ifndef __RAD__
#define __RAD__
#define RADCOPYRIGHT "Copyright (C) 1994-2000, RAD Game Tools, Inc."
#ifndef __RADRES__
// __RAD16__ means 16 bit code (Win16)
// __RAD32__ means 32 bit code (DOS, Win386, Win32s, Mac)
// __RADDOS__ means DOS code (16 or 32 bit)
// __RADWIN__ means Windows code (Win16, Win386, Win32s)
// __RADWINEXT__ means Windows 386 extender (Win386)
// __RADNT__ means Win32s code
// __RADMAC__ means Macintosh
// __RADX86__ means Intel x86
// __RADMMX__ means Intel x86 MMX instructions are allowed
// __RAD68K__ means 68K
// __RADPPC__ means PowerPC
// __RADLITTLEENDIAN__ means processor is little-endian (x86)
// __RADBIGENDIAN__ means processor is big-endian (680x0, PPC)
// __RADALLOWINLINES__ means this compiler allows inline function declarations
// use RADINLINE for the appropriate keyword
#if (defined(__MWERKS__) && !defined(__INTEL__)) || defined(__MRC__) || defined(THINK_C) || defined(powerc) || defined(macintosh) || defined(__powerc)
#define __RADMAC__
#if defined(powerc) || defined(__powerc)
#define __RADPPC__
#else
#define __RAD68K__
#endif
#define __RAD32__
#define __RADBIGENDIAN__
#if defined(__MWERKS__)
#if (defined(__cplusplus) || ! __option(only_std_keywords))
#define __RADALLOWINLINES__
#define RADINLINE inline
#endif
#elif defined(__MRC__)
#if defined(__cplusplus)
#define __RADALLOWINLINES__
#define RADINLINE inline
#endif
#endif
#else
#define __RADX86__
#define __RADMMX__
#ifdef __MWERKS__
#define _WIN32
#endif
#ifdef __DOS__
#define __RADDOS__
#endif
#ifdef __386__
#define __RAD32__
#endif
#ifdef _Windows //For Borland
#ifdef __WIN32__
#define WIN32
#else
#define __WINDOWS__
#endif
#endif
#ifdef _WINDOWS //For MS
#ifndef _WIN32
#define __WINDOWS__
#endif
#endif
#ifdef _WIN32
#define __RADWIN__
#define __RADNT__
#define __RAD32__
#else
#ifdef __NT__
#define __RADWIN__
#define __RADNT__
#define __RAD32__
#else
#ifdef __WINDOWS_386__
#define __RADWIN__
#define __RADWINEXT__
#define __RAD32__
#else
#ifdef __WINDOWS__
#define __RADWIN__
#define __RAD16__
#else
#ifdef WIN32
#define __RADWIN__
#define __RADNT__
#define __RAD32__
#endif
#endif
#endif
#endif
#endif
#define __RADLITTLEENDIAN__
// TODO - make sure these are set correctly for non-Mac versions
#define __RADALLOWINLINES__
#define RADINLINE __inline
#endif
#ifndef __RADALLOWINLINES__
#define RADINLINE
#endif
#if (!defined(__RADDOS__) && !defined(__RADWIN__) && !defined(__RADMAC__))
#error RAD.H did not detect your platform. Define __DOS__, __WINDOWS__, WIN32, macintosh, or powerc.
#endif
#ifdef __RADMAC__
// this define is for CodeWarrior 11's stupid new libs (even though
// we don't use longlong's).
#define __MSL_LONGLONG_SUPPORT__
#define RADLINK
#define RADEXPLINK
#ifdef __CFM68K__
#ifdef __RADINDLL__
#define RADEXPFUNC RADDEFFUNC __declspec(export)
#else
#define RADEXPFUNC RADDEFFUNC __declspec(import)
#endif
#else
#define RADEXPFUNC RADDEFFUNC
#endif
#define RADASMLINK
#else
#ifdef __RADNT__
#ifndef _WIN32
#define _WIN32
#endif
#ifndef WIN32
#define WIN32
#endif
#endif
#ifdef __RADWIN__
#ifdef __RAD32__
#ifdef __RADNT__
#define RADLINK __stdcall
#define RADEXPLINK __stdcall
#ifdef __RADINEXE__
#define RADEXPFUNC RADDEFFUNC
#else
#ifndef __RADINDLL__
#define RADEXPFUNC RADDEFFUNC __declspec(dllimport)
#ifdef __BORLANDC__
#if __BORLANDC__<=0x460
#undef RADEXPFUNC
#define RADEXPFUNC RADDEFFUNC
#endif
#endif
#else
#define RADEXPFUNC RADDEFFUNC __declspec(dllexport)
#endif
#endif
#else
#define RADLINK __pascal
#define RADEXPLINK __far __pascal
#define RADEXPFUNC RADDEFFUNC
#endif
#else
#define RADLINK __pascal
#define RADEXPLINK __far __pascal __export
#define RADEXPFUNC RADDEFFUNC
#endif
#else
#define RADLINK __pascal
#define RADEXPLINK __pascal
#define RADEXPFUNC RADDEFFUNC
#endif
#define RADASMLINK __cdecl
#endif
#ifdef __RADWIN__
#ifndef _WINDOWS
#define _WINDOWS
#endif
#endif
#ifdef __cplusplus
#define RADDEFFUNC extern "C"
#define RADDEFSTART extern "C" {
#define RADDEFEND }
#else
#define RADDEFFUNC
#define RADDEFSTART
#define RADDEFEND
#endif
RADDEFSTART
#define s8 signed char
#define u8 unsigned char
#define u32 unsigned long
#define s32 signed long
#define f32 float
#define f64 double
#if defined(__MWERKS__) || defined(__MRC__)
#define u64 unsigned long long
#define s64 signed long long
#else
#define u64 unsigned __int64
#define s64 signed __int64
#endif
/* 32 bit implementations */
#ifdef __RAD32__
#define PTR4
#define u16 unsigned short
#define s16 signed short
#ifdef __RADMAC__
#include <string.h>
#include <MacTypes.h>
#include <Memory.h>
#include <OSUtils.h>
#ifdef __MRC__
#include "intrinsics.h"
#endif
void radconv32a(void* p, u32 n);
u32 radloadu32(u32 a);
u32 radloadu32ptr(u32* p);
#define radstrcpy strcpy
#define radstrcat strcat
#define radmemcpy(dest,source,size) BlockMoveData((Ptr)(source),(Ptr)(dest),size)
#define radmemcpydb(dest,source,size) BlockMoveData((Ptr)(source),(Ptr)(dest),size)
#define radmemcmp memcmp
#define radmemset memset
#define radstrlen strlen
#define radstrchr strchr
#define radtoupper toupper
#define radstru32(s) ((u32)atol(s))
//s8 radstricmp(const void* s1,const void* s2);
#define radstrcmp strcmp
//char* radstrupr(void* s1);
//char* radstrlwr(void* s1);
u32 radsqr(u32 a);
u32 mult64anddiv(u32 m1,u32 m2,u32 d);
s32 radabs(s32 ab);
#define radabs32 radabs
//char* radstpcpy(void* dest,const void* source);
//char* radstpcpyrs(void* dest,const void* source);
void radmemset16(void* dest,u16 value,u32 size);
//void radmemset32(void* dest,u32 value,u32 size);
#define BreakPoint() DebugStr("\pBreakPoint() was called")
//u8 radinp(u16 p);
//void radoutp(u16 p,u8 v);
//u32 RADsqrt(u32 sq);
u32 RADCycleTimerAvail(void);
void RADCycleTimerStartAddr(u32* addr);
u32 RADCycleTimerDeltaAddr(u32* addr);
void RADCycleTimerStartAddr64(u64* addr);
void RADCycleTimerDeltaAddr64(u64* addr);
#define RADCycleTimerStart(var) RADCycleTimerStartAddr(&var)
#define RADCycleTimerDelta(var) RADCycleTimerDeltaAddr(&var)
#define RADCycleTimerStart64(var) RADCycleTimerStartAddr64(&var)
#define RADCycleTimerDelta64(var) RADCycleTimerDeltaAddr64(&var)
#ifdef __RAD68K__
#pragma parameter radconv32a(__A0,__D0)
void radconv32a(void* p,u32 n) ={0x4A80,0x600C,0x2210,0xE059,0x4841,0xE059,0x20C1,0x5380,0x6EF2};
// tst.l d0 bra.s @loope @loop: move.l (a0),d1 ror.w #8,d1 swap d1 ror.w #8,d1 move.l d1,(a0)+ sub.l #1,d0 bgt.s @loop @loope:
#endif
#ifdef __RADALLOWINLINES__
#if defined __RADPPC__ && defined(__MWERKS__) && (__MWERKS__ >= 0x2301) && 0
u32 RADINLINE radloadu32(register u32 x) {
register u32 t1, t2;
asm { // x = aa bb cc dd
rlwinm t1,x,24,0,23 // t1 = dd aa bb 00
rlwinm t2,x,8,24,31 // t2 = 00 00 00 aa
rlwimi t1,x,8, 8,15 // t1 = dd cc bb 00
or x,t1,t2 // x = dd cc bb aa
}
return x;
}
#else
u32 RADINLINE radloadu32(register u32 x) {
return (((x << 24) & 0xFF000000) |
((x << 8) & 0x00FF0000) |
((x >> 8) & 0x0000FF00) |
((x >> 24) & 0x000000FF));
}
#endif
#endif
#if defined(__RADPPC__) && (defined(__MWERKS__) || defined(__MRC__))
#define radloadu32ptr(p) (u32) __lwbrx((p),0)
#else
#define radloadu32ptr(p) radloadu32(*(u32*)(p));
#endif
#ifdef __RADALLOWINLINES__
u32 RADINLINE radsqr(u32 a) { return(a*a); }
#endif
#ifdef __RAD68K__
#pragma parameter __D0 mult64anddiv(__D0,__D1,__D2)
u32 mult64anddiv(u32 m1,u32 m2,u32 d) ={0x4C01,0x0C01,0x4C42,0x0C01};
// muls.l d1,d1:d0 divs.l d2,d1:d0
#endif
#if defined(__RADPPC__) && (defined(__MWERKS__) || defined(__MRC__))
#define radabs(ab) __abs((s32)(ab))
#elif defined(__RADALLOWINLINES__)
s32 RADINLINE radabs(s32 ab) { return (ab < 0) ? -ab : ab; }
#endif
#else
#define radconv32a(p,n) ((void)0)
#define radloadu32(a) ((u32)(a))
#define radloadu32ptr(p) *((u32*)(p))
#ifdef __WATCOMC__
u32 radsqr(s32 a);
#pragma aux radsqr = "mul eax" parm [eax] modify [EDX eax];
u32 mult64anddiv(u32 m1,u32 m2,u32 d);
#pragma aux mult64anddiv = "mul ecx" "div ebx" parm [eax] [ecx] [ebx] modify [EDX eax];
s32 radabs(s32 ab);
#pragma aux radabs = "test eax,eax" "jge skip" "neg eax" "skip:" parm [eax];
#define radabs32 radabs
u32 DOSOut(const char* str);
#pragma aux DOSOut = "cld" "mov ecx,0xffffffff" "xor eax,eax" "mov edx,edi" "repne scasb" "not ecx" "dec ecx" "mov ebx,1" "mov ah,0x40" "int 0x21" parm [EDI] modify [EAX EBX ECX EDX EDI] value [ecx];
void DOSOutNum(const char* str,u32 len);
#pragma aux DOSOutNum = "mov ah,0x40" "mov ebx,1" "int 0x21" parm [edx] [ecx] modify [eax ebx];
u32 ErrOut(const char* str);
#pragma aux ErrOut = "cld" "mov ecx,0xffffffff" "xor eax,eax" "mov edx,edi" "repne scasb" "not ecx" "dec ecx" "xor ebx,ebx" "mov ah,0x40" "int 0x21" parm [EDI] modify [EAX EBX ECX EDX EDI] value [ecx];
void ErrOutNum(const char* str,u32 len);
#pragma aux ErrOutNum = "mov ah,0x40" "xor ebx,ebx" "int 0x21" parm [edx] [ecx] modify [eax ebx];
void radmemset16(void* dest,u16 value,u32 size);
#pragma aux radmemset16 = "cld" "mov bx,ax" "shl eax,16" "mov ax,bx" "mov bl,cl" "shr ecx,1" "rep stosd" "mov cl,bl" "and cl,1" "rep stosw" parm [EDI] [EAX] [ECX] modify [EAX EDX EBX ECX EDI];
void radmemset(void* dest,u8 value,u32 size);
#pragma aux radmemset = "cld" "mov ah,al" "mov bx,ax" "shl eax,16" "mov ax,bx" "mov bl,cl" "shr ecx,2" "and bl,3" "rep stosd" "mov cl,bl" "rep stosb" parm [EDI] [AL] [ECX] modify [EAX EDX EBX ECX EDI];
void radmemset32(void* dest,u32 value,u32 size);
#pragma aux radmemset32 = "cld" "rep stosd" parm [EDI] [EAX] [ECX] modify [EAX EDX EBX ECX EDI];
void radmemcpy(void* dest,const void* source,u32 size);
#pragma aux radmemcpy = "cld" "mov bl,cl" "shr ecx,2" "rep movsd" "mov cl,bl" "and cl,3" "rep movsb" parm [EDI] [ESI] [ECX] modify [EBX ECX EDI ESI];
void __far *radfmemcpy(void __far* dest,const void __far* source,u32 size);
#pragma aux radfmemcpy = "cld" "push es" "push ds" "mov es,cx" "mov ds,dx" "mov ecx,eax" "shr ecx,2" "rep movsd" "mov cl,al" "and cl,3" "rep movsb" "pop ds" "pop es" parm [CX EDI] [DX ESI] [EAX] modify [ECX EDI ESI] value [CX EDI];
void radmemcpydb(void* dest,const void* source,u32 size); //Destination bigger
#pragma aux radmemcpydb = "std" "mov bl,cl" "lea esi,[esi+ecx-4]" "lea edi,[edi+ecx-4]" "shr ecx,2" "rep movsd" "and bl,3" "jz dne" "add esi,3" "add edi,3" "mov cl,bl" "rep movsb" "dne:" "cld" parm [EDI] [ESI] [ECX] modify [EBX ECX EDI ESI];
char* radstrcpy(void* dest,const void* source);
#pragma aux radstrcpy = "cld" "mov edx,edi" "lp:" "mov al,[esi]" "inc esi" "mov [edi],al" "inc edi" "cmp al,0" "jne lp" parm [EDI] [ESI] modify [EAX EDX EDI ESI] value [EDX];
char __far* radfstrcpy(void __far* dest,const void __far* source);
#pragma aux radfstrcpy = "cld" "push es" "push ds" "mov es,cx" "mov ds,dx" "mov edx,edi" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" "pop ds" "pop es" parm [CX EDI] [DX ESI] modify [EAX EDX EDI ESI] value [CX EDX];
char* radstpcpy(void* dest,const void* source);
#pragma aux radstpcpy = "cld" "lp:" "mov al,[esi]" "inc esi" "mov [edi],al" "inc edi" "cmp al,0" "jne lp" "dec edi" parm [EDI] [ESI] modify [EAX EDI ESI] value [EDI];
char* radstpcpyrs(void* dest,const void* source);
#pragma aux radstpcpyrs = "cld" "lp:" "mov al,[esi]" "inc esi" "mov [edi],al" "inc edi" "cmp al,0" "jne lp" "dec esi" parm [EDI] [ESI] modify [EAX EDI ESI] value [ESI];
u32 radstrlen(const void* dest);
#pragma aux radstrlen = "cld" "mov ecx,0xffffffff" "xor eax,eax" "repne scasb" "not ecx" "dec ecx" parm [EDI] modify [EAX ECX EDI] value [ECX];
char* radstrcat(void* dest,const void* source);
#pragma aux radstrcat = "cld" "mov ecx,0xffffffff" "mov edx,edi" "xor eax,eax" "repne scasb" "dec edi" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" \
parm [EDI] [ESI] modify [EAX ECX EDI ESI] value [EDX];
char* radstrchr(const void* dest,char chr);
#pragma aux radstrchr = "cld" "lp:" "lodsb" "cmp al,dl" "je fnd" "cmp al,0" "jnz lp" "mov esi,1" "fnd:" "dec esi" parm [ESI] [DL] modify [EAX ESI] value [esi];
s8 radmemcmp(const void* s1,const void* s2,u32 len);
#pragma aux radmemcmp = "cld" "rep cmpsb" "setne al" "jbe end" "neg al" "end:" parm [EDI] [ESI] [ECX] modify [ECX EDI ESI];
s8 radstrcmp(const void* s1,const void* s2);
#pragma aux radstrcmp = "lp:" "mov al,[esi]" "mov ah,[edi]" "cmp al,ah" "jne set" "cmp al,0" "je set" "inc esi" "inc edi" "jmp lp" "set:" "setne al" "jbe end" "neg al" "end:" \
parm [EDI] [ESI] modify [EAX EDI ESI];
s8 radstricmp(const void* s1,const void* s2);
#pragma aux radstricmp = "lp:" "mov al,[esi]" "mov ah,[edi]" "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub al,32" "c1:" "cmp ah,'a'" "jb c2" "cmp ah,'z'" "ja c2" "sub ah,32" "c2:" "cmp al,ah" "jne set" "cmp al,0" "je set" \
"inc esi" "inc edi" "jmp lp" "set:" "setne al" "jbe end" "neg al" "end:" \
parm [EDI] [ESI] modify [EAX EDI ESI];
s8 radstrnicmp(const void* s1,const void* s2,u32 len);
#pragma aux radstrnicmp = "lp:" "mov al,[esi]" "mov ah,[edi]" "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub al,32" "c1:" "cmp ah,'a'" "jb c2" "cmp ah,'z'" "ja c2" "sub ah,32" "c2:" "cmp al,ah" "jne set" "cmp al,0" "je set" \
"dec ecx" "jz set" "inc esi" "inc edi" "jmp lp" "set:" "setne al" "jbe end" "neg al" "end:" \
parm [EDI] [ESI] [ECX] modify [EAX ECX EDI ESI];
char* radstrupr(void* s1);
#pragma aux radstrupr = "mov ecx,edi" "lp:" "mov al,[edi]" "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub [edi],32" "c1:" "inc edi" "cmp al,0" "jne lp" parm [EDI] modify [EAX EDI] value [ecx];
char* radstrlwr(void* s1);
#pragma aux radstrlwr = "mov ecx,edi" "lp:" "mov al,[edi]" "cmp al,'A'" "jb c1" "cmp al,'Z'" "ja c1" "add [edi],32" "c1:" "inc edi" "cmp al,0" "jne lp" parm [EDI] modify [EAX EDI] value [ecx];
u32 radstru32(const void* dest);
#pragma aux radstru32 = "cld" "xor ecx,ecx" "xor ebx,ebx" "xor edi,edi" "lodsb" "cmp al,45" "jne skip2" "mov edi,1" "jmp skip" "lp:" "mov eax,10" "mul ecx" "lea ecx,[eax+ebx]" \
"skip:" "lodsb" "skip2:" "cmp al,0x39" "ja dne" "cmp al,0x30" "jb dne" "mov bl,al" "sub bl,0x30" "jmp lp" "dne:" "test edi,1" "jz pos" "neg ecx" "pos:" \
parm [ESI] modify [EAX EBX EDX EDI ESI] value [ecx];
u16 GetDS();
#pragma aux GetDS = "mov ax,ds" value [ax];
#ifdef __RADWINEXT__
#define _16To32(ptr16) ((void*)(((GetSelectorBase((u16)(((u32)(ptr16))>>16))+((u16)(u32)(ptr16)))-GetSelectorBase(GetDS()))))
#endif
#ifndef __RADWIN__
#define int86 int386
#define int86x int386x
#endif
#define u32regs x
#define u16regs w
#else
#define radstrcpy strcpy
#define radstrcat strcat
#define radmemcpy memcpy
#define radmemcpydb memmove
#define radmemcmp memcmp
#define radmemset memset
#define radstrlen strlen
#define radstrchr strchr
#define radtoupper toupper
#define radstru32(s) ((u32)atol(s))
#define radstricmp _stricmp
#define radstrcmp strcmp
#define radstrupr _strupr
#define radstrlwr _strlwr
#define BreakPoint() __asm {int 3}
#define DOSOut(str)
#ifdef _MSC_VER
#pragma warning( disable : 4035)
typedef char* RADPCHAR;
u32 __inline radsqr(u32 m) {
__asm {
mov eax,[m]
mul eax
}
}
u32 __inline mult64anddiv(u32 m1,u32 m2, u32 d) {
__asm {
mov eax,[m1]
mov ecx,[m2]
mul ecx
mov ecx,[d]
div ecx
}
}
s32 __inline radabs(s32 ab) {
__asm {
mov eax,[ab]
test eax,eax
jge skip
neg eax
skip:
}
}
u8 __inline radinp(u16 p) {
__asm {
mov dx,[p]
in al,dx
}
}
void __inline radoutp(u16 p,u8 v) {
__asm {
mov dx,[p]
mov al,[v]
out dx,al
}
}
RADPCHAR __inline radstpcpy(char* p1, char* p2) {
__asm {
mov edx,[p1]
mov ecx,[p2]
cld
lp:
mov al,[ecx]
inc ecx
mov [edx],al
inc edx
cmp al,0
jne lp
dec edx
mov eax,edx
}
}
RADPCHAR __inline radstpcpyrs(char* p1, char* p2) {
__asm {
mov edx,[p1]
mov ecx,[p2]
cld
lp:
mov al,[ecx]
inc ecx
mov [edx],al
inc edx
cmp al,0
jne lp
dec ecx
mov eax,ecx
}
}
void __inline radmemset16(void* dest,u16 value,u32 sizeb) {
__asm {
mov edi,[dest]
mov ax,[value]
mov ecx,[sizeb]
shl eax,16
cld
mov ax,[value]
mov bl,cl
shr ecx,1
rep stosd
mov cl,bl
and cl,1
rep stosw
}
}
void __inline radmemset32(void* dest,u32 value,u32 sizeb) {
__asm {
mov edi,[dest]
mov eax,[value]
mov ecx,[sizeb]
cld
rep stosd
}
}
u32 __inline __stdcall RADsqrt(u32 sq) {
__asm {
fild dword ptr [sq]
fsqrt
fistp word ptr [sq]
movzx eax,word ptr [sq]
}
}
u32 __inline RADCycleTimerAvail(void)
{
u32 rdtscavail=(u32)-1;
__try
{
__asm
{
#ifdef __MWERKS__
rdtsc
#else
#if _MSC_VER<=1100
__emit 0xf
__emit 0x31
#else
rdtsc
#endif
#endif
}
rdtscavail=1;
}
__except (1)
{
rdtscavail=(u32)-1;
}
return rdtscavail;
}
void __inline RADCycleTimerStartAddr(u32* addr)
{
__asm {
mov ecx,[addr]
#ifdef __MWERKS__
rdtsc
#else
#if _MSC_VER<=1100
__emit 0xf
__emit 0x31
#else
rdtsc
#endif
#endif
mov [ecx],eax
}
}
u32 __inline RADCycleTimerDeltaAddr(u32* addr)
{
__asm {
#ifdef __MWERKS__
rdtsc
#else
#if _MSC_VER<=1100
__emit 0xf
__emit 0x31
#else
rdtsc
#endif
#endif
mov ecx,[addr]
mov edx,eax
sub eax,[ecx]
mov [ecx],eax
}
}
void __inline RADCycleTimerStartAddr64(u64* addr)
{
__asm {
mov ecx,[addr]
#ifdef __MWERKS__
rdtsc
#else
#if _MSC_VER<=1100
__emit 0xf
__emit 0x31
#else
rdtsc
#endif
#endif
mov [ecx],eax
mov [ecx+4],edx
}
}
void __inline RADCycleTimerDeltaAddr64(u64* addr)
{
__asm {
#ifdef __MWERKS__
rdtsc
#else
#if _MSC_VER<=1100
__emit 0xf
__emit 0x31
#else
rdtsc
#endif
#endif
mov ecx,[addr]
sub eax,[ecx]
sbb edx,[ecx+4]
mov [ecx],eax
mov [ecx+4],edx
}
}
#define RADCycleTimerStart(var) RADCycleTimerStartAddr(&var)
#define RADCycleTimerDelta(var) RADCycleTimerDeltaAddr(&var)
#define RADCycleTimerStart64(var) RADCycleTimerStartAddr64(&var)
#define RADCycleTimerDelta64(var) RADCycleTimerDeltaAddr64(&var)
#pragma warning( default : 4035)
#endif
#endif
#endif
#else
#define PTR4 __far
#define u16 unsigned int
#define s16 signed int
#ifdef __WATCOMC__
u32 radsqr(s32 a);
#pragma aux radsqr = "shl edx,16" "mov dx,ax" "mov eax,edx" "xor edx,edx" "mul eax" "shld edx,eax,16" parm [dx ax] modify [DX ax] value [dx ax];
s16 radabs(s16 ab);
#pragma aux radabs = "test ax,ax" "jge skip" "neg ax" "skip:" parm [ax] value [ax];
s32 radabs32(s32 ab);
#pragma aux radabs32 = "test dx,dx" "jge skip" "neg dx" "neg ax" "sbb dx,0" "skip:" parm [dx ax] value [dx ax];
u32 DOSOut(const char far* dest);
#pragma aux DOSOut = "cld" "and edi,0xffff" "mov dx,di" "mov ecx,0xffffffff" "xor eax,eax" 0x67 "repne scasb" "not ecx" "dec ecx" "mov bx,1" "push ds" "push es" "pop ds" "mov ah,0x40" "int 0x21" "pop ds" "movzx eax,cx" "shr ecx,16" \
parm [ES DI] modify [AX BX CX DX DI ES] value [CX AX];
void DOSOutNum(const char far* str,u16 len);
#pragma aux DOSOutNum = "push ds" "mov ds,cx" "mov cx,bx" "mov ah,0x40" "mov bx,1" "int 0x21" "pop ds" parm [cx dx] [bx] modify [ax bx cx];
u32 ErrOut(const char far* dest);
#pragma aux ErrOut = "cld" "and edi,0xffff" "mov dx,di" "mov ecx,0xffffffff" "xor eax,eax" 0x67 "repne scasb" "not ecx" "dec ecx" "xor bx,bx" "push ds" "push es" "pop ds" "mov ah,0x40" "int 0x21" "pop ds" "movzx eax,cx" "shr ecx,16" \
parm [ES DI] modify [AX BX CX DX DI ES] value [CX AX];
void ErrOutNum(const char far* str,u16 len);
#pragma aux ErrOutNum = "push ds" "mov ds,cx" "mov cx,bx" "mov ah,0x40" "xor bx,bx" "int 0x21" "pop ds" parm [cx dx] [bx] modify [ax bx cx];
void radmemset(void far *dest,u8 value,u32 size);
#pragma aux radmemset = "cld" "and edi,0ffffh" "shl ecx,16" "mov cx,bx" "mov ah,al" "mov bx,ax" "shl eax,16" "mov ax,bx" "mov bl,cl" "shr ecx,2" 0x67 "rep stosd" "mov cl,bl" "and cl,3" "rep stosb" parm [ES DI] [AL] [CX BX];
void radmemset16(void far* dest,u16 value,u32 size);
#pragma aux radmemset16 = "cld" "and edi,0ffffh" "shl ecx,16" "mov cx,bx" "mov bx,ax" "shl eax,16" "mov ax,bx" "mov bl,cl" "shr ecx,1" "rep stosd" "mov cl,bl" "and cl,1" "rep stosw" parm [ES DI] [AX] [CX BX];
void radmemcpy(void far* dest,const void far* source,u32 size);
#pragma aux radmemcpy = "cld" "push ds" "mov ds,dx" "and esi,0ffffh" "and edi,0ffffh" "shl ecx,16" "mov cx,bx" "shr ecx,2" 0x67 "rep movsd" "mov cl,bl" "and cl,3" "rep movsb" "pop ds" parm [ES DI] [DX SI] [CX BX] modify [CX SI DI ES];
s8 radmemcmp(const void far* s1,const void far* s2,u32 len);
#pragma aux radmemcmp = "cld" "push ds" "mov ds,dx" "shl ecx,16" "mov cx,bx" "rep cmpsb" "setne al" "jbe end" "neg al" "end:" "pop ds" parm [ES DI] [DX SI] [CX BX] modify [CX SI DI ES];
char far* radstrcpy(void far* dest,const void far* source);
#pragma aux radstrcpy = "cld" "push ds" "mov ds,dx" "and esi,0xffff" "and edi,0xffff" "mov dx,di" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" "pop ds" parm [ES DI] [DX SI] modify [AX DX DI SI ES] value [es dx];
char far* radstpcpy(void far* dest,const void far* source);
#pragma aux radstpcpy = "cld" "push ds" "mov ds,dx" "and esi,0xffff" "and edi,0xffff" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" "dec di" "pop ds" parm [ES DI] [DX SI] modify [DI SI ES] value [es di];
u32 radstrlen(const void far* dest);
#pragma aux radstrlen = "cld" "and edi,0xffff" "mov ecx,0xffffffff" "xor eax,eax" 0x67 "repne scasb" "not ecx" "dec ecx" "movzx eax,cx" "shr ecx,16" parm [ES DI] modify [AX CX DI ES] value [CX AX];
char far* radstrcat(void far* dest,const void far* source);
#pragma aux radstrcat = "cld" "and edi,0xffff" "mov ecx,0xffffffff" "and esi,0xffff" "push ds" "mov ds,dx" "mov dx,di" "xor eax,eax" 0x67 "repne scasb" "dec edi" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" "pop ds" \
parm [ES DI] [DX SI] modify [AX CX DI SI ES] value [es dx];
char far* radstrchr(const void far* dest,char chr);
#pragma aux radstrchr = "cld" "lp:" 0x26 "lodsb" "cmp al,dl" "je fnd" "cmp al,0" "jnz lp" "xor ax,ax" "mov es,ax" "mov si,1" "fnd:" "dec si" parm [ES SI] [DL] modify [AX SI ES] value [es si];
s8 radstricmp(const void far* s1,const void far* s2);
#pragma aux radstricmp = "and edi,0xffff" "push ds" "mov ds,dx" "and esi,0xffff" "lp:" "mov al,[esi]" "mov ah,[edi]" "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub al,32" "c1:" \
"cmp ah,'a'" "jb c2" "cmp ah,'z'" "ja c2" "sub ah,32" "c2:" "cmp al,ah" "jne set" "cmp al,0" "je set" \
"inc esi" "inc edi" "jmp lp" "set:" "setne al" "jbe end" "neg al" "end:" "pop ds" \
parm [ES DI] [DX SI] modify [AX DI SI];
u32 radstru32(const void far* dest);
#pragma aux radstru32 = "cld" "xor ecx,ecx" "xor ebx,ebx" "xor edi,edi" 0x26 "lodsb" "cmp al,45" "jne skip2" "mov edi,1" "jmp skip" "lp:" "mov eax,10" "mul ecx" "lea ecx,[eax+ebx]" \
"skip:" 0x26 "lodsb" "skip2:" "cmp al,0x39" "ja dne" "cmp al,0x30" "jb dne" "mov bl,al" "sub bl,0x30" "jmp lp" "dne:" "test edi,1" "jz pos" "neg ecx" "pos:" \
"movzx eax,cx" "shr ecx,16" parm [ES SI] modify [AX BX DX DI SI] value [cx ax];
u32 mult64anddiv(u32 m1,u32 m2,u32 d);
#pragma aux mult64anddiv = "shl ecx,16" "mov cx,ax" "shrd eax,edx,16" "mov ax,si" "mul ecx" "shl edi,16" "mov di,bx" "div edi" "shld edx,eax,16" "and edx,0xffff" "and eax,0xffff" parm [cx ax] [dx si] [di bx] \
modify [ax bx cx dx si di] value [dx ax];
#endif
#endif
RADDEFEND
#define u32neg1 ((u32)(s32)-1)
#define RAD_align(var) var; u8 junk##var[4-(sizeof(var)&3)];
#define RAD_align_after(var) u8 junk##var[4-(sizeof(var)&3)]={0};
#define RAD_align_init(var,val) var=val; u8 junk##var[4-(sizeof(var)&3)]={0};
#define RAD_align_array(var,num) var[num]; u8 junk##var[4-(sizeof(var)&3)];
#define RAD_align_string(var,str) char var[]=str; u8 junk##var[4-(sizeof(var)&3)]={0};
typedef void PTR4* (RADLINK PTR4* RADMEMALLOC) (u32 bytes);
typedef void (RADLINK PTR4* RADMEMFREE) (void PTR4* ptr);
#ifdef __RADMAC__
#pragma export on
#endif
RADEXPFUNC void RADEXPLINK RADSetMemory(RADMEMALLOC a,RADMEMFREE f);
#ifdef __RADMAC__
#pragma export off
#endif
RADEXPFUNC void PTR4* RADEXPLINK radmalloc(u32 numbytes);
RADEXPFUNC void RADEXPLINK radfree(void PTR4* ptr);
#ifdef __RADDOS__
RADDEFSTART
extern void* RADTimerSetupAddr;
extern void* RADTimerReadAddr;
extern void* RADTimerDoneAddr;
RADDEFEND
typedef void RADEXPLINK (*RADTimerSetupType)(void);
typedef u32 RADEXPLINK (*RADTimerReadType)(void);
typedef void RADEXPLINK (*RADTimerDoneType)(void);
#define RADTimerSetup() ((RADTimerSetupType)(RADTimerSetupAddr))()
#define RADTimerRead() ((RADTimerReadType)(RADTimerReadAddr))()
#define RADTimerDone() ((RADTimerDoneType)(RADTimerDoneAddr))()
#else
#define RADTimerSetup()
#define RADTimerDone()
#if (defined(__RAD16__) || defined(__RADWINEXT__))
#define RADTimerRead timeGetTime
#else
RADEXPFUNC u32 RADEXPLINK RADTimerRead(void);
#endif
#endif
#ifdef __WATCOMC__
char bkbhit();
#pragma aux bkbhit = "mov ah,1" "int 0x16" "lahf" "shr eax,14" "and eax,1" "xor al,1" ;
char bgetch();
#pragma aux bgetch = "xor ah,ah" "int 0x16" "test al,0xff" "jnz done" "mov al,ah" "or al,0x80" "done:" modify [AX];
void BreakPoint();
#pragma aux BreakPoint = "int 3";
u8 radinp(u16 p);
#pragma aux radinp = "in al,dx" parm [DX];
u8 radtoupper(u8 p);
#pragma aux radtoupper = "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub al,32" "c1:" parm [al] value [al];
void radoutp(u16 p,u8 v);
#pragma aux radoutp = "out dx,al" parm [DX] [AL];
#else
// for multi-processor machines
#ifdef __RADNT__
#define LockedIncrement(var) __asm { lock inc [var] }
#define LockedDecrement(var) __asm { lock dec [var] }
void __inline LockedIncrementFunc(void PTR4* var) {
__asm {
mov eax,[var]
lock inc [eax]
}
}
void __inline LockedDecrementFunc(void PTR4* var) {
__asm {
mov eax,[var]
lock dec [eax]
}
}
#else
#ifdef __RADMAC__
#define LockedIncrement(var) {++(var);}
#define LockedDecrement(var) {--(var);}
#define LockedIncrementFunc(ptr) {++(*((u32*)(ptr)));}
#define LockedDecrementFunc(ptr) {--(*((u32*)(ptr)));}
#else
#define LockedIncrement(var) __asm { inc [var] }
#define LockedDecrement(var) __asm { dec [var] }
void __inline LockedIncrementFunc(void PTR4* var) { __asm { mov eax,[var]
inc [eax] } }
void __inline LockedDecrementFunc(void PTR4* var) { __asm { mov eax,[var]
dec [eax] } }
#endif
#endif
#endif
#endif
#endif

21
code/win32/resource.h Normal file
View File

@@ -0,0 +1,21 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by winquake.rc
//
#define IDS_STRING1 1
#define IDI_ICON1 1
#define IDB_BITMAP1 1
#define IDB_BITMAP2 128
#define IDC_CURSOR1 129
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1005
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,64 @@
//
//
// ShaderConstants.h
//
// Definitions for various shader constants
//
//
#ifndef _SHADERCONSTANTS_H_
#define _SHADERCONSTANTS_H_
#define CV_ZERO 0
#define CV_ONE 1
#define CV_HALF 2
#define CV_WORLDVIEWPROJ_0 4
#define CV_WORLDVIEWPROJ_1 5
#define CV_WORLDVIEWPROJ_2 6
#define CV_WORLDVIEWPROJ_3 7
#define CV_WORLDVIEW_0 8
#define CV_WORLDVIEW_1 9
#define CV_WORLDVIEW_2 10
#define CV_WORLDVIEW_3 11
#define CV_WORLDVIEWIT_0 12
#define CV_WORLDVIEWIT_1 13
#define CV_WORLDVIEWIT_2 14
#define CV_WORLD_0 15
#define CV_WORLD_1 16
#define CV_WORLD_2 17
#define CV_WORLD_3 18
#define CV_VIEWINV_0 19
#define CV_VIEWINV_1 20
#define CV_VIEWINV_2 21
#define CV_VIEWINV_3 22
#define CV_VIEW_0 23
#define CV_VIEW_1 24
#define CV_VIEW_2 25
#define CV_VIEW_3 26
#define CV_LIGHT_COLOR 50
#define CV_ONE_OVER_LIGHT_RANGE 51
#define CV_LIGHT_DIRECTION 52
#define CV_LIGHT_POSITION 53
#define CV_CAMERA_DIRECTION 54
#define CV_EXTRUSION_LENGTH 55
#define CV_SHADOW_FACTORS 56
#define CV_SHADOW_PLANE 57
#define CV_VIEWPORT_OFFSETS 95
#define CP_AMBIENT_COLOR 0
#define CP_DIFFUSE_COLOR 1
#define CP_EXTRACT_CUTOFF 2
#define CP_EXTRACT_SCALE 3
#endif

85
code/win32/snd_fx_img.h Normal file
View File

@@ -0,0 +1,85 @@
#pragma once
typedef enum _DSP_IMAGE_image_FX_INDICES {
GraphI3DL2_I3DL2Reverb = 0,
GraphXTalk_XTalk = 1,
GraphVoice_Voice_0 = 2,
GraphVoice_Voice_1 = 3,
GraphVoice_Voice_2 = 4,
GraphVoice_Voice_3 = 5
} DSP_IMAGE_image_FX_INDICES;
#define DSI3DL2_ENVIRONMENT_GraphI3DL2_I3DL2Reverb -1000, -100, 0.000000, 1.490000, 0.830000, -2602, 0.007000, 200, 0.011000, 100.000000, 100.000000, 5000.000000
typedef struct _GraphI3DL2_FX0_I3DL2Reverb_STATE {
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
DWORD dwInMixbinPtrs[2]; // XRAM offsets in DSP WORDS, of input mixbins
DWORD dwOutMixbinPtrs[35]; // XRAM offsets in DSP WORDS, of output mixbins
} GraphI3DL2_FX0_I3DL2Reverb_STATE, *LPGraphI3DL2_FX0_I3DL2Reverb_STATE;
typedef const GraphI3DL2_FX0_I3DL2Reverb_STATE *LPCGraphI3DL2_FX0_I3DL2Reverb_STATE;
typedef struct _GraphXTalk_FX0_XTalk_STATE {
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
DWORD dwInMixbinPtrs[4]; // XRAM offsets in DSP WORDS, of input mixbins
DWORD dwOutMixbinPtrs[4]; // XRAM offsets in DSP WORDS, of output mixbins
} GraphXTalk_FX0_XTalk_STATE, *LPGraphXTalk_FX0_XTalk_STATE;
typedef const GraphXTalk_FX0_XTalk_STATE *LPCGraphXTalk_FX0_XTalk_STATE;
typedef struct _GraphVoice_FX0_Voice_0_STATE {
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
DWORD dwInMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of input mixbins
DWORD dwOutMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of output mixbins
} GraphVoice_FX0_Voice_0_STATE, *LPGraphVoice_FX0_Voice_0_STATE;
typedef const GraphVoice_FX0_Voice_0_STATE *LPCGraphVoice_FX0_Voice_0_STATE;
typedef struct _GraphVoice_FX1_Voice_1_STATE {
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
DWORD dwInMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of input mixbins
DWORD dwOutMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of output mixbins
} GraphVoice_FX1_Voice_1_STATE, *LPGraphVoice_FX1_Voice_1_STATE;
typedef const GraphVoice_FX1_Voice_1_STATE *LPCGraphVoice_FX1_Voice_1_STATE;
typedef struct _GraphVoice_FX2_Voice_2_STATE {
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
DWORD dwInMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of input mixbins
DWORD dwOutMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of output mixbins
} GraphVoice_FX2_Voice_2_STATE, *LPGraphVoice_FX2_Voice_2_STATE;
typedef const GraphVoice_FX2_Voice_2_STATE *LPCGraphVoice_FX2_Voice_2_STATE;
typedef struct _GraphVoice_FX3_Voice_3_STATE {
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
DWORD dwInMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of input mixbins
DWORD dwOutMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of output mixbins
} GraphVoice_FX3_Voice_3_STATE, *LPGraphVoice_FX3_Voice_3_STATE;
typedef const GraphVoice_FX3_Voice_3_STATE *LPCGraphVoice_FX3_Voice_3_STATE;

BIN
code/win32/starwars.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

33
code/win32/win_file.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* UNPUBLISHED -- Rights reserved under the copyright laws of the
* United States. Use of a copyright notice is precautionary only and
* does not imply publication or disclosure.
*
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
*/
#ifndef _WIN_FILE_
#define _WIN_FILE_
typedef int wfhandle_t;
extern void WF_Init(void);
extern void WF_Shutdown(void);
extern wfhandle_t WF_Open(const char* name, bool read, bool aligned);
extern void WF_Close(wfhandle_t handle);
extern int WF_Read(void* buffer, int len, wfhandle_t handle);
extern int WF_Write(const void* buffer, int len, wfhandle_t handle);
extern int WF_Seek(int offset, int origin, wfhandle_t handle);
extern int WF_Tell(wfhandle_t handle);
extern int WF_Resize(int size, wfhandle_t handle);
int Sys_GetFileCode(const char *name);
void Sys_InitFileCodes(void);
void Sys_ShutdownFileCodes(void);
#endif _WIN_FILE_

View File

@@ -0,0 +1,171 @@
/*
* UNPUBLISHED -- Rights reserved under the copyright laws of the
* United States. Use of a copyright notice is precautionary only and
* does not imply publication or disclosure.
*
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
*/
#include "../game/q_shared.h"
#include "win_file.h"
#include "../qcommon/qcommon.h"
#ifdef _XBOX
#include <Xtl.h>
#endif
#ifdef _WINDOWS
#include <windows.h>
#endif
struct FileTable
{
bool m_bUsed;
bool m_bErrorsFatal;
HANDLE m_Handle;
};
FileTable* s_FileTable = NULL;
const int WF_MAX_OPEN_FILES = 8;
void WF_Init(void)
{
assert(!s_FileTable);
s_FileTable = new FileTable[WF_MAX_OPEN_FILES];
for (wfhandle_t i = 0; i < WF_MAX_OPEN_FILES; ++i)
{
s_FileTable[i].m_bUsed = false;
}
}
void WF_Shutdown(void)
{
assert(s_FileTable);
for (wfhandle_t i = 0; i < WF_MAX_OPEN_FILES; ++i)
{
if (s_FileTable[i].m_bUsed)
{
WF_Close(i);
}
}
delete [] s_FileTable;
s_FileTable = NULL;
}
static wfhandle_t WF_GetFreeHandle(void)
{
for (int i = 0; i < WF_MAX_OPEN_FILES; ++i)
{
if (!s_FileTable[i].m_bUsed)
{
return i;
}
}
return -1;
}
int WF_Open(const char* name, bool read, bool aligned)
{
wfhandle_t handle = WF_GetFreeHandle();
if (handle == -1) return -1;
s_FileTable[handle].m_Handle =
CreateFile(name, read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, 0,
read ? OPEN_EXISTING : OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL |(aligned ? FILE_FLAG_NO_BUFFERING : 0) , 0);
if (s_FileTable[handle].m_Handle != INVALID_HANDLE_VALUE)
{
s_FileTable[handle].m_bUsed = true;
// errors are fatal on game partition
s_FileTable[handle].m_bErrorsFatal = (name[0] == 'D' || name[0] == 'd');
return handle;
}
return -1;
}
void WF_Close(wfhandle_t handle)
{
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
s_FileTable[handle].m_bUsed);
CloseHandle(s_FileTable[handle].m_Handle);
s_FileTable[handle].m_bUsed = false;
}
int WF_Read(void* buffer, int len, wfhandle_t handle)
{
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
s_FileTable[handle].m_bUsed);
DWORD bytes;
if (!ReadFile(s_FileTable[handle].m_Handle, buffer, len, &bytes, 0) &&
s_FileTable[handle].m_bErrorsFatal)
{
#if defined(FINAL_BUILD)
extern void ERR_DiscFail(bool);
ERR_DiscFail(false);
#else
assert(0);
#endif
}
return bytes;
}
int WF_Write(const void* buffer, int len, wfhandle_t handle)
{
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
s_FileTable[handle].m_bUsed);
DWORD bytes;
WriteFile(s_FileTable[handle].m_Handle, buffer, len, &bytes, 0);
return bytes;
}
int WF_Seek(int offset, int origin, wfhandle_t handle)
{
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
s_FileTable[handle].m_bUsed);
switch (origin)
{
case SEEK_CUR: origin = FILE_CURRENT; break;
case SEEK_END: origin = FILE_END; break;
case SEEK_SET: origin = FILE_BEGIN; break;
default: assert(false);
}
return SetFilePointer(s_FileTable[handle].m_Handle, offset, 0, origin) < 0;
}
int WF_Tell(wfhandle_t handle)
{
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
s_FileTable[handle].m_bUsed);
return SetFilePointer(s_FileTable[handle].m_Handle, 0, 0, FILE_CURRENT);
}
int WF_Resize(int size, wfhandle_t handle)
{
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
s_FileTable[handle].m_bUsed);
SetFilePointer(s_FileTable[handle].m_Handle, size, NULL, FILE_BEGIN);
return SetEndOfFile(s_FileTable[handle].m_Handle);
}

350
code/win32/win_filecode.cpp Normal file
View File

@@ -0,0 +1,350 @@
/*
* UNPUBLISHED -- Rights reserved under the copyright laws of the
* United States. Use of a copyright notice is precautionary only and
* does not imply publication or disclosure.
*
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
*/
#include "../server/exe_headers.h"
#include "../client/client.h"
#include "../win32/win_local.h"
#include "../qcommon/qcommon.h"
#include "../qcommon/fixedmap.h"
#include "../zlib/zlib.h"
#include "../qcommon/files.h"
/***********************************************
*
* WINDOWS/XBOX VERSION
*
* Build a translation table, CRC -> file name. We have the memory.
*
************************************************/
#if defined(_WINDOWS)
#include <windows.h>
#elif defined(_XBOX)
#include <xtl.h>
#endif
struct FileInfo
{
char* name;
int size;
};
static VVFixedMap< FileInfo, unsigned int >* s_Files = NULL;
static byte* buffer;
HANDLE s_Mutex = INVALID_HANDLE_VALUE;
int _buildFileList(const char* path, bool insert, bool buildList)
{
WIN32_FIND_DATA data;
char spec[MAX_OSPATH];
int count = 0;
// Look for all files
Com_sprintf(spec, sizeof(spec), "%s\\*.*", path);
HANDLE h = FindFirstFile(spec, &data);
while (h != INVALID_HANDLE_VALUE)
{
char full[MAX_OSPATH];
Com_sprintf(full, sizeof(full), "%s\\%s", path, data.cFileName);
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// Directory -- lets go recursive
if (data.cFileName[0] != '.') {
count += _buildFileList(full, insert, buildList);
}
}
else
{
if(insert || buildList)
{
// Regular file -- add it to the table
strlwr(full);
unsigned int code = crc32(0, (const byte *)full, strlen(full));
FileInfo info;
info.name = CopyString(full);
info.size = data.nFileSizeLow;
if(insert)
{
s_Files->Insert(info, code);
}
if(buildList)
{
// get the length of the filename
int len;
len = strlen(info.name) + 1;
// save the file code
*(int*)buffer = code;
buffer += sizeof(code);
// save the name of the file
strcpy((char*)buffer,info.name);
buffer += len;
// save the size of the file
*(int*)buffer = info.size;
buffer += sizeof(info.size);
}
}
count++;
}
// Continue the loop
if (!FindNextFile(h, &data))
{
FindClose(h);
return count;
}
}
return count;
}
bool _buildFileListFromSavedList(void)
{
// open the file up for reading
FILE* in;
extern const char *Sys_RemapPath( const char *filename );
in = fopen( Sys_RemapPath( "xbx_filelist" ), "rb" );
if(!in)
{
return false;
}
// read in the number of files
int count;
if(!(fread(&count,sizeof(count),1,in)))
{
fclose(in);
return false;
}
// allocate memory for a temp buffer
byte* baseAddr;
int bufferSize;
bufferSize = count * ( 2 * sizeof(int) + MAX_OSPATH );
buffer = (byte*)Z_Malloc(bufferSize,TAG_TEMP_WORKSPACE,qtrue,32);
baseAddr = buffer;
// read the rest of the file into a big buffer
if(!(fread(buffer,bufferSize,1,in)))
{
fclose(in);
Z_Free(baseAddr);
return false;
}
// allocate some memory for s_Files
s_Files = new VVFixedMap<FileInfo, unsigned int>(count);
// loop through all the files write out the codes
int i;
for(i = 0; i < count; i++)
{
FileInfo info;
unsigned int code;
// read the code for the file
code = *(int*)buffer;
buffer += sizeof(code);
// read the filename
info.name = CopyString((char*)buffer);
buffer += (strlen(info.name) + 1);
// read the size of the file
info.size = *(int*)buffer;
buffer += sizeof(info.size);
// save the data - optimization: don't check for dupes!
s_Files->InsertUnsafe(info, code);
}
fclose(in);
Z_Free(baseAddr);
return true;
}
bool Sys_SaveFileCodes(void)
{
bool ret;
// get the number of files
int count;
count = _buildFileList(Sys_Cwd(), false, false);
// open a file for writing
FILE* out;
out = fopen("d:\\xbx_filelist","wb");
if(!out)
{
return false;
}
// allocate a buffer for writing
byte* baseAddr;
int bufferSize;
bufferSize = sizeof(int) + ( count * ( 2 * sizeof(int) + MAX_OSPATH ) );
baseAddr = (byte*)Z_Malloc(bufferSize,TAG_TEMP_WORKSPACE,qtrue,32);
buffer = baseAddr;
// write the number of files to the buffer
*(int*)buffer = count;
buffer += sizeof(count);
// fill up the rest of the buffer
ret = _buildFileList(Sys_Cwd(), false, true);
if(!ret)
{
// there was a problem
fclose(out);
Z_Free(baseAddr);
return false;
}
// attempt to write out the data
if(!(fwrite(baseAddr,bufferSize,1,out)))
{
// there was a problem
fclose(out);
Z_Free(baseAddr);
return false;
}
// everything went ok
fclose(out);
Z_Free(baseAddr);
return true;
}
void Sys_InitFileCodes(void)
{
bool ret;
int count = 0;
Z_PushNewDeleteTag( TAG_FILELIST );
// First: try to load an existing filecode cache
ret = _buildFileListFromSavedList();
// if we had trouble building the list that way
// we need to do it by searching the files
if( !ret )
{
// There was no filelist cache, make one
if( !Sys_SaveFileCodes() )
Com_Error( ERR_DROP, "ERROR: Couldn't create filecode cache\n" );
// Now re-read it
if( !_buildFileListFromSavedList() )
Com_Error( ERR_DROP, "ERROR: Couldn't re-read filecode cache\n" );
}
s_Files->Sort();
Z_PopNewDeleteTag();
// make it thread safe
s_Mutex = CreateMutex(NULL, FALSE, NULL);
}
void Sys_ShutdownFileCodes(void)
{
FileInfo* info = NULL;
info = s_Files->Pop();
while(info)
{
Z_Free(info->name);
info->name = NULL;
info = s_Files->Pop();
}
delete s_Files;
s_Files = NULL;
CloseHandle(s_Mutex);
}
int Sys_GetFileCode(const char* name)
{
WaitForSingleObject(s_Mutex, INFINITE);
// Get system level path
char* osname = FS_BuildOSPathUnMapped(name);
// Generate hash for file name
strlwr(osname);
unsigned int code = crc32(0, (const byte *)osname, strlen(osname));
// Check if the file exists
if (!s_Files->Find(code))
{
ReleaseMutex(s_Mutex);
return -1;
}
ReleaseMutex(s_Mutex);
return code;
}
const char* Sys_GetFileCodeName(int code)
{
WaitForSingleObject(s_Mutex, INFINITE);
FileInfo *entry = s_Files->Find(code);
if (entry)
{
ReleaseMutex(s_Mutex);
return entry->name;
}
ReleaseMutex(s_Mutex);
return NULL;
}
int Sys_GetFileCodeSize(int code)
{
WaitForSingleObject(s_Mutex, INFINITE);
FileInfo *entry = s_Files->Find(code);
if (entry)
{
ReleaseMutex(s_Mutex);
return entry->size;
}
ReleaseMutex(s_Mutex);
return -1;
}
// Quick function to re-scan for new files, update the filecode
// table, and dump the new one to disk
void Sys_FilecodeScan_f( void )
{
// Make an updated filecode cache
if( !Sys_SaveFileCodes() )
Com_Error( ERR_DROP, "ERROR: Couldn't create filecode cache\n" );
// Throw out our current list
Sys_ShutdownFileCodes();
// Re-init, which should use the new list we just made
Sys_InitFileCodes();
}

141
code/win32/win_gamma.cpp Normal file
View File

@@ -0,0 +1,141 @@
/*
** WIN_GAMMA.C
*/
// leave this as first line for PCH reasons...
//
#include "../server/exe_headers.h"
#include <assert.h>
#include "../renderer/tr_local.h"
#include "../qcommon/qcommon.h"
#include "glw_win.h"
#include "win_local.h"
static unsigned short s_oldHardwareGamma[3][256];
/*
** WG_CheckHardwareGamma
**
** Determines if the underlying hardware supports the Win32 gamma correction API.
*/
void WG_CheckHardwareGamma( void )
{
HDC hDC;
glConfig.deviceSupportsGamma = qfalse;
if ( !r_ignorehwgamma->integer )
{
hDC = GetDC( GetDesktopWindow() );
glConfig.deviceSupportsGamma = GetDeviceGammaRamp( hDC, s_oldHardwareGamma );
ReleaseDC( GetDesktopWindow(), hDC );
if ( glConfig.deviceSupportsGamma )
{
//
// do a sanity check on the gamma values
//
if ( ( HIBYTE( s_oldHardwareGamma[0][255] ) <= HIBYTE( s_oldHardwareGamma[0][0] ) ) ||
( HIBYTE( s_oldHardwareGamma[1][255] ) <= HIBYTE( s_oldHardwareGamma[1][0] ) ) ||
( HIBYTE( s_oldHardwareGamma[2][255] ) <= HIBYTE( s_oldHardwareGamma[2][0] ) ) )
{
glConfig.deviceSupportsGamma = qfalse;
VID_Printf( PRINT_WARNING, "WARNING: device has broken gamma support, generated gamma.dat\n" );
}
//
// make sure that we didn't have a prior crash in the game, and if so we need to
// restore the gamma values to at least a linear value
//
if ( ( HIBYTE( s_oldHardwareGamma[0][181] ) == 255 ) )
{
int g;
VID_Printf( PRINT_WARNING, "WARNING: suspicious gamma tables, using linear ramp for restoration\n" );
for ( g = 0; g < 255; g++ )
{
s_oldHardwareGamma[0][g] = g << 8;
s_oldHardwareGamma[1][g] = g << 8;
s_oldHardwareGamma[2][g] = g << 8;
}
}
}
}
}
/*
** GLimp_SetGamma
**
** This routine should only be called if glConfig.deviceSupportsGamma is TRUE
*/
void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] ) {
unsigned short table[3][256];
int i, j;
int ret;
OSVERSIONINFO vinfo;
if ( !glConfig.deviceSupportsGamma || r_ignorehwgamma->integer || !glw_state.hDC ) {
return;
}
//mapGammaMax();
for ( i = 0; i < 256; i++ ) {
table[0][i] = ( ( ( unsigned short ) red[i] ) << 8 ) | red[i];
table[1][i] = ( ( ( unsigned short ) green[i] ) << 8 ) | green[i];
table[2][i] = ( ( ( unsigned short ) blue[i] ) << 8 ) | blue[i];
}
// Win2K puts this odd restriction on gamma ramps...
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
GetVersionEx( &vinfo );
if ( vinfo.dwMajorVersion == 5 && vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
Com_DPrintf( "performing W2K gamma clamp.\n" );
for ( j = 0 ; j < 3 ; j++ ) {
for ( i = 0 ; i < 128 ; i++ ) {
if ( table[j][i] > ( (128+i) << 8 ) ) {
table[j][i] = (128+i) << 8;
}
}
if ( table[j][127] > 254<<8 ) {
table[j][127] = 254<<8;
}
}
} else {
Com_DPrintf( "skipping W2K gamma clamp.\n" );
}
// enforce constantly increasing
for ( j = 0 ; j < 3 ; j++ ) {
for ( i = 1 ; i < 256 ; i++ ) {
if ( table[j][i] < table[j][i-1] ) {
table[j][i] = table[j][i-1];
}
}
}
ret = SetDeviceGammaRamp( glw_state.hDC, table );
if ( !ret ) {
Com_Printf( "SetDeviceGammaRamp failed.\n" );
}
}
/*
** WG_RestoreGamma
*/
void WG_RestoreGamma( void )
{
if ( glConfig.deviceSupportsGamma )
{
HDC hDC;
hDC = GetDC( GetDesktopWindow() );
SetDeviceGammaRamp( hDC, s_oldHardwareGamma );
ReleaseDC( GetDesktopWindow(), hDC );
}
}

View File

@@ -0,0 +1,73 @@
/*
** WIN_GAMMA.C
*/
// leave this as first line for PCH reasons...
//
//#include "../server/exe_headers.h"
#include <assert.h>
#include "../game/q_shared.h"
#include "../renderer/tr_local.h"
#include "../qcommon/qcommon.h"
#include "win_local.h"
#if defined(_XBOX)
#include "glw_win_dx8.h"
#endif
/*
** WG_CheckHardwareGamma
**
** Determines if the underlying hardware supports the Win32 gamma correction API.
*/
void WG_CheckHardwareGamma( void )
{
glConfig.deviceSupportsGamma = qtrue;
}
/*
** GLimp_SetGamma
**
** This routine should only be called if glConfig.deviceSupportsGamma is TRUE
*/
void GLimp_SetGamma( float g ) {
#if defined(_GAMECUBE)
GXGamma gamma = GX_GM_1_0;
if (g >= 2.2f)
{
gamma = GX_GM_2_2;
}
else if (g >= 1.7f)
{
gamma = GX_GM_1_7;
}
GXSetDispCopyGamma(gamma);
#elif defined(_XBOX)
const int maxval = 255;
D3DGAMMARAMP ramp;
for ( int i = 0; i < 256; i++ )
{
int inf;
if ( g == 1 ) {
inf = maxval * i / 255.0f;
} else {
inf = maxval * pow ( i/255.0f, 1.0f / g ) + 0.5f;
}
if (inf < 0) {
inf = 0;
}
if (inf > maxval) {
inf = maxval;
}
ramp.red[i] = inf;
ramp.green[i] = inf;
ramp.blue[i] = inf;
}
glw_state->device->SetGammaRamp(D3DSGR_CALIBRATE, &ramp);
#endif
}

1815
code/win32/win_glimp.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,261 @@
// leave this as first line for PCH reasons...
//
#include "../server/exe_headers.h"
/*
** WIN_GLIMP.C
**
** This file contains ALL Win32 specific stuff having to do with the
** OpenGL refresh. When a port is being made the following functions
** must be implemented by the port:
**
** GLimp_EndFrame
** GLimp_Init
** GLimp_LogComment
** GLimp_Shutdown
**
** Note that the GLW_xxx functions are Windows specific GL-subsystem
** related functions that are relevant ONLY to win_glimp.c
*/
#include <assert.h>
#include "../renderer/tr_local.h"
#include "../qcommon/qcommon.h"
#include "win_local.h"
#if defined(_WINDOWS) || defined(_XBOX)
#include "glw_win_dx8.h"
#elif defined(_GAMECUBE)
#include "glw_win_gc.h"
#endif
extern void WG_CheckHardwareGamma( void );
static void GLW_InitExtensions( void );
static int GLW_CreateWindow( void );
//
// function declaration
//
void QGL_EnableLogging( qboolean enable );
qboolean QGL_Init( const char *dllname );
void QGL_Shutdown( void );
void GLW_Init(int width, int height, int colorbits, qboolean cdsFullscreen);
void GLW_Shutdown(void);
//
// variable declarations
//
glwstate_t *glw_state = NULL;
/*
** GLW_CreateWindow
**
** Responsible for creating the Alchemy window and initializing the OpenGL driver.
*/
static qboolean GLW_CreateWindow( int width, int height, int colorbits, qboolean cdsFullscreen )
{
GLW_Init(width, height, colorbits, cdsFullscreen);
IN_Init();
return qtrue;
}
//--------------------------------------------
static void GLW_InitTextureCompression( void )
{
glConfig.textureCompression = TC_NONE;
}
/*
** GLW_InitExtensions
*/
static void GLW_InitExtensions( void )
{
// Select our tc scheme
GLW_InitTextureCompression();
// GL_EXT_texture_env_add
glConfig.textureEnvAddAvailable = qfalse;
if ( strstr( glConfig.extensions_string, "EXT_texture_env_add" ) )
{
glConfig.textureEnvAddAvailable = qtrue;
}
// GL_EXT_texture_filter_anisotropic
glConfig.textureFilterAnisotropicAvailable = qfalse;
if ( strstr( glConfig.extensions_string, "EXT_texture_filter_anisotropic" ) )
{
glConfig.textureFilterAnisotropicAvailable = qtrue;
}
// GL_EXT_clamp_to_edge
glConfig.clampToEdgeAvailable = qfalse;
if ( strstr( glConfig.extensions_string, "GL_EXT_texture_edge_clamp" ) )
{
glConfig.clampToEdgeAvailable = qtrue;
}
// GL_ARB_multitexture
if ( strstr( glConfig.extensions_string, "GL_ARB_multitexture" ) )
{
if ( qglActiveTextureARB )
{
qglGetIntegerv( GL_MAX_ACTIVE_TEXTURES_ARB, &glConfig.maxActiveTextures );
if ( glConfig.maxActiveTextures < 2 )
{
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
}
}
}
}
/*
** GLW_LoadOpenGL
**
** GLimp_win.c internal function that attempts to load and use
** a specific OpenGL DLL.
*/
static qboolean GLW_LoadOpenGL()
{
char buffer[1024];
strlwr( strcpy( buffer, OPENGL_DRIVER_NAME ) );
//
// load the driver and bind our function pointers to it
//
if ( QGL_Init( buffer ) )
{
GLW_CreateWindow(640, 480, 24, 1);
return qtrue;
}
QGL_Shutdown();
return qfalse;
}
/*
** GLimp_EndFrame
*/
void GLimp_EndFrame (void)
{
// don't flip if drawing to front buffer
// if ( stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 )
{
}
}
static void GLW_StartOpenGL( void )
{
//
// load and initialize the specific OpenGL driver
//
if ( !GLW_LoadOpenGL() )
{
Com_Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem\n" );
}
}
/*
** GLimp_Init
**
** This is the platform specific OpenGL initialization function. It
** is responsible for loading OpenGL, initializing it, setting
** extensions, creating a window of the appropriate size, doing
** fullscreen manipulations, etc. Its overall responsibility is
** to make sure that a functional OpenGL subsystem is operating
** when it returns to the ref.
*/
void GLimp_Init( void )
{
// load appropriate DLL and initialize subsystem
GLW_StartOpenGL();
// get our config strings
glConfig.vendor_string = (const char *) qglGetString (GL_VENDOR);
glConfig.renderer_string = (const char *) qglGetString (GL_RENDERER);
glConfig.version_string = (const char *) qglGetString (GL_VERSION);
glConfig.extensions_string = (const char *) qglGetString (GL_EXTENSIONS);
if (!glConfig.vendor_string || !glConfig.renderer_string || !glConfig.version_string || !glConfig.extensions_string)
{
Com_Error( ERR_FATAL, "GLimp_Init() - Invalid GL Driver\n" );
}
// OpenGL driver constants
qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &glConfig.maxTextureSize );
// stubbed or broken drivers may have reported 0...
if ( glConfig.maxTextureSize <= 0 )
{
glConfig.maxTextureSize = 0;
}
GLW_InitExtensions();
WG_CheckHardwareGamma();
}
/*
** GLimp_Shutdown
**
** This routine does all OS specific shutdown procedures for the OpenGL
** subsystem.
*/
void GLimp_Shutdown( void )
{
// FIXME: Brian, we need better fallbacks from partially initialized failures
VID_Printf( PRINT_ALL, "Shutting down OpenGL subsystem\n" );
// Set the gamma back to normal
// GLimp_SetGamma(1.f);
// kill input system (tied to window)
IN_Shutdown();
// shutdown QGL subsystem
GLW_Shutdown();
QGL_Shutdown();
memset( &glConfig, 0, sizeof( glConfig ) );
memset( &glState, 0, sizeof( glState ) );
}
/*
** GLimp_LogComment
*/
void GLimp_LogComment( char *comment )
{
}
/*
===========================================================
SMP acceleration
===========================================================
*/
qboolean GLimp_SpawnRenderThread( void (*function)( void ) ) {
return qfalse;
}
void *GLimp_RendererSleep( void ) {
return NULL;
}
void GLimp_FrontEndSleep( void ) {
}
void GLimp_WakeRenderer( void *data ) {
}

View File

@@ -0,0 +1,673 @@
//
//
// Win_HighDynamicRange.cpp
//
// High dynamic range effect
//
//
#include "../server/exe_headers.h"
#include "../renderer/tr_local.h"
#include "glw_win_dx8.h"
#include "win_local.h"
#include "win_highdynamicrange.h"
#include "shader_constants.h"
#include <xgmath.h>
#include <xgraphics.h>
extern const char *Sys_RemapPath( const char *filename );
VVHighDynamicRange HDREffect;
VVHighDynamicRange::VVHighDynamicRange()
{
m_bInitialized = false;
m_dwHotBlurPixelShader = 0;
m_dwExtractHotPixelShader = 0;
}
void VVHighDynamicRange::Initialize()
{
// Create pixel shader
if(!(CreatePixelShader(Sys_RemapPath("base\\media\\hotblur.xpu"), &m_dwHotBlurPixelShader)))
return;
if(!(CreatePixelShader(Sys_RemapPath("base\\media\\extracthot.xpu"), &m_dwExtractHotPixelShader)))
return;
// Get size of render target
LPDIRECT3DSURFACE8 pRenderTarget;
glw_state->device->GetRenderTarget( &pRenderTarget );
D3DSURFACE_DESC descRenderTarget;
pRenderTarget->GetDesc( &descRenderTarget );
UINT Width = descRenderTarget.Width;
UINT Height = descRenderTarget.Height;
D3DFORMAT Format = descRenderTarget.Format;
pRenderTarget->Release();
// Create extract hot text
glw_state->device->CreateTexture( Width >> 1, Height >> 1, 1,
D3DUSAGE_RENDERTARGET, Format,
0, &m_rpHotImage);
// Make the size a factor of 2 smaller on each axis
glw_state->device->CreateTexture( Width >> 1, Height >> 2, 1,
D3DUSAGE_RENDERTARGET, Format,
0, &m_rpBlur[0]);
glw_state->device->CreateTexture( Width >> 2, Height >> 2, 1,
D3DUSAGE_RENDERTARGET, Format,
0, &m_rpBlur[1]);
// Set bloom scale
m_fBloomScale = 1.00f;
m_bInitialized = true;
}
void VVHighDynamicRange::Render()
{
if(!m_bInitialized)
return;
DWORD lighting, fog, srcblend, destblend, alphablend, zwrite, zenable;
glw_state->device->GetRenderState( D3DRS_LIGHTING, &lighting );
glw_state->device->GetRenderState( D3DRS_FOGENABLE, &fog );
glw_state->device->GetRenderState( D3DRS_SRCBLEND, &srcblend );
glw_state->device->GetRenderState( D3DRS_DESTBLEND, &destblend );
glw_state->device->GetRenderState( D3DRS_ALPHABLENDENABLE, &alphablend );
glw_state->device->GetRenderState( D3DRS_ZWRITEENABLE, &zwrite );
glw_state->device->GetRenderState( D3DRS_ZENABLE, &zenable );
HotBlur(); // Blur the hot values in the backbuffer
DrawHotBlur(); // Draw blurred hot values, add to scene
glw_state->device->SetRenderState( D3DRS_LIGHTING, lighting );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, fog );
glw_state->device->SetRenderState( D3DRS_SRCBLEND, srcblend );
glw_state->device->SetRenderState( D3DRS_DESTBLEND, destblend );
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, alphablend );
glw_state->device->SetRenderState( D3DRS_ZWRITEENABLE, zwrite );
glw_state->device->SetRenderState( D3DRS_ZENABLE, zenable );
}
void VVHighDynamicRange::DrawHotBlur()
{
if( !m_pBlur )
return;
LPDIRECT3DTEXTURE8 pTexture = m_pBlur;
// Get size of backbuffer
LPDIRECT3DSURFACE8 pRenderTarget;
glw_state->device->GetRenderTarget( &pRenderTarget );
D3DSURFACE_DESC descRenderTarget;
pRenderTarget->GetDesc( &descRenderTarget );
UINT Width = descRenderTarget.Width;
UINT Height = descRenderTarget.Height;
pRenderTarget->Release();
// Texture coordinates in linear format textures go from 0 to n-1 rather
// than the 0 to 1 that is used for swizzled textures.
D3DSURFACE_DESC desc;
pTexture->GetLevelDesc( 0, &desc );
struct BACKGROUNDVERTEX { D3DXVECTOR4 p; FLOAT tu, tv; } v[4];
v[0].p = D3DXVECTOR4( -0.5f, -0.5f, 1.0f, 1.0f );
v[0].tu = 0.0f; v[0].tv = 0.0f;
v[1].p = D3DXVECTOR4( Width - 0.5f, -0.5f, 1.0f, 1.0f );
v[1].tu = (float)desc.Width; v[1].tv = 0.0f;
v[2].p = D3DXVECTOR4( -0.5f, Height - 0.5f, 1.0f, 1.0f );
v[2].tu = 0.0f; v[2].tv = (float)desc.Height;
v[3].p = D3DXVECTOR4( Width - 0.5f, Height - 0.5f, 1.0f, 1.0f );
v[3].tu = (float)desc.Width; v[3].tv = (float)desc.Height;
// Set states
glw_state->device->SetPixelShader( 0 );
glw_state->device->SetTexture( 0, pTexture );
glw_state->device->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE2X );
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
glw_state->device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 0, D3DTSS_MAXMIPLEVEL, 0 );
glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
glw_state->device->SetRenderState( D3DRS_ZENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
XGCOLOR Blend(1.0f, 1.0f, 1.0f, 1.0f);
Blend*= r_hdrbloom->value;//m_fBloomScale; // adjust blend amount
glw_state->device->SetRenderState( D3DRS_TEXTUREFACTOR, Blend );
// add if requested
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
glw_state->device->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
glw_state->device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
glw_state->device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
// Render the screen-aligned quadrilateral
glw_state->device->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX1 );
glw_state->device->DrawVerticesUP( D3DPT_QUADSTRIP, 4, v, sizeof(BACKGROUNDVERTEX) );
glw_state->device->SetRenderState( D3DRS_ZENABLE, TRUE );
}
void VVHighDynamicRange::FilterCopy( LPDIRECT3DTEXTURE8 pTextureDst,
LPDIRECT3DTEXTURE8 pTextureSrc,
UINT nSample, FilterSample rSample[],
UINT nSuperSampleX, UINT nSuperSampleY,
bool bCrap,
RECT* pRectDst, RECT* pRectSrc
)
{
// Texture space pixel center == screen space pixel center
glw_state->device->SetScreenSpaceOffset( -0.5f, -0.5f );
// Save current render target and depth buffer
LPDIRECT3DSURFACE8 pRenderTarget, pZBuffer;
glw_state->device->GetRenderTarget( &pRenderTarget );
glw_state->device->GetDepthStencilSurface( &pZBuffer );
// Set destination as render target
LPDIRECT3DSURFACE8 pSurface = NULL;
pTextureDst->GetSurfaceLevel( 0, &pSurface );
glw_state->device->SetRenderTarget( pSurface, NULL ); // no depth-buffering
pSurface->Release();
// Get descriptions of source and destination
D3DSURFACE_DESC descSrc;
pTextureSrc->GetLevelDesc( 0, &descSrc );
D3DSURFACE_DESC descDst;
pTextureDst->GetLevelDesc( 0, &descDst );
// Setup rectangles if not specified on input
RECT rectSrc = { 0, 0, descSrc.Width, descSrc.Height };
if( pRectSrc == NULL ) pRectSrc = &rectSrc;
RECT rectDst = { 0, 0, descDst.Width, descDst.Height };
if( pRectDst == NULL )
{
// If the destination rectangle is not specified,
// we change it to match the source rectangle
rectDst.right = (pRectSrc->right - pRectSrc->left) / nSuperSampleX;
rectDst.bottom = (pRectSrc->bottom - pRectSrc->top) / nSuperSampleY;
pRectDst = &rectDst;
}
assert( (pRectDst->right - pRectDst->left) ==
(pRectSrc->right - pRectDst->left) / (INT)nSuperSampleX );
assert( (pRectDst->bottom - pRectDst->top) ==
(pRectSrc->bottom - pRectDst->top) / (INT)nSuperSampleY );
//Set render state for filtering
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
glw_state->device->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
glw_state->device->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
glw_state->device->SetRenderState( D3DRS_STENCILENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
// On first rendering, copy new value over current render target contents
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
// Setup subsequent renderings to add to previous value
glw_state->device->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
glw_state->device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
glw_state->device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
// Set texture state
for( UINT xx = 0; xx < 4; xx++)
{
// Use our source texture for all four stages
glw_state->device->SetTexture( xx, pTextureSrc);
glw_state->device->SetTextureStageState( xx, D3DTSS_COLOROP, D3DTOP_DISABLE );
glw_state->device->SetTextureStageState( xx, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
// Pass texture coords without transformation
glw_state->device->SetTextureStageState( xx, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
// Each texture has different tex coords
glw_state->device->SetTextureStageState( xx, D3DTSS_TEXCOORDINDEX, xx );
glw_state->device->SetTextureStageState( xx, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( xx, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( xx, D3DTSS_MAXMIPLEVEL, 0 );
glw_state->device->SetTextureStageState( xx, D3DTSS_MIPFILTER, D3DTEXF_NONE );
glw_state->device->SetTextureStageState( xx, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( xx, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( xx, D3DTSS_COLORKEYOP, D3DTCOLORKEYOP_DISABLE );
glw_state->device->SetTextureStageState( xx, D3DTSS_COLORSIGN, 0 );
glw_state->device->SetTextureStageState( xx, D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE );
}
// Use hot blur pixel shader
if(bCrap)
glw_state->device->SetPixelShader( m_dwExtractHotPixelShader );
else
glw_state->device->SetPixelShader( m_dwHotBlurPixelShader );
// For screen-space texture-mapped quadrilateral
glw_state->device->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX4 );
// Prepare quadrilateral vertices
float x0 = (float)pRectDst->left;
float y0 = (float)pRectDst->top;
float x1 = (float)pRectDst->right;
float y1 = (float)pRectDst->bottom;
struct Quad
{
float x, y, z, w1;
struct uv
{
float u, v;
}
tex[4]; // each texture has different offset
}
aQuad[4] =
{ // X Y Z 1/W u0 v0 u1 v1 u2 v2 u3 v3
{x0, y0, 1.0f, 1.0f, }, // texture coords are set below
{x1, y0, 1.0f, 1.0f, },
{x0, y1, 1.0f, 1.0f, },
{x1, y1, 1.0f, 1.0f, }
};
// Set rendering to just the destination rect
glw_state->device->SetScissors( 1, FALSE, (D3DRECT *)pRectDst );
// Draw a quad for each block of 4 filter coefficients
float fOffsetScaleU = (float)nSuperSampleX; // offset for supersample
float fOffsetScaleV = (float)nSuperSampleY;
float u0 = (float)pRectSrc->left;
float v0 = (float)pRectSrc->top;
float u1 = (float)pRectSrc->right;
float v1 = (float)pRectSrc->bottom;
if( XGIsSwizzledFormat( descSrc.Format ) )
{
float fWidthScale = 1.f / (float)descSrc.Width;
float fHeightScale = 1.f / (float)descSrc.Height;
fOffsetScaleU *= fWidthScale;
fOffsetScaleV *= fHeightScale;
u0 *= fWidthScale;
v0 *= fHeightScale;
u1 *= fWidthScale;
v1 *= fHeightScale;
}
xx = 0; // current texture stage
D3DCOLOR rColor[4];
DWORD rPSInput[4];
for( UINT iSample = 0; iSample < nSample; iSample++ )
{
// Set filter coefficients
float fValue = rSample[iSample].fValue;
if( fValue < 0.f )
{
rColor[xx] = D3DXCOLOR( -fValue, -fValue, -fValue, -fValue );
rPSInput[xx] = PS_INPUTMAPPING_SIGNED_NEGATE |
((xx % 2) ? PS_REGISTER_C1 : PS_REGISTER_C0);
}
else
{
rColor[xx] = D3DXCOLOR( fValue, fValue, fValue, fValue );
rPSInput[xx] = PS_INPUTMAPPING_SIGNED_IDENTITY |
((xx % 2) ? PS_REGISTER_C1 : PS_REGISTER_C0);
}
// Align supersamples with center of destination pixels
float fOffsetX = rSample[iSample].fOffsetX;// * fOffsetScaleU;
float fOffsetY = rSample[iSample].fOffsetY;// * fOffsetScaleV;
aQuad[0].tex[xx].u = u0 + fOffsetX;
aQuad[0].tex[xx].v = v0 + fOffsetY;
aQuad[1].tex[xx].u = u1 + fOffsetX;
aQuad[1].tex[xx].v = v0 + fOffsetY;
aQuad[2].tex[xx].u = u0 + fOffsetX;
aQuad[2].tex[xx].v = v1 + fOffsetY;
aQuad[3].tex[xx].u = u1 + fOffsetX;
aQuad[3].tex[xx].v = v1 + fOffsetY;
xx++; // Go to next stage
if( xx == 4 || iSample == nSample - 1 ) // max texture stages or last sample
{
// Zero out unused texture stage coefficients
// (Only for last filter sample, when number of samples is not divisible by 4)
for( ; xx < 4; xx++)
{
glw_state->device->SetTexture( xx, NULL );
rColor[xx] = 0;
rPSInput[xx] = PS_INPUTMAPPING_UNSIGNED_IDENTITY | PS_REGISTER_ZERO;
}
// Set coefficients
glw_state->device->SetRenderState( D3DRS_PSCONSTANT0_0, rColor[0] );
glw_state->device->SetRenderState( D3DRS_PSCONSTANT1_0, rColor[1] );
glw_state->device->SetRenderState( D3DRS_PSCONSTANT0_1, rColor[2] );
glw_state->device->SetRenderState( D3DRS_PSCONSTANT1_1, rColor[3] );
if(bCrap)
{
}
else
{
// Remap coefficients to proper sign
glw_state->device->SetRenderState(
D3DRS_PSRGBINPUTS0,
PS_COMBINERINPUTS( rPSInput[0] | PS_CHANNEL_RGB,
PS_REGISTER_T0 | PS_CHANNEL_RGB |
PS_INPUTMAPPING_SIGNED_IDENTITY,
rPSInput[1] | PS_CHANNEL_RGB,
PS_REGISTER_T1 | PS_CHANNEL_RGB |
PS_INPUTMAPPING_SIGNED_IDENTITY ) );
glw_state->device->SetRenderState(
D3DRS_PSALPHAINPUTS0,
PS_COMBINERINPUTS( rPSInput[0] | PS_CHANNEL_ALPHA,
PS_REGISTER_T0 | PS_CHANNEL_ALPHA |
PS_INPUTMAPPING_SIGNED_IDENTITY,
rPSInput[1] | PS_CHANNEL_ALPHA,
PS_REGISTER_T1 | PS_CHANNEL_ALPHA |
PS_INPUTMAPPING_SIGNED_IDENTITY ) );
glw_state->device->SetRenderState(
D3DRS_PSRGBINPUTS1,
PS_COMBINERINPUTS( rPSInput[2] | PS_CHANNEL_RGB,
PS_REGISTER_T2 | PS_CHANNEL_RGB |
PS_INPUTMAPPING_SIGNED_IDENTITY,
rPSInput[3] | PS_CHANNEL_RGB,
PS_REGISTER_T3 | PS_CHANNEL_RGB |
PS_INPUTMAPPING_SIGNED_IDENTITY ) );
glw_state->device->SetRenderState(
D3DRS_PSALPHAINPUTS1,
PS_COMBINERINPUTS( rPSInput[2] | PS_CHANNEL_ALPHA,
PS_REGISTER_T2 | PS_CHANNEL_ALPHA |
PS_INPUTMAPPING_SIGNED_IDENTITY,
rPSInput[3] | PS_CHANNEL_ALPHA,
PS_REGISTER_T3 | PS_CHANNEL_ALPHA |
PS_INPUTMAPPING_SIGNED_IDENTITY ) );
}
// Draw the quad to filter the coefficients so far
// One quad blends 4 textures
glw_state->device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, aQuad, sizeof(Quad) );
// On subsequent renderings, add to what's in the render target
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
xx = 0;
}
}
// Clear texture stages
for( xx=0; xx<4; xx++ )
{
glw_state->device->SetTexture( xx, NULL );
glw_state->device->SetTextureStageState( xx, D3DTSS_COLOROP, D3DTOP_DISABLE );
glw_state->device->SetTextureStageState( xx, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
glw_state->device->SetTextureStageState( xx, D3DTSS_MIPMAPLODBIAS, 0 );
}
// Restore render target and zbuffer
glw_state->device->SetRenderTarget( pRenderTarget, pZBuffer );
if( pRenderTarget )
pRenderTarget->Release();
if( pZBuffer )
pZBuffer->Release();
glw_state->device->SetScreenSpaceOffset( 0.0f, 0.0f );
}
void VVHighDynamicRange::ExtractHot( LPDIRECT3DTEXTURE8 pTextureDst,
LPDIRECT3DTEXTURE8 pTextureSrc,
UINT nSuperSampleX, UINT nSuperSampleY,
RECT* pRectDst, RECT* pRectSrc )
{
// Texture space pixel center == screen space pixel center
glw_state->device->SetScreenSpaceOffset( -0.5f, -0.5f );
// Save current render target and depth buffer
LPDIRECT3DSURFACE8 pRenderTarget, pZBuffer;
glw_state->device->GetRenderTarget( &pRenderTarget );
glw_state->device->GetDepthStencilSurface( &pZBuffer );
// Surface that has the depth-buffer as data, used as an RGBA texture:
D3DSurface zBufferSurface;
D3DSURFACE_DESC descZ;
pZBuffer->GetDesc( &descZ );
XGSetSurfaceHeader( descZ.Width, descZ.Height, D3DFMT_LIN_A8R8G8B8, &zBufferSurface, pZBuffer->Data, descZ.Width * 4 );
// Set destination as render target
LPDIRECT3DSURFACE8 pSurface = NULL;
pTextureDst->GetSurfaceLevel( 0, &pSurface );
glw_state->device->SetRenderTarget( pSurface, NULL ); // no depth-buffering
pSurface->Release();
// Get descriptions of source and destination
D3DSURFACE_DESC descSrc;
pTextureSrc->GetLevelDesc( 0, &descSrc );
D3DSURFACE_DESC descDst;
pTextureDst->GetLevelDesc( 0, &descDst );
// Setup rectangles if not specified on input
RECT rectSrc = { 0, 0, descSrc.Width, descSrc.Height };
if( pRectSrc == NULL ) pRectSrc = &rectSrc;
RECT rectDst = { 0, 0, descDst.Width, descDst.Height };
if( pRectDst == NULL )
{
// If the destination rectangle is not specified,
// we change it to match the source rectangle
rectDst.right = (pRectSrc->right - pRectSrc->left) / nSuperSampleX;
rectDst.bottom = (pRectSrc->bottom - pRectSrc->top) / nSuperSampleY;
pRectDst = &rectDst;
}
assert( (pRectDst->right - pRectDst->left) ==
(pRectSrc->right - pRectDst->left) / (INT)nSuperSampleX );
assert( (pRectDst->bottom - pRectDst->top) ==
(pRectSrc->bottom - pRectDst->top) / (INT)nSuperSampleY );
//Set render state for filtering
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
glw_state->device->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
glw_state->device->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
// glw_state->device->SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS ); // New
// glw_state->device->SetRenderState( D3DRS_STENCILENABLE, FALSE ); // Stencil done in PS
glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
glw_state->device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
glw_state->device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
// Put our original back buffer in texture 0, put the old Z/Stencil in texture 1:
glw_state->device->SetTexture( 0, pTextureSrc );
glw_state->device->SetTexture( 1, (LPDIRECT3DTEXTURE8)&zBufferSurface );
glw_state->device->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE );
glw_state->device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
glw_state->device->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
glw_state->device->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
// Pass texture coords without transformation
glw_state->device->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
glw_state->device->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
// Each texture has different tex coords
glw_state->device->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU,
D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV,
D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 0, D3DTSS_MAXMIPLEVEL, 0 );
glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_GAUSSIANCUBIC );
glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_GAUSSIANCUBIC );
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORKEYOP,
D3DTCOLORKEYOP_DISABLE );
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORSIGN, 0 );
glw_state->device->SetTextureStageState( 0, D3DTSS_ALPHAKILL,
D3DTALPHAKILL_DISABLE );
// Z/Stencil is similar, but we don't want any filtering, just sampling:
glw_state->device->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
glw_state->device->SetTextureStageState( 1, D3DTSS_ADDRESSU,
D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 1, D3DTSS_ADDRESSV,
D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 1, D3DTSS_MAXMIPLEVEL, 0 );
glw_state->device->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE );
glw_state->device->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_POINT );
glw_state->device->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_POINT );
glw_state->device->SetTextureStageState( 1, D3DTSS_COLORKEYOP,
D3DTCOLORKEYOP_DISABLE );
glw_state->device->SetTextureStageState( 1, D3DTSS_COLORSIGN, 0 );
glw_state->device->SetTextureStageState( 1, D3DTSS_ALPHAKILL,
D3DTALPHAKILL_DISABLE );
// Use extract hot pixel shader
glw_state->device->SetPixelShader( m_dwExtractHotPixelShader );
float CutoffScale[8];
CutoffScale[0] = CutoffScale[1] = CutoffScale[2] = CutoffScale[3] = r_hdrcutoff->value;
CutoffScale[4] = CutoffScale[5] = CutoffScale[6] = CutoffScale[7] = r_hdrcutoff->value / (1.0f - r_hdrcutoff->value);
glw_state->device->SetPixelShaderConstant( CP_EXTRACT_CUTOFF, CutoffScale, 2 );
// For screen-space texture-mapped quadrilateral
glw_state->device->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX1 );
// Prepare quadrilateral vertices
float x0 = (float)pRectDst->left;
float y0 = (float)pRectDst->top;
float x1 = (float)pRectDst->right;
float y1 = (float)pRectDst->bottom;
struct Quad
{
float x, y, z, w1;
struct uv
{
float u, v;
}
tex;
}
aQuad[4] =
{ // X Y Z 1/W u0 v0 u1 v1 u2 v2 u3 v3
{x0, y0, 1.0f, 1.0f, }, // texture coords are set below
{x1, y0, 1.0f, 1.0f, },
{x0, y1, 1.0f, 1.0f, },
{x1, y1, 1.0f, 1.0f, }
};
// Set rendering to just the destination rect
glw_state->device->SetScissors( 1, FALSE, (D3DRECT *)pRectDst );
// Draw a quad for each block of 4 filter coefficients
float u0 = (float)pRectSrc->left;
float v0 = (float)pRectSrc->top;
float u1 = (float)pRectSrc->right;
float v1 = (float)pRectSrc->bottom;
if( XGIsSwizzledFormat( descSrc.Format ) )
{
float fWidthScale = 1.f / (float)descSrc.Width;
float fHeightScale = 1.f / (float)descSrc.Height;
u0 *= fWidthScale;
v0 *= fHeightScale;
u1 *= fWidthScale;
v1 *= fHeightScale;
}
aQuad[0].tex.u = u0;
aQuad[0].tex.v = v0;
aQuad[1].tex.u = u1;
aQuad[1].tex.v = v0;
aQuad[2].tex.u = u0;
aQuad[2].tex.v = v1;
aQuad[3].tex.u = u1;
aQuad[3].tex.v = v1;
// Draw the quad
glw_state->device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP,
2, aQuad, sizeof(Quad) );
glw_state->device->SetTexture( 0, NULL );
glw_state->device->SetTexture( 1, NULL );
// Restore render target and zbuffer
glw_state->device->SetRenderTarget( pRenderTarget, pZBuffer );
if( pRenderTarget )
pRenderTarget->Release();
if( pZBuffer )
pZBuffer->Release();
glw_state->device->SetScreenSpaceOffset( 0.0f, 0.0f );
// Restore ztest?
// glw_state->device->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
}
void VVHighDynamicRange::HotBlur()
{
// Make D3DTexture wrapper around current render target
LPDIRECT3DSURFACE8 pRenderTarget;
glw_state->device->GetRenderTarget( &pRenderTarget );
D3DSURFACE_DESC descRenderTarget;
pRenderTarget->GetDesc( &descRenderTarget );
D3DTexture RenderTargetTexture;
ZeroMemory( &RenderTargetTexture, sizeof(RenderTargetTexture) );
XGSetTextureHeader( descRenderTarget.Width, descRenderTarget.Height,
1, 0, descRenderTarget.Format, 0,
&RenderTargetTexture, pRenderTarget->Data,
descRenderTarget.Width * 4 );
pRenderTarget->Release();
// Filters align to blurriest point in supersamples, on the pixel centers
// This takes advantage of the bilinear filtering in the texture map lookup.
FilterSample YFilter[] = // 1221 4-tap filter in Y
{
{ 2.0f/6.f, 0.0f, 1.0f },
{ 1.0f/6.f, 0.0f, 3.0f },
{ 2.0f/6.f, 0.0f, -1.0f },
{ 1.0f/6.f, 0.0f, -3.0f },
};
FilterSample XFilter[] = // 1221 4-tap filter in X
{
{ 2.0f/6.f, 1.0f, 0.0f },
{ 1.0f/6.f, 3.0f, 0.0f },
{ 2.0f/6.f, -1.0f, 0.0f },
{ 1.0f/6.f, -3.0f, 0.0f },
};
D3DTexture *pTextureSrc;
D3DTexture *pTextureDst;
pTextureDst = &RenderTargetTexture; // source is backbuffer
// extract "hot" portion of hte image with downsampling
pTextureSrc = pTextureDst;
pTextureDst = m_rpHotImage; // destination is blur texture
ExtractHot( pTextureDst, pTextureSrc, 2, 2 );
// ExtractHot( pTextureDst, pTextureSrc, 1, 1 );
// 2 passes: Vertical gaussian (1221) followed by
// horizontal gaussian (1221), with 2x2 downsampling
pTextureSrc = pTextureDst; // destination is next blur texture
pTextureDst = m_rpBlur[0]; // destination is blur texture
FilterCopy(pTextureDst, pTextureSrc, 4, YFilter, 1, 2, false);
pTextureSrc = pTextureDst; // source is previous blur texture
pTextureDst = m_rpBlur[1]; // destination is next blur texture
FilterCopy(pTextureDst, pTextureSrc, 4, XFilter, 2, 1, false);
m_pBlur = pTextureDst;
}

View File

@@ -0,0 +1,77 @@
//
//
// Win_HighDynamicRange.h
//
// Declaration of high dynamic range effect class
//
//
#ifndef _WIN_HIGHDYNAMICRANGE_H_
#define _WIN_HIGHDYNAMICRANGE_H_
struct FilterSample
{
float fValue; // coefficient
float fOffsetX, fOffsetY; // subpixel offsets of supersamples in
// destination coordinates
};
class VVHighDynamicRange
{
// The blur filters are multipass and need temporary space.
#define BLUR_COUNT 2
D3DTexture *m_rpHotImage; // hot image
D3DTexture *m_rpBlur[BLUR_COUNT]; // bluring textures of decreasing size
D3DTexture *m_pBlur; // current blur texture, set by Blur()
// Light blend intensity scale factor
float m_fBloomScale;
// Pixel shader handles
DWORD m_dwHotBlurPixelShader; // blur the hot image
DWORD m_dwExtractHotPixelShader; // extract hot image
bool m_bInitialized;
// Filtering routine that draws the source texture multiple
// times, with sub-pixel offsets and filter coefficients.
void FilterCopy( LPDIRECT3DTEXTURE9 pTextureDst,
LPDIRECT3DTEXTURE9 pTextureSrc,
UINT nSample,
FilterSample rSample[],
UINT nSuperSampleX,
UINT nSuperSampleY,
bool bCrap,
RECT *pRectDst = NULL, // The destination texture is
// written only within this
// region.
RECT *pRectSrc = NULL );// The source texture is read
// outside of this region by
// the halfwidth of the
// filter.
// extract hot image with downsamping
void ExtractHot( LPDIRECT3DTEXTURE9 pTextureDst,
LPDIRECT3DTEXTURE9 pTextureSrc,
UINT nSuperSampleX, UINT nSuperSampleY,
RECT* pRectDst = NULL,
RECT* pRectSrc = NULL );
// Blur hot texture and set m_pBlur. Calls FilterCopy with
// different filter coefficients and offsets
void HotBlur();
// Demonstrate the inputs to the full high dynamic range effect.
void DrawHotBlur(); // draw blurred "hot" texture
public:
virtual void Initialize();
virtual void Render();
VVHighDynamicRange();
};
extern VVHighDynamicRange HDREffect;
#endif

1147
code/win32/win_input.cpp Normal file

File diff suppressed because it is too large Load Diff

101
code/win32/win_input.h Normal file
View File

@@ -0,0 +1,101 @@
#ifndef _WIN_INPUT_H_
#define _WIN_INPUT_H_
bool IN_ControllersChanged(int inserted[], int removed[]);
#if defined (_XBOX ) || defined (_GAMECUBE)
#define _USE_RUMBLE
#endif
bool IN_AnyButtonPressed(void);
void IN_enableRumble( void );
void IN_disableRumble( void );
bool IN_usingRumble( void );
int IN_CreateRumbleScript(int controller, int numStates, bool deleteWhenFinished);
void IN_DeleteRumbleScript(int whichScript);
void IN_KillRumbleScript(int whichScript);
void IN_ExecuteRumbleScript(int whichScript);
bool IN_AdvanceToNextState(int whichScript);
void IN_KillRumbleScripts(int controller);
void IN_KillRumbleScripts( void );
#define IN_CMD_GOTO_XTIMES -5
#define IN_CMD_GOTO -6
#define IN_CMD_DEC_ARG2 -7
#define IN_CMD_INC_ARG2 -8
#define IN_CMD_DEC_ARG1 -9
#define IN_CMD_INC_ARG1 -10
#ifdef _XBOX
#define IN_CMD_DEC_LEFT -70
#define IN_CMD_DEC_RIGHT -71
#define IN_CMD_INC_LEFT -72
#define IN_CMD_INC_RIGHT -73
#endif
#if defined (_XBOX) // ----- XBOX --------
int IN_AddRumbleState(int whichScript, int leftSpeed, int rightSpeed, int timeInMs);
int IN_AddEffectFade4(int whichScript, int startLeft, int startRight, int endLeft, int endRight, int timeInMs);
int IN_AddEffectFadeExp6(int whichScript, int startLeft, int startRight, int endLeft, int endRight, char factor, int timeInMs);
#elif defined (_GAMECUBE) // ---- GAME CUBE ----
#define IN_GCACTION_START 1
#define IN_GCACTION_STOP 2
#define IN_GCACTION_STOPHARD 3
int IN_AddRumbleState(int whichScript, int action, int timeInMs, int arg = 0);
#endif // ------END IF-------
int IN_AddRumbleStateSpecial(int whichScript, int action, int arg1, int arg2);
void IN_KillRumbleState(int whichScript, int index);
void IN_PauseRumbling(int controller);
void IN_PauseRumbling( void );
void IN_UnPauseRumbling(int controller);
void IN_UnPauseRumbling( void );
void IN_TogglePauseRumbling(int controller);
void IN_TogglePauseRumbling( void );
int IN_GetMainController();
void IN_SetMainController(int id);
void IN_PadUnplugged(int controller);
void IN_PadPlugged(int controller);
void IN_CommonJoyPress(int controller, fakeAscii_t button, bool pressed);
void IN_CommonUpdate(void);
#define IN_MAX_JOYSTICKS 2
// Stores gamepad joystick info
struct JoystickInfo
{
bool valid;
float x, y;
};
// Stores gamepad id and joysick info
struct PadInfo
{
JoystickInfo joyInfo[2];
int padId;
};
// Buffer for gamepad info
extern PadInfo _padInfo;
bool IN_RumbleAdjust(int controller, int left, int right);
void IN_RumbleInit (void);
void IN_RumbleShutdown (void);
void IN_RumbleFrame (void);
#endif // END _WIN_INPUT_H_

View File

@@ -0,0 +1,900 @@
// #include "../server/exe_headers.h"
#include "../client/client.h"
//JLF
#include "../client/client_ui.h"
#include "../qcommon/qcommon.h"
#ifdef _JK2MP
#include "../ui/keycodes.h"
#else
#include "../client/keycodes.h"
#endif
#include "win_local.h"
#include "win_input.h"
cvar_t *inSplashMenu = NULL;
cvar_t *controllerOut = NULL;
static void HandleDebugJoystickPress(fakeAscii_t button);
static bool _UIRunning = false;
static bool IN_ControllerMustBePlugged(int controller);
// By default, cheatpad is turned on except in final build. Just change
// here to modify that.
#ifndef FINAL_BUILD
//#define DEBUG_CONTROLLER
#endif
// Controller connection globals
static signed char uiControllerNotification = -1;
bool noControllersConnected = false;
bool wasPlugged[4];
int mainControllerDelayedUnplug = 0;
PadInfo _padInfo; // gamepad thumbstick buffer
/**********************************************************
*
* CHEAT FUNCTIONS
*
**********************************************************/
bool Cheat_God( void )
{
Cbuf_ExecuteText( EXEC_APPEND, "god\n" );
return true;
}
void Cheat_GiveAll( void )
{
Cbuf_ExecuteText(EXEC_APPEND, "give all\n");
}
extern bool Cheat_ChangeSaber( void ); // In wp_saber.cpp
#include "../game/anims.h"
#include "../cgame/cg_local.h"
static bool isDeathAnimation( int anim )
{
switch( anim )
{
case BOTH_DEATH1: //# First Death anim
case BOTH_DEATH2: //# Second Death anim
case BOTH_DEATH3: //# Third Death anim
case BOTH_DEATH4: //# Fourth Death anim
case BOTH_DEATH5: //# Fifth Death anim
case BOTH_DEATH6: //# Sixth Death anim
case BOTH_DEATH7: //# Seventh Death anim
case BOTH_DEATH8: //#
case BOTH_DEATH9: //#
case BOTH_DEATH10: //#
case BOTH_DEATH11: //#
case BOTH_DEATH12: //#
case BOTH_DEATH13: //#
case BOTH_DEATH14: //#
case BOTH_DEATH14_UNGRIP: //# Desann's end death (cin #35)
case BOTH_DEATH14_SITUP: //# Tavion sitting up after having been thrown (cin #23)
case BOTH_DEATH15: //#
case BOTH_DEATH16: //#
case BOTH_DEATH17: //#
case BOTH_DEATH18: //#
case BOTH_DEATH19: //#
case BOTH_DEATH20: //#
case BOTH_DEATH21: //#
case BOTH_DEATH22: //#
case BOTH_DEATH23: //#
case BOTH_DEATH24: //#
case BOTH_DEATH25: //#
case BOTH_DEATHFORWARD1: //# First Death in which they get thrown forward
case BOTH_DEATHFORWARD2: //# Second Death in which they get thrown forward
case BOTH_DEATHFORWARD3: //# Tavion's falling in cin# 23
case BOTH_DEATHBACKWARD1: //# First Death in which they get thrown backward
case BOTH_DEATHBACKWARD2: //# Second Death in which they get thrown backward
case BOTH_DEATH1IDLE: //# Idle while close to death
case BOTH_LYINGDEATH1: //# Death to play when killed lying down
case BOTH_STUMBLEDEATH1: //# Stumble forward and fall face first death
case BOTH_FALLDEATH1: //# Fall forward off a high cliff and splat death - start
case BOTH_FALLDEATH1INAIR: //# Fall forward off a high cliff and splat death - loop
case BOTH_FALLDEATH1LAND: //# Fall forward off a high cliff and splat death - hit bottom
case BOTH_DEAD1: //# First Death finished pose
case BOTH_DEAD2: //# Second Death finished pose
case BOTH_DEAD3: //# Third Death finished pose
case BOTH_DEAD4: //# Fourth Death finished pose
case BOTH_DEAD5: //# Fifth Death finished pose
case BOTH_DEAD6: //# Sixth Death finished pose
case BOTH_DEAD7: //# Seventh Death finished pose
case BOTH_DEAD8: //#
case BOTH_DEAD9: //#
case BOTH_DEAD10: //#
case BOTH_DEAD11: //#
case BOTH_DEAD12: //#
case BOTH_DEAD13: //#
case BOTH_DEAD14: //#
case BOTH_DEAD15: //#
case BOTH_DEAD16: //#
case BOTH_DEAD17: //#
case BOTH_DEAD18: //#
case BOTH_DEAD19: //#
case BOTH_DEAD20: //#
case BOTH_DEAD21: //#
case BOTH_DEAD22: //#
case BOTH_DEAD23: //#
case BOTH_DEAD24: //#
case BOTH_DEAD25: //#
case BOTH_DEADFORWARD1: //# First thrown forward death finished pose
case BOTH_DEADFORWARD2: //# Second thrown forward death finished pose
case BOTH_DEADBACKWARD1: //# First thrown backward death finished pose
case BOTH_DEADBACKWARD2: //# Second thrown backward death finished pose
case BOTH_LYINGDEAD1: //# Killed lying down death finished pose
case BOTH_STUMBLEDEAD1: //# Stumble forward death finished pose
case BOTH_FALLDEAD1LAND: //# Fall forward and splat death finished pose
case BOTH_DEADFLOP1: //# React to being shot from First Death finished pose
case BOTH_DEADFLOP2: //# React to being shot from Second Death finished pose
case BOTH_DISMEMBER_HEAD1: //#
case BOTH_DISMEMBER_TORSO1: //#
case BOTH_DISMEMBER_LLEG: //#
case BOTH_DISMEMBER_RLEG: //#
case BOTH_DISMEMBER_RARM: //#
case BOTH_DISMEMBER_LARM: //#
case BOTH_DEATH_ROLL: //# Death anim from a roll
case BOTH_DEATH_FLIP: //# Death anim from a flip
case BOTH_DEATH_SPIN_90_R: //# Death anim when facing 90 degrees right
case BOTH_DEATH_SPIN_90_L: //# Death anim when facing 90 degrees left
case BOTH_DEATH_SPIN_180: //# Death anim when facing backwards
case BOTH_DEATH_LYING_UP: //# Death anim when lying on back
case BOTH_DEATH_LYING_DN: //# Death anim when lying on front
case BOTH_DEATH_FALLING_DN: //# Death anim when falling on face
case BOTH_DEATH_FALLING_UP: //# Death anim when falling on back
case BOTH_DEATH_CROUCHED: //# Death anim when crouched
return true;
break;
default:
return false;
break;
}
}
bool Cheat_WinLevel( void )
{
// Do not do this while any UI is active. It's dangerous:
extern int Key_GetCatcher( void );
if( Key_GetCatcher() == KEYCATCH_UI )
return false;
// Also, don't do it during cutscenes:
extern bool in_camera;
if( in_camera || ( g_entities[0].client && isDeathAnimation(g_entities[0].client->ps.legsAnim)))
return false;
// All maps (except kor2) have a trigger item named end_level
Cbuf_ExecuteText( EXEC_APPEND, "use end_level\n" );
return true;
}
#ifndef XBOX_DEMO
bool Cheat_LevelSelect( void )
{
// Set cvar that enables the level select menu:
Cvar_SetValue( "ui_levelselect", 1 );
return true;
}
#endif
extern bool Cheat_InfiniteForce( void ); // In wp_saber.cpp
#if YELLOW_MODE
extern bool enableYellowMode;
char yellowModeLevel = 0;
bool enableYellowStage2 = false;
bool Cheat_Yellow_Stage2( void )
{
if(!enableYellowStage2)
return false;
if(IN_GetMainController() != 0)
return false;
if( g_entities[0].client && isDeathAnimation(g_entities[0].client->ps.legsAnim))
enableYellowMode = true;
else
enableYellowMode = false;
return enableYellowMode;
}
bool Cheat_Yellow_Stage1( void )
{
if(IN_GetMainController() != 1)
return false;
if(yellowModeLevel == 0) // step one, in a cutscene
{
extern bool in_camera;
if(in_camera)
{
yellowModeLevel++;
return true;
}
}
else if( yellowModeLevel == 1 ) // step two, during the splash screen
{
if(inSplashMenu->integer)
{
yellowModeLevel++;
return true;
}
}
else if( yellowModeLevel == 2 ) // step three, while force hud is active
{
if(cg.forceHUDActive)
{
yellowModeLevel++;
return true;
}
}
if(yellowModeLevel == 3) // eveything is ok, now reset and move to stage 2
{
enableYellowStage2 = true;
yellowModeLevel = 4;
return true;
}
return false;
}
#endif // YELLOW_MODE
bool Cheat_AllForce( void )
{
// Do not do this while the force config UI is running. That causes SERIOUS problems:
extern bool UI_ForceConfigUIActive( void );
if( UI_ForceConfigUIActive() )
return false;
// Set all Light powers to level 3:
Cbuf_ExecuteText( EXEC_APPEND, "setForceHeal 3\nsetMindTrick 3\nsetForceProtect 3\nsetForceAbsorb 3\n" );
// Set all Dark powers to level 3:
Cbuf_ExecuteText( EXEC_APPEND, "setForceGrip 3\nsetForceLightning 3\nsetForceRage 3\nsetForceDrain 3\n" );
return true;
}
bool Cheat_KungFoo( void )
{
Cbuf_ExecuteText( EXEC_APPEND, "iknowkungfu\n");
return qtrue;
}
//
// CHEAT DATA
//
// Every cheat is a sequence of D-pad presses, performed while the right
// thumbstick is being pressed. The cheat sequences are all length 6, and
// each cheat is tied to a void (void) function. Mapping:
// 5 - Up, 7 - Down, 8 - Left, 6 - Right
typedef bool(*xcommandC_t)(void);
struct cheat_t
{
fakeAscii_t buttons[6];
xcommandC_t function;
};
cheat_t cheats[] = {
{ {A_JOY7, A_JOY5, A_JOY8, A_JOY6, A_JOY7, A_JOY5}, Cheat_God },
//{ {A_JOY6, A_JOY6, A_JOY8, A_JOY8, A_JOY7, A_JOY5}, Cheat_GiveAll },
{ {A_JOY7, A_JOY8, A_JOY5, A_JOY7, A_JOY6, A_JOY5}, Cheat_ChangeSaber },
{ {A_JOY5, A_JOY5, A_JOY7, A_JOY7, A_JOY8, A_JOY6}, Cheat_WinLevel },
#ifndef XBOX_DEMO
{ {A_JOY6, A_JOY8, A_JOY6, A_JOY7, A_JOY6, A_JOY5}, Cheat_LevelSelect },
#endif
{ {A_JOY5, A_JOY7, A_JOY5, A_JOY8, A_JOY5, A_JOY6}, Cheat_InfiniteForce },
{ {A_JOY8, A_JOY7, A_JOY6, A_JOY5, A_JOY7, A_JOY7}, Cheat_AllForce },
// { {A_JOY8, A_JOY7, A_JOY6, A_JOY5, A_JOY7, A_JOY8}, Cheat_KungFoo },
#if YELLOW_MODE
{ {A_JOY5, A_JOY7, A_JOY5, A_JOY8, A_JOY6, A_JOY5}, Cheat_Yellow_Stage1 },
{ {A_JOY5, A_JOY6, A_JOY8, A_JOY5, A_JOY7, A_JOY7}, Cheat_Yellow_Stage2 },
#endif // YELLOW_MODE
};
const int numCheats = sizeof(cheats) / sizeof(cheats[0]);
bool enteringCheat = false;
int cheatLength = 0;
fakeAscii_t curCheat[6];
//If the Xbox white or black button was held for less than this amount of
//time while a selection bar was up, the user wants to use the button rather
//than reassign it.
#define MAX_WB_HOLD_TIME 500
static fakeAscii_t UIJoy2Key(fakeAscii_t button)
{
switch(button) {
// D-Pad
case A_JOY7:
return A_CURSOR_DOWN;
case A_JOY5:
return A_CURSOR_UP;
case A_JOY6:
return A_CURSOR_RIGHT;
case A_JOY8:
return A_CURSOR_LEFT;
// A and B
case A_JOY15:
return A_MOUSE1;
case A_JOY14:
return A_ESCAPE;
// X and Y
case A_JOY16:
return A_DELETE;
case A_JOY13:
return A_BACKSPACE;
// L and R triggers
case A_JOY11:
return A_PAGE_UP;
case A_JOY12:
return A_PAGE_DOWN;
// Start and Back
case A_JOY4:
return A_MOUSE1;
case A_JOY1:
return A_ESCAPE;
// White and Black
case A_JOY9:
return A_HOME;
case A_JOY10:
return A_END;
// Left and Right thumbstick - do nothing in the UI
case A_JOY2:
return A_SPACE;
case A_JOY3:
return A_SPACE;
}
return A_SPACE; //Invalid button.
}
struct
{
int button;
bool pressed;
} uiKeyQueue[2][5] = {0};
int uiQueueLen[2] = {0};
int uiLastKeyUpDown[2] = {0};
int uiLastKeyLeftRight[2] = {0};
void IN_UIEmptyQueue()
{
/// If the ui is not running then this doesn't have any effect
if (!_UIRunning)
{
uiQueueLen[0] = uiQueueLen[1] = 0;
return;
}
// BTO - No CM, bypass that logic.
// for (int i = 0; i < ClientManager::NumClients(); i++)
for (int i = 0; i < 1; ++i)
{
// ClientManager::ActivateClient(i);
int found = 0;
int bCancel = 0;
for (int j = 0; j < uiQueueLen[i]; j++)
{
switch (uiKeyQueue[i][j].button)
{
case A_CURSOR_DOWN:
case A_CURSOR_UP:
if ( found & 2 ) // Was a left/right key pressed already?
bCancel = 1;
found |= 1;
break;
case A_CURSOR_RIGHT:
case A_CURSOR_LEFT:
if ( found & 1 ) // Was an up/down key already pressed?
bCancel = 1;
found |= 2;
break;
}
}
if (!bCancel) // was it cancelled?
{
for (int j = 0; j < uiQueueLen[i]; j++)
{
int time = Sys_Milliseconds();
switch (uiKeyQueue[i][j].button)
{
case A_CURSOR_DOWN:
case A_CURSOR_UP:
if (uiLastKeyLeftRight[i])
{
if (uiLastKeyLeftRight[i] > time) // don't allow up/down till left/right has enough leway time
{
continue;
}
}
uiLastKeyUpDown[i] = time + 150; /// 250 ms sound right?
break;
case A_CURSOR_LEFT:
case A_CURSOR_RIGHT:
if (uiLastKeyUpDown[i])
{
if (uiLastKeyUpDown[i] > time) // don't allow up/down till left/right has enough leway time
{
continue;
}
}
uiLastKeyLeftRight[i] = time + 150; /// 250 ms sound right?
break;
}
Sys_QueEvent(0, SE_KEY, uiKeyQueue[i][j].button, uiKeyQueue[i][j].pressed, 0, NULL);
}
}
}
// Reset the queue
uiQueueLen[0] = uiQueueLen[1] = 0;
}
// extern void G_DemoKeypress();
// extern void CG_SkipCredits(void);
char lastControllerUsed = 0;
void IN_CommonJoyPress(int controller, fakeAscii_t button, bool pressed)
{
#ifdef XBOX_DEMO
// Reset the demo timer so that we don't auto-reboot to CDX
extern void Demo_TimerKeypress( void );
Demo_TimerKeypress();
#endif
lastControllerUsed = controller;
// Cheat system hooks. The right thumbstick button has to be held for a cheat:
if (button == A_JOY3)
{
if (pressed)
{
// Just pressed the right thumstick in. Reset cheat detector
enteringCheat = true;
cheatLength = 0;
}
else
{
enteringCheat = false;
if (cheatLength == 6)
{
for( int i = 0; i < numCheats; ++i)
{
if( memcmp( &cheats[i].buttons[0], &curCheat[0], sizeof(curCheat) ) == 0 )
{
if(cheats[i].function())
S_StartLocalSound( S_RegisterSound( "sound/vehicles/x-wing/s-foil" ), CHAN_AUTO );
}
}
}
}
}
else if (enteringCheat && pressed)
{
// Handle all other buttons while entering a cheat
if (cheatLength == 6 || (button != A_JOY5 && button != A_JOY6 && button != A_JOY7 && button != A_JOY8))
{
// If we press too many buttons, or anything but the D-pad, cancel entry:
enteringCheat = false;
cheatLength = 0;
}
else
{
// We pressed a d-pad button, we're entering a cheat, and there's still room
curCheat[cheatLength++] = button;
}
}
// Check for special cases for map hack
#ifndef FINAL_BUILD
if (Cvar_VariableIntegerValue("cl_maphack"))
{
if (_UIRunning && button == A_JOY11 && pressed)
{
// Left trigger -> F1
Sys_QueEvent( 0, SE_KEY, A_F1, pressed, 0, NULL );
return;
}
else if (_UIRunning && button == A_JOY12 && pressed)
{
// Right trigger -> F2
Sys_QueEvent( 0, SE_KEY, A_F2, pressed, 0, NULL );
return;
}
else if (_UIRunning && button == A_JOY4 && pressed)
{
// Start button -> F3
//IN_SetMainController(controller);
Sys_QueEvent( 0, SE_KEY, A_F3, pressed, 0, NULL );
return;
}
}
#endif
if(inSplashMenu->integer)
{
// START always works, A only works if the popup isn't shown:
if(button == A_JOY4 || (button == A_JOY15 && controllerOut->integer < 0))
{
Sys_QueEvent( 0, SE_KEY, _UIRunning ? UIJoy2Key(button) : button, pressed, 0, NULL );
}
return;
}
int controllerout = controllerOut->integer;
if(controllerout != -1)
{
if(controllerout == controller && (button == A_JOY4))// || button == A_JOY15))
Sys_QueEvent( 0, SE_KEY, _UIRunning ? UIJoy2Key(button) : button, pressed, 0, NULL );
return;
}
if(IN_GetMainController() == controller )
{
// Always map start button to ESCAPE
if (!_UIRunning && button == A_JOY4 && cls.state != CA_CINEMATIC)
Sys_QueEvent( 0, SE_KEY, A_ESCAPE, pressed, 0, NULL );
#ifdef DEBUG_CONTROLLER
if (controller != 3)
#endif
Sys_QueEvent( 0, SE_KEY, _UIRunning ? UIJoy2Key(button) : button, pressed, 0, NULL );
}
#ifdef DEBUG_CONTROLLER
if (controller == 3 && pressed)
{
HandleDebugJoystickPress(button);
return;
}
#endif
//JLF
}
qboolean g_noCheckAxis = qfalse;
/**********
IN_CommonUpdate
Updates thumbstick events based on _padInfo and ui_thumbStickMode
**********/
void IN_CommonUpdate()
{
extern int Key_GetCatcher( void );
_UIRunning = Key_GetCatcher() == KEYCATCH_UI;
// Even in the UI, only the main controller should be able to scroll:
if( _UIRunning && _padInfo.padId == IN_GetMainController() )
{
Sys_QueEvent( 0,
SE_MOUSE,
(_padInfo.joyInfo[0].x + _padInfo.joyInfo[1].x) * 4.0f,
(_padInfo.joyInfo[0].y + _padInfo.joyInfo[1].y) * -4.0f,
0,
NULL );
}
else if(_padInfo.padId == IN_GetMainController())
{
// Find out how to configure the thumbsticks
//int thumbStickMode = Cvar_Get("ui_thumbStickMode", "0" , 0)->integer;
int thumbStickMode = cl_thumbStickMode->integer;
switch(thumbStickMode)
{
case 0:
// Configure left thumbstick to move forward/back & strafe left/right
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_SIDE, _padInfo.joyInfo[0].x * 127.0f, 0, NULL );
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_FORWARD, _padInfo.joyInfo[0].y * 127.0f, 0, NULL );
// Configure right thumbstick for freelook
Sys_QueEvent( 0, SE_MOUSE, _padInfo.joyInfo[1].x * 48.0f, _padInfo.joyInfo[1].y * 48.0f, 0, NULL );
break;
case 1:
// Configure left thumbstick for freelook
Sys_QueEvent( 0, SE_MOUSE, _padInfo.joyInfo[0].x * 48.0f, _padInfo.joyInfo[0].y * 48.0f, 0, NULL );
// Configure right thumbstick to move forward/back & strafe left/right
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_SIDE, _padInfo.joyInfo[1].x * 127.0f, 0, NULL );
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_FORWARD, _padInfo.joyInfo[1].y * 127.0f, 0, NULL );
break;
case 2:
// Configure left thumbstick to move forward/back & turn left/right
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_FORWARD, _padInfo.joyInfo[0].y * 127.0f, 0, NULL );
Sys_QueEvent( 0, SE_MOUSE, _padInfo.joyInfo[0].x * 48.0f, 0.0f, 0, NULL );
// Configure right thumbstick to look up/down & strafe left/right
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_SIDE, _padInfo.joyInfo[1].x * 127.f, 0, NULL );
Sys_QueEvent( 0, SE_MOUSE, 0.0f, _padInfo.joyInfo[1].y * 48.0f, 0, NULL );
break;
case 3:
// Configure left thumbstick to look up/down & strafe left/right
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_SIDE, _padInfo.joyInfo[0].x * 127.f, 0, NULL );
Sys_QueEvent( 0, SE_MOUSE, 0.0f, _padInfo.joyInfo[0].y * 48.0f, 0, NULL );
// Configure right thumbstick to move forward/back & turn left/right
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_FORWARD, _padInfo.joyInfo[1].y * 127.0f, 0, NULL );
Sys_QueEvent( 0, SE_MOUSE, _padInfo.joyInfo[1].x * 48.0f, 0.0f, 0, NULL );
break;
default:
break;
}
}
}
void startsetMainController(int controller)
{
IN_SetMainController(controller);
if ( !wasPlugged[controller])
{
mainControllerDelayedUnplug = 1 << controller;
}
}
/*********
IN_DisplayControllerUnplugged
*********/
static void IN_DisplayControllerUnplugged(int controller)
{
uiControllerNotification = controller;
bool noControllersConnected = !wasPlugged[0] &&
!wasPlugged[1] &&
!wasPlugged[2] &&
!wasPlugged[3];
if ( !( cls.keyCatchers & KEYCATCH_UI ) )
{
if ( cls.state == CA_ACTIVE )
{
if (controller == IN_GetMainController())
{
Cvar_SetValue("ControllerOutNum", controller);
UI_SetActiveMenu( "ingame","noController" );
}
}
}
else // UI
{
if(inSplashMenu->integer && noControllersConnected)
{
Cvar_SetValue("ControllerOutNum", 4);
UI_SetActiveMenu("ui_popup", "noController");
}
else if( controller == IN_GetMainController())
{
Cvar_SetValue("ControllerOutNum", controller);
UI_SetActiveMenu("ui_popup", "noController");
}
}
// END JLF
}
/*********
IN_ClearControllerUnplugged
*********/
static void IN_ClearControllerUnplugged(void)
{
uiControllerNotification = -1;
//TODO Add a call to the UI that removes the controller disconnected
// message from the screen.
// VM_Call( uivm, UI_CONTROLLER_UNPLUGGED, false, 0);
}
qboolean CurrentStateIsInteractive()
{
if (cls.state == CA_UNINITIALIZED ||
cls.state ==CA_CONNECTING||
cls.state ==CA_CONNECTED||
cls.state ==CA_CHALLENGING||
cls.state ==CA_PRIMED||
cls.state ==CA_CINEMATIC ||
!SG_GameAllowedToSaveHere(qtrue))
return qfalse;
return qtrue;
}
// Magic flag used to avoid popping up the "no controllers" dialog if
// none were present when we booted (but not from MP)
bool hadAController = false;
/*********
IN_ControllerMustBePlugged
*********/
static bool IN_ControllerMustBePlugged(int controller)
{
if( cls.state == CA_LOADING ||
cls.state == CA_CONNECTING ||
cls.state == CA_CONNECTED ||
cls.state == CA_CHALLENGING ||
cls.state == CA_PRIMED ||
cls.state == CA_CINEMATIC)
{
return false;
}
// If we're at the splash screen, have no controllers anymore, and there
// was a controller ever inserted into the machine:
extern bool Sys_QuickStart();
if( inSplashMenu->integer &&
!wasPlugged[0] && !wasPlugged[1] &&
!wasPlugged[2] && !wasPlugged[3] &&
hadAController )
return true;
// If we're at the splash screen, and anything else above is false
// (we have another controller, or there's never been a controller):
if( inSplashMenu->integer )
return false;
// OK. In all other cases, we need the main controller:
return (controller == IN_GetMainController());
}
/*********
IN_PadUnplugged
*********/
void IN_PadUnplugged(int controller)
{
if(wasPlugged[controller])
{
Com_Printf("\tController %d unplugged\n",controller);
}
//JLF moved
wasPlugged[controller] = false;
//IN_CheckForNoControllers();
if(IN_ControllerMustBePlugged(controller)&& SG_GameAllowedToSaveHere(qtrue))
{
//If UI isn't busy, inform it about controller loss.
if(uiControllerNotification == -1 && Cvar_VariableIntegerValue("ControllerOutNum")<0)
{
IN_DisplayControllerUnplugged(controller);
mainControllerDelayedUnplug &= ~( 1<< controller);
}
// else
// mainControllerDelayedUnplug = 1 << controller;
}
else
{
if ( controller == IN_GetMainController())
{
//store somehow for checking again later
mainControllerDelayedUnplug = 1 << controller;
}
}
// wasPlugged[controller] = false;
}
/*********
IN_PadPlugged
*********/
void IN_PadPlugged(int controller)
{
if(!wasPlugged[controller])
{
Com_Printf("\tController %d plugged\n",controller);
}
if(IN_ControllerMustBePlugged(controller)&& SG_GameAllowedToSaveHere(qtrue))
{
//If UI is dealing with this controller, tell it to stop.
if(uiControllerNotification == controller || (_UIRunning && cls.state != CA_ACTIVE ))
{
IN_ClearControllerUnplugged();
}
}
else
{
if (controller == IN_GetMainController())
{
//store somehow for checking again later
mainControllerDelayedUnplug &= ~(1 << controller);
}
}
wasPlugged[controller] = true;
noControllersConnected = false;
hadAController = true;
}
/*********
IN_GetMainController
*********/
int IN_GetMainController(void)
{
return cls.mainGamepad;
}
/*********
IN_SetMainController
*********/
void IN_SetMainController(int id)
{
cls.mainGamepad = id;
}
/**********************************************************
*
* DEBUGGING CODE
*
**********************************************************/
#ifdef DEBUG_CONTROLLER
static void HandleDebugJoystickPress(fakeAscii_t button)
{
switch(button) {
case A_JOY13: // Right pad up (yellow)
Cbuf_ExecuteText(EXEC_APPEND, "give all\n");
break;
case A_JOY16: // Right pad left (blue)
Cbuf_ExecuteText(EXEC_APPEND, "viewpos\n");
break;
case A_JOY14: // Right pad right (red)
Cbuf_ExecuteText(EXEC_APPEND, "noclip\n");
break;
case A_JOY15: // Right pad down (green)
Cbuf_ExecuteText(EXEC_APPEND, "god\n");
break;
case A_JOY4: // Start
break;
case A_JOY1: // back
break;
case A_JOY2: // Left thumbstick
extern void Z_CompactStats(void);
Z_CompactStats();
break;
case A_JOY12: // Upper right trigger
break;
case A_JOY8: // Left pad left
break;
case A_JOY6: // Left pad right
break;
case A_JOY5: // Left pad up
break;
case A_JOY7: // Left pad down
break;
case A_JOY11: // Upper left trigger
break;
case A_JOY9: // White button
break;
case A_JOY10: // Black button
break;
}
}
#endif

View File

@@ -0,0 +1,686 @@
/*
* UNPUBLISHED -- Rights reserved under the copyright laws of the
* United States. Use of a copyright notice is precautionary only and
* does not imply publication or disclosure.
*
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
*/
#include "../cgame/cg_local.h"
#include "../server/exe_headers.h"
#include "win_local.h"
#include "win_input.h"
//MB #include "../client/cl_data.h"
#include "../game/q_shared.h"
extern qboolean G_ActivePlayerNormal(void);
static int rumble_timer = 0;
cvar_t* in_shaking_rumble; // 1 - shaking rumble on, 0 - shaking rumble off
struct rumblestate_t
{
int timeToStop;
// Right motor speed on Xbox, action type on Gamecube
int arg1;
// Left motor speed on Xbox, secondary action type on Gamecube
int arg2;
};
struct rumblestate_special_t
{
int code;
int arg1;
int arg2;
};
struct rumblescript_t
{
int nextStateAt;
int controller;
int currentState;
int usedStates;
int numStates;
bool autoDelete;
rumblestate_t *states;
};
struct rumblestatus_t
{
bool changed;
bool killed;
bool paused;
int timePaused;
};
#define MAX_RUMBLE_STATES 10
#define MAX_RUMBLE_SCRIPTS 10
#define MAX_RUMBLE_CONTROLLERS 4
// In rumblestate, highest speed for each side takes precidence
// Number of rumble states is fairly small, so a plain array will work fine
static rumblestatus_t rumbleStatus[MAX_RUMBLE_CONTROLLERS];
static rumblescript_t rumbleScripts[MAX_RUMBLE_SCRIPTS];
cvar_t* in_useRumble = NULL;
bool IN_usingRumble( void )
{
return in_useRumble->integer;
}
// Creates a rumble script with numStates
// Returns -1 on no more room, otherwise an identifier to use for scripts
int IN_CreateRumbleScript(int controller, int numStates, bool deleteWhenFinished)
{
if (!IN_usingRumble()) return -1;
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return -1;
assert (numStates > 0 && numStates < MAX_RUMBLE_STATES);
int i;
for (i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
{
if (rumbleScripts[i].states == 0)
break;
}
if (i == MAX_RUMBLE_SCRIPTS)
return -1; // Ran out of scripts
rumbleScripts[i].autoDelete = deleteWhenFinished;
rumbleScripts[i].controller = controller;
rumbleScripts[i].currentState = 0;
rumbleScripts[i].nextStateAt = 0;
rumbleScripts[i].numStates = numStates;
rumbleScripts[i].usedStates = 0;
rumbleScripts[i].states = new rumblestate_t[numStates];
memset(rumbleScripts[i].states, 0, sizeof(rumblestate_t) * numStates);
return i;
}
// A negative time will last until you kill it explicitly
// Returns index, used to kill or change a state in a script
int IN_AddRumbleStateFull(int whichScript, int arg1, int arg2, int timeInMs)
{
if (!IN_usingRumble()) return -1;
assert(whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
assert(rumbleScripts[whichScript].usedStates < rumbleScripts[whichScript].numStates);
// Get the current state
rumblescript_t *curScript = &rumbleScripts[whichScript];
rumblestate_t *curState = &curScript->states[curScript->usedStates];
curState->arg1 = arg1;
curState->arg2 = arg2;
curState->timeToStop = timeInMs;
return curScript->usedStates++;
}
int IN_AddRumbleState(int whichScript, int leftSpeed, int rightSpeed, int timeInMs)
{
return IN_AddRumbleStateFull(whichScript, leftSpeed, rightSpeed, timeInMs);
}
int IN_AddRumbleStateSpecial(int whichScript, int action, int arg1, int arg2)
{
if (!IN_usingRumble()) return -1;
assert(whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
assert(rumbleScripts[whichScript].usedStates < rumbleScripts[whichScript].numStates);
// Get the current state
rumblescript_t *curScript = &rumbleScripts[whichScript];
rumblestate_special_t *curState = (rumblestate_special_t*)&curScript->states[curScript->usedStates];
curState->code = action;
curState->arg1 = arg1;
curState->arg2 = arg2;
return curScript->usedStates++;
}
int IN_AddEffectFade4(int whichScript, int startLeft, int startRight,
int endLeft, int endRight, int timeInMs)
{
const int fadeSmoothness = 50; // number of ms between updates, smaller is smoother
int e = IN_AddRumbleState(whichScript, startLeft, startRight, fadeSmoothness); // Lasts for fadeSmoothness ms
if (startLeft < endLeft) // Fade increases
{
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_LEFT, e,
(endLeft - startLeft) * fadeSmoothness / timeInMs);
}
else
{
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_LEFT, e,
(startLeft - endLeft) * fadeSmoothness / timeInMs);
}
if (startRight < endRight)
{
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_RIGHT, e,
(endRight - startRight) * fadeSmoothness / timeInMs);
}
else
{
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_RIGHT, e,
(startRight - endRight) * fadeSmoothness / timeInMs);
}
return IN_AddRumbleStateSpecial(whichScript, IN_CMD_GOTO_XTIMES,
e, timeInMs / fadeSmoothness);
}
int IN_AddEffectFadeExp6(int whichScript, int startLeft, int startRight,
int endLeft, int endRight, char factor, int timeInMs)
{
const int fadeSmoothness = 10; // number of ms between updates, smaller is smoother
int state = IN_AddRumbleState(whichScript, startLeft, startRight, fadeSmoothness); // Lasts for fadeSmoothness ms
if (startLeft < endLeft) // Fade increases
{
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_LEFT, state,
(endLeft - startLeft) * fadeSmoothness / timeInMs -
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
);
}
else
{
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_LEFT, state,
(startLeft - endLeft) * fadeSmoothness / timeInMs -
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
);
}
if (startRight < endRight)
{
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_RIGHT, state,
(endRight - startRight) * fadeSmoothness / timeInMs -
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
);
}
else
{
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_RIGHT, state,
(startRight - endRight) * fadeSmoothness / timeInMs -
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
);
}
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_ARG2, state + 1, factor);
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_ARG2, state + 2, factor);
return IN_AddRumbleStateSpecial(whichScript, IN_CMD_GOTO_XTIMES,
state, timeInMs / fadeSmoothness);
}
// Kills a rumble state based on index
void IN_KillRumbleState(int whichScript, int index)
{
if (!IN_usingRumble()) return;
assert( whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
assert( index < rumbleScripts[whichScript].numStates );
rumbleScripts[whichScript].states[index].timeToStop = 0;
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
}
// Stops the script, if script has autodelete on then it will get deleted, otherwise it will only stop
void IN_KillRumbleScript(int whichScript)
{
if (!IN_usingRumble()) return;
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
rumbleScripts[whichScript].nextStateAt = 0;
if (rumbleScripts[whichScript].autoDelete)
{
if (rumbleScripts[whichScript].states)
delete [] rumbleScripts[whichScript].states;
rumbleScripts[whichScript].states = 0;
}
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
}
// Stops Rumbling for specific controller
void IN_KillRumbleScripts(int controller)
{
if (!IN_usingRumble()) return;
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
if (rumbleStatus[controller].killed == true) return;
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
{
if (rumbleScripts[i].controller == controller)
IN_KillRumbleScript(i);
}
rumbleStatus[controller].killed = IN_RumbleAdjust(controller, 0, 0);
}
// Stops Rumbling on all controllers
void IN_KillRumbleScripts( void )
{
if (!IN_usingRumble()) return;
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
IN_KillRumbleScript(i);
for (int j = 0; j < MAX_RUMBLE_CONTROLLERS; j++)
{
if (!rumbleStatus[j].killed)
{
rumbleStatus[j].killed = IN_RumbleAdjust(j, 0, 0);
}
}
}
void IN_DeleteRumbleScript(int whichScript)
{
if (!IN_usingRumble()) return;
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
if (rumbleScripts[whichScript].states)
delete [] rumbleScripts[whichScript].states;
rumbleScripts[whichScript].nextStateAt = 0;
rumbleScripts[whichScript].states = 0;
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
}
int IN_RunSpecialScript(int whichScript)
{
rumblestate_special_t *sp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState];
switch (sp->code)
{
// updates the current state pointer
// uses arg1
case IN_CMD_GOTO:
rumbleScripts[whichScript].currentState = sp->arg1;
return rumbleScripts[whichScript].states[sp->arg1].timeToStop;
break;
// does a goto, and decreases count of arg2, until 0
case IN_CMD_GOTO_XTIMES:
if (--sp->arg2 >= 0)
{
rumbleScripts[whichScript].currentState = sp->arg1;
return rumbleScripts[whichScript].states[sp->arg1].timeToStop;
}
else // Go onto next cmd
{
if (!IN_AdvanceToNextState(whichScript))
return -2; // Done
return -1;
}
break;
// Decreasae Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to decrease arg2 of state by
case IN_CMD_DEC_ARG2:
{
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
temp->arg2 -= sp->arg2;
}
break;
// Increase Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to increase arg2 of state by
case IN_CMD_INC_ARG2:
{
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
temp->arg2 += sp->arg2;
}
break;
// Decreasae Arg1 of a State, sp->arg1 = state, sp->arg2 = amount to decrease arg1 of state by
case IN_CMD_DEC_ARG1:
{
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
temp->arg1 -= sp->arg2;
}
break;
// Increase Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to increase arg1 of state by
case IN_CMD_INC_ARG1:
{
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
temp->arg1 += sp->arg2;
}
break;
case IN_CMD_DEC_LEFT:
rumbleScripts[whichScript].states[sp->arg1].arg2 -= sp->arg2;
if (rumbleScripts[whichScript].states[sp->arg1].arg2 < 0)
rumbleScripts[whichScript].states[sp->arg1].arg2 = 0;
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
return -2; // Done
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
break;
case IN_CMD_DEC_RIGHT:
rumbleScripts[whichScript].states[sp->arg1].arg1 -= sp->arg2;
if (rumbleScripts[whichScript].states[sp->arg1].arg1 < 0)
rumbleScripts[whichScript].states[sp->arg1].arg1 = 0;
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
return -2; // Done
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
break;
case IN_CMD_INC_LEFT:
rumbleScripts[whichScript].states[sp->arg1].arg2 += sp->arg2;
if (rumbleScripts[whichScript].states[sp->arg1].arg2 > 65534)
rumbleScripts[whichScript].states[sp->arg1].arg2 = 65534;
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
return -2; // Done
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
break;
case IN_CMD_INC_RIGHT:
rumbleScripts[whichScript].states[sp->arg1].arg1 += sp->arg2;
if (rumbleScripts[whichScript].states[sp->arg1].arg1 > 65534)
rumbleScripts[whichScript].states[sp->arg1].arg1 = 65534;
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
return -2; // Done
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
break;
}
return 0;
}
int IN_Time()
{
//mb return ClientManager::ActiveClient().cg.time;
return cg.time;
}
int testTime;
void IN_ExecuteRumbleScript(int whichScript)
{
if (!IN_usingRumble()) return;
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
// Can't execute an empty script???
assert (rumbleScripts[whichScript].usedStates > 0);
rumbleScripts[whichScript].currentState = 0;
int cmd = rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState].timeToStop;
if (cmd < 0)
{
cmd = IN_RunSpecialScript(whichScript);
}
rumbleScripts[whichScript].nextStateAt = -1;//IN_Time() + cmd;
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
rumbleStatus[rumbleScripts[whichScript].controller].killed = false;
testTime = IN_Time();
}
void IN_PauseRumbling(int controller)
{
if (!IN_usingRumble()) return;
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
if (rumbleStatus[controller].paused == true) return;
rumbleStatus[controller].timePaused = IN_Time();
rumbleStatus[controller].paused = IN_RumbleAdjust(controller, 0, 0);
IN_KillRumbleScripts();
}
void IN_UnPauseRumbling(int controller)
{
if (!IN_usingRumble()) return;
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
// can't unpause a control that wasn't paused
if (rumbleStatus[controller].paused == false) return;
int cur_time = IN_Time();
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
{
if (rumbleScripts[i].controller == controller)
{
if (rumbleScripts[i].nextStateAt == 0) continue;
// update the time to stop based on how long it was paused
rumbleScripts[i].nextStateAt += (cur_time - rumbleStatus[controller].timePaused);
}
}
rumbleStatus[controller].paused = false;
rumbleStatus[controller].changed = true;
rumbleStatus[controller].killed = false;
IN_KillRumbleScripts();
}
void IN_TogglePauseRumbling(int controller)
{
if (!IN_usingRumble()) return;
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
if (rumbleStatus[controller].paused)
IN_UnPauseRumbling(controller);
else
IN_PauseRumbling(controller);
}
// Pauses rumbling on all controllers
void IN_PauseRumbling( void )
{
if (!IN_usingRumble()) return;
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
IN_PauseRumbling(i);
}
// UnPauses rumbling on all controllers
void IN_UnPauseRumbling( void )
{
if (!IN_usingRumble()) return;
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
IN_UnPauseRumbling(i);
}
// Toggles Pausing on all controllers
void IN_TogglePauseRumbling( void )
{
if (!IN_usingRumble()) return;
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
IN_TogglePauseRumbling(i);
}
// Returns false when the end of the script is reached
bool IN_AdvanceToNextState(int whichScript)
{
assert( whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS );
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
{
// Script is at its end, so kill it( which deletes only if autodelete
IN_KillRumbleScript(whichScript);
return false;
}
// Advance a state
rumbleScripts[whichScript].currentState++;
int cmd = rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState].timeToStop;
while (cmd < 0)
{
cmd = IN_RunSpecialScript(whichScript);
if (cmd == -1) return true;
if (cmd == -2) return false;
}
rumbleScripts[whichScript].nextStateAt = IN_Time() + cmd;
return true;
}
// Max rumble takes precidence
// Other possibility is some kind of sum of all the speeds
// Call this once a frame, to update the controller based on the rumble states
extern qboolean _UI_IsFullscreen( void );
void IN_UpdateRumbleFromStates()
{
if(_UI_IsFullscreen())
{
IN_KillRumbleScripts();
return;
}
int i;
int value[MAX_RUMBLE_CONTROLLERS][2];
int cur_time = IN_Time();
bool canKillScripts = false;
memset(value, 0, sizeof(int)*MAX_RUMBLE_CONTROLLERS*2);
for (i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
{
// If rumble is paused on current controller than skip this rumble state
if ( rumbleStatus[rumbleScripts[i].controller].paused) continue;
//*mb ClientManager::ActivateByControllerId(rumbleScripts[i].controller);
if ( !IN_usingRumble() )
{
IN_KillRumbleScript(i);
continue;
}
/*mb
if (!ClientManager::ActiveGentity() || !G_ActivePlayerNormal())
{
IN_KillRumbleScript(i);
continue;
}
*/
// Unset state so skip
if ( rumbleScripts[i].nextStateAt == 0) continue;
canKillScripts = true;
if ( rumbleScripts[i].nextStateAt == -1)
{
int cmd = rumbleScripts[i].states[rumbleScripts[i].currentState].timeToStop;
rumbleScripts[i].nextStateAt = cur_time + cmd;
}
// Time is up on this rumble state
if ( rumbleScripts[i].nextStateAt < cur_time)
{
// If timeToStop is < cur_time and > 0 then end this state otherwise (negative number) always rumble
if (rumbleScripts[i].nextStateAt > 0)
{
rumbleStatus[rumbleScripts[i].controller].changed = true;
rumbleStatus[rumbleScripts[i].controller].killed = false;
if (!IN_AdvanceToNextState(i)) // Returns false if reached the end of script
continue;
}
}
rumblescript_t *curScript = &rumbleScripts[i];
if (value[curScript->controller][0] < curScript->states[curScript->currentState].arg2)
value[curScript->controller][0] = curScript->states[curScript->currentState].arg2;
if (value[curScript->controller][1] < curScript->states[curScript->currentState].arg1)
value[curScript->controller][1] = curScript->states[curScript->currentState].arg1;
}
// Go through the 4 controller ports
for (i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
{
// paused, so do nothing for this controller
if ( rumbleStatus[i].paused) continue;
// Only update the actual hardware if a state has changed
if (!rumbleStatus[i].changed) continue;
IN_RumbleAdjust(i, value[i][0], value[i][1]);
// State has changed
rumbleStatus[i].changed = false;
}
if(canKillScripts)
{
if( (cur_time - rumble_timer) > 5000 )
IN_KillRumbleScripts();
}
else
{
rumble_timer = cur_time;
}
}
/*
==================
IN_RumbleInit
==================
*/
void IN_RumbleInit (void) {
memset(&rumbleStatus, 0, sizeof(rumblestatus_t)*MAX_RUMBLE_CONTROLLERS);
memset(&rumbleScripts, 0, sizeof(rumblescript_t)*MAX_RUMBLE_SCRIPTS);
in_useRumble = Cvar_Get( "in_useRumble", "1", 0 );
in_shaking_rumble = Cvar_Get("in_shaking_rumble", "1", 0);
}
/*
==================
IN_RumbleShutdown
==================
*/
void IN_RumbleShutdown (void) {
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
{
if (rumbleScripts[i].states)
delete [] rumbleScripts[i].states;
rumbleScripts[i].states = 0;
rumbleScripts[i].nextStateAt = 0;
}
}
/*
==================
IN_RumbleFrame
==================
*/
void IN_RumbleFrame (void)
{
// Check to see if we need to pause rumbling
if(cl_paused->integer && !rumbleStatus[IN_GetMainController()].paused)
{
IN_PauseRumbling(IN_GetMainController());
}
else if(!cl_paused->integer && rumbleStatus[IN_GetMainController()].paused)
{
IN_UnPauseRumbling(IN_GetMainController());
}
// Update the states
IN_UpdateRumbleFromStates();
}

View File

@@ -0,0 +1,339 @@
// win_input.c -- win32 mouse and joystick code
// 02/21/97 JCB Added extended DirectInput code to support external controllers.
// leave this as first line for PCH reasons...
//
// #include "../server/exe_headers.h"
#include <xtl.h>
#include "glw_win_dx8.h"
#include "../client/client.h"
#include "../qcommon/qcommon.h"
#ifdef _JK2MP
#include "../ui/keycodes.h"
#else
#include "../client/keycodes.h"
#endif
#include "win_local.h"
#include "win_input.h"
#define IN_MAX_CONTROLLERS 4
void IN_UIEmptyQueue();
void IN_CheckForNoControllers();
struct inputstate_t
{
struct controller_t
{
HANDLE handle;
XINPUT_STATE state;
XINPUT_FEEDBACK feedback;
};
controller_t controllers[IN_MAX_CONTROLLERS];
};
inputstate_t *in_state = NULL;
/*
=========================================================================
JOYSTICK
=========================================================================
*/
//JLF moved here for multiple access (then not used multiple times. oh well.)
extern bool noControllersConnected;
// Process all the insertions and removals, updating handles and such
void IN_ProcessChanges(DWORD dwInsert, DWORD dwRemove)
{
for(int port = 0; port < IN_MAX_CONTROLLERS; ++port)
{
// Close removals.
if((1 << port) & dwRemove)
{
if ( in_state->controllers[port].handle )
{
XInputClose( in_state->controllers[port].handle );
in_state->controllers[port].handle = 0;
}
IN_PadUnplugged(port);
}
// Open insertions.
if( (1 << port) & dwInsert )
{
in_state->controllers[port].handle = XInputOpen( XDEVICE_TYPE_GAMEPAD, port, XDEVICE_NO_SLOT, NULL );
IN_PadPlugged(port);
}
}
return;
}
/*********
IN_CheckForNoControllers()
If there are no controllers plugged in, the UI
is notified so it can display an appropriate
message.
*********/
void IN_CheckForNoControllers()
{
extern bool noControllersConnected;
if(!noControllersConnected)
{
extern bool wasPlugged[4];
if( !wasPlugged[0] &&
!wasPlugged[1] &&
!wasPlugged[2] &&
!wasPlugged[3] )
{
// Tell the UI that there are no controllers connected
// VM_Call( uivm, UI_CONTROLLER_UNPLUGGED, true, -1);
noControllersConnected = true;
}
}
}
/*
=========================================================================
RUMBLE SUPPORT
=========================================================================
*/
bool IN_RumbleAdjust(int controller, int left, int right)
{
assert(controller >= 0 && controller < IN_MAX_CONTROLLERS);
// Get a device handle for the controller. This may fail.
HANDLE handle = in_state->controllers[controller].handle;
if (!handle) return false;
XINPUT_FEEDBACK* fb = &in_state->controllers[controller].feedback;
// If a prior rumble update is still pending, go away
if (fb->Header.dwStatus == ERROR_IO_PENDING) return false;
fb->Rumble.wLeftMotorSpeed = left;
fb->Rumble.wRightMotorSpeed = right;
return ERROR_IO_PENDING == XInputSetState(handle, fb);
}
/*
=========================================================================
=========================================================================
*/
/*
igBool IN_WindowClose(igWindow *window)
{
SV_Shutdown ("Server quit\n");
CL_Shutdown ();
Com_Shutdown ();
Sys_Quit ();
return true;
}
*/
/*
===========
IN_Shutdown
===========
*/
void IN_Shutdown( void ) {
IN_RumbleShutdown();
delete in_state;
in_state = NULL;
}
/*
===========
IN_Init
===========
*/
void IN_Init( void )
{
in_state = new inputstate_t;
// Initialize support for 4 gamepads
XDEVICE_PREALLOC_TYPE xdpt[] = {
{XDEVICE_TYPE_GAMEPAD, 4}
};
// Initialize the peripherals. We can only ever
// call XInitDevices once, no matter what.
static bool bInputInitialized = false;
if (!bInputInitialized)
XInitDevices( sizeof(xdpt) / sizeof(XDEVICE_PREALLOC_TYPE), xdpt );
bInputInitialized = true;
// Zero all of our data, including handles
memset(in_state->controllers, 0, sizeof(in_state->controllers));
// Find out the status of all gamepad ports, then open them
IN_ProcessChanges( XGetDevices( XDEVICE_TYPE_GAMEPAD ), 0 );
IN_RumbleInit();
}
static inline float _joyAxisConvert(SHORT x)
{
// Change scale
float y = x / 32767.0;
// Cheesy deadzone
if(fabs(y) < 0.25f)
{
y = 0.0f;
}
return y;
}
// How many controls on the xbox gamepad?
#define IN_NUM_DIGITAL_BUTTONS 8
#define IN_NUM_ANALOG_BUTTONS 8
// Cutoff where the analog buttons are considered to be "pressed"
// This should be smarter.
#define IN_ANALOG_BUTTON_THRESHOLD 64
void IN_UpdateGamepad(int port)
{
// Lookup table to convert the digital buttons to fakeAscii_t, in mask order
const fakeAscii_t digitalXlat[IN_NUM_DIGITAL_BUTTONS] = {
A_JOY5, // DPAD_UP
A_JOY7, // DPAD_DOWN
A_JOY8, // DPAD_LEFT
A_JOY6, // DPAD_RIGHT
A_JOY4, // Start
A_JOY1, // Back
A_JOY2, // Left stick
A_JOY3 // Right stick
};
// Lookup table to convet the analog buttons to fakeAscii_t, in DX order
const fakeAscii_t analogXlat[IN_NUM_ANALOG_BUTTONS] = {
A_JOY15, // A
A_JOY14, // B
A_JOY16, // X
A_JOY13, // Y
A_JOY10, // Black
A_JOY9, // White
A_JOY11, // Left trigger
A_JOY12 // Right trigger
};
// Get new state
XINPUT_STATE newState;
XInputGetState( in_state->controllers[port].handle, &newState );
// Get old state
XINPUT_STATE &oldState(in_state->controllers[port].state);
int buttonIdx;
bool oldPressed, newPressed;
// Check all digital buttons first
for (buttonIdx = 0; buttonIdx < IN_NUM_DIGITAL_BUTTONS; ++buttonIdx)
{
oldPressed = oldState.Gamepad.wButtons & (1 << buttonIdx);
newPressed = newState.Gamepad.wButtons & (1 << buttonIdx);
if (oldPressed != newPressed)
IN_CommonJoyPress(port, digitalXlat[buttonIdx], newPressed);
}
// Now check all analog buttons
for (buttonIdx = 0; buttonIdx < IN_NUM_ANALOG_BUTTONS; ++buttonIdx)
{
oldPressed = oldState.Gamepad.bAnalogButtons[buttonIdx] > IN_ANALOG_BUTTON_THRESHOLD;
newPressed = newState.Gamepad.bAnalogButtons[buttonIdx] > IN_ANALOG_BUTTON_THRESHOLD;
if (oldPressed != newPressed)
IN_CommonJoyPress(port, analogXlat[buttonIdx], newPressed);
}
// Update joysticks
_padInfo.joyInfo[0].x = _joyAxisConvert(newState.Gamepad.sThumbLX);
_padInfo.joyInfo[0].y = _joyAxisConvert(newState.Gamepad.sThumbLY);
_padInfo.joyInfo[1].x = _joyAxisConvert(newState.Gamepad.sThumbRX);
_padInfo.joyInfo[1].y = _joyAxisConvert(newState.Gamepad.sThumbRY);
_padInfo.joyInfo[0].valid = _padInfo.joyInfo[1].valid = true;
_padInfo.padId = port;
// Copy state back
oldState = newState;
// Update game
IN_CommonUpdate();
}
extern qboolean CurrentStateIsInteractive();
extern int mainControllerDelayedUnplug;
extern void startsetMainController(int controller);
extern int gLaunchController;
/*
==================
IN_Frame
Called every frame, even if not generating commands
==================
*/
//extern int ignoreInputTime;
extern vmCvar_t ControllerOutNum;
void IN_Frame (void)
{
static qboolean first = qtrue;
if (in_state)
{
// First, check for changes in device status (removed/inserted pads)
DWORD dwInsert, dwRemove;
if( XGetDeviceChanges( XDEVICE_TYPE_GAMEPAD, &dwInsert, &dwRemove ) )
{
IN_ProcessChanges(dwInsert, dwRemove);
}
if ( first )
{
// We only force the controller to be locked when we came from MP:
extern bool Sys_QuickStart( void );
if( Sys_QuickStart() )
{
Com_Printf("\tController %d initialized\n", gLaunchController);
startsetMainController(gLaunchController);
// We're bypassing splash menu!
Cvar_SetValue( "inSplashMenu", 0 );
}
// Only do this check once, no matter what:
first = qfalse;
}
if ( mainControllerDelayedUnplug && CurrentStateIsInteractive() && ControllerOutNum.integer < 0)
IN_ProcessChanges(0, mainControllerDelayedUnplug);
// Generate callbacks for each controller that's plugged in
for (int port = 0; port < IN_MAX_CONTROLLERS; ++port)
if (in_state->controllers[port].handle)
IN_UpdateGamepad(port);
IN_UIEmptyQueue();
IN_RumbleFrame();
}
}

View File

@@ -0,0 +1,977 @@
//
//
// win_lighteffects.cpp
//
// Various lighting effects w/ pixel shaders
//
//
#ifdef VV_LIGHTING
#include "../server/exe_headers.h"
#include "../renderer/tr_local.h"
#include "glw_win_dx8.h"
#include "win_local.h"
#include "../renderer/tr_lightmanager.h"
#include "win_lighteffects.h"
#include <xgraphics.h>
#include <xgmath.h>
#include "shader_constants.h"
LightEffects::LightEffects()
{
m_pCubeMap = NULL;
m_pBumpMap = NULL;
m_pSpecularMap = NULL;
m_pFalloffMap = NULL;
m_dwVertexShaderLight = 0L;
m_dwPixelShaderLight = 0L;
m_dwVertexShaderSpecular_Dynamic = 0L;
m_dwPixelShaderSpecular_Dynamic = 0L;
m_dwVertexShaderSpecular_Static = 0L;
m_dwPixelShaderSpecular_Static = 0L;
m_dwVertexShaderEnvironment = 0L;
m_dwVertexShaderBump = 0L;
m_dwPixelShaderBump = 0L;
m_bInLightPhase = false;
m_bInitialized = false;
Initialize();
}
LightEffects::~LightEffects()
{
if( m_pCubeMap )
m_pCubeMap->Release();
m_pCubeMap = NULL;
if(m_pBumpMap)
m_pBumpMap->Release();
m_pBumpMap = NULL;
if(m_pFalloffMap)
m_pFalloffMap->Release();
m_pFalloffMap = NULL;
if(m_pSpecularMap)
m_pSpecularMap->Release();
m_pSpecularMap = NULL;
if( glw_state->device )
{
glw_state->device->DeleteVertexShader( m_dwVertexShaderLight );
glw_state->device->DeletePixelShader( m_dwPixelShaderLight );
glw_state->device->DeleteVertexShader( m_dwVertexShaderSpecular_Dynamic );
glw_state->device->DeletePixelShader( m_dwPixelShaderSpecular_Dynamic );
glw_state->device->DeleteVertexShader( m_dwVertexShaderSpecular_Static );
glw_state->device->DeletePixelShader( m_dwPixelShaderSpecular_Static );
glw_state->device->DeleteVertexShader( m_dwVertexShaderEnvironment );
glw_state->device->DeletePixelShader( m_dwPixelShaderBump );
glw_state->device->DeleteVertexShader( m_dwVertexShaderBump );
}
}
void LightEffects::StartLightPhase()
{
m_bInLightPhase = true;
}
void LightEffects::EndLightPhase()
{
m_bInLightPhase = false;
}
extern const char *Sys_RemapPath( const char *filename );
bool LightEffects::Initialize()
{
HRESULT hr;
// Create a vertex shader
DWORD dwVertexDecl[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
D3DVSD_REG( 2, D3DVSDT_FLOAT2 ), // v2 = Base tex coords
D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // v3 = Tangent space tangent
D3DVSD_END()
};
if(!( CreateVertexShader(Sys_RemapPath("base\\media\\dlight.xvu"), dwVertexDecl, &m_dwVertexShaderLight)))
return false;
if(!( CreateVertexShader(Sys_RemapPath("base\\media\\specular_dynamic.xvu"), dwVertexDecl, &m_dwVertexShaderSpecular_Dynamic)))
return false;
if(!( CreateVertexShader(Sys_RemapPath("base\\media\\specular_static.xvu"), dwVertexDecl, &m_dwVertexShaderSpecular_Static)))
return false;
DWORD dwVertexDeclBump[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
D3DVSD_REG( 2, D3DVSDT_FLOAT2 ), // v2 = Base tex coords 0
D3DVSD_REG( 3, D3DVSDT_FLOAT2 ), // v2 = Base tex coords 1
D3DVSD_REG( 4, D3DVSDT_FLOAT3 ), // v4 = Tangent space tangent
D3DVSD_END()
};
if(!( CreateVertexShader(Sys_RemapPath("base\\media\\bump.xvu"), dwVertexDeclBump, &m_dwVertexShaderBump)))
return false;
DWORD dwVertexDeclEnv[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // v2 = Color
D3DVSD_END()
};
if(!( CreateVertexShader(Sys_RemapPath("base\\media\\environment.xvu"), dwVertexDeclEnv, &m_dwVertexShaderEnvironment)))
return false;
// Create the pixel shader
if(!(CreatePixelShader(Sys_RemapPath("base\\media\\dlight.xpu"), &m_dwPixelShaderLight)))
return false;
if(!(CreatePixelShader(Sys_RemapPath("base\\media\\specular_dynamic.xpu"), &m_dwPixelShaderSpecular_Dynamic)))
return false;
if(!(CreatePixelShader(Sys_RemapPath("base\\media\\specular_static.xpu"), &m_dwPixelShaderSpecular_Static)))
return false;
if(!(CreatePixelShader(Sys_RemapPath("base\\media\\bump.xpu"), &m_dwPixelShaderBump)))
return false;
hr = D3DXCreateTextureFromFileEx(glw_state->device,
Sys_RemapPath("base\\media\\defaultbump.dds"),
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
0,
D3DFMT_A8R8G8B8,
0,
D3DX_FILTER_LINEAR,
D3DX_FILTER_LINEAR,
0,
NULL,
NULL,
&m_pBumpMap);
if (FAILED(hr))
{
return false;
}
hr = D3DXCreateTextureFromFileEx(glw_state->device,
Sys_RemapPath("base\\media\\diffspec.dds"),
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
0,
D3DFMT_A8R8G8B8,
0,
D3DX_FILTER_LINEAR,
D3DX_FILTER_LINEAR,
0,
NULL,
NULL,
&m_pSpecularMap);
if (FAILED(hr))
{
return false;
}
// Create the volume falloff texture
UINT width = 32,
height = 32,
depth = 32,
levels = 1;
D3DFORMAT format = D3DFMT_A8;
if (FAILED (hr = glw_state->device->CreateVolumeTexture(width, height, depth,
1, 0, format, D3DPOOL_DEFAULT, &m_pFalloffMap) ) )
{
return false;
}
// Fill the volume texture
D3DVOLUME_DESC desc;
D3DLOCKED_BOX lock;
m_pFalloffMap->GetLevelDesc( 0, &desc );
m_pFalloffMap->LockBox( 0, &lock, 0, 0L );
BYTE* pBits = (BYTE*)lock.pBits;
for( UINT w=0; w<width; w++ )
{
for( UINT v=0; v<height; v++ )
{
for( UINT u=0; u<depth; u++ )
{
FLOAT x = (2.0f*u)/(width-1) - 1.0f; // Ranges from -1 to +1
FLOAT y = (2.0f*v)/(height-1) - 1.0f; // Ranges from -1 to +1
FLOAT z = (2.0f*w)/(depth-1) - 1.0f;
FLOAT distance = (float)(x*x + y*y + z*z);
if (distance == 0)
{
*pBits++ = (BYTE)255;
}
else
{
FLOAT falloff = min(1.0f, max(0.0f, ((1.0f/2.0f)/distance - 1.0f/2.0f)/1.0f ) );
*pBits++ = (BYTE)(255*falloff);
}
}
}
}
DWORD dwPixelSize = XGBytesPerPixelFromFormat( desc.Format );
DWORD dwTextureSize = desc.Width * desc.Height * desc.Depth * dwPixelSize;
BYTE* pSrcBits = new BYTE[ dwTextureSize ];
memcpy( pSrcBits, lock.pBits, dwTextureSize );
XGSwizzleBox( pSrcBits, 0, 0, NULL, lock.pBits,
desc.Width, desc.Height, desc.Depth,
NULL, dwPixelSize );
delete [] pSrcBits;
m_pFalloffMap->UnlockBox( 0 );
// Create the normalization cube map
if(!CreateNormalizationCubeMap( 64, &m_pCubeMap ))
return false;
m_bInitialized = true;
return true;
}
bool LightEffects::RenderDynamicLights()
{
VVdlight_t *dl;
shaderStage_t *dStage;
vec3_t origin;
byte clipBits[SHADER_MAX_VERTEXES];
glIndex_t hitIndexes[SHADER_MAX_INDEXES];
int numIndexes;
float radius;
int fogging;
vec3_t dist;
vec3_t e1;
vec3_t e2;
vec3_t normal;
float fac;
if(!VVLightMan.num_dlights)
return true;
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
glw_state->device->SetTextureStageState( 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
glw_state->device->SetTextureStageState( 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
glw_state->device->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 3, D3DTSS_MIPFILTER, D3DTEXF_POINT );
glw_state->device->SetTextureStageState( 2, D3DTSS_ALPHAKILL, D3DTALPHAKILL_ENABLE);
// GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
if(tess.shader->isBumpMap)
{
for ( int stage = 0; stage < tess.shader->numUnfoggedPasses; stage++ )
{
shaderStage_t *pStage = &tess.xstages[stage];
if(pStage->isBumpMap)
{
glwstate_t::texturexlat_t::iterator i = glw_state->textureXlat.find(pStage->bundle[1].image->texnum);
glw_state->device->SetTexture( 1, i->second.mipmap );
}
}
}
else
glw_state->device->SetTexture(1, m_pBumpMap);
glw_state->device->SetTexture(2, m_pFalloffMap);
glw_state->device->SetTexture(3, m_pCubeMap);
glw_state->device->SetPixelShader(m_dwPixelShaderLight);
glw_state->device->SetVertexShader(m_dwVertexShaderLight);
for(int l = 0; l < VVLightMan.num_dlights; l++)
{
if(!(tess.dlightBits & (1 << l)))
continue;
dl = &VVLightMan.dlights[l];
if(!dl)
continue;
// Not going to bother testing all the polygons in a ghoul2 model
// they almost always all end up in range anyway
if(!backEnd.currentEntity->e.ghoul2)
{
VectorCopy( dl->transformed, origin );
radius = dl->radius;
int clipall = 63;
for (int i = 0 ; i < tess.numVertexes ; i++)
{
int clip;
VectorSubtract( origin, tess.xyz[i], dist );
clip = 0;
if ( dist[0] < -radius )
{
clip |= 1;
}
else if ( dist[0] > radius )
{
clip |= 2;
}
if ( dist[1] < -radius )
{
clip |= 4;
}
else if ( dist[1] > radius )
{
clip |= 8;
}
if ( dist[2] < -radius )
{
clip |= 16;
}
else if ( dist[2] > radius )
{
clip |= 32;
}
clipBits[i] = clip;
clipall &= clip;
}
if ( clipall )
{
continue; // this surface doesn't have any of this light
}
// build a list of triangles that need light
numIndexes = 0;
for ( i = 0 ; i < tess.numIndexes ; i += 3 )
{
int a, b, c;
a = tess.indexes[i];
b = tess.indexes[i+1];
c = tess.indexes[i+2];
if ( clipBits[a] & clipBits[b] & clipBits[c] )
{
continue; // not lighted
}
VectorSubtract( tess.xyz[a], tess.xyz[b], e1);
VectorSubtract( tess.xyz[c], tess.xyz[b], e2);
CrossProduct(e1,e2,normal);
VectorNormalize(normal);
fac=DotProduct(normal,origin)-DotProduct(normal, tess.xyz[a]);
if (fac >= radius) // out of range
{
continue;
}
// save the indexes
hitIndexes[numIndexes] = tess.indexes[i];
hitIndexes[numIndexes + 1] = tess.indexes[i + 1];
hitIndexes[numIndexes + 2] = tess.indexes[i + 2];
numIndexes += 3;
if (numIndexes>=SHADER_MAX_VERTEXES-3)
{
break; // we are out of space, so we are done :)
}
}
if ( !numIndexes ) {
continue;
}
}
//don't have fog enabled when we redraw with alpha test, or it will double over
//and screw the tri up -rww
if (r_drawfog->value == 2 &&
tr.world &&
(tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs))
{
fogging = qglIsEnabled(GL_FOG);
if (fogging)
{
qglDisable(GL_FOG);
}
}
else
{
fogging = 0;
}
dStage = NULL;
if (tess.shader && qglActiveTextureARB)
{
int i = 0;
while (i < tess.shader->numUnfoggedPasses)
{
const int blendBits = (GLS_SRCBLEND_BITS+GLS_DSTBLEND_BITS);
if (((tess.shader->stages[i].bundle[0].image && !tess.shader->stages[i].bundle[0].isLightmap && !tess.shader->stages[i].bundle[0].numTexMods && tess.shader->stages[i].bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[i].bundle[0].tcGen != TCGEN_FOG) ||
(tess.shader->stages[i].bundle[1].image && !tess.shader->stages[i].bundle[1].isLightmap && !tess.shader->stages[i].bundle[1].numTexMods && tess.shader->stages[i].bundle[1].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[i].bundle[1].tcGen != TCGEN_FOG)) &&
(tess.shader->stages[i].stateBits & blendBits) == 0 )
{ //only use non-lightmap opaque stages
dStage = &tess.shader->stages[i];
break;
}
i++;
}
}
if (dStage)
{
GL_SelectTexture( 0 );
GL_State(0);
// animMaps don't actually have a texture in image, it's an array of image pointers:
if (dStage->bundle[0].numImageAnimations > 1)
{
int index;
if (backEnd.currentEntity->e.renderfx & RF_SETANIMINDEX )
{
index = backEnd.currentEntity->e.skinNum;
}
else
{
// it is necessary to do this messy calc to make sure animations line up
// exactly with waveforms of the same frequency
index = myftol( backEnd.refdef.floatTime * dStage->bundle[0].imageAnimationSpeed * FUNCTABLE_SIZE );
index >>= FUNCTABLE_SIZE2;
if ( index < 0 ) {
index = 0; // may happen with shader time offsets
}
}
if ( dStage->bundle[0].oneShotAnimMap )
{
if ( index >= dStage->bundle[0].numImageAnimations )
{
// stick on last frame
index = dStage->bundle[0].numImageAnimations - 1;
}
}
else
{
// loop
index %= dStage->bundle[0].numImageAnimations;
}
GL_Bind( *((image_t**)dStage->bundle[0].image + index) );
}
else if (dStage->bundle[0].image && !dStage->bundle[0].isLightmap && !dStage->bundle[0].numTexMods && dStage->bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && dStage->bundle[0].tcGen != TCGEN_FOG)
{
GL_Bind( dStage->bundle[0].image );
}
else
{
GL_Bind( dStage->bundle[1].image );
}
GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);// | GLS_DEPTHFUNC_EQUAL);
}
else
{
GL_Bind( tr.whiteImage );
GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE);// | GLS_DEPTHFUNC_EQUAL );
}
glwstate_t::texturexlat_t::iterator inf = glw_state->textureXlat.find(glw_state->currentTexture[0]);
glw_state->device->SetTexture(0, inf->second.mipmap);
D3DXVECTOR4 vecLightRange(1.0f / dl->radius, 0.0f, 0.0f, 0.0f);
glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
glw_state->device->SetPixelShaderConstant(CP_DIFFUSE_COLOR, &dl->color[0], 1);
ProcessVertices( (D3DXVECTOR3*)&dl->direction, (D3DXVECTOR3*)&dl->transformed );
if(backEnd.currentEntity->e.ghoul2)
renderObject_Light( tess.numIndexes, tess.indexes );
else
renderObject_Light( numIndexes, hitIndexes );
if (fogging)
{
qglEnable(GL_FOG);
}
}
glw_state->device->SetPixelShader( 0 );
// This is kinda a hack to get the quake renderer to discard
// these textures after they are used here, instead of applying
// them to more geometry
glState.currenttextures[0] = -2;
glState.currenttextures[1] = -2;
glw_state->currentTexture[0] = -2;
glw_state->currentTexture[1] = -2;
glw_state->device->SetTextureStageState( 2, D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE);
glw_state->device->SetTexture(2, NULL);
glw_state->device->SetTexture(3, NULL);
return true;
}
void LightEffects::RenderSpecular()
{
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
glwstate_t::texturexlat_t::iterator i = glw_state->textureXlat.find(glw_state->currentTexture[0]);
glw_state->device->SetTexture( 0, i->second.mipmap );
glw_state->device->SetTexture( 2, m_pSpecularMap );
glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(tr.viewParms.or.axis[0][0],
tr.viewParms.or.axis[0][1],
tr.viewParms.or.axis[0][2],
1.0f), 1 );
RenderSpecular_Static();
if(tess.dlightBits)
RenderSpecular_Dynamic();
glw_state->device->SetPixelShader(0);
// This is kinda a hack to get the quake renderer to discard
// these textures after they are used here, instead of applying
// them to more geometry
glState.currenttextures[0] = -2;
glState.currenttextures[1] = -2;
glw_state->currentTexture[0] = -2;
glw_state->currentTexture[1] = -2;
}
bool LightEffects::RenderSpecular_Dynamic()
{
VVdlight_t *dl;
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
glw_state->device->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_POINT );
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTexture( 3, m_pFalloffMap );
glw_state->device->SetPixelShader(m_dwPixelShaderSpecular_Dynamic);
glw_state->device->SetVertexShader(m_dwVertexShaderSpecular_Dynamic);
for(int i = 0; i < VVLightMan.num_dlights; i++)
{
if(!(tess.dlightBits & (1 << i)))
continue;
dl = &VVLightMan.dlights[i];
D3DXVECTOR4 vecLightRange(1.0f / dl->radius, 0.0f, 0.0f, 0.0f);
glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
ProcessVertices( (D3DXVECTOR3*)&dl->direction, (D3DXVECTOR3*)&dl->transformed );
renderObject_Light( tess.numIndexes, tess.indexes);
}
glw_state->device->SetTexture( 3, NULL );
return true;
}
bool LightEffects::RenderSpecular_Static()
{
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
glw_state->device->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_NONE );
glw_state->device->SetPixelShader(m_dwPixelShaderSpecular_Static);
glw_state->device->SetVertexShader(m_dwVertexShaderSpecular_Static);
ProcessVertices( NULL, NULL );
D3DXVECTOR4 vLight;
if (backEnd.currentEntity && (backEnd.currentEntity->e.hModel||backEnd.currentEntity->e.ghoul2) )
{
vLight.x = backEnd.currentEntity->lightDir[0];
vLight.y = backEnd.currentEntity->lightDir[1];
vLight.z = backEnd.currentEntity->lightDir[2];
}
else
{
// These values were taken from the RB_CalcSpecularAlpha default case
vLight.x = -960.0f;
vLight.y = 1920.0f;
vLight.z = 96.0f;
}
vLight.w = 1.0f;
glw_state->device->SetVertexShaderConstant(CV_LIGHT_DIRECTION, vLight, 1);
renderObject_Light( tess.numIndexes, tess.indexes );
return true;
}
bool LightEffects::RenderEnvironment()
{
glw_state->device->SetRenderState( D3DRS_LIGHTING, false );
glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(backEnd.ori.viewOrigin[0],
backEnd.ori.viewOrigin[1],
backEnd.ori.viewOrigin[2],
1.0f), 1 );
ProcessVertices(NULL, NULL);
XGMATRIX *view, viewtran;
view = (XGMATRIX*)glw_state->matrixStack[glw_state->MatrixMode_Model]->GetTop();
XGMatrixTranspose( &viewtran, view );
glw_state->device->SetVertexShaderConstant(CV_VIEW_0, viewtran, 4);
glw_state->device->SetVertexShader(m_dwVertexShaderEnvironment);
renderObject_Env();
return true;
}
// Renders bump maps without the benefit of dynamic lights
void LightEffects::RenderBump()
{
glw_state->device->SetRenderState( D3DRS_LIGHTING, false );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, false );
glwstate_t::texturexlat_t::iterator i = glw_state->textureXlat.find(glw_state->currentTexture[0]);
glw_state->device->SetTexture( 0, i->second.mipmap );
i = glw_state->textureXlat.find(glw_state->currentTexture[1]);
glw_state->device->SetTexture( 1, i->second.mipmap );
glw_state->device->SetTextureStageState(0, D3DTSS_MAXANISOTROPY, i->second.anisotropy);
glw_state->device->SetTextureStageState(0, D3DTSS_MINFILTER, i->second.minFilter);
glw_state->device->SetTextureStageState(0, D3DTSS_MIPFILTER, i->second.mipFilter);
glw_state->device->SetTextureStageState(0, D3DTSS_MAGFILTER, i->second.magFilter);
glw_state->device->SetTextureStageState(0, D3DTSS_ADDRESSU, i->second.wrapU);
glw_state->device->SetTextureStageState(0, D3DTSS_ADDRESSV, i->second.wrapV);
glw_state->device->SetTextureStageState(1, D3DTSS_MAXANISOTROPY, i->second.anisotropy);
glw_state->device->SetTextureStageState(1, D3DTSS_MINFILTER, i->second.minFilter);
glw_state->device->SetTextureStageState(1, D3DTSS_MIPFILTER, i->second.mipFilter);
glw_state->device->SetTextureStageState(1, D3DTSS_MAGFILTER, i->second.magFilter);
glw_state->device->SetTextureStageState(1, D3DTSS_ADDRESSU, i->second.wrapU);
glw_state->device->SetTextureStageState(1, D3DTSS_ADDRESSV, i->second.wrapV);
glw_state->device->SetRenderState(D3DRS_SPECULARENABLE, true);
glw_state->device->SetPixelShader(m_dwPixelShaderBump);
glw_state->device->SetVertexShader(m_dwVertexShaderBump);
ProcessVertices( NULL, NULL );
D3DXVECTOR4 vAmbient, vDiffuse, vLightDir;
if (backEnd.currentEntity && (backEnd.currentEntity->e.hModel||backEnd.currentEntity->e.ghoul2) )
{
if(tess.shader->stages[tess.currentPass].rgbGen == CGEN_LIGHTING_DIFFUSE_ENTITY)
{
vAmbient.x = (backEnd.currentEntity->ambientLight[0] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[0] / 255.0);
vAmbient.y = (backEnd.currentEntity->ambientLight[1] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[1] / 255.0);
vAmbient.z = (backEnd.currentEntity->ambientLight[2] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[2] / 255.0);
}
else
{
vAmbient.x = backEnd.currentEntity->ambientLight[0] / 255.f;
vAmbient.y = backEnd.currentEntity->ambientLight[1] / 255.f;
vAmbient.z = backEnd.currentEntity->ambientLight[2] / 255.f;
}
vDiffuse.x = backEnd.currentEntity->directedLight[0] / 255.f;
vDiffuse.y = backEnd.currentEntity->directedLight[1] / 255.f;
vDiffuse.z = backEnd.currentEntity->directedLight[2] / 255.f;
vLightDir.x = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[0] );
vLightDir.y = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[1] );
vLightDir.z = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[2] );
}
else
{
vec3_t sundir;
sundir[0] = r_sundir_x->value;
sundir[1] = r_sundir_y->value;
sundir[2] = r_sundir_z->value;
VectorNormalize(sundir);
vLightDir.x = sundir[0];//tr.sunDirection[0];
vLightDir.y = sundir[1];//tr.sunDirection[1];
vLightDir.z = sundir[2];//tr.sunDirection[2];
vLightDir.w = 1.0f;
vAmbient.x = tr.sunAmbient[0] / 1.5f;
vAmbient.y = tr.sunAmbient[1] / 1.5f;
vAmbient.z = tr.sunAmbient[2] / 1.5f;
vDiffuse.x = 1.0f;
vDiffuse.y = 1.0f;
vDiffuse.z = 1.0f;
}
glw_state->device->SetPixelShaderConstant(CP_AMBIENT_COLOR, vAmbient, 1);
glw_state->device->SetPixelShaderConstant(CP_DIFFUSE_COLOR, vDiffuse, 1);
glw_state->device->SetVertexShaderConstant(CV_LIGHT_DIRECTION, vLightDir, 1);
glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(tr.viewParms.or.axis[0][0],
tr.viewParms.or.axis[0][1],
tr.viewParms.or.axis[0][2],
1.0f), 1 );
renderObject_Bump();
glw_state->device->SetPixelShader( 0 );
glw_state->device->SetRenderState(D3DRS_SPECULARENABLE, false);
}
//bool LightEffects::RenderStaticLights()
//{
// VVslight_t *sl;
//
// for(int i = 0; i < tess.numSlights; i++)
// {
// sl = &VVLightMan.slights[tess.slightBits[i]];
//
// D3DXVECTOR4 vecLightRange(1.0f / (sl->radius * 2.0f), sl->radius, 1.0f, 1.0f);
// glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
//
// glw_state->device->SetVertexShaderConstant(CV_LIGHT_COLOR, &sl->color[0], 1);
//
// ProcessVertices( NULL, (D3DXVECTOR3*)&sl->origin );
//
// renderObject_Light();
//
// tess.currentPass++;
// }
//
// return true;
//}
void LightEffects::ProcessVertices( D3DXVECTOR3* pDirLightDir, D3DXVECTOR3* pPtLightPos )
{
// Just in case, this doesn't always get set
glw_state->device->SetTransform( D3DTS_PROJECTION, glw_state->matrixStack[glw_state->MatrixMode_Projection]->GetTop() );
// Compute the matrix set
XGMATRIX matComposite, matProjectionViewport, matWorld;
// Get the projection viewport matrix the fixed pipeline uses.
// The viewport matrix includes the viewport x,y scale and the
// appropriate z scale.
glw_state->device->GetProjectionViewportMatrix( &matProjectionViewport );
D3DVIEWPORT8 view;
glw_state->device->GetViewport(&view);
// Gotta do this to fix an XDK bug
// GetProjectionViewportMatrix does not seem to reflect the viewport values
// when the viewport is offset
matProjectionViewport._31 += view.X;
matProjectionViewport._32 += view.Y;
XGMatrixMultiply( &matComposite, (XGMATRIX*)glw_state->matrixStack[glwstate_t::MatrixMode_Model]->GetTop(), &matProjectionViewport );
// Transpose and set the composite matrix.
XGMatrixTranspose( &matComposite, &matComposite );
glw_state->device->SetVertexShaderConstant( CV_WORLDVIEWPROJ_0, &matComposite, 4 );
if (pPtLightPos)
glw_state->device->SetVertexShaderConstant( CV_LIGHT_POSITION, pPtLightPos, 1 );
// Set viewport offsets.
float fViewportOffsets[4] = { 0.53125f, 0.53125f, 0.0f, 0.0f };
glw_state->device->SetVertexShaderConstant( CV_VIEWPORT_OFFSETS, &fViewportOffsets, 1 );
// Set common constants
glw_state->device->SetVertexShaderConstant(CV_ONE, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f), 1);
glw_state->device->SetVertexShaderConstant(CV_HALF, D3DXVECTOR4(0.5f, 0.5f, 0.5f, 0.5f), 1);
}
inline D3DCOLOR VectorToRGBA( const D3DXVECTOR3* v, FLOAT fHeight = 1.0f )
{
D3DCOLOR r = (D3DCOLOR)( ( v->x + 1.0f ) * 127.5f );
D3DCOLOR g = (D3DCOLOR)( ( v->y + 1.0f ) * 127.5f );
D3DCOLOR b = (D3DCOLOR)( ( v->z + 1.0f ) * 127.5f );
D3DCOLOR a = (D3DCOLOR)( 255.0f * fHeight );
return( (a<<24L) + (r<<16L) + (g<<8L) + (b<<0L) );
}
bool LightEffects::CreateNormalizationCubeMap( DWORD dwSize, LPDIRECT3DCUBETEXTURE8* ppCubeMap )
{
HRESULT hr;
// Create the cube map
if( FAILED( hr = glw_state->device->CreateCubeTexture( dwSize, 1, 0, D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT, ppCubeMap ) ) )
return false;
// Allocate temp space for swizzling the cubemap surfaces
DWORD* pSourceBits = new DWORD[ dwSize * dwSize ];
// Fill all six sides of the cubemap
for( DWORD i=0; i<6; i++ )
{
// Lock the i'th cubemap surface
LPDIRECT3DSURFACE8 pCubeMapFace;
(*ppCubeMap)->GetCubeMapSurface( (D3DCUBEMAP_FACES)i, 0, &pCubeMapFace );
// Write the RGBA-encoded normals to the surface pixels
DWORD* pPixel = pSourceBits;
D3DXVECTOR3 n;
FLOAT w, h;
for( DWORD y = 0; y < dwSize; y++ )
{
h = (FLOAT)y / (FLOAT)(dwSize-1); // 0 to 1
h = ( h * 2.0f ) - 1.0f; // -1 to 1
for( DWORD x = 0; x < dwSize; x++ )
{
w = (FLOAT)x / (FLOAT)(dwSize-1); // 0 to 1
w = ( w * 2.0f ) - 1.0f; // -1 to 1
// Calc the normal for this texel
switch( i )
{
case D3DCUBEMAP_FACE_POSITIVE_X: // +x
n.x = +1.0;
n.y = -h;
n.z = -w;
break;
case D3DCUBEMAP_FACE_NEGATIVE_X: // -x
n.x = -1.0;
n.y = -h;
n.z = +w;
break;
case D3DCUBEMAP_FACE_POSITIVE_Y: // y
n.x = +w;
n.y = +1.0;
n.z = +h;
break;
case D3DCUBEMAP_FACE_NEGATIVE_Y: // -y
n.x = +w;
n.y = -1.0;
n.z = -h;
break;
case D3DCUBEMAP_FACE_POSITIVE_Z: // +z
n.x = +w;
n.y = -h;
n.z = +1.0;
break;
case D3DCUBEMAP_FACE_NEGATIVE_Z: // -z
n.x = -w;
n.y = -h;
n.z = -1.0;
break;
}
// Store the normal as an RGBA color
D3DXVec3Normalize( &n, &n );
*pPixel++ = VectorToRGBA( &n );
}
}
// Swizzle the result into the cubemap face surface
D3DLOCKED_RECT lock;
pCubeMapFace->LockRect( &lock, 0, 0L );
XGSwizzleRect( pSourceBits, 0, NULL, lock.pBits, dwSize, dwSize,
NULL, sizeof(DWORD) );
pCubeMapFace->UnlockRect();
// Release the cubemap face
pCubeMapFace->Release();
}
// Free temp space
if( pSourceBits )
delete [] pSourceBits;
pSourceBits = NULL;
return true;
}
#endif // VV_LIGHTING

View File

@@ -0,0 +1,52 @@
//
//
// win_lightefects.h
//
// Declaration of class for pixel shader light effects
//
//
#ifndef _WIN_LIGHTEFFECTS_H_
#define _WIN_LIGHTEFFECTS_H_
class LightEffects
{
public:
LPDIRECT3DCUBETEXTURE9 m_pCubeMap; // Normalization cubemap
LPDIRECT3DTEXTURE9 m_pBumpMap;
LPDIRECT3DTEXTURE9 m_pSpecularMap;
LPDIRECT3DVOLUMETEXTURE9 m_pFalloffMap;
DWORD m_dwVertexShaderLight;
DWORD m_dwPixelShaderLight;
DWORD m_dwVertexShaderSpecular_Dynamic;
DWORD m_dwPixelShaderSpecular_Dynamic;
DWORD m_dwVertexShaderSpecular_Static;
DWORD m_dwPixelShaderSpecular_Static;
DWORD m_dwVertexShaderEnvironment;
DWORD m_dwVertexShaderBump;
DWORD m_dwPixelShaderBump;
bool m_bInLightPhase;
bool m_bInitialized;
public:
LightEffects();
virtual ~LightEffects();
bool Initialize();
void ProcessVertices(D3DXVECTOR3* pDirLightDir, D3DXVECTOR3* pPtLightPos);
bool RenderDynamicLights();
bool RenderStaticLights();
void RenderSpecular();
bool RenderSpecular_Dynamic();
bool RenderSpecular_Static();
bool RenderEnvironment();
void RenderBump();
bool CreateNormalizationCubeMap( DWORD dwSize, LPDIRECT3DCUBETEXTURE9* ppCubeMap );
void StartLightPhase();
void EndLightPhase();
};
#endif

79
code/win32/win_local.h Normal file
View File

@@ -0,0 +1,79 @@
// win_local.h: Win32-specific Quake3 header file
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning(disable : 4201)
#pragma warning( push )
#endif
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning( pop )
#endif
#ifndef _XBOX
#define DIRECTINPUT_VERSION 0x0800 //[ 0x0300 | 0x0500 | 0x0700 | 0x0800 ]
#include <dinput.h>
#include <dsound.h>
#else
#include "../qcommon/platform.h"
#endif
void IN_MouseEvent (int mstate);
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
void Sys_CreateConsole( void );
void Sys_DestroyConsole( void );
char *Sys_ConsoleInput (void);
// Input subsystem
void IN_Init (void);
void IN_Shutdown (void);
void IN_JoystickCommands (void);
void IN_Move (usercmd_t *cmd);
// add additional non keyboard / non mouse movement on top of the keyboard move cmd
void IN_DeactivateWin32Mouse( void);
void IN_Activate (qboolean active);
void IN_Frame (void);
// window procedure
#ifndef _XBOX
LONG WINAPI MainWndProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
#endif
void Conbuf_AppendText( const char *msg );
void SNDDMA_Activate( qboolean bAppActive );
#ifndef _XBOX
typedef struct
{
HWND hWnd;
HINSTANCE hInstance;
qboolean activeApp;
qboolean isMinimized;
OSVERSIONINFO osversion;
// when we get a windows message, we store the time off so keyboard processing
// can know the exact time of an event
unsigned sysMsgTime;
} WinVars_t;
extern WinVars_t g_wv;
#endif
#define MAX_QUED_EVENTS 256
#define MASK_QUED_EVENTS ( MAX_QUED_EVENTS - 1 )
#define YELLOW_MODE 0

1241
code/win32/win_main.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,332 @@
// win_main.h
#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"
#include "../client/client.h"
#include "win_local.h"
#include "resource.h"
#ifndef _GAMECUBE
#include <errno.h>
#include <float.h>
#include <fcntl.h>
#include <stdio.h>
#include <direct.h>
#include <io.h>
#include <conio.h>
#endif
//#define SPANK_MONKEYS //----(SA) commented out for running net developer release builds
int sys_monkeySpank;
/*
==================
Sys_MonkeyShouldBeSpanked
==================
*/
int Sys_MonkeyShouldBeSpanked( void ) {
return sys_monkeySpank;
}
/*
==================
Sys_FunctionCmp
==================
*/
int Sys_FunctionCmp(void *f1, void *f2) {
int i, j, l;
byte func_end[32] = {0xC3, 0x90, 0x90, 0x00};
byte *ptr, *ptr2;
byte *f1_ptr, *f2_ptr;
ptr = (byte *) f1;
if (*(byte *)ptr == 0xE9) {
//Com_Printf("f1 %p1 jmp %d\n", (int *) f1, *(int*)(ptr+1));
f1_ptr = (byte*)(((byte*)f1) + (*(int *)(ptr+1)) + 5);
}
else {
f1_ptr = ptr;
}
//Com_Printf("f1 ptr %p\n", f1_ptr);
ptr = (byte *) f2;
if (*(byte *)ptr == 0xE9) {
//Com_Printf("f2 %p jmp %d\n", (int *) f2, *(int*)(ptr+1));
f2_ptr = (byte*)(((byte*)f2) + (*(int *)(ptr+1)) + 5);
}
else {
f2_ptr = ptr;
}
//Com_Printf("f2 ptr %p\n", f2_ptr);
#ifdef _DEBUG
sprintf((char *)func_end, "%c%c%c%c%c%c%c", 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3);
#endif
for (i = 0; i < 1024; i++) {
for (j = 0; func_end[j]; j++) {
if (f1_ptr[i+j] != func_end[j])
break;
}
if (!func_end[j]) {
break;
}
}
#ifdef _DEBUG
l = i + 7;
#else
l = i + 2;
#endif
//Com_Printf("function length = %d\n", l);
for (i = 0; i < l; i++) {
// check for a potential function call
if (*((byte *) &f1_ptr[i]) == 0xE8) {
// get the function pointers in case this really is a function call
ptr = (byte *) (((byte *) &f1_ptr[i]) + (*(int *) &f1_ptr[i+1])) + 5;
ptr2 = (byte *) (((byte *) &f2_ptr[i]) + (*(int *) &f2_ptr[i+1])) + 5;
// if it was a function call and both f1 and f2 call the same function
if (ptr == ptr2) {
i += 4;
continue;
}
}
if (f1_ptr[i] != f2_ptr[i])
return qfalse;
}
return qtrue;
}
/*
==================
Sys_FunctionCheckSum
==================
*/
int Sys_FunctionCheckSum(void *f1) {
int i, j, l;
unsigned shermcrap;
byte func_end[32] = {0xC3, 0x90, 0x90, 0x00};
byte *ptr;
byte *f1_ptr;
ptr = (byte *) f1;
if (*(byte *)ptr == 0xE9) {
//Com_Printf("f1 %p1 jmp %d\n", (int *) f1, *(int*)(ptr+1));
f1_ptr = (byte*)(((byte*)f1) + (*(int *)(ptr+1)) + 5);
}
else {
f1_ptr = ptr;
}
//Com_Printf("f1 ptr %p\n", f1_ptr);
#ifdef _DEBUG
sprintf((char *)func_end, "%c%c%c%c%c%c%c", 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3);
#endif
for (i = 0; i < 1024; i++) {
for (j = 0; func_end[j]; j++) {
if (f1_ptr[i+j] != func_end[j])
break;
}
if (!func_end[j]) {
break;
}
}
#ifdef _DEBUG
l = i + 7;
#else
l = i + 2;
#endif
//Com_Printf("function length = %d\n", l);
shermcrap = Com_BlockChecksum( f1_ptr, l );
return (int)shermcrap;
}
//NOTE TTimo: heavily NON PORTABLE, PLZ DON'T USE
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=447
#if 0
//----(SA) added
/*
==============
Sys_ShellExecute
- Windows only
Performs an operation on a specified file.
See info on ShellExecute() for details
==============
*/
int Sys_ShellExecute(char *op, char *file, qboolean doexit, char *params, char *dir ) {
unsigned int retval;
char *se_op;
// set default operation to "open"
if(op) se_op = op;
else se_op = "open";
// probably need to protect this some in the future so people have
// less chance of system invasion with this powerful interface
// (okay, not so invasive, but could be annoying/rude)
retval = (UINT)ShellExecute(NULL, se_op, file, params, dir, SW_NORMAL); // only option forced by game is 'sw_normal'
if( retval <= 32) { // ERROR
Com_DPrintf("Sys_ShellExecuteERROR: %d\n", retval);
return retval;
}
if ( doexit ) {
// (SA) this works better for exiting cleanly...
Cbuf_ExecuteText( EXEC_APPEND, "quit" );
}
return 999; // success
}
//----(SA) end
#endif
/*
==================
Sys_BeginProfiling
==================
*/
void Sys_BeginProfiling( void ) {
// this is just used on the mac build
}
/*
==============
Sys_DefaultCDPath
==============
*/
char *Sys_DefaultCDPath( void ) {
return "";
}
/*
==============
Sys_DefaultBasePath
==============
*/
char *Sys_DefaultBasePath( void ) {
return Sys_Cwd();
}
/*
========================================================================
EVENT LOOP
========================================================================
*/
sysEvent_t eventQue[MAX_QUED_EVENTS];
int eventHead, eventTail;
byte sys_packetReceived[MAX_MSGLEN];
/*
================
Sys_QueEvent
A time of 0 will get the current time
Ptr should either be null, or point to a block of data that can
be freed by the game later.
================
*/
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr ) {
sysEvent_t *ev;
ev = &eventQue[ eventHead & MASK_QUED_EVENTS ];
if ( eventHead - eventTail >= MAX_QUED_EVENTS ) {
Com_Printf("Sys_QueEvent: overflow\n");
// we are discarding an event, but don't leak memory
if ( ev->evPtr ) {
Z_Free( ev->evPtr );
}
eventTail++;
}
eventHead++;
if ( time == 0 ) {
time = Sys_Milliseconds();
}
ev->evTime = time;
ev->evType = type;
ev->evValue = value;
ev->evValue2 = value2;
ev->evPtrLength = ptrLength;
ev->evPtr = ptr;
}
//================================================================
/*
=================
Sys_Net_Restart_f
Restart the network subsystem
=================
*/
void Sys_Net_Restart_f( void ) {
// NET_Restart();
}
//=======================================================================
void Sys_InitStreamThread( void ) {
}
void Sys_ShutdownStreamThread( void ) {
}
void Sys_BeginStreamedFile( fileHandle_t f, int readAhead ) {
}
void Sys_EndStreamedFile( fileHandle_t f ) {
}
int Sys_StreamedRead( void *buffer, int size, int count, fileHandle_t f ) {
return FS_Read( buffer, size * count, f );
}
void Sys_StreamSeek( fileHandle_t f, int offset, int origin ) {
FS_Seek( f, offset, origin );
}
void *Sys_InitializeCriticalSection() {
return (void*)-1;
}
void Sys_EnterCriticalSection(void *ptr) {
}
void Sys_LeaveCriticalSection(void *ptr) {
}

View File

@@ -0,0 +1,821 @@
#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"
#include "../client/client.h"
#include "win_local.h"
#include "resource.h"
#include <float.h>
#include <stdio.h>
#include "../game/g_public.h"
#include <xonline.h>
#include "glw_win_dx8.h"
#include "../qcommon/xb_settings.h"
#ifdef _XBOX
#include <IO.h>
#define NEWDECL __cdecl
#ifndef FINAL_BUILD
#include "dbg_console_xbox.h"
#endif
#endif
int gLaunchController = 0;
extern int eventHead, eventTail;
extern sysEvent_t eventQue[MAX_QUED_EVENTS];
extern byte sys_packetReceived[MAX_MSGLEN];
void *NEWDECL operator new(size_t size)
{
return Z_Malloc(size, TAG_NEWDEL, qfalse);
}
void *NEWDECL operator new[](size_t size)
{
return Z_Malloc(size, TAG_NEWDEL, qfalse);
}
void NEWDECL operator delete[](void *ptr)
{
if (ptr)
Z_Free(ptr);
}
void NEWDECL operator delete(void *ptr)
{
if (ptr)
Z_Free(ptr);
}
/*
================
Sys_Init
Called after the common systems (cvars, files, etc)
are initialized
================
*/
extern void Sys_In_Restart_f(void);
extern void Sys_Net_Restart_f(void);
void Sys_Init( void )
{
Cmd_AddCommand ("in_restart", Sys_In_Restart_f);
Cmd_AddCommand ("net_restart", Sys_Net_Restart_f);
}
#ifdef XBOX_DEMO
// When we're a demo, we're not running from D:\, so we need some hacks:
char demoBasePath[64];
#endif
char *Sys_Cwd( void )
{
static char cwd[MAX_OSPATH];
#ifdef XBOX_DEMO
strcpy( cwd, demoBasePath );
#else
strcpy(cwd, "d:");
#endif
return cwd;
}
/*
=================
Sys_In_Restart_f
Restart the input subsystem
=================
*/
void Sys_In_Restart_f( void ) {
}
/*
=============
Sys_Error
Show the early console as an error dialog
=============
*/
void Sys_Error( const char *error, ... ) {
va_list argptr;
char text[256];
va_start (argptr, error);
vsprintf (text, error, argptr);
va_end (argptr);
#ifdef _GAMECUBE
printf(text);
#else
OutputDebugString(text);
#endif
#if 0 // UN-PORT
Com_ShutdownZoneMemory();
Com_ShutdownHunkMemory();
#endif
exit (1);
}
/*
================
Sys_GetEvent
================
*/
sysEvent_t Sys_GetEvent( void ) {
sysEvent_t ev;
// return if we have data
if ( eventHead > eventTail ) {
eventTail++;
return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ];
}
// check for network packets
msg_t netmsg;
MSG_Init( &netmsg, sys_packetReceived, sizeof( sys_packetReceived ) );
// return if we have data
if ( eventHead > eventTail ) {
eventTail++;
return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ];
}
// create an empty event to return
memset( &ev, 0, sizeof( ev ) );
ev.evTime = Sys_Milliseconds();
return ev;
}
void Sys_Print(const char *msg)
{
#ifdef _GAMECUBE
printf(msg);
#else
OutputDebugString(msg);
#endif
}
/*
==============
Sys_Log
==============
*/
void Sys_Log( const char *file, const char *msg ) {
Sys_Log(file, msg, strlen(msg), strchr(msg, '\n') ? true : false);
}
/*
==============
Sys_Log
==============
*/
void Sys_Log( const char *file, const void *buffer, int size, bool flush ) {
#ifndef FINAL_BUILD
static bool unableToLog = false;
// Once we've failed to write to the log files once, bail out.
// This lets us put release builds on DVD without recompiling.
if (unableToLog)
return;
struct FileInfo
{
char name[MAX_QPATH];
FILE *handle;
};
const int LOG_MAX_FILES = 4;
static FileInfo files[LOG_MAX_FILES];
static int num_files = 0;
FileInfo* cur = NULL;
for (int f = 0; f < num_files; ++f)
{
if (!stricmp(file, files[f].name))
{
cur = &files[f];
break;
}
}
if (cur == NULL)
{
if (num_files >= LOG_MAX_FILES)
{
Sys_Print("Too many log files!\n");
return;
}
cur = &files[num_files++];
strcpy(cur->name, file);
cur->handle = NULL;
}
char fullname[MAX_QPATH];
sprintf(fullname, "d:\\%s", cur->name);
if (!cur->handle)
{
cur->handle = fopen(fullname, "wb");
if (cur->handle == NULL)
{
Sys_Print("Unable to open log file!\n");
unableToLog = true;
return;
}
}
if (size == 1) fputc(*(char*)buffer, cur->handle);
else fwrite(buffer, size, 1, cur->handle);
if (flush)
{
fflush(cur->handle);
}
#endif
}
#ifdef _XBOX
HANDLE Sys_FileStreamMutex = INVALID_HANDLE_VALUE;
#endif
void Win_Init(void)
{
#ifdef _XBOX
Sys_FileStreamMutex = CreateMutex(NULL, FALSE, NULL);
#endif
}
/*
=====================
XBE SWITCHING SUPPORT
=====================
*/
#ifdef XBOX_DEMO
// Filled in when we're launched from CDX
LD_DEMO demoLaunchData;
bool demoLaunchDataValid = false;
// If we were launched by the user, or someone has pressed a key
// then the timer should not count down during movies/loading:
bool demoTimerAlways = false;
int demoTimer = 0;
#endif
// Takes a filename (relative to ".") and pre-pends the right path. This
// is needed for demos where the game won't be running from D:
const char *Sys_RemapPath( const char *filename )
{
#ifdef XBOX_DEMO
return va( "%s\\%s", demoBasePath, filename );
#else
return va( "D:\\%s", filename );
#endif
}
// Despite what you may think, this function actually just returns
// a value telling you if you *should* quick-boot -- ie skip intro
// cinematics and such. Only supposed to XGetLaunchInfo once per
// boot, so we cache the results.
//
// This function always gets called at startup, so we also use it
// to retrieve the launch info for a demo
#define LAUNCH_MAGIC "J3D1"
bool Sys_QuickStart( void )
{
static bool retVal = false;
static bool initialized = false;
if( initialized )
return retVal;
initialized = true;
#ifdef XBOX_DEMO
// Default to D:\, this gets replaced below if CDX started us
strcpy( demoBasePath, "D:" );
gLaunchController = 0; // Irrelevant in demo
retVal = false; // We never come from MP (eg), so always false
DWORD launchType;
DWORD result = XGetLaunchInfo( &launchType, (LAUNCH_DATA *) &demoLaunchData );
if( result == ERROR_SUCCESS && launchType == LDT_TITLE )
{
// We were launched by CDX:
demoLaunchDataValid = true;
// How we were launched affects timer behavior:
demoTimerAlways = (demoLaunchData.dwRunmode == XLDEMO_RUNMODE_KIOSKMODE);
// Need to re-map paths, as D:\\ doesn't work now:
Q_strncpyz( demoBasePath, demoLaunchData.szLaunchedXBE, sizeof(demoBasePath), qtrue );
// Find our executable name in the path, and truncate the string there:
char *pXBE = strstr( demoBasePath, "\\default.xbe" );
if( !pXBE )
Com_Error( ERR_FATAL, "Error re-mapping D drive\n" );
*pXBE = 0;
// Fix the video path:
extern char XBOX_VIDEO_PATH[64];
strcpy( XBOX_VIDEO_PATH, demoBasePath );
strcat( XBOX_VIDEO_PATH, "\\base\\video\\" );
}
return retVal;
#else
DWORD launchType;
LAUNCH_DATA ld;
if( (XGetLaunchInfo( &launchType, &ld ) != ERROR_SUCCESS) ||
(launchType != LDT_TITLE) ||
strcmp((const char *)&ld.Data[1], LAUNCH_MAGIC) )
return (retVal = false);
gLaunchController = ld.Data[0];
// Magic number to disable settings/saving
if( ld.Data[5] == 0x42 )
Settings.Disable();
return (retVal = true);
#endif
}
extern int IN_GetMainController(void);
extern void SP_DrawMPLoadScreen(void);
// Takes an extra parameter so that the accepted invite code can pass
// in the XONLINE_ACCEPTED_INVITE to be copied into launch data.
//
// For the demo, the only valid reason is "demo", and pData should be NULL
void Sys_Reboot( const char *reason, const void *pData )
{
#ifdef XBOX_DEMO
if( pData || !demoLaunchDataValid || Q_stricmp( reason, "demo" ) != 0 )
Com_Error( ERR_DROP, "Invalid Sys_Reboot call\n" );
// Kill off the sound and stream threads:
S_Shutdown();
extern void Sys_StreamShutdown(void);
Sys_StreamShutdown();
// Now return to CDX
XLaunchNewImage( demoLaunchData.szLauncherXBE, (LAUNCH_DATA *) &demoLaunchData );
// Should never return!
#else
LAUNCH_DATA ld;
const char *path = NULL;
int controller;
memset( &ld, 0, sizeof(ld) );
controller = IN_GetMainController();
ld.Data[0] = (byte) controller;
Com_Printf("\tController %d Passed\n",controller);
if (!Q_stricmp(reason, "multiplayer"))
{
path = "d:\\jamp.xbe";
SP_DrawMPLoadScreen();
// Set a magic number if saving is disabled
if( Settings.IsDisabled() )
ld.Data[1] = 0x42;
// Flag that there is no invite in the launch data:
ld.Data[2] = 0;
}
else if (!Q_stricmp(reason, "invite"))
{
path = "d:\\jamp.xbe";
SP_DrawMPLoadScreen();
// Set a magic number if saving is disabled
if( Settings.IsDisabled() )
ld.Data[1] = 0x42;
// Flag that we're including an invite with the launch data:
ld.Data[2] = 1;
memcpy( &ld.Data[3], pData, sizeof(XONLINE_ACCEPTED_GAMEINVITE) );
}
else
{
Com_Error( ERR_FATAL, "Unknown reboot code %s\n", reason );
}
// Title should not be doing ANYTHING in the background.
// Shutting down sound ensures that the sound thread is gone
S_Shutdown();
// Similarly, kill off the streaming thread
extern void Sys_StreamShutdown(void);
Sys_StreamShutdown();
// Keep the loading screen up while we reboot!
glw_state->device->PersistDisplay();
XLaunchNewImage(path, &ld);
// This function should not return!
Com_Error( ERR_FATAL, "ERROR: XLaunchNewImage returned\n" );
#endif
}
static XONLINE_ACCEPTED_GAMEINVITE acceptedGameInvite;
// Used to check for the presence of an accepted invite for our game on the HD.
// Can only return true on the FIRST call.
bool Sys_InviteExists( void )
{
#ifdef XBOX_DEMO
return false;
#else
static bool initialized = false;
if( initialized )
return false;
initialized = true;
// If we just came from the MP XBE, don't auto-reboot again. That's just silly.
if( Sys_QuickStart() )
return false;
// Try to retrieve an invitation from the HD (this requires that we start XOnline):
XOnlineStartup( NULL );
HRESULT hr = XOnlineFriendsGetAcceptedGameInvite( &acceptedGameInvite );
XOnlineCleanup();
return (hr == S_OK);
#endif
}
// Reboot to MP to join the game that we have an invite for:
void Sys_JoinInvite( void )
{
// Aha. Well, XTL seems to blow this away now, so we need to copy it to launch_data. Bleh.
Sys_Reboot( "invite", &acceptedGameInvite );
// Never returns!
}
#ifdef XBOX_DEMO
// Timer code for the demo:
static int lastTime = 0;
static bool demoTimerPaused = false;
// Notify the demo timer of a keypress, which resets the timer, and ensures
// that the timer no longer runs during FMV/loading (if it was before)
void Demo_TimerKeypress( void )
{
demoTimerAlways = false;
// Reset the timer:
demoTimer = demoLaunchData.dwTimeout;
// Stamp the diff-timer
lastTime = Sys_Milliseconds();
}
// Update the timer, and check to see if we should reboot:
void Demo_TimerUpdate( void )
{
// Handle first call correctly
if( !lastTime )
{
demoTimer = demoLaunchData.dwTimeout;
lastTime = Sys_Milliseconds();
}
int newTime = Sys_Milliseconds();
int diffTime = newTime - lastTime;
lastTime = newTime;
// If the timer isn't supposed to run, and we're "paused", don't update:
extern bool in_camera;
if( !demoTimerAlways && (demoTimerPaused || in_camera) )
return;
// If we weren't even launched by CDX in the first place, or were given
// a zero timeout, do nothing:
if( !demoLaunchDataValid || !demoLaunchData.dwTimeout )
return;
// Time ran out?
if( demoTimer < diffTime )
Sys_Reboot( "demo", NULL );
demoTimer -= diffTime;
}
// Pause/unpause the demo timer when entering/exiting non-interactive state:
void Demo_TimerPause( bool bPaused )
{
// Always stamp the timer right before we change state:
Demo_TimerUpdate();
demoTimerPaused = bPaused;
}
#endif
/*
==================
WinMain
==================
*/
#if defined (_XBOX)
int __cdecl main()
#elif defined (_GAMECUBE)
int main(int argc, char* argv[])
#endif
{
// Z_SetFreeOSMem();
// I'm going to kill someone. This should not be necessary. No, really.
Direct3D_SetPushBufferSize(1024*1024, 128*1024);
// get the initial time base
Sys_Milliseconds();
// Need to fetch this stuff REALLY early so that path re-mappnig works
// for renderer startup. Bleh.
Sys_QuickStart();
Win_Init();
Com_Init( "" );
// Run one frame, to finish loading (calls CL_StartHunkUsers)...
IN_Frame();
Com_Frame();
extern void G_AllocGentities( void );
G_AllocGentities();
// And then quickly copy all the planet binks to the Z: drive
extern void Sys_BinkCopyInit(void);
Sys_BinkCopyInit();
// main game loop
while( 1 ) {
IN_Frame();
Com_Frame();
// Poll debug console for new commands
#ifndef FINAL_BUILD
DebugConsoleHandleCommands();
#endif
}
return 0;
}
char *Sys_GetClipboardData(void) { return NULL; }
void Sys_StartProcess(char *, qboolean) {}
void Sys_OpenURL(char *, int) {}
void Sys_Quit(void) {}
void Sys_ShowConsole(int, int) {}
void Sys_Mkdir(const char *) {}
int Sys_LowPhysicalMemory(void) { return 0; }
void Sys_FreeFileList(char **filelist)
{
// All strings in a file list are allocated at once, so we just need to
// do two frees, one for strings, one for the pointers.
if ( filelist )
{
if ( filelist[0] )
Z_Free( filelist[0] );
Z_Free( filelist );
}
}
#ifdef _JK2MP
char** Sys_ListFiles(const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs)
#else
char** Sys_ListFiles(const char *directory, const char *extension, int *numfiles, qboolean wantsubs)
#endif
{
#ifdef _JK2MP
// MP has extra filter paramter. We don't support that.
if (filter)
{
assert(!"Sys_ListFiles doesn't support filter on console!");
return NULL;
}
#endif
// Hax0red console version of Sys_ListFiles. We mangle our arguments to get a standard filename
// That file should exist, and contain the list of files that meet this search criteria.
char listFilename[MAX_OSPATH];
char *listFile, *curFile, *end;
int nfiles;
char **retList;
// S00per hack
#ifdef XBOX_DEMO
const char *basePath = Sys_RemapPath( "base\\" );
if (strstr(directory, basePath))
directory += strlen( basePath );
#else
if (strstr(directory, "d:\\base\\"))
directory += 8;
#endif
if (!extension)
{
extension = "";
}
else if (extension[0] == '/' && extension[1] == 0)
{
// Passing a slash as extension will find directories
extension = "dir";
}
else if (extension[0] == '.')
{
// Skip over leading .
extension++;
}
// Build our filename
Com_sprintf(listFilename, sizeof(listFilename), "%s\\_console_%s_list_", directory, extension);
if (FS_ReadFile( listFilename, (void**)&listFile ) <= 0)
{
if(listFile) {
FS_FreeFile(listFile);
}
Com_Printf( "WARNING: List file %s not found\n", listFilename );
if (numfiles)
*numfiles = 0;
return NULL;
}
// Do a first pass to count number of files in the list
nfiles = 0;
curFile = listFile;
while (true)
{
// Find end of line
end = strchr(curFile, '\r');
if (end)
{
// Should have a \n next -- skip them both
end += 2;
}
else
{
end = strchr(curFile, '\n');
if (end) end++;
else end = curFile + strlen(curFile);
}
// Is the line empty? If so, we're done.
if (!curFile || !curFile[0]) break;
++nfiles;
// Advance to next line
curFile = end;
}
// Fill in caller's pointer for number of files found
if (numfiles) *numfiles = nfiles;
// Did we find any files at all?
if (nfiles == 0)
{
FS_FreeFile(listFile);
return NULL;
}
// Allocate a file list, and quick string pool, but use LISTFILES
retList = (char **) Z_Malloc( ( nfiles + 1 ) * sizeof( *retList ), TAG_LISTFILES, qfalse);
// Our string pool is actually slightly too large, but it's temporary, and that's better
// than slightly too small
char *stringPool = (char *) Z_Malloc( strlen(listFile) + 1, TAG_LISTFILES, qfalse );
// Now go through the list of files again, and fill in the list to be returned
nfiles = 0;
curFile = listFile;
while (true)
{
// Find end of line
end = strchr(curFile, '\r');
if (end)
{
// Should have a \n next -- skip them both
*end++ = '\0';
*end++ = '\0';
}
else
{
end = strchr(curFile, '\n');
if (end) *end++ = '\0';
else end = curFile + strlen(curFile);
}
// Is the line empty? If so, we're done.
int curStrSize = strlen(curFile);
if (curStrSize < 1)
{
retList[nfiles] = NULL;
break;
}
// Alloc a small copy
//retList[nfiles++] = CopyString( curFile );
retList[nfiles++] = stringPool;
strcpy(stringPool, curFile);
stringPool += (curStrSize + 1);
// Advance to next line
curFile = end;
}
// Free the special file's buffer
FS_FreeFile( listFile );
return retList;
}
/*
=================
Sys_UnloadGame
=================
*/
void Sys_UnloadGame( void ) {
}
/*
=================
Sys_GetGameAPI
Loads the game dll
=================
*/
#ifndef _JK2MP
void *Sys_GetGameAPI (void *parms)
{
extern game_export_t *GetGameAPI( game_import_t *import );
return GetGameAPI((game_import_t *)parms);
}
#endif
/*
=================
Sys_LoadCgame
Used to hook up a development dll
=================
*/
// void * Sys_LoadCgame( void )
#ifndef _JK2MP
void * Sys_LoadCgame( int (**entryPoint)(int, ...), int (*systemcalls)(int, ...) )
{
extern void CG_PreInit();
extern void cg_dllEntry( int (*syscallptr)( int arg,... ) );
extern int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7 );
cg_dllEntry(systemcalls);
*entryPoint = (int (*)(int,...))vmMain;
// CG_PreInit();
return 0;
}
#endif
/* VVFIXME: More stubs */
qboolean Sys_FileOutOfDate( LPCSTR psFinalFileName /* dest */, LPCSTR psDataFileName /* src */ )
{
return qfalse;
}
qboolean Sys_CopyFile(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, qboolean bOverwrite)
{
return qfalse;
}
qboolean Sys_CheckCD( void )
{
return qtrue;
}

1342
code/win32/win_qal_xbox.cpp Normal file

File diff suppressed because it is too large Load Diff

4276
code/win32/win_qgl.cpp Normal file

File diff suppressed because it is too large Load Diff

6963
code/win32/win_qgl_dx8.cpp Normal file

File diff suppressed because it is too large Load Diff

281
code/win32/win_shared.cpp Normal file
View File

@@ -0,0 +1,281 @@
// leave this as first line for PCH reasons...
//
#include "../server/exe_headers.h"
#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"
#include "win_local.h"
/*
================
Sys_Milliseconds
================
*/
int Sys_Milliseconds (void)
{
static int sys_timeBase = timeGetTime();
int sys_curtime;
sys_curtime = timeGetTime() - sys_timeBase;
return sys_curtime;
}
/*
** --------------------------------------------------------------------------------
**
** PROCESSOR STUFF
**
** --------------------------------------------------------------------------------
*/
static inline void CPUID( int func, unsigned int regs[4] )
{
unsigned regEAX, regEBX, regECX, regEDX;
__asm mov eax, func
__asm __emit 00fh
__asm __emit 0a2h
__asm mov regEAX, eax
__asm mov regEBX, ebx
__asm mov regECX, ecx
__asm mov regEDX, edx
regs[0] = regEAX;
regs[1] = regEBX;
regs[2] = regECX;
regs[3] = regEDX;
}
static int IsPentium( void )
{
__asm
{
pushfd // save eflags
pop eax
test eax, 0x00200000 // check ID bit
jz set21 // bit 21 is not set, so jump to set_21
and eax, 0xffdfffff // clear bit 21
push eax // save new value in register
popfd // store new value in flags
pushfd
pop eax
test eax, 0x00200000 // check ID bit
jz good
jmp err // cpuid not supported
set21:
or eax, 0x00200000 // set ID bit
push eax // store new value
popfd // store new value in EFLAGS
pushfd
pop eax
test eax, 0x00200000 // if bit 21 is on
jnz good
jmp err
}
err:
return qfalse;
good:
return qtrue;
}
static int Is3DNOW( void )
{
unsigned regs[4];
char pstring[16];
char processorString[13];
// get name of processor
CPUID( 0, ( unsigned int * ) pstring );
processorString[0] = pstring[4];
processorString[1] = pstring[5];
processorString[2] = pstring[6];
processorString[3] = pstring[7];
processorString[4] = pstring[12];
processorString[5] = pstring[13];
processorString[6] = pstring[14];
processorString[7] = pstring[15];
processorString[8] = pstring[8];
processorString[9] = pstring[9];
processorString[10] = pstring[10];
processorString[11] = pstring[11];
processorString[12] = 0;
// REMOVED because you can have 3DNow! on non-AMD systems
// if ( strcmp( processorString, "AuthenticAMD" ) )
// return qfalse;
// check AMD-specific functions
CPUID( 0x80000000, regs );
if ( regs[0] < 0x80000000 )
return qfalse;
// bit 31 of EDX denotes 3DNOW! support
CPUID( 0x80000001, regs );
if ( regs[3] & ( 1 << 31 ) )
return qtrue;
return qfalse;
}
static int IsKNI( void )
{
unsigned regs[4];
// get CPU feature bits
CPUID( 1, regs );
// bit 25 of EDX denotes KNI existence
if ( regs[3] & ( 1 << 25 ) )
{
// Ok, CPU supports this instruction, but does the OS?
//
// Test a KNI instruction and make sure you don't get an exception...
//
__try
{
__asm
{
pushad;
// orps xmm1,xmm1; // Below are the op codes for this instruction
// emits will compile w/ MSVC 5.0 compiler
// You can comment these out and uncomment the
// orps when using the Intel Compiler
__emit 0x0f
__emit 0x56
__emit 0xc9
popad;
}
}// If OS creates an exception, it doesn't support Pentium III Instructions
__except(EXCEPTION_EXECUTE_HANDLER)
{
return qfalse;
}
return qtrue;
}
return qfalse;
}
static int IsWIL( void )
{
unsigned regs[4];
// get CPU feature bits
CPUID( 1, regs );
// bit 26 of EDX denotes WIL existence
if ( regs[3] & ( 1 << 26 ) )
{
// Ok, CPU supports this instruction, but does the OS?
//
// Test a WIL instruction and make sure you don't get an exception...
//
__try
{
__asm
{
pushad;
// xorpd xmm0,xmm0; // Willamette New Instructions
__emit 0x0f
__emit 0x56
__emit 0xc9
popad;
}
}// If OS creates an exception, it doesn't support PentiumIV Instructions
__except(EXCEPTION_EXECUTE_HANDLER)
{
// if(_exception_code()==STATUS_ILLEGAL_INSTRUCTION) // forget it, any exception should count as fail for safety
return qfalse; // Willamette New Instructions not supported
}
return qtrue; // Williamette/P4 instructions available
}
return qfalse;
}
static int IsMMX( void )
{
unsigned int regs[4];
// get CPU feature bits
CPUID( 1, regs );
// bit 23 of EDX denotes MMX existence
if ( regs[3] & ( 1 << 23 ) )
return qtrue;
return qfalse;
}
int Sys_GetProcessorId( void )
{
#if defined _M_ALPHA
return CPUID_AXP;
#elif !defined _M_IX86
return CPUID_GENERIC;
#else
// verify we're at least a Pentium or 486 w/ CPUID support
if ( !IsPentium() )
return CPUID_INTEL_UNSUPPORTED;
// check for MMX
if ( !IsMMX() )
{
// Pentium or PPro
return CPUID_INTEL_PENTIUM;
}
// see if we're an AMD 3DNOW! processor
if ( Is3DNOW() )
{
return CPUID_AMD_3DNOW;
}
// see if we're an Intel Katmai
if ( IsKNI() )
{
// if we are, see if we're a Williamette as well...
//
if ( IsWIL() )
{
return CPUID_INTEL_WILLIAMETTE;
}
return CPUID_INTEL_KATMAI;
}
// by default we're functionally a vanilla Pentium/MMX or P2/MMX
return CPUID_INTEL_MMX;
#endif
}
//============================================
char *Sys_GetCurrentUser( void )
{
#ifdef _XBOX
return NULL;
#else
static char s_userName[1024];
unsigned long size = sizeof( s_userName );
if ( !GetUserName( s_userName, &size ) )
strcpy( s_userName, "player" );
if ( !s_userName[0] )
{
strcpy( s_userName, "player" );
}
return s_userName;
#endif
}

414
code/win32/win_snd.cpp Normal file
View File

@@ -0,0 +1,414 @@
// leave this as first line for PCH reasons...
//
#include "../server/exe_headers.h"
#include <float.h>
#include "../client/snd_local.h"
#include "win_local.h"
HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c)
#define SECONDARY_BUFFER_SIZE 0x10000
extern int s_UseOpenAL;
static qboolean dsound_init;
static int sample16;
static DWORD gSndBufSize;
static DWORD locksize;
static LPDIRECTSOUND pDS;
static LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
static HINSTANCE hInstDS;
static int SNDDMA_InitDS ();
static const char *DSoundError( int error ) {
switch ( error ) {
case DSERR_BUFFERLOST:
return "DSERR_BUFFERLOST";
case DSERR_INVALIDCALL:
return "DSERR_INVALIDCALLS";
case DSERR_INVALIDPARAM:
return "DSERR_INVALIDPARAM";
case DSERR_PRIOLEVELNEEDED:
return "DSERR_PRIOLEVELNEEDED";
case DSERR_ALLOCATED:
return "DSERR_ALLOCATED";
case DSERR_UNINITIALIZED:
return "DSERR_UNINITIALIZED";
case DSERR_UNSUPPORTED:
return "DSERR_UNSUPPORTED ";
}
return "unknown";
}
/*
==================
SNDDMA_Shutdown
==================
*/
void SNDDMA_Shutdown( void ) {
Com_DPrintf( "Shutting down sound system\n" );
if ( pDS ) {
Com_DPrintf( "Destroying DS buffers\n" );
if ( pDS )
{
Com_DPrintf( "...setting NORMAL coop level\n" );
pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_NORMAL );
}
if ( pDSBuf )
{
Com_DPrintf( "...stopping and releasing sound buffer\n" );
pDSBuf->Stop( );
pDSBuf->Release( );
}
// only release primary buffer if it's not also the mixing buffer we just released
if ( pDSPBuf && ( pDSBuf != pDSPBuf ) )
{
Com_DPrintf( "...releasing primary buffer\n" );
pDSPBuf->Release( );
}
pDSBuf = NULL;
pDSPBuf = NULL;
dma.buffer = NULL;
Com_DPrintf( "...releasing DS object\n" );
pDS->Release( );
}
if ( hInstDS ) {
Com_DPrintf( "...freeing DSOUND.DLL\n" );
FreeLibrary( hInstDS );
hInstDS = NULL;
}
pDS = NULL;
pDSBuf = NULL;
pDSPBuf = NULL;
dsound_init = qfalse;
memset ((void *)&dma, 0, sizeof (dma));
}
/*
==================
SNDDMA_Init
Initialize direct sound
Returns false if failed
==================
*/
qboolean SNDDMA_Init(void) {
memset ((void *)&dma, 0, sizeof (dma));
dsound_init = qfalse;
if ( !SNDDMA_InitDS () ) {
return qfalse;
}
dsound_init = qtrue;
Com_DPrintf("Completed successfully\n" );
return qtrue;
}
static int SNDDMA_InitDS ()
{
HRESULT hresult;
qboolean pauseTried;
DSBUFFERDESC dsbuf;
DSBCAPS dsbcaps;
WAVEFORMATEX format;
Com_Printf( "Initializing DirectSound\n");
if ( !hInstDS ) {
Com_DPrintf( "...loading dsound.dll: " );
hInstDS = LoadLibrary("dsound.dll");
if ( hInstDS == NULL ) {
Com_Printf ("failed\n");
return 0;
}
Com_DPrintf ("ok\n");
pDirectSoundCreate = (long (__stdcall *)(struct _GUID *,struct IDirectSound ** ,struct IUnknown *))
GetProcAddress(hInstDS,"DirectSoundCreate");
if ( !pDirectSoundCreate ) {
Com_Printf ("*** couldn't get DS proc addr ***\n");
return 0;
}
}
Com_DPrintf( "...creating DS object: " );
pauseTried = qfalse;
while ( ( hresult = iDirectSoundCreate( NULL, &pDS, NULL ) ) != DS_OK ) {
if ( hresult != DSERR_ALLOCATED ) {
Com_Printf( "failed\n" );
return 0;
}
if ( pauseTried ) {
Com_Printf ("failed, hardware already in use\n" );
return 0;
}
// first try just waiting five seconds and trying again
// this will handle the case of a sysyem beep playing when the
// game starts
Com_DPrintf ("retrying...\n");
Sleep( 3000 );
pauseTried = qtrue;
}
Com_DPrintf( "ok\n" );
Com_DPrintf("...setting DSSCL_PRIORITY coop level: " );
if ( DS_OK != pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_PRIORITY ) ) {
Com_Printf ("failed\n");
SNDDMA_Shutdown ();
return qfalse;
}
Com_DPrintf("ok\n" );
// create the secondary buffer we'll actually work with
dma.channels = 2;
dma.samplebits = 16;
if (s_khz->integer == 44)
dma.speed = 44100;
else if (s_khz->integer == 22)
dma.speed = 22050;
else
dma.speed = 11025;
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = dma.channels;
format.wBitsPerSample = dma.samplebits;
format.nSamplesPerSec = dma.speed;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign;
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
#define idDSBCAPS_GETCURRENTPOSITION2 0x00010000
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCHARDWARE | idDSBCAPS_GETCURRENTPOSITION2;
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
dsbuf.lpwfxFormat = &format;
Com_DPrintf( "...creating secondary buffer: " );
hresult = pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL);
if (hresult != DS_OK)
{
if ( hresult == DSERR_CONTROLUNAVAIL )
{
Com_Printf( " - Ancient version of DirectX - this will slow FPS\n" );
dsbuf.dwFlags &= ~idDSBCAPS_GETCURRENTPOSITION2; // lose this DX8 cursor-position feature, and try again
hresult = pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL);
}
if (hresult != DS_OK)
{
// we can't even specify sounds should be in hardware?...
//
// ( this seems to happen on integrated sound devices (eg SoundMax), regardless of DX version )
//
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY; // note that DX docs say that this can still use hardware if it wants to, since neither DSBCAPS_LOCHARDWARE nor DSBCAPS_LOCSOFTWARE were specified
hresult = pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL);
if (hresult != DS_OK) {
Com_Printf( "failed to create secondary buffer - %s\n", DSoundError( hresult ) );
SNDDMA_Shutdown ();
return qfalse;
}
}
}
Com_Printf( "locked hardware. ok\n" );
// Make sure mixer is active
if ( DS_OK != pDSBuf->Play(0, 0, DSBPLAY_LOOPING) ) {
Com_Printf ("*** Looped sound play failed ***\n");
SNDDMA_Shutdown ();
return qfalse;
}
memset(&dsbcaps, 0, sizeof(dsbcaps));
dsbcaps.dwSize = sizeof(dsbcaps);
// get the returned buffer size
if ( DS_OK != pDSBuf->GetCaps (&dsbcaps) ) {
Com_Printf ("*** GetCaps failed ***\n");
SNDDMA_Shutdown ();
return qfalse;
}
gSndBufSize = dsbcaps.dwBufferBytes;
dma.channels = format.nChannels;
dma.samplebits = format.wBitsPerSample;
dma.speed = format.nSamplesPerSec;
dma.samples = gSndBufSize/(dma.samplebits/8);
dma.submission_chunk = 1;
dma.buffer = NULL; // must be locked first
sample16 = (dma.samplebits/8) - 1;
SNDDMA_BeginPainting ();
if (dma.buffer)
memset(dma.buffer, 0, dma.samples * dma.samplebits/8);
SNDDMA_Submit ();
return 1;
}
/*
==============
SNDDMA_GetDMAPos
return the current sample position (in mono samples read)
inside the recirculating dma buffer, so the mixing code will know
how many sample are required to fill it up.
===============
*/
int SNDDMA_GetDMAPos( void ) {
MMTIME mmtime;
int s;
DWORD dwWrite;
if ( !dsound_init ) {
return 0;
}
mmtime.wType = TIME_SAMPLES;
pDSBuf->GetCurrentPosition(&mmtime.u.sample, &dwWrite);
s = mmtime.u.sample;
s >>= sample16;
s &= (dma.samples-1);
return s;
}
/*
==============
SNDDMA_BeginPainting
Makes sure dma.buffer is valid
===============
*/
void SNDDMA_BeginPainting( void ) {
int reps;
DWORD dwSize2;
DWORD *pbuf, *pbuf2;
HRESULT hresult;
DWORD dwStatus;
if ( !pDSBuf ) {
return;
}
// if the buffer was lost or stopped, restore it and/or restart it
if ( pDSBuf->GetStatus (&dwStatus) != DS_OK ) {
Com_Printf ("Couldn't get sound buffer status\n");
}
if (dwStatus & DSBSTATUS_BUFFERLOST)
pDSBuf->Restore ();
if (!(dwStatus & DSBSTATUS_PLAYING))
pDSBuf->Play(0, 0, DSBPLAY_LOOPING);
// lock the dsound buffer
reps = 0;
dma.buffer = NULL;
while ((hresult = pDSBuf->Lock(0, gSndBufSize, (void **)&pbuf, &locksize,
(void **)&pbuf2, &dwSize2, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
Com_Printf( "SNDDMA_BeginPainting: Lock failed with error '%s'\n", DSoundError( hresult ) );
S_Shutdown ();
return;
}
else
{
pDSBuf->Restore( );
}
if (++reps > 2)
return;
}
dma.buffer = (unsigned char *)pbuf;
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
Also unlocks the dsound buffer
===============
*/
void SNDDMA_Submit( void ) {
// unlock the dsound buffer
if ( pDSBuf ) {
pDSBuf->Unlock(dma.buffer, locksize, NULL, 0);
}
}
/*
=================
SNDDMA_Activate
When we change windows we need to do this
=================
*/
void SNDDMA_Activate( qboolean bAppActive )
{
if (s_UseOpenAL)
{
S_AL_MuteAllSounds(!bAppActive);
}
if ( !pDS ) {
return;
}
if ( DS_OK != pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_PRIORITY ) ) {
Com_Printf ("sound SetCooperativeLevel failed\n");
SNDDMA_Shutdown ();
}
}
// I know this is a bit horrible, but I need to pass our LPDIRECTSOUND ptr to Bink for video playback,
// and I don't want other modules to have to know about LPDIRECTSOUND handles, hence the int casting
//
// (I'd prefer to use DWORD, but not all modules understand those)
//
unsigned int SNDDMA_GetDSHandle(void)
{
return (unsigned int) pDS;
}

View File

@@ -0,0 +1,474 @@
//
//
// win_stencilshadow.cpp
//
// Stencil shadow computation/rendering
//
//
#include "../server/exe_headers.h"
#include "../renderer/tr_local.h"
#include "../renderer/tr_lightmanager.h"
#include "glw_win_dx8.h"
#include "win_local.h"
#include "win_stencilshadow.h"
#include <xgraphics.h>
#include <xgmath.h>
#include "shader_constants.h"
StencilShadow StencilShadower;
StencilShadow::StencilShadow()
{
m_dwVertexShaderShadow = 0;
for(int i = 0; i < SHADER_MAX_VERTEXES / 2; i++)
{
m_extrusionIndicators[i] = 1.0f;
}
}
StencilShadow::~StencilShadow()
{
if(m_dwVertexShaderShadow)
glw_state->device->DeleteVertexShader(m_dwVertexShaderShadow);
}
extern const char *Sys_RemapPath( const char *filename );
bool StencilShadow::Initialize()
{
// Create a vertex shader
DWORD dwVertexDecl[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
D3DVSD_REG( 1, D3DVSDT_FLOAT1 ), // v1 = Extrusion determinant
D3DVSD_END()
};
if(!( CreateVertexShader(Sys_RemapPath("base\\media\\shadow.xvu"), dwVertexDecl, &m_dwVertexShaderShadow)))
return false;
return true;
}
void StencilShadow::AddEdge( unsigned short i1, unsigned short i2, byte facing )
{
#ifndef DISABLE_STENCILSHADOW
int c;
c = m_numEdgeDefs[ i1 ];
if ( c == MAX_EDGE_DEFS )
{
Com_Printf("WARNING: MAX_EDGE_DEFS overflow!\n");
return; // overflow
}
m_edgeDefs[ i1 ][ c ].i2 = i2;
m_edgeDefs[ i1 ][ c ].facing = facing;
m_numEdgeDefs[ i1 ]++;
#endif
}
void StencilShadow::BuildEdges()
{
#ifndef DISABLE_STENCILSHADOW
int i;
int c;
int j;
unsigned short i2;
int numTris;
unsigned short o1, o2, o3;
int hit[2];
int c2, k;
// an edge is NOT a silhouette edge if its face doesn't face the light,
// or if it has a reverse paired edge that also faces the light.
// A well behaved polyhedron would have exactly two faces for each edge,
// but lots of models have dangling edges or overfanned edges
m_nIndexes = 0;
m_nIndexesCap = 0;
for ( i = 0 ; i < tess.numVertexes ; i++ )
{
c = m_numEdgeDefs[ i ];
for ( j = 0 ; j < c ; j++ )
{
if ( !m_edgeDefs[ i ][ j ].facing )
{
continue;
}
/*i2 = m_edgeDefs[ i ][ j ].i2;
m_shadowIndexes[m_nIndexes++] = i;
m_shadowIndexes[m_nIndexes++] = i + tess.numVertexes;
m_shadowIndexes[m_nIndexes++] = i2 + tess.numVertexes;
m_shadowIndexes[m_nIndexes++] = i2;*/
hit[0] = 0;
hit[1] = 0;
i2 = m_edgeDefs[ i ][ j ].i2;
c2 = m_numEdgeDefs[ i2 ];
for ( k = 0 ; k < c2 ; k++ ) {
if ( m_edgeDefs[ i2 ][ k ].i2 == i ) {
hit[ m_edgeDefs[ i2 ][ k ].facing ]++;
}
}
// if it doesn't share the edge with another front facing
// triangle, it is a sil edge
if ( hit[ 1 ] == 0 ) {
m_shadowIndexes[m_nIndexes++] = i;
m_shadowIndexes[m_nIndexes++] = i + tess.numVertexes;
m_shadowIndexes[m_nIndexes++] = i2 + tess.numVertexes;
m_shadowIndexes[m_nIndexes++] = i2;
}
}
}
if(!m_nIndexes)
return;
#ifdef _STENCIL_REVERSE
//Carmack Reverse<tm> method requires that volumes
//be capped properly -rww
numTris = tess.numIndexes / 3;
for ( i = 0 ; i < numTris ; i++ )
{
if ( !m_facing[i] )
{
continue;
}
o1 = tess.indexes[ i*3 + 0 ];
o2 = tess.indexes[ i*3 + 1 ];
o3 = tess.indexes[ i*3 + 2 ];
m_shadowIndexesCap[m_nIndexesCap++] = o1;
m_shadowIndexesCap[m_nIndexesCap++] = o2;
m_shadowIndexesCap[m_nIndexesCap++] = o3;
m_shadowIndexesCap[m_nIndexesCap++] = o3 + tess.numVertexes;
m_shadowIndexesCap[m_nIndexesCap++] = o2 + tess.numVertexes;
m_shadowIndexesCap[m_nIndexesCap++] = o1 + tess.numVertexes;
}
#endif // _STENCIL_REVERSE
#endif
}
bool StencilShadow::BuildFromLight()
{
#ifndef DISABLE_STENCILSHADOW
int i;
int numTris;
vec3_t lightDir, ground;
float d;
// we can only do this if we have enough space in the vertex buffers
if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) {
return false;
}
//controlled method - try to keep shadows in range so they don't show through so much -rww
//VectorCopy( backEnd.currentEntity->shadowDir, lightDir );
//
//ground[0] = backEnd.ori.axis[0][2];
//ground[1] = backEnd.ori.axis[1][2];
//ground[2] = backEnd.ori.axis[2][2];
//d = DotProduct( lightDir, ground );
//// don't let the shadows get too long or go negative
//if ( d < 0.8 ) {
// VectorMA( lightDir, (0.8 - d), ground, lightDir );
// d = DotProduct( lightDir, ground );
//}
//d = 1.0 / d;
//lightDir[0] = lightDir[0] * d;
//lightDir[1] = lightDir[1] * d;
//lightDir[2] = lightDir[2] * d;
//VectorNormalize(lightDir);
vec3_t entLight;
VectorCopy( backEnd.currentEntity->lightDir, entLight );
entLight[2] = 0.0f;
VectorNormalize(entLight);
//Oh well, just cast them straight down no matter what onto the ground plane.
//This presets no chance of screwups and still looks better than a stupid
//shader blob.
VectorSet(lightDir, entLight[0]*0.3f, entLight[1]*0.3f, 1.0f);
// Set the vertex shader constants
D3DXVECTOR4 light = D3DXVECTOR4(lightDir[0], lightDir[1], lightDir[2], 1.0f);
glw_state->device->SetVertexShaderConstant( CV_LIGHT_DIRECTION, light, 1 );
glw_state->device->SetVertexShaderConstant( CV_SHADOW_FACTORS, D3DXVECTOR4(backEnd.ori.origin[0],
backEnd.ori.origin[1],
backEnd.ori.origin[2],
1.0f), 1);
glw_state->device->SetVertexShaderConstant( CV_SHADOW_PLANE, D3DXVECTOR4( backEnd.currentEntity->e.shadowPlane - 16.0f,
backEnd.currentEntity->e.shadowPlane - 16.0f,
backEnd.currentEntity->e.shadowPlane - 16.0f,
1.0f), 1);
// Create a second set of vertices to be projected
memcpy(&tess.xyz[tess.numVertexes], &tess.xyz[0], sizeof(vec4_t) * tess.numVertexes);
// decide which triangles face the light
memset( m_numEdgeDefs, 0, sizeof(short) * tess.numVertexes );
numTris = tess.numIndexes / 3;
for ( i = 0 ; i < numTris ; i++ )
{
short i1, i2, i3;
vec3_t d1, d2, normal;
float *v1, *v2, *v3;
float d;
i1 = tess.indexes[ i*3 + 0 ];
i2 = tess.indexes[ i*3 + 1 ];
i3 = tess.indexes[ i*3 + 2 ];
v1 = tess.xyz[ i1 ];
v2 = tess.xyz[ i2 ];
v3 = tess.xyz[ i3 ];
VectorSubtract( v2, v1, d1 );
VectorSubtract( v3, v1, d2 );
CrossProduct( d1, d2, normal );
d = DotProduct( normal, lightDir );
if ( d > 0 ) {
m_facing[ i ] = 1;
} else {
m_facing[ i ] = 0;
}
// create the edges
AddEdge( i1, i2, m_facing[ i ] );
AddEdge( i2, i3, m_facing[ i ] );
AddEdge( i3, i1, m_facing[ i ] );
}
return true;
#else
return false;
#endif
}
void StencilShadow::RenderShadow()
{
#ifndef DISABLE_STENCILSHADOW
DWORD lighting, fog, srcblend, destblend, alphablend, zwrite, zfunc, cullmode;
GL_State(GLS_DEFAULT);
glw_state->device->GetRenderState( D3DRS_LIGHTING, &lighting );
glw_state->device->GetRenderState( D3DRS_FOGENABLE, &fog );
glw_state->device->GetRenderState( D3DRS_SRCBLEND, &srcblend );
glw_state->device->GetRenderState( D3DRS_DESTBLEND, &destblend );
glw_state->device->GetRenderState( D3DRS_ALPHABLENDENABLE, &alphablend );
glw_state->device->GetRenderState( D3DRS_ZWRITEENABLE, &zwrite );
glw_state->device->GetRenderState( D3DRS_ZFUNC, &zfunc );
glw_state->device->GetRenderState( D3DRS_CULLMODE, &cullmode );
pVerts = NULL;
pExtrusions = NULL;
GL_Bind( tr.whiteImage );
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
glw_state->device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ZERO );
// Disable z-buffer writes (note: z-testing still occurs), and enable the
// stencil-buffer
glw_state->device->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_STENCILENABLE, TRUE );
// Don't bother with interpolating color
glw_state->device->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
glw_state->device->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESS );
// Set up stencil compare function, reference value, and masks.
// Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true.
// Note: since we set up the stencil-test to always pass, the STENCILFAIL
// renderstate is really not needed.
glw_state->device->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
#ifdef _STENCIL_REVERSE
glw_state->device->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR );
glw_state->device->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
glw_state->device->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
#else
glw_state->device->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
glw_state->device->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
glw_state->device->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_INCR );
#endif
// If ztest passes, inc/decrement stencil buffer value
glw_state->device->SetRenderState( D3DRS_STENCILREF, 0x1 );
glw_state->device->SetRenderState( D3DRS_STENCILMASK, 0x7f ); //0xffffffff );
glw_state->device->SetRenderState( D3DRS_STENCILWRITEMASK, 0x7f ); //0xffffffff );
// Make sure that no pixels get drawn to the frame buffer
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
glw_state->device->SetRenderState( D3DRS_COLORWRITEENABLE, 0 );
glw_state->device->SetTexture(0, NULL);
glw_state->device->SetTexture(1, NULL);
// Compute the matrix set
XGMATRIX matComposite, matProjectionViewport, matWorld;
glw_state->device->GetProjectionViewportMatrix( &matProjectionViewport );
XGMatrixMultiply( &matComposite, (XGMATRIX*)glw_state->matrixStack[glwstate_t::MatrixMode_Model]->GetTop(), &matProjectionViewport );
// Transpose and set the composite matrix.
XGMatrixTranspose( &matComposite, &matComposite );
glw_state->device->SetVertexShaderConstant( CV_WORLDVIEWPROJ_0, &matComposite, 4 );
// Set viewport offsets.
float fViewportOffsets[4] = { 0.53125f, 0.53125f, 0.0f, 0.0f };
glw_state->device->SetVertexShaderConstant( CV_VIEWPORT_OFFSETS, &fViewportOffsets, 1 );
glw_state->device->SetVertexShader(m_dwVertexShaderShadow);
#ifdef _STENCIL_REVERSE
qglCullFace( GL_FRONT );
#else
qglCullFace( GL_BACK );
#endif
BuildEdges();
// Draw front-side of shadow volume in stencil/z only
if(m_nIndexes)
renderObject_Shadow( D3DPT_QUADLIST, m_nIndexes, m_shadowIndexes );
#ifdef _STENCIL_REVERSE
if(m_nIndexesCap)
renderObject_Shadow( D3DPT_TRIANGLELIST, m_nIndexesCap, m_shadowIndexesCap );
#endif
// Now reverse cull order so back sides of shadow volume are written.
#ifdef _STENCIL_REVERSE
qglCullFace( GL_BACK );
#else
qglCullFace( GL_FRONT );
#endif
// Decrement stencil buffer value
#ifdef _STENCIL_REVERSE
glw_state->device->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR );
#else
glw_state->device->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_DECR );
#endif
// Draw back-side of shadow volume in stencil/z only
if(m_nIndexes)
renderObject_Shadow( D3DPT_QUADLIST, m_nIndexes, m_shadowIndexes );
#ifdef _STENCIL_REVERSE
if(m_nIndexesCap)
renderObject_Shadow( D3DPT_TRIANGLELIST, m_nIndexesCap, m_shadowIndexesCap );
#endif
// Restore render states
glw_state->device->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALL );
glw_state->device->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
glw_state->device->SetRenderState( D3DRS_STENCILENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_LIGHTING, lighting );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, fog );
glw_state->device->SetRenderState( D3DRS_SRCBLEND, srcblend );
glw_state->device->SetRenderState( D3DRS_DESTBLEND, destblend );
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, alphablend );
glw_state->device->SetRenderState( D3DRS_ZWRITEENABLE, zwrite );
glw_state->device->SetRenderState( D3DRS_ZFUNC, zfunc );
glw_state->device->SetRenderState( D3DRS_CULLMODE, cullmode );
#endif
}
void StencilShadow::FinishShadows()
{
#ifndef DISABLE_STENCILSHADOW
DWORD lighting, fog, srcblend, destblend, alphablend;
glw_state->device->GetRenderState( D3DRS_LIGHTING, &lighting );
glw_state->device->GetRenderState( D3DRS_FOGENABLE, &fog );
glw_state->device->GetRenderState( D3DRS_SRCBLEND, &srcblend );
glw_state->device->GetRenderState( D3DRS_DESTBLEND, &destblend );
glw_state->device->GetRenderState( D3DRS_ALPHABLENDENABLE, &alphablend );
// The stencilbuffer values indicates # of shadows that overlap each pixel.
// We only want to draw pixels that are in shadow, which was set up in
// RenderShadow() such that StencilBufferValue >= 1. In the Direct3D API,
// the stencil test is pseudo coded as:
// StencilRef CompFunc StencilBufferValue
// so we set our renderstates with StencilRef = 1 and CompFunc = LESSEQUAL.
glw_state->device->SetRenderState( D3DRS_STENCILENABLE, TRUE );
glw_state->device->SetRenderState( D3DRS_STENCILREF, 0);//0x1 );
glw_state->device->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_NOTEQUAL);//D3DCMP_LESSEQUAL );
glw_state->device->SetRenderState( D3DRS_STENCILMASK, 0x7f ); // New!
glw_state->device->SetRenderState( D3DRS_STENCILWRITEMASK, 0x7f ); //255 );
// Set renderstates (disable z-buffering and turn on alphablending)
glw_state->device->SetRenderState( D3DRS_ZENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
glw_state->device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
glw_state->device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
// Set the hardware to draw black, alpha-blending pixels
glw_state->device->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TFACTOR );
glw_state->device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
glw_state->device->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR );
glw_state->device->SetRenderState( D3DRS_TEXTUREFACTOR, 0x50000000 );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
// Draw the big, darkening square
static FLOAT v[4][4] =
{
{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f },
{ 640 - 0.5f, 0 - 0.5f, 0.0f, 1.0f },
{ 640 - 0.5f, 480 - 0.5f, 0.0f, 1.0f },
{ 0 - 0.5f, 480 - 0.5f, 0.0f, 1.0f },
};
glw_state->device->SetVertexShader( D3DFVF_XYZRHW );
glw_state->device->DrawPrimitiveUP( D3DPT_QUADLIST, 1, v, sizeof(v[0]) );
// Restore render states
glw_state->device->SetRenderState( D3DRS_ZENABLE, TRUE );
glw_state->device->SetRenderState( D3DRS_STENCILENABLE, FALSE );
glw_state->device->SetRenderState( D3DRS_LIGHTING, lighting );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, fog );
glw_state->device->SetRenderState( D3DRS_SRCBLEND, srcblend );
glw_state->device->SetRenderState( D3DRS_DESTBLEND, destblend );
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, alphablend );
#endif
}

View File

@@ -0,0 +1,63 @@
//
//
// win_stencilshadow.h
//
// Declaration for stencil shadowing class
//
//
#ifndef _WIN_STENCILSHADOW_H_
#define _WIN_STENCILSHADOW_H_
// Quick way turn off all stencilshadow code, and get back 170k of memory:
//#define DISABLE_STENCILSHADOW
// Enable this to enable Carmack's stencil reverse method
#define _STENCIL_REVERSE
typedef struct
{
// facing is only one bit, but we can't do better than 4 bytes without
// packing all the data we need into a single unsigned short, which
// isn't really worth it. (unless we REALLY need 64k at some point).
unsigned short i2;
byte facing;
} edgeDef_t;
#define MAX_EDGE_DEFS 16
class StencilShadow
{
public:
#ifndef DISABLE_STENCILSHADOW
edgeDef_t m_edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
short m_numEdgeDefs[SHADER_MAX_VERTEXES];
byte m_facing[SHADER_MAX_INDEXES/3];
unsigned short m_shadowIndexes[SHADER_MAX_INDEXES];
unsigned short m_nIndexes;
float m_extrusionIndicators[SHADER_MAX_VERTEXES/2];
#ifdef _STENCIL_REVERSE
unsigned short m_shadowIndexesCap[SHADER_MAX_INDEXES];
unsigned short m_nIndexesCap;
#endif
#endif
DWORD m_dwVertexShaderShadow;
DWORD *pVerts; // For reusing vertices in multiple shadow renderings
DWORD *pExtrusions;
StencilShadow();
~StencilShadow();
bool Initialize();
void AddEdge( unsigned short i1, unsigned short i2, byte facing );
void BuildEdges();
bool BuildFromLight();
void RenderShadow();
void FinishShadows();
};
extern StencilShadow StencilShadower;
#endif

View File

@@ -0,0 +1,511 @@
/*
* UNPUBLISHED -- Rights reserved under the copyright laws of the
* United States. Use of a copyright notice is precautionary only and
* does not imply publication or disclosure.
*
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
*/
#include "../server/exe_headers.h"
#include "../client/client.h"
#include "win_local.h"
#include "../qcommon/qcommon.h"
#include "../zlib/zlib.h"
#if defined(_WINDOWS)
#include <windows.h>
#elif defined(_XBOX)
#include <xtl.h>
#endif
extern void Z_SetNewDeleteTemporary(bool);
#define STREAM_SLOW_READ 0
#include "../client/snd_local_console.h"
#include <deque>
extern HANDLE Sys_FileStreamMutex;
extern int Sys_GetFileCodeSize(int code);
#define STREAM_MAX_OPEN 48
struct StreamInfo
{
unsigned int file;
volatile bool used;
volatile bool error;
volatile bool opening;
volatile bool reading;
};
static StreamInfo* s_Streams = NULL;
enum IORequestType
{
IOREQ_OPEN,
IOREQ_READ,
IOREQ_SHUTDOWN,
};
struct IORequest
{
IORequestType type;
streamHandle_t handle;
DWORD data[3];
};
typedef std::deque<IORequest> requestqueue_t;
requestqueue_t* s_IORequestQueue = NULL;
HANDLE s_Thread = INVALID_HANDLE_VALUE;
HANDLE s_QueueMutex = INVALID_HANDLE_VALUE;
HANDLE s_QueueLen = INVALID_HANDLE_VALUE;
#include "../qcommon/fixedmap.h"
#pragma pack(push, 1)
typedef struct
{
unsigned char filenameFlags;
int offset;
int size;
} sound_file_t;
#pragma pack(pop)
static HANDLE soundfile = INVALID_HANDLE_VALUE;
static VVFixedMap< sound_file_t, unsigned int >* soundLookup = NULL;
void Sys_StreamInitialize( void );
static DWORD WINAPI _streamThread(LPVOID)
{
for (;;)
{
IORequest req;
DWORD bytes;
StreamInfo* strm;
// Wait for the IO queue to fill
WaitForSingleObject(s_QueueLen, INFINITE);
// Grab the next IO request
WaitForSingleObject(s_QueueMutex, INFINITE);
assert(!s_IORequestQueue->empty());
req = s_IORequestQueue->front();
s_IORequestQueue->pop_front();
ReleaseMutex(s_QueueMutex);
int offset = 0;
sound_file_t* crap;
// Process request
switch (req.type)
{
case IOREQ_OPEN:
strm = &s_Streams[req.handle];
assert(strm->used);
strm->file = req.data[0];
strm->error = (strm->file == -1);
strm->opening = false;
break;
/*
{
const char* name = Sys_GetFileCodeName(req.data[0]);
WaitForSingleObject(Sys_FileStreamMutex, INFINITE);
strm->file =
CreateFile(name, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ReleaseMutex(Sys_FileStreamMutex);
}
strm->error = (strm->file == INVALID_HANDLE_VALUE);
strm->opening = false;
break;
*/
case IOREQ_READ:
{
strm = &s_Streams[req.handle];
assert(strm->used);
WaitForSingleObject(Sys_FileStreamMutex, INFINITE);
crap = soundLookup->Find(strm->file);
if(crap)
{
offset = crap->offset + req.data[2];
strm->error = (SetFilePointer(soundfile, offset, 0, FILE_BEGIN) != offset) ||
(ReadFile(soundfile, (void*)req.data[0], req.data[1], &bytes, NULL) == 0);
}
else
{
strm->error = true;
}
/*
strm->error =
(SetFilePointer(strm->file, req.data[2], 0, FILE_BEGIN) != req.data[2] ||
ReadFile(strm->file, (void*)req.data[0], req.data[1], &bytes, NULL) == 0);
*/
ReleaseMutex(Sys_FileStreamMutex);
strm->reading = false;
}
break;
case IOREQ_SHUTDOWN:
ExitThread(0);
break;
}
}
return TRUE;
}
static void _sendIORequest(const IORequest& req)
{
// Add request to queue
WaitForSingleObject(s_QueueMutex, INFINITE);
Z_SetNewDeleteTemporary(true);
s_IORequestQueue->push_back(req);
Z_SetNewDeleteTemporary(false);
ReleaseMutex(s_QueueMutex);
// Let IO thread know it has one more pending request
ReleaseSemaphore(s_QueueLen, 1, NULL);
}
void Sys_IORequestQueueClear(void)
{
WaitForSingleObject(s_QueueMutex, INFINITE);
delete s_IORequestQueue;
s_IORequestQueue = new requestqueue_t;
ReleaseMutex(s_QueueMutex);
}
void Sys_StreamInit(void)
{
Sys_StreamInitialize();
// Create array for storing open streams
s_Streams = (StreamInfo*)Z_Malloc(
STREAM_MAX_OPEN * sizeof(StreamInfo), TAG_FILESYS, qfalse);
for (int i = 0; i < STREAM_MAX_OPEN; ++i)
{
s_Streams[i].used = false;
}
// Create queue to hold requests for IO thread
s_IORequestQueue = new requestqueue_t;
// Create a thread to service IO
s_QueueMutex = CreateMutex(NULL, FALSE, NULL);
s_QueueLen = CreateSemaphore(NULL, 0, STREAM_MAX_OPEN * 3, NULL);
s_Thread = CreateThread(NULL, 64*1024, _streamThread, 0, 0, NULL);
}
void Sys_StreamShutdown(void)
{
// Tell the IO thread to shutdown
IORequest req;
req.type = IOREQ_SHUTDOWN;
_sendIORequest(req);
// Wait for thread to close
WaitForSingleObject(s_Thread, INFINITE);
// Kill IO thread
CloseHandle(s_Thread);
CloseHandle(s_QueueLen);
CloseHandle(s_QueueMutex);
// Remove queue of IO requests
delete s_IORequestQueue;
// Remove streaming table
Z_Free(s_Streams);
}
static streamHandle_t GetFreeHandle(void)
{
for (streamHandle_t i = 1; i < STREAM_MAX_OPEN; ++i)
{
if (!s_Streams[i].used) return i;
}
// handle 0 is invalid by convention
return 0;
}
int Sys_StreamOpen(int code, streamHandle_t *handle)
{
// Find a free handle
*handle = GetFreeHandle();
if (*handle == 0)
{
return -1;
}
// Find the file size
sound_file_t* crap = soundLookup->Find(code);
int size = -1;
if(crap)
{
size = crap->size;
}
if (size < 0)
{
*handle = 0;
return -1;
}
// Init stream data
s_Streams[*handle].used = true;
s_Streams[*handle].opening = true;
s_Streams[*handle].reading = false;
s_Streams[*handle].error = false;
// Send an open request to the thread
IORequest req;
req.type = IOREQ_OPEN;
req.handle = *handle;
req.data[0] = code;
_sendIORequest(req);
// Return file size
return size;
}
bool Sys_StreamRead(void* buffer, int size, int pos, streamHandle_t handle)
{
assert((unsigned int)buffer % 32 == 0);
// Handle must be valid. Do not allow multiple reads.
if (!s_Streams[handle].used || s_Streams[handle].reading) return false;
// Ready to read
s_Streams[handle].reading = true;
s_Streams[handle].error = false;
// Request IO threading reading
IORequest req;
req.type = IOREQ_READ;
req.handle = handle;
req.data[0] = (DWORD)buffer;
req.data[1] = size;
req.data[2] = pos;
_sendIORequest(req);
return true;
}
bool Sys_StreamIsReading(streamHandle_t handle)
{
return s_Streams[handle].used && s_Streams[handle].reading;
}
bool Sys_StreamIsError(streamHandle_t handle)
{
return s_Streams[handle].used && s_Streams[handle].error;
}
void Sys_StreamClose(streamHandle_t handle)
{
if (s_Streams[handle].used)
{
// Block until read is done
while (s_Streams[handle].opening || s_Streams[handle].reading);
// Close the file
// CloseHandle(s_Streams[handle].file);
s_Streams[handle].used = false;
}
}
extern char* FS_BuildOSPathUnMapped(const char* name);
unsigned int Sys_GetSoundFileCode(const char* name)
{
// Get system level path
char* osname = FS_BuildOSPathUnMapped(name);
// Generate hash for file name
strlwr(osname);
unsigned int code = crc32(0, (const byte *)osname, strlen(osname));
return code;
}
unsigned int Sys_GetSoundFileCodeFlags(unsigned int code)
{
sound_file_t* sf;
sf = soundLookup->Find(code);
if(!sf)
{
return 0;
}
else
{
return sf->filenameFlags;
}
}
int Sys_GetSoundFileCodeSize(unsigned int code)
{
sound_file_t* sf;
sf = soundLookup->Find(code);
if(!sf)
{
return -1;
}
else
{
return sf->size;
}
}
#if PROFILE_SOUND
VVFixedMap< char*, unsigned int>* soundCrc = NULL;
void Sys_LoadSoundCRCFile( void )
{
FILE* file;
file = fopen("d:\\base\\soundbank\\crclookup.txt", "rb");
if(!file)
return;
int numberOfLines = 0;
unsigned int crc = 0;
char name[255];
// count the number of lines
while(1)
{
if(fscanf(file, "%d %s", &crc, name) == -1)
break;
numberOfLines++;
}
// allocate memory for the crc lookup
soundCrc = new VVFixedMap<char*, unsigned int>(numberOfLines);
// actually read and store the data
fseek(file, 0, SEEK_SET);
while(1)
{
if(fscanf(file, "%d %s", &crc, name) == -1)
break;
char *temp = (char*)Z_Malloc(strlen(name) + 1, TAG_SND_RAWDATA, qtrue);
strcpy(temp, name);
soundCrc->Insert(temp, crc);
}
soundCrc->Sort();
fclose(file);
}
char* Sys_GetSoundName( unsigned int crc )
{
char* name = *soundCrc->Find(crc);
return name;
}
#endif // PROFILE_SOUND
extern const char *Sys_RemapPath( const char *filename );
void Sys_StreamInitialize( void )
{
// open the sound file
soundfile = CreateFile(
Sys_RemapPath("base\\soundbank\\sound.bnk"),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS,
NULL );
// fill in the lookup table
HANDLE table = INVALID_HANDLE_VALUE;
table = CreateFile(
Sys_RemapPath("base\\soundbank\\sound.tbl"),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
DWORD fileSize = 0;
fileSize = GetFileSize(
table,
NULL);
int numberOfRecords = fileSize / ((sizeof(unsigned int) * 3) + 1);
soundLookup = new VVFixedMap<sound_file_t, unsigned int>(numberOfRecords);
byte* tempData = (byte*)Z_Malloc(fileSize, TAG_TEMP_WORKSPACE, true, 32);
byte* restore = tempData;
DWORD bytesRead;
ReadFile(
table,
tempData,
fileSize,
&bytesRead,
NULL );
if(bytesRead != fileSize)
Com_Error(0,"Could not read sound index file.\n");
CloseHandle(table);
for(int i = 0; i < numberOfRecords; i++)
{
unsigned int filecode = *(unsigned int*)tempData;
tempData += sizeof(unsigned int);
unsigned int offset = *(unsigned int*)tempData;
tempData += sizeof(unsigned int);
int size = *(int*)tempData;
tempData += sizeof(int);
unsigned char filenameFlags = *(unsigned char*)tempData;
tempData++;
sound_file_t sfile;
sfile.offset = offset;
sfile.size = size;
sfile.filenameFlags = filenameFlags;
soundLookup->Insert(sfile, filecode);
}
soundLookup->Sort();
Z_Free(restore);
#if PROFILE_SOUND
Sys_LoadSoundCRCFile();
#endif
}

536
code/win32/win_syscon.cpp Normal file
View File

@@ -0,0 +1,536 @@
// win_syscon.h
// leave this as first line for PCH reasons...
//
#include "../server/exe_headers.h"
#include "../client/client.h"
#include "win_local.h"
#include "resource.h"
#include <errno.h>
#include <float.h>
#include <fcntl.h>
#include <stdio.h>
#include <direct.h>
#include <io.h>
#include <conio.h>
#define COPY_ID 1
#define QUIT_ID 2
#define CLEAR_ID 3
#define ERRORBOX_ID 10
#define ERRORTEXT_ID 11
#define EDIT_ID 100
#define INPUT_ID 101
typedef struct
{
HWND hWnd;
HWND hwndBuffer;
HWND hwndButtonClear;
HWND hwndButtonCopy;
HWND hwndButtonQuit;
HWND hwndErrorBox;
HWND hwndErrorText;
HBITMAP hbmLogo;
HBITMAP hbmClearBitmap;
HBRUSH hbrEditBackground;
HBRUSH hbrErrorBackground;
HFONT hfBufferFont;
HFONT hfButtonFont;
HWND hwndInputLine;
char errorString[80];
char consoleText[512], returnedText[512];
int visLevel;
qboolean quitOnClose;
int windowWidth, windowHeight;
WNDPROC SysInputLineWndProc;
} WinConData;
static WinConData s_wcd;
static LONG WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char *cmdString;
static qboolean s_timePolarity;
switch (uMsg)
{
case WM_ACTIVATE:
if ( LOWORD( wParam ) != WA_INACTIVE )
{
SetFocus( s_wcd.hwndInputLine );
}
if ( com_viewlog )
{
// if the viewlog is open, check to see if it's being minimized
if ( com_viewlog->integer == 1 )
{
if ( HIWORD( wParam ) ) // minimized flag
{
Cvar_Set( "viewlog", "2" );
}
}
else if ( com_viewlog->integer == 2 )
{
if ( !HIWORD( wParam ) ) // minimized flag
{
Cvar_Set( "viewlog", "1" );
}
}
}
break;
case WM_CLOSE:
//cmdString = CopyString( "quit" );
//Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
if ( s_wcd.quitOnClose )
{
PostQuitMessage( 0 );
}
else
{
Sys_ShowConsole( 0, qfalse );
Cvar_Set( "viewlog", "0" );
}
return 0;
case WM_CTLCOLORSTATIC:
if ( ( HWND ) lParam == s_wcd.hwndBuffer )
{
SetBkColor( ( HDC ) wParam, RGB( 0, 0, 0 ) );
SetTextColor( ( HDC ) wParam, RGB( 249, 249, 000 ) );
return ( long ) s_wcd.hbrEditBackground;
}
else if ( ( HWND ) lParam == s_wcd.hwndErrorBox )
{
if ( s_timePolarity & 1 )
{
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
SetTextColor( ( HDC ) wParam, RGB( 0xff, 0x00, 0x00 ) );
}
else
{
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
SetTextColor( ( HDC ) wParam, RGB( 0x00, 0x00, 0x00 ) );
}
return ( long ) s_wcd.hbrErrorBackground;
}
return FALSE;
break;
case WM_COMMAND:
if ( wParam == COPY_ID )
{
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
SendMessage( s_wcd.hwndBuffer, WM_COPY, 0, 0 );
}
else if ( wParam == QUIT_ID )
{
if ( s_wcd.quitOnClose )
{
PostQuitMessage( 0 );
}
else
{
cmdString = CopyString( "quit" );
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
}
}
else if ( wParam == CLEAR_ID )
{
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, ( LPARAM ) "" );
UpdateWindow( s_wcd.hwndBuffer );
}
break;
case WM_CREATE:
s_wcd.hbrEditBackground = CreateSolidBrush( RGB( 0x00, 0x00, 0x00 ) );
s_wcd.hbrErrorBackground = CreateSolidBrush( RGB( 0x80, 0x80, 0x80 ) );
SetTimer( hWnd, 1, 1000, NULL );
break;
case WM_ERASEBKGND:
return DefWindowProc( hWnd, uMsg, wParam, lParam );
case WM_TIMER:
if ( wParam == 1 )
{
s_timePolarity = !s_timePolarity;
if ( s_wcd.hwndErrorBox )
{
InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
}
}
break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char inputBuffer[1024];
switch ( uMsg )
{
case WM_KILLFOCUS:
if ( ( HWND ) wParam == s_wcd.hWnd ||
( HWND ) wParam == s_wcd.hwndErrorBox )
{
SetFocus( hWnd );
return 0;
}
break;
case WM_CHAR:
if ( wParam == 13 )
{
GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) );
strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 );
strcat( s_wcd.consoleText, "\n" );
SetWindowText( s_wcd.hwndInputLine, "" );
Sys_Print( va( "]%s\n", inputBuffer ) );
return 0;
}
}
return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
}
/*
** Sys_CreateConsole
*/
void Sys_CreateConsole( void )
{
HDC hDC;
WNDCLASS wc;
RECT rect;
const char *DEDCLASS = "JK2MP WinConsole";
int nHeight;
int swidth, sheight;
int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
memset( &wc, 0, sizeof( wc ) );
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) ConWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_wv.hInstance;
wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH__ *)COLOR_INACTIVEBORDER;//(HBRUSH__ *)COLOR_WINDOW;
wc.lpszMenuName = 0;
wc.lpszClassName = DEDCLASS;
if ( !RegisterClass (&wc) ) {
return;
}
rect.left = 0;
rect.right = 600;
rect.top = 0;
rect.bottom = 450;
AdjustWindowRect( &rect, DEDSTYLE, FALSE );
hDC = GetDC( GetDesktopWindow() );
swidth = GetDeviceCaps( hDC, HORZRES );
sheight = GetDeviceCaps( hDC, VERTRES );
ReleaseDC( GetDesktopWindow(), hDC );
s_wcd.windowWidth = rect.right - rect.left + 1;
s_wcd.windowHeight = rect.bottom - rect.top + 1;
s_wcd.hWnd = CreateWindowEx( 0,
DEDCLASS,
"Jedi Knight®: Jedi Academy SP Console",
DEDSTYLE,
( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
NULL,
NULL,
g_wv.hInstance,
NULL );
if ( s_wcd.hWnd == NULL )
{
return;
}
//
// create fonts
//
hDC = GetDC( s_wcd.hWnd );
nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY), 72);
s_wcd.hfBufferFont = CreateFont( nHeight,
0,
0,
0,
FW_LIGHT,
0,
0,
0,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
FF_MODERN | FIXED_PITCH,
"Courier New" );
ReleaseDC( s_wcd.hWnd, hDC );
//
// create the input line
//
s_wcd.hwndInputLine = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER |
ES_LEFT | ES_AUTOHSCROLL,
6, 400, s_wcd.windowWidth-20, 20,
s_wcd.hWnd,
( HMENU ) INPUT_ID, // child window ID
g_wv.hInstance, NULL );
//
// create the buttons
//
s_wcd.hwndButtonCopy = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
5, 425, 72, 24,
s_wcd.hWnd,
( HMENU ) COPY_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndButtonCopy, WM_SETTEXT, 0, ( LPARAM ) "copy" );
s_wcd.hwndButtonClear = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
82, 425, 72, 24,
s_wcd.hWnd,
( HMENU ) CLEAR_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndButtonClear, WM_SETTEXT, 0, ( LPARAM ) "clear" );
s_wcd.hwndButtonQuit = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
s_wcd.windowWidth-92, 425, 72, 24,
s_wcd.hWnd,
( HMENU ) QUIT_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndButtonQuit, WM_SETTEXT, 0, ( LPARAM ) "quit" );
//
// create the scrollbuffer
//
s_wcd.hwndBuffer = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
6, 40, s_wcd.windowWidth-20, 354,
s_wcd.hWnd,
( HMENU ) EDIT_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndBuffer, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
s_wcd.SysInputLineWndProc = ( WNDPROC ) SetWindowLong( s_wcd.hwndInputLine, GWL_WNDPROC, ( long ) InputLineWndProc );
SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
SendMessage( s_wcd.hwndBuffer, EM_LIMITTEXT, ( WPARAM ) 0x7fff, 0 );
ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT);
UpdateWindow( s_wcd.hWnd );
SetForegroundWindow( s_wcd.hWnd );
SetFocus( s_wcd.hwndInputLine );
s_wcd.visLevel = 1;
}
/*
** Sys_DestroyConsole
*/
void Sys_DestroyConsole( void ) {
if ( s_wcd.hWnd ) {
DeleteObject(s_wcd.hbrEditBackground);
DeleteObject(s_wcd.hbrErrorBackground);
DeleteObject(s_wcd.hfBufferFont);
ShowWindow( s_wcd.hWnd, SW_HIDE );
CloseWindow( s_wcd.hWnd );
DestroyWindow( s_wcd.hWnd );
s_wcd.hWnd = 0;
}
}
/*
** Sys_ShowConsole
*/
void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
{
s_wcd.quitOnClose = quitOnClose;
if ( visLevel == s_wcd.visLevel )
{
if (quitOnClose) {//attempt to bring it to the front on error exit
SetForegroundWindow( s_wcd.hWnd );
SetFocus( s_wcd.hwndInputLine );
}
return;
}
s_wcd.visLevel = visLevel;
if ( !s_wcd.hWnd ){
return;
}
switch ( visLevel )
{
case 0:
ShowWindow( s_wcd.hWnd, SW_HIDE );
break;
case 1:
ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL );
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
if (quitOnClose) {//attempt to bring it to the front on error exit
SetForegroundWindow( s_wcd.hWnd );
SetFocus( s_wcd.hwndInputLine );
}
break;
case 2:
ShowWindow( s_wcd.hWnd, SW_MINIMIZE );
break;
default:
Sys_Error( "Invalid visLevel %d sent to Sys_ShowConsole\n", visLevel );
break;
}
}
/*
** Sys_ConsoleInput
*/
char *Sys_ConsoleInput( void )
{
if ( s_wcd.consoleText[0] == 0 )
{
return NULL;
}
strcpy( s_wcd.returnedText, s_wcd.consoleText );
s_wcd.consoleText[0] = 0;
return s_wcd.returnedText;
}
/*
** Conbuf_AppendText
*/
void Conbuf_AppendText( const char *pMsg )
{
#define CONSOLE_BUFFER_SIZE 16384
if ( !s_wcd.hWnd ) {
return;
}
char buffer[CONSOLE_BUFFER_SIZE*4];
char *b = buffer;
const char *msg;
int bufLen;
int i = 0;
static unsigned long s_totalChars;
//
// if the message is REALLY long, use just the last portion of it
//
if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 )
{
msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1;
}
else
{
msg = pMsg;
}
//
// copy into an intermediate buffer
//
while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) )
{
if ( msg[i] == '\n' && msg[i+1] == '\r' )
{
b[0] = '\r';
b[1] = '\n';
b += 2;
i++;
}
else if ( msg[i] == '\r' )
{
b[0] = '\r';
b[1] = '\n';
b += 2;
}
else if ( msg[i] == '\n' )
{
b[0] = '\r';
b[1] = '\n';
b += 2;
}
else if ( Q_IsColorString( &msg[i] ) )
{
i++;
}
else
{
*b= msg[i];
b++;
}
i++;
}
*b = 0;
bufLen = b - buffer;
s_totalChars += bufLen;
//
// replace selection instead of appending if we're overflowing
//
if ( s_totalChars > 0x7fff )
{
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
s_totalChars = bufLen;
}
//
// put this text into the windows console
//
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer );
}
/*
** Sys_SetErrorText
*/
void Sys_SetErrorText( const char *buf )
{
Q_strncpyz( s_wcd.errorString, buf, sizeof( s_wcd.errorString ) );
if ( !s_wcd.hwndErrorBox )
{
s_wcd.hwndErrorBox = CreateWindow( "static", NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN,
6, 5, s_wcd.windowWidth-20, 30,
s_wcd.hWnd,
( HMENU ) ERRORBOX_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndErrorBox, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
SetWindowText( s_wcd.hwndErrorBox, s_wcd.errorString );
DestroyWindow( s_wcd.hwndInputLine );
s_wcd.hwndInputLine = NULL;
}
}

325
code/win32/win_video.cpp Normal file
View File

@@ -0,0 +1,325 @@
// Filename:- win_video.cpp
//
// leave this as first line for PCH reasons...
//
#include "../server/exe_headers.h"
#include "../client/client.h"
#include "win_local.h"
/*
#include "bink.h"
static HANDLE hBinkFile = NULL;
static HBINK hBink = NULL;
*/
extern unsigned int SNDDMA_GetDSHandle(void);
extern int s_soundStarted; // if 0, game is running in silent mode
// ret qtrue if success...
//
qboolean VIDEO_GetDims(int *piWidth, int *piHeight)
{
/*
if (hBink)
{
if (piWidth && piHeight)
{
// *piWidth = hBink->Width; // Width (1 based, 640 for example)
if (hBink->decompwidth == hBink->Width/2)
{
*piWidth = hBink->decompwidth;
}
else
{
*piWidth = hBink->Width;
}
if (hBink->decompheight == hBink->Height/2)
{
*piHeight = hBink->decompheight;
}
else
{
*piHeight = hBink->Height;
}
return qtrue;
}
}
*/
return qfalse;
}
// ret qtrue if no reason to delay...
//
qboolean VIDEO_NextFrameReady(void)
{
/* if (hBink && BinkWait(hBink))
{
return qfalse;
}
*/
return qtrue;
}
void VIDEO_Pause(qboolean bPaused)
{
/*
if (hBink)
{
BinkPause(hBink, bPaused);
}
*/
}
void VIDEO_Mute(qboolean bMute)
{
/*
if (!s_soundStarted)
bMute = qtrue; // <g>
if (hBink)
{
// BinkSetSoundOnOff(hBink, !bMute); // this has a bug, and freezes video playback
BinkSetVolume(hBink,bMute?0:32768); // effectively the same, and instant, not just to next audio packet
}
*/
}
// advance to the next Bink Frame, qtrue if not finished playback
//
//qboolean VIDEO_NextFrame( byte *pbDestBuffer ) // pbDestBuffer will be sizeof Vid dims *4
qboolean VIDEO_NextFrame( byte *pbDestBuffer, int iBytesPerLine, qboolean &bFrameSkipped)
{
/*
if (hBink)
{
bFrameSkipped = BinkDoFrame(hBink);
if (!bFrameSkipped)
{
//extern cvar_t *r_speeds;
//int start,end;
//if ( r_speeds->integer )
//{
// start = Sys_Milliseconds();
//}
BinkCopyToBuffer( hBink, // HBINK bnk,
pbDestBuffer, // void* dest,
iBytesPerLine,//hBink->Width*4, // u32 destpitch (bytes, not pixels)
hBink->Height, // u32 destheight
0, // u32 destx
0, // u32 desty,
BINKSURFACE32R
//|BINKCOPYALL
|BINKCOPYNOSCALING // important, or you'll crash on half-height compressed videos now!
);
//if ( r_speeds->integer )
//{
// end = Sys_Milliseconds();
// Com_Printf( "BinkCopyToBuffer(): %i msec\n", end - start );
//}
}
// finished?
//
qboolean bStillPlaying = qtrue;
if (hBink->FrameNum == hBink->Frames)
{
bStillPlaying = qfalse; // finished
}
else
{
BinkNextFrame(hBink);
}
return bStillPlaying;
}
*/
return qfalse; // will only get here if some sort of error in Q3 logic (which does happen) so that this is called
// at the wrong time.
}
// called even if not fully opened, so check everything...
//
void VIDEO_Close(void)
{
/*
if (hBink)
{
#ifdef _DEBUG
BINKSUMMARY Summary;
BinkGetSummary(hBink, &Summary);
Com_DPrintf("\nBINK Playback Summary:\n\n");
Com_DPrintf("TotalTime: %d\n",Summary.TotalTime); //
Com_DPrintf("FileFrameRate: %d\n",Summary.FileFrameRate); // frame rate
Com_DPrintf("FileFrameRateDiv: %d\n",Summary.FileFrameRateDiv); // frame rate divisor
Com_DPrintf("FrameRate: %d\n",Summary.FrameRate); // frame rate
Com_DPrintf("FrameRateDiv: %d\n",Summary.FrameRateDiv); // frame rate divisor
Com_DPrintf("TotalOpenTime: %d\n",Summary.TotalOpenTime); // Time to open and prepare for decompression
Com_DPrintf("TotalFrames: %d\n",Summary.TotalFrames); // Total Frames
Com_DPrintf("TotalPlayedFrames: %d\n",Summary.TotalPlayedFrames); // Total Frames played
Com_DPrintf("SkippedFrames: %d\n",Summary.SkippedFrames); // Total number of skipped frames
Com_DPrintf("SkippedBlits: %d\n",Summary.SkippedBlits); // Total number of skipped blits
Com_DPrintf("SoundSkips: %d\n",Summary.SoundSkips); // Total number of sound skips
Com_DPrintf("TotalBlitTime: %d\n",Summary.TotalBlitTime); // Total time spent blitting
Com_DPrintf("TotalReadTime: %d\n",Summary.TotalReadTime); // Total time spent reading
Com_DPrintf("TotalVideoDecompTime: %d\n",Summary.TotalVideoDecompTime); // Total time spent decompressing video
Com_DPrintf("TotalAudioDecompTime: %d\n",Summary.TotalAudioDecompTime); // Total time spent decompressing audio
Com_DPrintf("TotalBackReadTime: %d\n",Summary.TotalBackReadTime); // Total time spent reading in background
Com_DPrintf("TotalReadSpeed: %d\n",Summary.TotalReadSpeed); // Total io speed (bytes/second)
Com_DPrintf("SlowestFrameTime: %d\n",Summary.SlowestFrameTime); // Slowest single frame time (ms)
Com_DPrintf("Slowest2FrameTime: %d\n",Summary.Slowest2FrameTime); // Second slowest single frame time (ms)
Com_DPrintf("SlowestFrameNum: %d\n",Summary.SlowestFrameNum); // Slowest single frame number
Com_DPrintf("Slowest2FrameNum: %d\n",Summary.Slowest2FrameNum); // Second slowest single frame number
Com_DPrintf("AverageDataRate: %d\n",Summary.AverageDataRate); // Average data rate of the movie
Com_DPrintf("AverageFrameSize: %d\n",Summary.AverageFrameSize); // Average size of the frame
Com_DPrintf("HighestMemAmount: %d\n",Summary.HighestMemAmount); // Highest amount of memory allocated
Com_DPrintf("TotalIOMemory: %d\n",Summary.TotalIOMemory); // Total extra memory allocated
Com_DPrintf("HighestIOUsed: %d\n",Summary.HighestIOUsed); // Highest extra memory actually used
Com_DPrintf("Highest1SecRate: %d\n",Summary.Highest1SecRate); // Highest 1 second rate
Com_DPrintf("Highest1SecFrame: %d\n",Summary.Highest1SecFrame); // Highest 1 second start frame
Com_DPrintf("\n");
#endif
BinkClose(hBink);
hBink = NULL;
SNDDMA_Activate();
}
if (hBinkFile)
{
CloseHandle(hBinkFile);
hBinkFile = NULL;
}
*/
}
/*
static qboolean VIDEO_Open2(char *psPathlessBaseName, qboolean qbInGame, qboolean qbTestOpenOnly, int iLanguageNumber)
{
char sLocalFilename[MAX_OSPATH];
// Get the Quake filesystem to see if it exists, and fill in some internal structs as to where it really is,
// and what offset (if PAK) etc...
//
Com_sprintf (sLocalFilename, sizeof(sLocalFilename), "video/%s.bik", psPathlessBaseName);
char *psActualFilename;
int iSeekOffset;
qboolean bResult = FS_GetExtendedInfo_FOpenFileRead(sLocalFilename, &psActualFilename, &iSeekOffset);
if (!bResult)
{
if (!qbTestOpenOnly)
{
Com_Printf(S_COLOR_RED"Couldn't open %s\n", sLocalFilename);
}
return qfalse;
}
if (qbTestOpenOnly)
return qtrue;
// Now re-open as a Windoze HANDLE, because Bink doesn't use FILE * types...
//
hBinkFile = CreateFile( psActualFilename, // LPCTSTR lpFileName, // pointer to name of the file
GENERIC_READ, // DWORD dwDesiredAccess, // access (read-write) mode
FILE_SHARE_READ, // DWORD dwShareMode, // share mode
NULL, // LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
OPEN_EXISTING, // DWORD dwCreationDisposition, // how to create
FILE_FLAG_SEQUENTIAL_SCAN,// DWORD dwFlagsAndAttributes, // file attributes
NULL // HANDLE hTemplateFile // handle to file with attributes to
);
if (hBinkFile == INVALID_HANDLE_VALUE)
{
Com_Printf(S_COLOR_RED"Error converting FILE* to HANDLE for Bink, file: %s\n", psActualFilename);
return qfalse;
}
// Opened ok, now seek the handle to the correct position for starting (ie if inside a PAK file etc)
//
DWORD dwFileOffset = SetFilePointer(hBinkFile, // HANDLE hFile, // handle of file
iSeekOffset,// LONG lDistanceToMove, // number of bytes to move file pointer
NULL, // PLONG lpDistanceToMoveHigh, // pointer to high-order DWORD of distance to move
FILE_BEGIN // DWORD dwMoveMethod // how to move
);
if (dwFileOffset != iSeekOffset)
{
VIDEO_Close();
Com_Printf( S_COLOR_RED"Error seeking to Bink video start (offset %d), file: %s\n", iSeekOffset,psActualFilename);
return qfalse;
}
// ok, I think we're ready...
//
if (!cls.soundStarted || s_soundStarted) // sound system not started (occurs in very first video), or sound desired
{
BinkSoundUseDirectSound(SNDDMA_GetDSHandle());
BinkSetSoundTrack(iLanguageNumber); // select the language anyway here, regardless of multi-lingual file or not
}
else
{
BinkSetSoundTrack(BINKNOSOUND);
}
// hBink = BinkOpen("d:\\kiss.bik",0);
hBink = BinkOpen((char *)hBinkFile,BINKFILEHANDLE | BINKSNDTRACK);
if (!hBink)
{
VIDEO_Close();
Com_Printf( S_COLOR_RED"Unrecognised video file: %s\n", psActualFilename);
return qfalse;
}
if (!s_soundStarted) // game running in silent mode?
{
VIDEO_Mute(qtrue);
}
return qtrue;
}
*/
// now modified to take different languages into account...
//
qboolean VIDEO_Open(char *psPathlessBaseName, qboolean qbInGame, qboolean qbTestOpenOnly, int iLanguageNumber)
{
/*
qboolean qbReturn = VIDEO_Open2(psPathlessBaseName, qbInGame, qbTestOpenOnly, iLanguageNumber);
if (qbReturn)
{
if (!qbTestOpenOnly && hBink)
{
// check we didn't try to (eg) select German audio on a file with 1 track (eg just music)
//
if (iLanguageNumber+1 > hBink->NumTracks)
{
VIDEO_Close();
return VIDEO_Open2(psPathlessBaseName, qbInGame, qbTestOpenOnly, 0);
}
}
}
return qbReturn;
*/
return qfalse;
}
//////////////// eof //////////////////

532
code/win32/win_wndproc.cpp Normal file
View File

@@ -0,0 +1,532 @@
// leave this as first line for PCH reasons...
//
#include "../server/exe_headers.h"
#include "../client/client.h"
#include "win_local.h"
// The only directly referenced keycode - the console key (which gives different ascii codes depending on locale)
#define CONSOLE_SCAN_CODE 0x29
WinVars_t g_wv;
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL (WM_MOUSELAST+1) // message that will be supported by the OS
#endif
static UINT MSH_MOUSEWHEEL;
// Console variables that we need to access from this module
cvar_t *vid_xpos; // X coordinate of window position
cvar_t *vid_ypos; // Y coordinate of window position
cvar_t *sr_fullscreen;
#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
static qboolean s_alttab_disabled;
static void WIN_DisableAltTab( void )
{
if ( s_alttab_disabled )
return;
if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
{
RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
}
else
{
BOOL old;
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
}
s_alttab_disabled = qtrue;
}
static void WIN_EnableAltTab( void )
{
if ( s_alttab_disabled )
{
if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
{
UnregisterHotKey( 0, 0 );
}
else
{
BOOL old;
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
}
s_alttab_disabled = qfalse;
}
}
/*
==================
VID_AppActivate
==================
*/
static void VID_AppActivate(BOOL fActive, BOOL minimize)
{
g_wv.isMinimized = minimize;
Key_ClearStates(); // FIXME!!!
// we don't want to act like we're active if we're minimized
if (fActive && !g_wv.isMinimized )
{
g_wv.activeApp = qtrue;
}
else
{
g_wv.activeApp = qfalse;
}
// minimize/restore mouse-capture on demand
if (!g_wv.activeApp )
{
IN_Activate (qfalse);
}
else
{
IN_Activate (qtrue);
}
}
static byte virtualKeyConvert[0x92][2] =
{
{ 0, 0 },
{ A_MOUSE1, A_MOUSE1 }, // VK_LBUTTON 01 Left mouse button
{ A_MOUSE2, A_MOUSE2 }, // VK_RBUTTON 02 Right mouse button
{ 0, 0 }, // VK_CANCEL 03 Control-break processing
{ A_MOUSE3, A_MOUSE3 }, // VK_MBUTTON 04 Middle mouse button (three-button mouse)
{ A_MOUSE4, A_MOUSE4 }, // VK_XBUTTON1 05 Windows 2000/XP: X1 mouse button
{ A_MOUSE5, A_MOUSE5 }, // VK_XBUTTON2 06 Windows 2000/XP: X2 mouse button
{ 0, 0 }, // 07 Undefined
{ A_BACKSPACE, A_BACKSPACE }, // VK_BACK 08 BACKSPACE key
{ A_TAB, A_TAB }, // VK_TAB 09 TAB key
{ 0, 0 }, // 0A Reserved
{ 0, 0 }, // 0B Reserved
{ A_KP_5, 0 }, // VK_CLEAR 0C CLEAR key
{ A_ENTER, A_KP_ENTER }, // VK_RETURN 0D ENTER key
{ 0, 0 }, // 0E Undefined
{ 0, 0 }, // 0F Undefined
{ A_SHIFT, A_SHIFT }, // VK_SHIFT 10 SHIFT key
{ A_CTRL, A_CTRL }, // VK_CONTROL 11 CTRL key
{ A_ALT, A_ALT }, // VK_MENU 12 ALT key
{ A_PAUSE, A_PAUSE }, // VK_PAUSE 13 PAUSE key
{ A_CAPSLOCK, A_CAPSLOCK }, // VK_CAPITAL 14 CAPS LOCK key
{ 0, 0 }, // VK_KANA 15 IME Kana mode
{ 0, 0 }, // 16 Undefined
{ 0, 0 }, // VK_JUNJA 17 IME Junja mode
{ 0, 0 }, // VK_FINAL 18 IME final mode
{ 0, 0 }, // VK_KANJI 19 IME Kanji mode
{ 0, 0 }, // 1A Undefined
{ A_ESCAPE, A_ESCAPE }, // VK_ESCAPE 1B ESC key
{ 0, 0 }, // VK_CONVERT 1C IME convert
{ 0, 0 }, // VK_NONCONVERT 1D IME nonconvert
{ 0, 0 }, // VK_ACCEPT 1E IME accept
{ 0, 0 }, // VK_MODECHANGE 1F IME mode change request
{ A_SPACE, A_SPACE }, // VK_SPACE 20 SPACEBAR
{ A_KP_9, A_PAGE_UP }, // VK_PRIOR 21 PAGE UP key
{ A_KP_3, A_PAGE_DOWN }, // VK_NEXT 22 PAGE DOWN key
{ A_KP_1, A_END }, // VK_END 23 END key
{ A_KP_7, A_HOME }, // VK_HOME 24 HOME key
{ A_KP_4, A_CURSOR_LEFT }, // VK_LEFT 25 LEFT ARROW key
{ A_KP_8, A_CURSOR_UP }, // VK_UP 26 UP ARROW key
{ A_KP_6, A_CURSOR_RIGHT }, // VK_RIGHT 27 RIGHT ARROW key
{ A_KP_2, A_CURSOR_DOWN }, // VK_DOWN 28 DOWN ARROW key
{ 0, 0 }, // VK_SELECT 29 SELECT key
{ 0, 0 }, // VK_PRINT 2A PRINT key
{ 0, 0 }, // VK_EXECUTE 2B EXECUTE key
{ A_PRINTSCREEN, A_PRINTSCREEN }, // VK_SNAPSHOT 2C PRINT SCREEN key
{ A_KP_0, A_INSERT }, // VK_INSERT 2D INS key
{ A_KP_PERIOD, A_DELETE }, // VK_DELETE 2E DEL key
{ 0, 0 }, // VK_HELP 2F HELP key
{ A_0, A_0 }, // 30 0 key
{ A_1, A_1 }, // 31 1 key
{ A_2, A_2 }, // 32 2 key
{ A_3, A_3 }, // 33 3 key
{ A_4, A_4 }, // 34 4 key
{ A_5, A_5 }, // 35 5 key
{ A_6, A_6 }, // 36 6 key
{ A_7, A_7 }, // 37 7 key
{ A_8, A_8 }, // 38 8 key
{ A_9, A_9 }, // 39 9 key
{ 0, 0 }, // 3A Undefined
{ 0, 0 }, // 3B Undefined
{ 0, 0 }, // 3C Undefined
{ 0, 0 }, // 3D Undefined
{ 0, 0 }, // 3E Undefined
{ 0, 0 }, // 3F Undefined
{ 0, 0 }, // 40 Undefined
{ A_CAP_A, A_CAP_A }, // 41 A key
{ A_CAP_B, A_CAP_B }, // 42 B key
{ A_CAP_C, A_CAP_C }, // 43 C key
{ A_CAP_D, A_CAP_D }, // 44 D key
{ A_CAP_E, A_CAP_E }, // 45 E key
{ A_CAP_F, A_CAP_F }, // 46 F key
{ A_CAP_G, A_CAP_G }, // 47 G key
{ A_CAP_H, A_CAP_H }, // 48 H key
{ A_CAP_I, A_CAP_I }, // 49 I key
{ A_CAP_J, A_CAP_J }, // 4A J key
{ A_CAP_K, A_CAP_K }, // 4B K key
{ A_CAP_L, A_CAP_L }, // 4C L key
{ A_CAP_M, A_CAP_M }, // 4D M key
{ A_CAP_N, A_CAP_N }, // 4E N key
{ A_CAP_O, A_CAP_O }, // 4F O key
{ A_CAP_P, A_CAP_P }, // 50 P key
{ A_CAP_Q, A_CAP_Q }, // 51 Q key
{ A_CAP_R, A_CAP_R }, // 52 R key
{ A_CAP_S, A_CAP_S }, // 53 S key
{ A_CAP_T, A_CAP_T }, // 54 T key
{ A_CAP_U, A_CAP_U }, // 55 U key
{ A_CAP_V, A_CAP_V }, // 56 V key
{ A_CAP_W, A_CAP_W }, // 57 W key
{ A_CAP_X, A_CAP_X }, // 58 X key
{ A_CAP_Y, A_CAP_Y }, // 59 Y key
{ A_CAP_Z, A_CAP_Z }, // 5A Z key
{ 0, 0 }, // VK_LWIN 5B Left Windows key (Microsoft® Natural® keyboard)
{ 0, 0 }, // VK_RWIN 5C Right Windows key (Natural keyboard)
{ 0, 0 }, // VK_APPS 5D Applications key (Natural keyboard)
{ 0, 0 }, // 5E Reserved
{ 0, 0 }, // VK_SLEEP 5F Computer Sleep key
{ A_KP_0, A_KP_0 }, // VK_NUMPAD0 60 Numeric keypad 0 key
{ A_KP_1, A_KP_1 }, // VK_NUMPAD1 61 Numeric keypad 1 key
{ A_KP_2, A_KP_2 }, // VK_NUMPAD2 62 Numeric keypad 2 key
{ A_KP_3, A_KP_3 }, // VK_NUMPAD3 63 Numeric keypad 3 key
{ A_KP_4, A_KP_4 }, // VK_NUMPAD4 64 Numeric keypad 4 key
{ A_KP_5, A_KP_5 }, // VK_NUMPAD5 65 Numeric keypad 5 key
{ A_KP_6, A_KP_6 }, // VK_NUMPAD6 66 Numeric keypad 6 key
{ A_KP_7, A_KP_7 }, // VK_NUMPAD7 67 Numeric keypad 7 key
{ A_KP_8, A_KP_8 }, // VK_NUMPAD8 68 Numeric keypad 8 key
{ A_KP_9, A_KP_9 }, // VK_NUMPAD9 69 Numeric keypad 9 key
{ A_MULTIPLY, A_MULTIPLY }, // VK_MULTIPLY 6A Multiply key
{ A_KP_PLUS, A_KP_PLUS }, // VK_ADD 6B Add key
{ 0, 0 }, // VK_SEPARATOR 6C Separator key
{ A_KP_MINUS, A_KP_MINUS }, // VK_SUBTRACT 6D Subtract key
{ A_KP_PERIOD, A_KP_PERIOD }, // VK_DECIMAL 6E Decimal key
{ A_DIVIDE, A_DIVIDE }, // VK_DIVIDE 6F Divide key
{ A_F1, A_F1 }, // VK_F1 70 F1 key
{ A_F2, A_F2 }, // VK_F2 71 F2 key
{ A_F3, A_F3 }, // VK_F3 72 F3 key
{ A_F4, A_F4 }, // VK_F4 73 F4 key
{ A_F5, A_F5 }, // VK_F5 74 F5 key
{ A_F6, A_F6 }, // VK_F6 75 F6 key
{ A_F7, A_F7 }, // VK_F7 76 F7 key
{ A_F8, A_F8 }, // VK_F8 77 F8 key
{ A_F9, A_F9 }, // VK_F9 78 F9 key
{ A_F10, A_F10 }, // VK_F10 79 F10 key
{ A_F11, A_F11 }, // VK_F11 7A F11 key
{ A_F12, A_F12 }, // VK_F12 7B F12 key
{ 0, 0 }, // VK_F13 7C F13 key
{ 0, 0 }, // VK_F14 7D F14 key
{ 0, 0 }, // VK_F15 7E F15 key
{ 0, 0 }, // VK_F16 7F F16 key
{ 0, 0 }, // VK_F17 80H F17 key
{ 0, 0 }, // VK_F18 81H F18 key
{ 0, 0 }, // VK_F19 82H F19 key
{ 0, 0 }, // VK_F20 83H F20 key
{ 0, 0 }, // VK_F21 84H F21 key
{ 0, 0 }, // VK_F22 85H F22 key
{ 0, 0 }, // VK_F23 86H F23 key
{ 0, 0 }, // VK_F24 87H F24 key
{ 0, 0 }, // 88 Unassigned
{ 0, 0 }, // 89 Unassigned
{ 0, 0 }, // 8A Unassigned
{ 0, 0 }, // 8B Unassigned
{ 0, 0 }, // 8C Unassigned
{ 0, 0 }, // 8D Unassigned
{ 0, 0 }, // 8E Unassigned
{ 0, 0 }, // 8F Unassigned
{ A_NUMLOCK, A_NUMLOCK }, // VK_NUMLOCK 90 NUM LOCK key
{ A_SCROLLLOCK, A_SCROLLLOCK } // VK_SCROLL 91
};
/*
=======
MapKey
Map from windows to quake keynums
=======
*/
static int MapKey (ulong key, word wParam)
{
ulong result, scan, extended;
// Check for the console key (hard code to the key you would expect)
scan = ( key >> 16 ) & 0xff;
if(scan == CONSOLE_SCAN_CODE)
{
return(A_CONSOLE);
}
// Try to convert the virtual key directly
result = 0;
extended = (key >> 24) & 1;
if(wParam > 0 && wParam <= VK_SCROLL)
{
result = virtualKeyConvert[wParam][extended];
}
// Get the unshifted ascii code (if any)
if(!result)
{
result = MapVirtualKey(wParam, 2) & 0xff;
}
// Output any debug prints
// if(in_debug && in_debug->integer & 1)
// {
// Com_Printf("WM_KEY: %x : %x : %x\n", key, wParam, result);
// }
return(result);
}
/*
====================
MainWndProc
main window procedure
====================
*/
#define WM_BUTTON4DOWN (WM_MOUSELAST+2)
#define WM_BUTTON4UP (WM_MOUSELAST+3)
#define MK_BUTTON4L 0x0020
#define MK_BUTTON4R 0x0040
LONG WINAPI MainWndProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
byte code;
if ( uMsg == MSH_MOUSEWHEEL )
{
if ( ( ( int ) wParam ) > 0 )
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELUP, qtrue, 0, NULL );
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELUP, qfalse, 0, NULL );
}
else
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELDOWN, qtrue, 0, NULL );
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELDOWN, qfalse, 0, NULL );
}
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
switch (uMsg)
{
case WM_MOUSEWHEEL:
//
//
// this chunk of code theoretically only works under NT4 and Win98
// since this message doesn't exist under Win95
//
if ( ( short ) HIWORD( wParam ) > 0 )
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELUP, qtrue, 0, NULL );
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELUP, qfalse, 0, NULL );
}
else
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELDOWN, qtrue, 0, NULL );
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELDOWN, qfalse, 0, NULL );
}
break;
case WM_CREATE:
g_wv.hWnd = hWnd;
vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
sr_fullscreen = Cvar_Get ("r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");
if ( sr_fullscreen->integer )
{
WIN_DisableAltTab();
}
else
{
WIN_EnableAltTab();
}
break;
#if 0
case WM_DISPLAYCHANGE:
Com_DPrintf( "WM_DISPLAYCHANGE\n" );
// we need to force a vid_restart if the user has changed
// their desktop resolution while the game is running,
// but don't do anything if the message is a result of
// our own calling of ChangeDisplaySettings
if ( com_insideVidInit ) {
break; // we did this on purpose
}
// something else forced a mode change, so restart all our gl stuff
Cbuf_AddText( "vid_restart\n" );
break;
#endif
case WM_DESTROY:
// let sound and input know about this?
g_wv.hWnd = NULL;
if ( sr_fullscreen->integer )
{
WIN_EnableAltTab();
}
break;
case WM_CLOSE:
Cbuf_ExecuteText( EXEC_APPEND, "quit" );
break;
case WM_ACTIVATE:
{
int fActive, fMinimized;
fActive = LOWORD(wParam);
fMinimized = (BOOL) HIWORD(wParam);
VID_AppActivate( fActive != WA_INACTIVE, fMinimized);
SNDDMA_Activate( fActive != WA_INACTIVE && !fMinimized );
}
break;
case WM_MOVE:
{
int xPos, yPos;
RECT r;
int style;
if (!sr_fullscreen->integer )
{
xPos = (short) LOWORD(lParam); // horizontal position
yPos = (short) HIWORD(lParam); // vertical position
r.left = 0;
r.top = 0;
r.right = 1;
r.bottom = 1;
style = GetWindowLong( hWnd, GWL_STYLE );
AdjustWindowRect( &r, style, FALSE );
Cvar_SetValue( "vid_xpos", xPos + r.left);
Cvar_SetValue( "vid_ypos", yPos + r.top);
vid_xpos->modified = qfalse;
vid_ypos->modified = qfalse;
if ( g_wv.activeApp )
{
IN_Activate (qtrue);
}
}
}
break;
// this is complicated because Win32 seems to pack multiple mouse events into
// one update sometimes, so we always check all states and look for events
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
case WM_BUTTON4DOWN:
case WM_BUTTON4UP:
{
int temp;
temp = 0;
if (wParam & MK_LBUTTON)
temp |= 1;
if (wParam & MK_RBUTTON)
temp |= 2;
if (wParam & MK_MBUTTON)
temp |= 4;
if (wParam & MK_BUTTON4L)
temp |= 8;
if (wParam & MK_BUTTON4R)
temp |= 16;
IN_MouseEvent (temp);
}
break;
case WM_SYSCOMMAND:
if ( (wParam&0xFFF0) == SC_SCREENSAVE || (wParam&0xFFF0) == SC_MONITORPOWER)
{
return 0;
}
break;
case WM_SYSKEYDOWN:
if ( wParam == VK_RETURN ) //alt-enter
{
if ( sr_fullscreen && !ge || (ge->GameAllowedToSaveHere() && !(cls.keyCatchers&KEYCATCH_UI)) )
{//okay, don't switch if the game is running while in a cinematic or in the menu
Cvar_SetValue( "r_fullscreen", !sr_fullscreen->integer );
Cbuf_AddText( "vid_restart\n" );
}
return 0;
}
// fall through
case WM_KEYDOWN:
code = MapKey( lParam, wParam );
if(code)
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, code, qtrue, 0, NULL );
}
break;
case WM_SYSKEYUP:
case WM_KEYUP:
code = MapKey( lParam, wParam );
if(code)
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, code, qfalse, 0, NULL );
}
break;
case WM_CHAR:
if(((lParam >> 16) & 0xff) != CONSOLE_SCAN_CODE)
{
Sys_QueEvent( g_wv.sysMsgTime, SE_CHAR, wParam, 0, 0, NULL );
}
// Output any debug prints
// if(in_debug && in_debug->integer & 2)
// {
// Com_Printf("WM_CHAR: %x\n", wParam);
// }
break;
case WM_POWERBROADCAST:
if (wParam == PBT_APMQUERYSUSPEND)
{
#ifndef FINAL_BUILD
Com_Printf("Cannot go into hibernate / standby mode while game is running!\n");
#endif
return BROADCAST_QUERY_DENY;
}
break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}

101
code/win32/winquake.rc Normal file
View File

@@ -0,0 +1,101 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) 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
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "starwars.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "AutoVersion.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
PRODUCTVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "Raven Software"
VALUE "CompanyName", "Activision Inc"
VALUE "FileDescription", "Jedi Academy SP"
VALUE "FileVersion", VERSION_STRING
VALUE "InternalName", "JASP"
VALUE "LegalCopyright", "Copyright (C) 2003"
VALUE "OriginalFilename", "jasp.exe"
VALUE "ProductName", "Jedi Knight®: Jedi Academy"
VALUE "ProductVersion", VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,126 @@
/*
* UNPUBLISHED -- Rights reserved under the copyright laws of the
* United States. Use of a copyright notice is precautionary only and
* does not imply publication or disclosure.
*
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
*/
#ifndef __XBOX_TEXTURE_MAN_H__
#define __XBOX_TEXTURE_MAN_H__
#include "glw_win_dx8.h"
#include <xtl.h>
// Texture allocator that never frees anything, just grows until it's totally reset:
class StaticTextureAllocator
{
public:
StaticTextureAllocator( void ) { }
void Initialize( unsigned long size )
{
base = (unsigned char *) D3D_AllocContiguousMemory( size, 0 );
allocPoint = 0;
poolSize = size;
maxAlloc = 0;
swappedSize = 0;
swappedPoint = 0;
}
// No bookkeeping necessary, texNum is unused:
void *Allocate( unsigned long size, GLuint texNum )
{
#ifndef FINAL_BUILD
if( allocPoint + size > poolSize )
throw "Static texture pool full";
#endif
// Current location:
void *retVal = base + allocPoint;
// Advance, then round up:
allocPoint += size;
allocPoint = (allocPoint + 127) & ~127;
#ifndef FINAL_BUILD
if( allocPoint > maxAlloc )
maxAlloc = allocPoint;
#endif
return retVal;
}
void Reset( void )
{
// Just move our allocation marker back to the start:
allocPoint = 0;
}
// This is used by the bink code to make room for a giant texture
// that doesn't need to live at the same time as any others
void SwapTextureMemory( unsigned long size )
{
assert( !swappedPoint && !swappedSize && (size < poolSize) );
// Save off old texturePoint:
swappedPoint = allocPoint;
swappedSize = size;
// Reset texture pool to the beginning of the block:
allocPoint = 0;
// Save whatever's there now:
DWORD dwWritten = 0;
HANDLE h = CreateFile( "Z:\\texswap", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
assert( h != INVALID_HANDLE_VALUE );
if( !WriteFile( h, base, size, &dwWritten, NULL ) || (dwWritten != size) )
assert( 0 );
CloseHandle( h );
}
void UnswapTextureMemory( void )
{
assert( swappedSize );
// Read back the data we dumped out before:
DWORD dwRead = 0;
HANDLE h = CreateFile( "Z:\\texswap", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
assert( h != INVALID_HANDLE_VALUE );
if( !ReadFile( h, base, swappedSize, &dwRead, NULL ) || (dwRead != swappedSize) )
assert( 0 );
CloseHandle( h );
// Reset texture point
allocPoint = swappedPoint;
swappedPoint = 0;
swappedSize = 0;
}
unsigned long Size( void )
{
return allocPoint;
}
private:
unsigned char *base;
unsigned long allocPoint;
unsigned long poolSize;
unsigned long maxAlloc;
// Extra bookkeeping for Bink texture nastiness:
unsigned long swappedSize;
unsigned long swappedPoint;
};
// Global texture allocators:
extern StaticTextureAllocator gTextures;
#endif