Plan for Pat Wilson
by Pat Wilson · 01/27/2005 (11:59 am) · 14 comments
---+Roadblocks Galore
I seem to be running into roadblocks on all of my shiny projects lately. I have two projects which I have labled "shiny" because they were shiny objects which I started chasing after giggling regardless of weather or not they were technically useful. (Although, as my last .plan showed they can lead to good things)
---++Torque Effect Canvas
The last .plan was the beginning of the GuiEffectCanvas class, the first task was to make GuiCanvas behave well if subclassed which turned out to be just some minor changes regarding buffer swapping, adding 'virtual' to the methods etc. I'm not 100% happy with the changes regarding buffer swapping. I think I may put my brain together with the Almighty Garney and figure out a slightly cleaner way to do this. I have some ideas. Anyway, this lets you make a canvas which, any time setContent is called, it will transition from the current content, to the next content in various cool ways.
---++The World of Warcraft iTunes Plugin
The whole goal of this project was to be able to, from within World of Warcraft (or any fullscreen 3d program for that matter) to be able to hit a key, and see a display, and type in a regular expression, and have iTunes build a playlist from that and play it. This quickly exploded into a full-blown library for hijacking a Direct3D device.
---+++Direct3D Device Hijacking
My other project if you have been reading my blog is two part. One part is a Windows DLL that will hook in and hijack a Direct3D device from any D3D9 application, without having to copy a DLL into the directory or anything. This is nothing new, of course, people have been using it for wallhacks for a while. The new thing is that I can then render to this context from a DIFFERENT process. See, the way DLL memory sharing works is that a pointer which is valid in one process is not valid in another process. General memory security type thing which can probably be hacked around, but this is a much more elegant solution. The bottom line is, if I want to render to a context, it has to be in the process that created that context. My solution was to take the RPC stuff from TNL and use that to make calls in one process and execute them in another. Right now it actually uses TNL, in the future it will just use the call marshalling (I couldn't find a good link on this) stuff and use some kind of shared data buffer. It pretty much goes like this.
Start Loader Application (All this does is load my DLL into memory, think of this as the server)
Start D3D9 Application (This is now getting it's calls routed through an instance of my DLL, so I can see and hijack them all, think of each D3D9 app as a client)
When Present is called, it will say to the server:
This is, in essence, the start of the main loop for the code which uses the hijacked device, and it does it's rendering and whatnot. It then says back to the client:
This will work with OpenGL as well, I just haven't gotten to it. This development is currently slightly stalled while I mull over the inter-process communication interface. I originally wanted to make it a GFXDevice but I eventually decided GFX was too heavyweight, so I went with an API I did for a CS project called NinjaSquid, and I am thinking now that that was too heavyweight. The goal is to release this on another, exciting, unannounced section of GarageGames to use in whatever they want. I realize this will be the ultimate Wallhack creation tool, and I don't really support this, unless you are wallhacking in Americas Army, then it's ok. Just watch out though cuz aparantly, "The Army is angry, and we're coming for you." Yeah, whatever guys.
---+++Windows COM
The functional half of the plugin is to use the COM interface that Apple supplied for iTunes (I added a layer of abstraction so it can be ported to the Mac easily, don't worry) and wire that up to a nonexclusive, background DirectInput keyboard device so that it could sit and listen to keystrokes and detect when I wanted it to start parsing a regex. So I started just using the handy 'std::cin' and quickly was able to do stuff like type 'play', 'next' etc into a console and have it work. Sweet! Well then I came to using the IITLibraryPlaylist::Search function. I got out of memory returned. Huh, that's wierd. So I tried using it in a WSH with a Jscript. That worked fine. Try back in C++ it was trying to allocate 0xF786A1A6 bytes of memory...almost 4 gigs of memory. I have no idea what I did wrong, but since it is (in theory) instantiating the same code from Jscript as I am in C++, I can only assume that I did something very wrong with my COM usage in C++, so at 1AM last night I gave up on that and decided I'd get my ass off Ben's couch and go home.
---++Mostly Unrelated Rant
On a side note. What is it with SVN and having troubles if a file exists that is the same as one one in the repository. Here's the setup. Joe Maruschak set me up with a very useful test map texture (It's got the texture coordinates on it and it's a B&W checker grid. These artists have all these useful things! It's great!) for use with testing the texture coordinate distortion thing for the vector fields. So I had a non-versioned copy of TestMap.jpg in common. When I got home I realized I needed that, so I re-downloaded it, and added it to common, then added it to the SVN repo. When I got to work and tried to update, I got an error because a 'file of the same name exists'. Well DUH, try running a damn CRC check on it and see if it's the same damn file. Treat it like any other file, give me a DIFF if it's an ASCII file. Grrrr. It seems like we've come so far from CVS but we can't get anything that's competent unless we shell out for PerForce.
---++What's up with this formatting!?
You may have noticed there are an aweful lot of hyperlinks in this .plan and I seem to be adding strange formatting things. Why would I do such a thing? It's a secret that I will leave to the Almighty Garney to unveil at the proper time.
Wow that was a hell of a .plan. Lets see how many comments are on this one. I've noticed an inverse relationship between the length of my .plan and the number of comments. For those of you in the audience that are following along, all this development took place over 5 days, along with work on Marble Blast and Zap. I don't think that any of us at GarageGames ever "go home" with our brains.
I seem to be running into roadblocks on all of my shiny projects lately. I have two projects which I have labled "shiny" because they were shiny objects which I started chasing after giggling regardless of weather or not they were technically useful. (Although, as my last .plan showed they can lead to good things)
---++Torque Effect Canvas
The last .plan was the beginning of the GuiEffectCanvas class, the first task was to make GuiCanvas behave well if subclassed which turned out to be just some minor changes regarding buffer swapping, adding 'virtual' to the methods etc. I'm not 100% happy with the changes regarding buffer swapping. I think I may put my brain together with the Almighty Garney and figure out a slightly cleaner way to do this. I have some ideas. Anyway, this lets you make a canvas which, any time setContent is called, it will transition from the current content, to the next content in various cool ways.
---++The World of Warcraft iTunes Plugin
The whole goal of this project was to be able to, from within World of Warcraft (or any fullscreen 3d program for that matter) to be able to hit a key, and see a display, and type in a regular expression, and have iTunes build a playlist from that and play it. This quickly exploded into a full-blown library for hijacking a Direct3D device.
---+++Direct3D Device Hijacking
My other project if you have been reading my blog is two part. One part is a Windows DLL that will hook in and hijack a Direct3D device from any D3D9 application, without having to copy a DLL into the directory or anything. This is nothing new, of course, people have been using it for wallhacks for a while. The new thing is that I can then render to this context from a DIFFERENT process. See, the way DLL memory sharing works is that a pointer which is valid in one process is not valid in another process. General memory security type thing which can probably be hacked around, but this is a much more elegant solution. The bottom line is, if I want to render to a context, it has to be in the process that created that context. My solution was to take the RPC stuff from TNL and use that to make calls in one process and execute them in another. Right now it actually uses TNL, in the future it will just use the call marshalling (I couldn't find a good link on this) stuff and use some kind of shared data buffer. It pretty much goes like this.
Start Loader Application (All this does is load my DLL into memory, think of this as the server)
Start D3D9 Application (This is now getting it's calls routed through an instance of my DLL, so I can see and hijack them all, think of each D3D9 app as a client)
When Present is called, it will say to the server:
Quote:It then will sit and block on the Present call until the 'server' is done rendering to it.
Ok I am about to swap buffers, render to me.
This is, in essence, the start of the main loop for the code which uses the hijacked device, and it does it's rendering and whatnot. It then says back to the client:
Quote:And present is allowed to resume, and lo-and-behold, you have graphics rendered from one process onto another processes hijacked D3D9 device.
I am done rendering, continue execution.
This will work with OpenGL as well, I just haven't gotten to it. This development is currently slightly stalled while I mull over the inter-process communication interface. I originally wanted to make it a GFXDevice but I eventually decided GFX was too heavyweight, so I went with an API I did for a CS project called NinjaSquid, and I am thinking now that that was too heavyweight. The goal is to release this on another, exciting, unannounced section of GarageGames to use in whatever they want. I realize this will be the ultimate Wallhack creation tool, and I don't really support this, unless you are wallhacking in Americas Army, then it's ok. Just watch out though cuz aparantly, "The Army is angry, and we're coming for you." Yeah, whatever guys.
---+++Windows COM
The functional half of the plugin is to use the COM interface that Apple supplied for iTunes (I added a layer of abstraction so it can be ported to the Mac easily, don't worry) and wire that up to a nonexclusive, background DirectInput keyboard device so that it could sit and listen to keystrokes and detect when I wanted it to start parsing a regex. So I started just using the handy 'std::cin' and quickly was able to do stuff like type 'play', 'next' etc into a console and have it work. Sweet! Well then I came to using the IITLibraryPlaylist::Search function. I got out of memory returned. Huh, that's wierd. So I tried using it in a WSH with a Jscript. That worked fine. Try back in C++ it was trying to allocate 0xF786A1A6 bytes of memory...almost 4 gigs of memory. I have no idea what I did wrong, but since it is (in theory) instantiating the same code from Jscript as I am in C++, I can only assume that I did something very wrong with my COM usage in C++, so at 1AM last night I gave up on that and decided I'd get my ass off Ben's couch and go home.
---++Mostly Unrelated Rant
On a side note. What is it with SVN and having troubles if a file exists that is the same as one one in the repository. Here's the setup. Joe Maruschak set me up with a very useful test map texture (It's got the texture coordinates on it and it's a B&W checker grid. These artists have all these useful things! It's great!) for use with testing the texture coordinate distortion thing for the vector fields. So I had a non-versioned copy of TestMap.jpg in common. When I got home I realized I needed that, so I re-downloaded it, and added it to common, then added it to the SVN repo. When I got to work and tried to update, I got an error because a 'file of the same name exists'. Well DUH, try running a damn CRC check on it and see if it's the same damn file. Treat it like any other file, give me a DIFF if it's an ASCII file. Grrrr. It seems like we've come so far from CVS but we can't get anything that's competent unless we shell out for PerForce.
---++What's up with this formatting!?
You may have noticed there are an aweful lot of hyperlinks in this .plan and I seem to be adding strange formatting things. Why would I do such a thing? It's a secret that I will leave to the Almighty Garney to unveil at the proper time.
Wow that was a hell of a .plan. Lets see how many comments are on this one. I've noticed an inverse relationship between the length of my .plan and the number of comments. For those of you in the audience that are following along, all this development took place over 5 days, along with work on Marble Blast and Zap. I don't think that any of us at GarageGames ever "go home" with our brains.
About the author
#2
01/27/2005 (12:58 pm)
I'll comment since your .plan is so long and virtually screams for them, but I don't have anything to say, so I'll leave it at that :)
#3
WoW builds in a heck of a lot of functionality with it's lua scriptable interface, I guess to deter people from doing it the hardcore way.
01/27/2005 (4:05 pm)
Pat, there was a lot of this Graphics Device hijacking in the MMO Asherons Call. A huge community built up around various gui tools. People built a whole API for adding gui elements to the game that had the look and feel of the rest of the UI. There were all kind of additions. They also snooped the process bytes for various information and reverse engineered the network packet formats so that they could listen to network events and read data from the client. Shortly after each new version came out you could download a new xml file that had all the byte offsets for various elements in the client "gold", "inventory" etc. It was really quite impressive.WoW builds in a heck of a lot of functionality with it's lua scriptable interface, I guess to deter people from doing it the hardcore way.
#4
01/27/2005 (4:25 pm)
The problem with the LUA interface, Dan, is that I have no access to the outside world. I don't even have File I/O to do some kind of hacky file parsing thing. Otherwise that would be the ideal solution.
#5
01/27/2005 (6:50 pm)
Pat... Blizzard isn't real appreciative of things like that... they tend to Ban first and don't ask questions later
#6
01/27/2005 (6:55 pm)
Bummer. I want to see them detect it :P
#7
01/27/2005 (8:12 pm)
Looks like a data formatting system to me. :) ---+ is the title heading, ---++ is subheading, and so on.
#9
01/28/2005 (2:27 pm)
After a bit more time working with the iTunes SDK, I am almost entirely convinced that I am the only person who has ever tried doing anything useful with it in C++. The most amazing thing about COM is that it works at all. I don't know who's demented brainchild COM was in the first place but working with it in anything but a wipe-your-ass language is a nightmare, beyond BSTR and VARIENT even. In Jscript it's perfectly ok to do:var albumPlaylist = iTunesApp.CreatePlaylist( albumNameKey ); albumPlaylist.AddTrack( someTrack );That's fine...great, but what type is albumPlaylist...well in C++ it's:
HRESULT IiTunes::CreatePlaylist ([in] BSTR playlistName,[out, retval] IITPlaylist **iPlaylist)So this must mean that albumPlaylist is of type IITPlaylist...but wait, AddTrack isn't a method of IITPlaylist. It's only a method of IITUserPlaylist...so how do I get a IITUserPlaylist? Well as far as I can tell...I can't. I tried casting it, that didn't work so well when I went to try to add a track. I'm pretty sure that someone who knows COM well could do it, but I'm also pretty sure that anyone who knows COM pretty well needs abuse counciling because this is one of the most fantastic pieces of garbage I have ever seen.
#10
01/28/2005 (3:17 pm)
For those of you who are actually following along, the answer on how to convert is this:Quote:playlist is of type IITPlaylist, mITPlaylist is of type IITUserPlaylist.
mIiTunes->CreatePlaylist( pltitle, &playlist );
playlist->QueryInterface( &mITPlaylist );
#11
02/01/2005 (8:31 am)
Isn't COM microsoft's brainchild? I think it should be renamed CUM for CUMbersome.
#12
02/02/2005 (7:22 am)
Isn't DirectX technically COM?
#13
02/02/2005 (2:27 pm)
Ed, it is, in theory, COM, however it's not 100% COM. Basically, COM is too slow, so they really hacked the hell out of it for DX.
#14
Did you find a solution for such a thing?
01/13/2006 (11:26 am)
I think I'm the second person trying to do something useful with the iTunes Windows COM SDK and C++. I figured out the whole QueryInterface thing, and managed to add and edit tracks within my own playlist (created with CreatePlaylist). However, one can successfully use QueryInterface on a playlist from the iPod or the main Library, but afterwards you get a fatal exception (or can catch it of course) if you attempt to add a track (AddTrack) or add a file (AddFile).Did you find a solution for such a thing?

Torque Owner J. Alan Atherton
Let's try something else.
==@@@ What does this do?
I guess we'll see what it's all about soon enough.