Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Fri Jul 30, 2010 10:08 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 35 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Project: Doom 3 MetaMod
PostPosted: Sat Oct 15, 2005 1:37 am 
Offline
has joined the game

Joined: Tue Oct 11, 2005 5:42 pm
Posts: 27
Doom 3 MetaMod

I'm writing a metamod for the Doom3 engine.

A brief description of DMM:
Quote:
Doom MetaMod (DMM) is a Doom3 modification that acts as a node between the engine and game mod, allowing plugins to be loaded which can change normally inaccessible game behavior or add new functionality.


The system uses SourceHook. If you've ever written a plugin for MetaMod:Source for the Half-Life2 engine, you are already familiar with SourceHook. This allows you to hook any virtual function you desire, multiple times if necessary. Since the Doom interface is primarly virtual functions, this works perfect. You can declare a "hook" of say some function Printf() in idGame, and when that function is called anywhere your function is called. Your function can choose to just observe this event, modify it, or completely override the original Printf() call (ie, you can stop the real function from being called if you want).

The website for DMM is: http://doommod.sf.net/
DMM is open source, and released under the GPL, as are plugins.
Currently I have not released any code, but it does work.

Screenshots are available here: http://doommod.sf.net/ss/
There are only two at the moment, shows very basic DMM interface (1 plugin is loaded called dmm_stub).

A more detailed description is available at: http://doommod.sourceforge.net/index.php?nav=whatisit
You'll have to forgive me if anything there is inaccurate relating to the engine setup (please correct me if I'm wrong), I'm fairly new to the Doom engine, but I'm a veteran to C/C++.

In any event, currently I'm trying to rebuild the SDK. As many of you know, the code is quite heavily coupled. Therefore if you wanted your plugin to say, deal with some physics thing, you may have to include the headers for the physics code and possibly compile and link the core physics implementation.

Breaking up the SDK is a primary concern for me at this point in development; it is key to get an SDK where the headers can be easily used by plugins, otherwise the benefit of plugins greatly decreases. As of now (about 2 days work with a friend of mine, CyberMind, who created a similar project Quake3 MultiMod for quake3 http://q3mm.org/ ) I have 74 SDK files split off and operating properly.

I do need help though. As you guys are coders for the Doom engine, what parts of the SDK do you feel are critical to break off and fix? I have idLib almost done, as well as things like idGame and the like.

I'm also open to suggestions and criticisms, this is my first time attempting to implement any type of "metamod" system (or any game for that matter). :)

Note: I'm hoping creating DMM and getting it out to you guys will really help in the development of new mods (well plugins would be the word for it with DMM). I've noticed it's very difficult at this time to create a small mod, such as the flashlight one, and use other smaller mods alongside it, such as the infinite run or something similar. I beleive this system would bring modularity to the mod community, and help produce quality works that are easy to distribute and use.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 15, 2005 2:06 am 
Offline
picked up 100 armour

Joined: Sat Jan 15, 2005 4:52 am
Posts: 107
I'm not familiar with sourcehook, but will it be possible to abstract this so that it can run on any OS? It would be a pity if it was windows-only...


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 15, 2005 2:42 am 
Offline
has joined the game

Joined: Tue Oct 11, 2005 5:42 pm
Posts: 27
Tenko wrote:
I'm not familiar with sourcehook, but will it be possible to abstract this so that it can run on any OS? It would be a pity if it was windows-only...


Actually I'm running Gentoo Linux. I have not yet ported DMM to Windows (there should only be a few small changes), SourceHook however is fully compatible with both Windows and Linux.

SourceHook is easy to use. Here's a code segment from my dmm_stub plugin which intercepts any calls to idCommon->Printf().

Code:
SH_DECL_HOOK0_void_vafmt(idCommon, Printf, SH_NOATTRIB, 0);

void test(const char* msg) {
   printf("[dmm_stub] intercepted console message \"%s\"\n", msg);
   RETURN_META(MRES_IGNORED);
}


/*
*   The DMM plugin entry point.
*   Called when the plugin is loaded.
*/
C_DLLEXPORT void dmm_main(struct plugin_info_t** pinfo, struct dmm_t* dmm_api, int unid) {
   /*
    *   Initialize the plugin data structures - this is required.
    */
   PLUGIN_INIT();

   SH_ADD_HOOK_STATICFUNC(idCommon, Printf, dmm.engine->common, test, 0);
}


The first line:
Code:
SH_DECL_HOOK0_void_vafmt(idCommon, Printf, SH_NOATTRIB, 0);

Creates a compile-time function which will handle how to deal with Printf() calls.

The line:
Code:
SH_ADD_HOOK_STATICFUNC(idCommon, Printf, dmm.engine->common, test, 0);

Is where my plugin tells SourceHook that I want to intercept idCommon->Printf() calls. My custom function I want to be called before the real Printf() is test().

The line:
Code:
RETURN_META(MRES_IGNORED);

Tells SourceHook that I do not want to stop the real Printf() from being called. There are a few different return macros which allow you to do things like stop the real Printf() from being called, or to override what the real Printf() return should be (obviously there is no return for a void function, but it's useful for functions that return information you want to handle yourself).

It's not too difficult after you step in and hook two or three functions, you get the hang of it.

Their official documentation is at: http://www.sourcemm.net/?go=docs&doc=coding
Most of it is relevant to DMM, except for a few of the "Other Macros" and "Global Variables" which are specific to MetaMod:Source.

It's a very powerful system, especially for Doom where virtual functions are all over the place :)


Last edited by para- on Sun Oct 16, 2005 10:02 pm, edited 2 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 16, 2005 7:15 pm 
Offline
picked up 200 ammo
User avatar

Joined: Mon Feb 07, 2005 10:07 pm
Posts: 226
Location: Welly, NZ
this sounds awesome. sure we will have to make most of the methods on the SDK classes virtual but they really should be anyway. good work.

_________________
shoot first, edit later.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 16, 2005 10:18 pm 
Offline
found a secret

Joined: Wed Sep 08, 2004 8:48 am
Posts: 562
Can you tell us how this exactly works? I don't want to look to the code right now, just to see how it works. One point I'm really interested in is, wether it is possible to also hook into functions that are inaccessible because we don't have the sourcecode for it. From your description here in the postings it is not clear to me what exactly is possible and what not.

It still sounds pretty cool to me. :)


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Sun Oct 16, 2005 10:56 pm 
Offline
has joined the game

Joined: Tue Oct 11, 2005 5:42 pm
Posts: 27
sparhawk wrote:
Can you tell us how this exactly works? I don't want to look to the code right now, just to see how it works. One point I'm really interested in is, wether it is possible to also hook into functions that are inaccessible because we don't have the sourcecode for it. From your description here in the postings it is not clear to me what exactly is possible and what not.

It still sounds pretty cool to me. :)


I didn't write SourceHook (the part of the code that's responsible for actually seeking out and modifying the vtable pointers), but from what the author tells me you can hook any function where you have:
  1. a virtual function you want to hook
  2. the function prototype (in the SDK headers)
  3. a pointer to an instance of the object you want to hook

Most of the stuff from the engine API are in the form of virtual functions, as is the game API.

If you don't have the SDK handy, here's a real quick breakdown of those.

The game API:
Code:
class idGame {
public:
   virtual                  ~idGame() {}
   virtual void            Init( void ) = 0;
   virtual void            Shutdown( void ) = 0;
   virtual void            SetLocalClient( int clientNum ) = 0;
   virtual const idDict *      SetUserInfo( int clientNum, const idDict &userInfo, bool isClient, bool canModify ) = 0;
   virtual const idDict *      GetUserInfo( int clientNum ) = 0;
   virtual void            ThrottleUserInfo( void ) = 0;
   virtual void            SetServerInfo( const idDict &serverInfo ) = 0;
   virtual const idDict &      GetPersistentPlayerInfo( int clientNum ) = 0;
   virtual void            SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo ) = 0;
   virtual void            InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed ) = 0;
   virtual bool            InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ) = 0;
   virtual void            SaveGame( idFile *saveGameFile ) = 0;
   virtual void            MapShutdown( void ) = 0;
   virtual void            CacheDictionaryMedia( const idDict *dict ) = 0;
   virtual void            SpawnPlayer( int clientNum ) = 0;
   virtual gameReturn_t      RunFrame( const usercmd_t *clientCmds ) = 0;
   virtual bool            Draw( int clientNum ) = 0;
   virtual escReply_t         HandleESC( idUserInterface **gui ) = 0;
   virtual idUserInterface *   StartMenu() = 0;
   virtual const char *      HandleGuiCommands( const char *menuCommand ) = 0;
   virtual allowReply_t      ServerAllowClient( int numClients, const char *IP, const char *guid, const char *password, char reason[MAX_STRING_CHARS] ) = 0;
   virtual void            ServerClientConnect( int clientNum ) = 0;
   virtual void            ServerClientBegin( int clientNum ) = 0;
   virtual void            ServerClientDisconnect( int clientNum ) = 0;
   virtual void            ServerWriteInitialReliableMessages( int clientNum ) = 0;
   virtual void            ServerWriteSnapshot( int clientNum, int sequence, idBitMsg &msg, byte *clientInPVS, int numPVSClients ) = 0;
   virtual bool            ServerApplySnapshot( int clientNum, int sequence ) = 0;
   virtual void            ServerProcessReliableMessage( int clientNum, const idBitMsg &msg ) = 0;
   virtual void            ClientReadSnapshot( int clientNum, int sequence, const int gameFrame, const int gameTime, const int dupeUsercmds, const int aheadOfServer, const idBitMsg &msg ) = 0;
   virtual bool            ClientApplySnapshot( int clientNum, int sequence ) = 0;
   virtual void            ClientProcessReliableMessage( int clientNum, const idBitMsg &msg ) = 0;
   virtual gameReturn_t      ClientPrediction( int clientNum, const usercmd_t *clientCmds ) = 0;
   virtual void            SelectTimeGroup( int timeGroup ) = 0;
   virtual int               GetTimeGroupTime( int timeGroup ) = 0;
   virtual idStr            GetBestGameType( const char* map, const char* gametype ) = 0;
   virtual void            GetClientStats( int clientNum, char *data, const int len ) = 0;
   virtual void            SwitchTeam( int clientNum, int team ) = 0;
   virtual bool            DownloadRequest( const char *IP, const char *guid, const char *paks, char urls[ MAX_STRING_CHARS ] ) = 0;
};


Unfortunately game_local (the actual game class) inherits from this class and therefore the newly added functions are not virtual and unhookable. However, any engine to game calls will only use the above functions, as the engine doesn't know about how game_local is constructed. Therefore you should still have complete access to everything game-wise.

The engine code is much more in depth, but here's a quick rundown of that section. The following structure is given to a game from the engine when it is loaded:
Code:
typedef struct {

   int                     version;            // API version
   idSys *                  sys;               // non-portable system services
   idCommon *               common;               // common
   idCmdSystem *            cmdSystem;            // console command system
   idCVarSystem *            cvarSystem;            // console variable system
   idFileSystem *            fileSystem;            // file system
   idNetworkSystem *         networkSystem;         // network system
   idRenderSystem *         renderSystem;         // render system
   idSoundSystem *            soundSystem;         // sound system
   idRenderModelManager *      renderModelManager;      // render model manager
   idUserInterfaceManager *   uiManager;            // user interface manager
   idDeclManager *            declManager;         // declaration manager
   idAASFileManager *         AASFileManager;         // AAS file manager
   idCollisionModelManager *   collisionModelManager;   // collision model manager

} gameImport_t;


Most (if not all, I don't recall off the top of my head) are virtual interfaces. A quick example:
Code:
class idCommon {
public:
   virtual                  ~idCommon( void ) {}
   virtual void            Init( int argc, const char **argv, const char *cmdline ) = 0;
   virtual void            Shutdown( void ) = 0;
   virtual void            Quit( void ) = 0;
   virtual bool            IsInitialized( void ) const = 0;
   virtual void            Frame( void ) = 0;
   virtual void            GUIFrame( bool execCmd, bool network ) = 0;
   virtual void            Async( void ) = 0;
   virtual void            StartupVariable( const char *match, bool once ) = 0;
   virtual void            InitTool( const toolFlag_t tool, const idDict *dict ) = 0;
   virtual void            ActivateTool( bool active ) = 0;
   virtual void            WriteConfigToFile( const char *filename ) = 0;
   virtual void            WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd ) = 0;
   virtual void            BeginRedirect( char *buffer, int buffersize, void (*flush)( const char * ) ) = 0;
   virtual void            EndRedirect( void ) = 0;
   virtual void            SetRefreshOnPrint( bool set ) = 0;
   virtual void            Printf( const char *fmt, ... )id_attribute((format(printf,2,3))) = 0;
   virtual void            VPrintf( const char *fmt, va_list arg ) = 0;
   virtual void            DPrintf( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
   virtual void            Warning( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
   virtual void            DWarning( const char *fmt, ...) id_attribute((format(printf,2,3))) = 0;
   virtual void            PrintWarnings( void ) = 0;
   virtual void            ClearWarnings( const char *reason ) = 0;
   virtual void            Error( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
   virtual void            FatalError( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
   virtual const idLangDict *   GetLanguageDict( void ) = 0;
};


In my previous post I used an example where I was hooking idCommon::Printf() that was supplied by the engine from the gameImport_t structure :)

Hopefully this answers your question. It's pretty nice just about everything in terms of engine<->game interaction is provided in a virtual context, so DMM plugins should have the ability to do just about anything you would want to do with them.

The execution of DMM is relatively straight forward. Normally...
  1. the engine finds and loads the game, passing to it the engine API
  2. the game does all its startup stuff
  3. the game returns its API to the engine
With DMM in the mix, the procedure is modified to be:
  1. the engine finds and loads DMM, passing to it the engine API
  2. DMM finds and loads the game, passing to it the engine API
  3. the game does all its startup stuff
  4. the game returns its API to DMM
  5. DMM finds all plugins
  6. DMM loads a plugin, passing to it the engine API and game API
  7. go back to the previous step until all plugins are loaded
  8. DMM returns the game API to the engine
After loading, besides unloading on shutdown, DMM's job is to manage how plugins should behave (ie, paused, unpaused, etc) and provide a console interface for user control. Other smaller abilities may be added if required, but DMM is more-or-less idle after loading, the plugins are where all the "work" is done.

edit
sparhawk wrote:
One point I'm really interested in is, wether it is possible to also hook into functions that are inaccessible because we don't have the sourcecode for it.

You don't need the source code of a function to hook it, just an instance to the object and the prototype. For example, no source to the idCommon::Printf() function is available, but the prototype and instance is so it is hookable via SourceHook.

If you're interested in how SourceHook works, I have a very basic understanding of it. You can email the author for a detailed explaination, but this might help also...
To hook a function you must declare with a macro (see my previous post) what the function you are hooking is called, and the parameters and return types it takes. This macro creates a compile-time function which is used to determine how to proceed with handling the hook you make to it later.
When you actually declare a hook with SourceHook, SourceHook will go to the address in memory of the instance of the object you specify, and attempt to locate its vtable. Within the vtable it will look for the function you asked it to, and modify the pointer to the function normally called to point to SourceHook. When that function is called, since the vtable pointer is now directed at SourceHook, SourceHook will go through a list it has stored internally of what functions should be called at this point and in what order. Typically, there are pre-functions, the real function, then post-functions, called in that order. When you hook a function you can specify if you want it to be pre or post executed. Unhooking a function will instruct SourceHook to relocate the vtable entry it found previously, and modify the pointer to the hooked function to be the original pointer. This in effect causes no additional overhead of invoking a hooked function (except the little that is produced by SourceHook's internal list, and that of the actual functions that have to be invoked).


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 12:35 pm 
Offline
found a secret

Joined: Wed Sep 08, 2004 8:48 am
Posts: 562
para- wrote:
If you don't have the SDK handy, here's a real quick breakdown of those.


Actually I'm mostly interested in modifying the behaviour of renderSystem->CaptureRenderToFile, which is virtual, so that SourceHook should work. But I don't know if it will help me in this case, because I need to modify it's behaviour. As I understand this, I can only hook into a function to get a kind of trigger, when I want to do something extra, but it could still be helpfull to me.

Quote:
Hopefully this answers your question. It's pretty nice just about everything in terms of engine<->game interaction is provided in a virtual context, so DMM plugins should have the ability to do just about anything you would want to do with them.


We will see. :) What I need is to redirect the rendering, which is done to a file, into some memry block instead. Don't know if this would be possible.


Quote:
If you're interested in how SourceHook works, I have a very basic understanding of it. You can email the author for a detailed explaination, but this might help also...


I will definitley ask him, though I have some ideas how this may work. I once wrote such a function myself, but it was quite different. For my code I wrote a disassmbler, that disassmbled the first few instructions and move them to some other location. Then I overwrote the original code with a jump pointing to my own function and after I was finished with my own code, it called the original code which I saved before. But I doubt that SourceHook uses this approach, because it only works with virtual functions.

Thanks for the info! :)


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 5:58 pm 
Offline
has joined the game

Joined: Tue Oct 11, 2005 5:42 pm
Posts: 27
sparhawk wrote:
Actually I'm mostly interested in modifying the behaviour of renderSystem->CaptureRenderToFile, which is virtual, so that SourceHook should work. But I don't know if it will help me in this case, because I need to modify it's behaviour. As I understand this, I can only hook into a function to get a kind of trigger, when I want to do something extra, but it could still be helpfull to me.


In worst case you could just move entire functions from the SDK to your plugin, and modify them as needed, then tell tell SourceHook not to call the originial function, thereby replacing the SDK's version with your custom one. A benefit of this is that your compiled plugin would be much smaller than the SDK, and easily distrubutable if you wanted to hand it out.

sparhawk wrote:
I will definitley ask him, though I have some ideas how this may work. I once wrote such a function myself, but it was quite different. For my code I wrote a disassmbler, that disassmbled the first few instructions and move them to some other location. Then I overwrote the original code with a jump pointing to my own function and after I was finished with my own code, it called the original code which I saved before. But I doubt that SourceHook uses this approach, because it only works with virtual functions.


I'm relatively new to this area, seems very interesting to me. You may be talking about Detours, which is similar to SourceHook but can hook nonvirtual functions be overwriting a few opcodes in the function to make a jump to your custom one :)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 6:46 pm 
Offline
is connecting to Doom3world.org

Joined: Mon Oct 17, 2005 6:22 pm
Posts: 7
SourceHook only overwrites the function pointer in the vtable. It sets the vtable entry to its own function (generated by the SH_DECL_HOOK* macros), which iterates through the pre hooks and invokes them, then invokes the original function (if required), then iterates through the post hooks and invokes them.

Hooking non-virtual functions is a much bigger issue (as you said); you actually have to overwrite the function code to make it work properly. This can be difficult with weird functions (such as functions which start with a relative jmp). BAILOPAN has posted some posts about hooking non-virtual functions on http://www.sourcemod.net/devlog

I don't like overwriting code because it's very platform specific and it doesn't work with things like PaX in the kernel.

_________________
PM


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 9:43 pm 
Offline
found a secret

Joined: Wed Sep 08, 2004 8:48 am
Posts: 562
PM wrote:
Hooking non-virtual functions is a much bigger issue (as you said); you actually have to overwrite the function code to make it work properly. This can be difficult with weird functions (such as functions which start with a relative jmp).


Yes. That's why I wrote the dissasembler, but you are right about relative jumps. I didn't consider them at that time. It's not a big problem though, because nowadays most programs are compiled, and they have a standard header how they start in 99% of the time. Still to make it bulletproof it would need some polishing.

Quote:
BAILOPAN has posted some posts about hooking non-virtual functions on http://www.sourcemod.net/devlog

I don't like overwriting code because it's very platform specific and it doesn't work with things like PaX in the kernel.


Problem is, with my mod I get a performance hit of about 25 FPS on average, because I can't make a rendersnapshot into memory. If I could avoid this, I would have no second thoughts using such a a method. On Linux it's easier, because I could tell the users to create a small RAM disk, and then link the outputfile to it, so the overhead would be much less, but this doesn't work on Windows, because Doom 3 translates all pathnames and I can't change that, and there are no links like on UNIX to make that trick.


WOW! When I just wrote the above I had an idea, how I can use this SourceHook to actually achieve what I need! If the pathtranslation algorithm is also a virtual function, then I'm set. I can use a RAM disk, intercept the path translation, and redirect it to the RAM disk, without D3 getting aware of it. I will definitely try this, and see wether the performance improves or not. It might well be that the drivercode may cause most performanceoverhead, but I doubt it. I guess this is really the physical disc access, so I need to avoid it at all costs.

I guess that para- just saved my day. :)


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 5:39 pm 
Offline
found a secret

Joined: Wed Sep 08, 2004 8:48 am
Posts: 562
I just wanted to start evaluating this sourcehook stuff, so I downloaded the sourcode and moved the relevant files over to my project. But I get a lot of errors. I guess this is something simple like a define, a compilerswitch or some buildoption. Does anybody know how to resolve these? It also would be interesting to get a fully working copy of your current source if you don't mind. This could also help me determine how to include this code in my mod.

Code:
sourcehook.cpp
d:\SRC\darkmod_src\DarkMod\sourcehook.h(63) : warning C4005: 'vsnprintf' : macro redefinition
        d:\SRC\darkmod_src\idlib\str.h(44) : see previous definition of 'vsnprintf'
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(121) : warning C4346: '_Ufn::argument_type' : dependent name is not a type
        prefix with 'typename' to indicate a type
        e:\Programme\Microsoft Visual Studio\VC98\Include\functional(129) : see reference to class template instantiation 'std::unary_negate<_Ufn>' being compiled
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(121) : error C2923: 'std::unary_function' : '_Ufn::argument_type' is invalid as template argument '#1', type expected
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(125) : warning C4346: '_Ufn::argument_type' : dependent name is not a type
        prefix with 'typename' to indicate a type
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(125) : error C2061: syntax error : identifier 'argument_type'
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(138) : warning C4346: '_Bfn::first_argument_type' : dependent name is not a type
        prefix with 'typename' to indicate a type
        e:\Programme\Microsoft Visual Studio\VC98\Include\functional(147) : see reference to class template instantiation 'std::binary_negate<_Bfn>' being compiled
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(138) : error C2923: 'std::binary_function' : '_Bfn::first_argument_type' is invalid as template argument '#1', type expected
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(138) : warning C4346: '_Bfn::second_argument_type' : dependent name is not a type
        prefix with 'typename' to indicate a type
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(138) : error C2923: 'std::binary_function' : '_Bfn::second_argument_type' is invalid as template argument '#2', type expected
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(142) : warning C4346: '_Bfn::first_argument_type' : dependent name is not a type
        prefix with 'typename' to indicate a type
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(142) : error C2061: syntax error : identifier 'first_argument_type'
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(156) : warning C4346: '_Bfn::second_argument_type' : dependent name is not a type
        prefix with 'typename' to indicate a type
        e:\Programme\Microsoft Visual Studio\VC98\Include\functional(166) : see reference to class template instantiation 'std::binder1st<_Bfn>' being compiled
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(156) : error C2923: 'std::unary_function' : '_Bfn::second_argument_type' is invalid as template argument '#1', type expected
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(156) : warning C4346: '_Bfn::result_type' : dependent name is not a type
        prefix with 'typename' to indicate a type
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(156) : error C2923: 'std::unary_function' : '_Bfn::result_type' is invalid as template argument '#2', type expected
e:\Programme\Microsoft Visual Studio\VC98\Include\functional(158) : warning C4346: '_Bfn::first_argument_type' : dependent name is not a type
        prefix with 'typename' to indicate a type


There are a lot more, but I guess they will go away if I know how to remove the above errors.


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 7:24 pm 
Offline
is connecting to Doom3world.org

Joined: Mon Oct 17, 2005 6:22 pm
Posts: 7
Hmm. Hmm hmm.

1) It looks like you're not using the newest sourcehook version (which doesn't use STL due to libstdc++ version problems on linux).

2) What compiler are you using? I'd guess it's a MSVC 6 but I might be wrong. Anyway, I've never tested it with MSVC 6 and I'm almost sure it shouldn't work. gcc/mingw or MSVC >= 7 is ok.

3) It looks like idlib #define vsnprintf on linux; Just add an #ifndef vsnprintf .. #endif block around #define #vsnprintf that somewhere in sourcehook.h

_________________
PM


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 7:32 pm 
Offline
found a secret

Joined: Wed Sep 08, 2004 8:48 am
Posts: 562
PM wrote:
1) It looks like you're not using the newest sourcehook version (which doesn't use STL due to libstdc++ version problems on linux).


I guess the newest version is on CVS? I downloaded the sourcetar from the homepage which was version 1.02 or something, I think.

Quote:
2) What compiler are you using? I'd guess it's a MSVC 6 but I might be wrong. Anyway, I've never tested it with MSVC 6 and I'm almost sure it shouldn't work. gcc/mingw or MSVC >= 7 is ok.


Visual Studio NET 2003, but later I will use it on Linux as well. We will port the code once we have a stable version.

Quote:
3) It looks like idlib #define vsnprintf on linux; Just add an #ifndef vsnprintf .. #endif block around #define #vsnprintf that somewhere in sourcehook.h


Don't know if this is the problem, but I will take a look at this as well.

Thanks.


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 8:35 pm 
Offline
is connecting to Doom3world.org

Joined: Mon Oct 17, 2005 6:22 pm
Posts: 7
Well, you can get the newest SH files from http://www.tcwonline.org/cgi-bin/viewcv ... ourcehook/ . Note that the interface has changed so it won't work if you compiled the manager with the old version and the plugin with the new version.

Anyway, MSVC 2003 is 7.1 so that should be ok. Interesting, I don't have the doom3 sdk myself so I'm afraid I can't do much; do id use the STL? My best bet would be something in idlib making STL not compile or you messed something up =P

_________________
PM


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 8:51 pm 
Offline
has joined the game

Joined: Tue Oct 11, 2005 5:42 pm
Posts: 27
PM wrote:
My best bet would be something in idlib making STL not compile or you messed something up =P


sparhawk, take a look at src/idlib/Str.h.

Code:
#define strcmp                  idStr::Cmp              // use_idStr_Cmp
#define strncmp                 use_idStr_Cmpn
#define StrCmpN                 use_idStr_Cmpn
#define strcmpi                 use_idStr_Icmp
#define StrCmpI                 use_idStr_Icmp
#define stricmp                 idStr::Icmp             // use_idStr_Icmp
#define _stricmp                use_idStr_Icmp
#define strcasecmp              use_idStr_Icmp
#define strnicmp                use_idStr_Icmpn
#define _strnicmp               use_idStr_Icmpn
#define _memicmp                use_idStr_Icmpn
#define StrCmpNI                use_idStr_Icmpn
#define snprintf                use_idStr_snPrintf
#define _snprintf               use_idStr_snPrintf
#define vsnprintf               use_idStr_vsnPrintf
#define _vsnprintf              use_idStr_vsnPrintf


In either case, I hope to be making an initial release of DMM soon. I'm aiming for a release candidate before or during this weekend, which will include DMM, a full SDK header tree, precompiled SDK libraries, and an example plugin which hooks a function with SH. :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 19, 2005 11:13 am 
Offline
found a secret

Joined: Wed Sep 08, 2004 8:48 am
Posts: 562
I hope you keep us update here, because I think this is a very interesting project and could help a lot of coders.


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Wed Oct 19, 2005 1:27 pm 
Offline
found a secret

Joined: Wed Sep 08, 2004 8:48 am
Posts: 562
PM wrote:
Anyway, MSVC 2003 is 7.1 so that should be ok. Interesting, I don't have the doom3 sdk myself so I'm afraid I can't do much; do id use the STL? My best bet would be something in idlib making STL not compile or you messed something up =P


Now I found out what the problem was. I put it in the game DLL. After putting it in idLib and doing some minor changes, it compiles now. :)

On to the next step.


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Wed Oct 19, 2005 6:26 pm 
Offline
found a secret

Joined: Wed Sep 08, 2004 8:48 am
Posts: 562
In the above posting with the sample code, where did you get that PLUGIN_INIT() from? I couldn't find it anywhere.

Edit: I really would appreciate it if you could post a fully working sample, because it's rather frustrating to work with these bits and pieces. It seems that you already did a lot of backgroundwork which is not aparent from your posting, when I try to match it up with SourceHook. And I didn't really find a good documentation on how exactly SourceHook is supposed to be used.


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Wed Oct 19, 2005 9:45 pm 
Offline
has joined the game

Joined: Tue Oct 11, 2005 5:42 pm
Posts: 27
sparhawk wrote:
In the above posting with the sample code, where did you get that PLUGIN_INIT() from? I couldn't find it anywhere.

Edit: I really would appreciate it if you could post a fully working sample, because it's rather frustrating to work with these bits and pieces. It seems that you already did a lot of backgroundwork which is not aparent from your posting, when I try to match it up with SourceHook. And I didn't really find a good documentation on how exactly SourceHook is supposed to be used.


There really isn't any formal documentation for SourceHook (yet). PM originally wrote it specifically(?) for a similar MetaMod device for the Source Half-Life2 engine. This is apparent when you try to use SourceHook, you find it's implemented in such a way that you can assoicate various hooks with various "plugins" (quoted because the act of using modules isn't necessary, they simply denote modular behavior).

Anyhow, because of this background, documentation specific to SourceHook wasn't really needed. The author of SourceMM (the other metamod engine for Half-Life) worked closely with PM to integrate the features.

So, at this point the best way to figure out how to use it is either to look at the SourceMM code, my code (which I will be releasing within a few days, or at least putting in the pubicly viewable CVS), or the SourceHook code itself.

I can say this though, you'll need to declare a global pointer of type SourceHook::ISourceHook called g_SHPtr. This should point to an instance of SourceHook::CSourceHookImpl.

sparhawk wrote:
In the above posting with the sample code, where did you get that PLUGIN_INIT() from? I couldn't find it anywhere.


This macro is specific to DMM. I use it to help keep writing plugins simple, as plugin authors will not need to modify the code has.

Code:
#define PLUGIN_INIT()   do { \
                     memcpy(&dmm, dmm_api, sizeof(struct dmm_t)); \
                     g_SHPtr = dmm.sourcehook; \
                     g_PLID = unid; \
                     *pinfo = &plugin; \
                  } while (0)


The two g_* variables are specific to SourceHook, the rest is for DMM. I would put my code into the CVS so you can read through it (it's pretty clean and easy to skim through IMO), but I'm not quite ready to plublicly release anything yet. Once I tie up a few loose ends I'll make an initial commit and if you'd like, I'll paste the link here for you to check out. :)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 20, 2005 6:47 am 
Offline
is connecting to Doom3world.org

Joined: Mon Oct 17, 2005 6:22 pm
Posts: 7
Basically to make SourceHook work, you need:
1) #include "sourcehook.h"

2) Declare a global SourceHook::ISourceHook pointer called g_SHPtr (you can use a different name, but then you have to #define SH_GLOB_SHPTR [your global variable name] before including sourcehook.h)

3) Declare a global variable of type SourceHook::Plugin which should be called g_PLID (again, you can customize the name by #defining SH_GLOB_PLUGPTR before including sourcehook.h; also note that _PLUGPTR is somewhat misleading as it doesn't matter what it is - the only thing that matters is that it's different for each plugin). If your system is not plugin-based, just set this to 0. I might add a #define which disables plugin-functionality later.

4) Somewhere, you'll need to make an instance of the SourceHook::CSourceHookImpl and assign a pointer to it to the g_SHPtr variable (preferably BEFORE doing any SH_ADD_HOOK operation or similar; otherwise it will crash). I usually use a global but you can allocate it on the heap if you want.

5) Then "declare" the hooks outside of any functions (you can declare them in namespaces though) using the SH_DECL_HOOK* macros

6) Then you can add / remove hooks using the SH_ADD_HOOK* / SH_REMOVE_HOOK* macros.

If you're writing for SourceMM, it does step 1, 2, 3 and 4 for you (you have to use some macro though). I think Doom3 Metamod will provide similar functionality.

I hope I didn't forget anything; feel free to ask any questions.

_________________
PM


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 35 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Oneofthe8devilz and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group