Home > Archive > A86 Assembler > May 2004 > DirectX in HLA
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| NoDot 2004-04-27, 10:34 pm |
| I've posted this elsewhere, but I've finally decided to post it here.
Does anyone know an example of using DirectX in HLA. I'll even settle
for an example of OpenXX material. (Just make sure it's a turtorial
on it.)
Please, help me here.
| |
| Nathan C. Baker 2004-04-28, 3:31 am |
|
"NoDot" <no_dot@msn.com> wrote in message
news:dfed44a6.0404271706.21a0e899@posting.google.com...
> I've posted this elsewhere, but I've finally decided to post it here.
>
> Does anyone know an example of using DirectX in HLA. I'll even settle
> for an example of OpenXX material. (Just make sure it's a turtorial
> on it.)
>
> Please, help me here.
>
Just download the DirectX and OpenGL examples written for other assemblers
and convert them to the HLA sytax. This means flipping the SRC/DEST
operands and a bunch of extra typing -- "(", ")", and ";" for each line --
and greatly increases your chances for syntax errors but it shouldn't be too
hard of a task.
| |
|
| no_dot@msn.com (NoDot) écrivait news:dfed44a6.0404271706.21a0e899
@posting.google.com:
> I've posted this elsewhere, but I've finally decided to post it here.
>
> Does anyone know an example of using DirectX in HLA. I'll even settle
> for an example of OpenXX material. (Just make sure it's a turtorial
> on it.)
>
> Please, help me here.
>
>
No, sorry, no example, but you have _many_ for all
Assemblers.
Betov.
< http://betov.free.fr/RosAsm.html >
| |
| Charles Banas 2004-04-28, 6:31 am |
| NoDot wrote:
> I've posted this elsewhere, but I've finally decided to post it here.
>
> Does anyone know an example of using DirectX in HLA. I'll even settle
> for an example of OpenXX material. (Just make sure it's a turtorial
> on it.)
>
> Please, help me here.
>
i don't know of any HLA examples of anything, to be honest.
but NeHe's OpenGL tutorials have example code in assembly suitable for
MASM and (i think) NASM. might help guide you in the right direction:
http://nehe.gamedev.net/
http://nexe.gamedev.net/ used to be NeHe's DirectX alter-ego
so-to-speak, but its format has since changed. i don't know of anything
else with DirectX in assembly, though i don't doubt it's possible.
(although, it would probably be easier to write a wrapper library in C
and use those functions from assembly than to code all of the object
code that DirectX seems to mandate.)
| |
|
| "Nathan C. Baker" <nbaker2328@charter.net> wrote in message news:<108ugmmcik3158e@corp.supernews.com>...
> "NoDot" <no_dot@msn.com> wrote in message
> news:dfed44a6.0404271706.21a0e899@posting.google.com...
>
> Just download the DirectX and OpenGL examples written for other assemblers
> and convert them to the HLA sytax. This means flipping the SRC/DEST
> operands and a bunch of extra typing -- "(", ")", and ";" for each line --
> and greatly increases your chances for syntax errors but it shouldn't be too
> hard of a task.
The examples I've seen usually use MASM and use the OOP library for
MASM. Drives me crazy. I just thought of something, so I'll go and
have a look.
| |
|
| > http://nexe.gamedev.net/ used to be NeHe's DirectX alter-ego
> so-to-speak, but its format has since changed. i don't know of anything
> else with DirectX in assembly, though i don't doubt it's possible.
> (although, it would probably be easier to write a wrapper library in C
> and use those functions from assembly than to code all of the object
> code that DirectX seems to mandate.)
The reason I'm using HLA is because my Borland C++ compiler (OK the
problem is the linker) can't handle the DirectX SDK libraries. If it
could handle them them I wouldn't be here right now asking for this
information.
| |
| Charles Banas 2004-05-03, 1:04 pm |
| NoDot wrote:
>
>
> The reason I'm using HLA is because my Borland C++ compiler (OK the
> problem is the linker) can't handle the DirectX SDK libraries. If it
> could handle them them I wouldn't be here right now asking for this
> information.
>
well, for the linker to suport DirectX, it needs the linkable libraries
to be in a format it can recognize. IIRC, Borland uses the OMF format,
as does Intel. Microsoft uses a bastardized COFF format called "PE".
GCC generally supports everything except OMF, i think.
there are libraries for GCC that support DirectX 7, and maybe 8.
but as far as HLA goes (or any non-C++ language, for that matter), you
need a pre-written library, or to write one yourself, that can load and
call all of the functions that DirectX uses.
i don't know how much time you have on your hands, but if you want to
implement an object-based library that exports DirectX calls in a usable
calling convention, then you, sir, are very talented.
(someone correct me if i'm wrong here somewhere. but i do recall
reading that the vtables format Microsoft uses in DirectX kept GCC from
supporting it for a very long time.)
| |
| Randall Hyde 2004-05-03, 1:04 pm |
|
"Charles Banas" <uce@ftc.gov> wrote in message
news:1096leqeqmeodfb@news.supernews.com...
> but as far as HLA goes (or any non-C++ language, for that matter), you
> need a pre-written library, or to write one yourself, that can load and
> call all of the functions that DirectX uses.
Hmmm... Last time I checked, the C++ language definition didn't include
DirectX as part of the language :-).
For *every* language, HLA, MASM, C++, whatever, you need the
"pre-written" library, it's call "Direct-X".
What the OP needs is a header file with the proper definitions for the
DirectX
calls, which is true, again, for nearly every language that interfaces to
external
functions. As has been pointed out, these external definitions are very
simple
to create (in HLA, as in MASM, etc.), so the best advice to the OP is to
study the Direct-X tutorials for MASM and create the appropriate external
declarations for HLA.
>
> i don't know how much time you have on your hands, but if you want to
> implement an object-based library that exports DirectX calls in a usable
> calling convention, then you, sir, are very talented.
OTOH, he might also be using HLA, which allows the creation of
object-oriented modules in assembly a breeze. :-)
>
> (someone correct me if i'm wrong here somewhere. but i do recall
> reading that the vtables format Microsoft uses in DirectX kept GCC from
> supporting it for a very long time.)
That's the beauty of assembly language.
You can interface with just about anything.
Cheers,
Randy Hyde
| |
|
| > (someone correct me if i'm wrong here somewhere. but i do recall
> reading that the vtables format Microsoft uses in DirectX kept GCC from
> supporting it for a very long time.)
The problem I seem to be having in HLA, it seems, is getting the
vtable information. I might be accessing it incorrectly. What is
their vtable format?
| |
| Charles Banas 2004-05-03, 1:04 pm |
| Randall Hyde wrote:
>
> Hmmm... Last time I checked, the C++ language definition didn't include
> DirectX as part of the language :-).
>
Thank God.
> For *every* language, HLA, MASM, C++, whatever, you need the
> "pre-written" library, it's call "Direct-X".
>
very true.
> What the OP needs is a header file with the proper definitions for the
> DirectX
> calls, which is true, again, for nearly every language that interfaces to
> external
> functions. As has been pointed out, these external definitions are very
> simple
> to create (in HLA, as in MASM, etc.), so the best advice to the OP is to
> study the Direct-X tutorials for MASM and create the appropriate external
> declarations for HLA.
>
which i submit is a difficult task given that DirectX makes copious use
of C++ classes with just about every feature known to man:
multiple-inheritance, virtual functions, etc.
wrtiting support for all of that in a language is no easy task, i'm
sure, and creates quite a bit of difficulty in calling any DirectX code.
IMHO, the solution to the issue is to create a wrapper library (written
in C++) that exports (in a C or Pascal-like calling convention) all of
the functions that one might need to write DirectX code. AFAIK, other
than OpenGL/DirectX wrappers, no such wrapper exists.
>
>
>
>
> OTOH, he might also be using HLA, which allows the creation of
> object-oriented modules in assembly a breeze. :-)
>
which, honestly, still seems like quite a feat with all fo the features
and code bloat that DirectX takes advantage of.
>
>
>
>
> That's the beauty of assembly language.
> You can interface with just about anything.
including Microsoft's COM code bloat?
the comp.lang.C++ FAQ outlines some of the problems in section [32.8,
9]. http://www.parashift.com/c++-faq-lite/
i don't deny it's possible to se DirectX from HLA. but is it worth all
of the work involved in *CREATING* the header files and libraries you need?
| |
| Charles Banas 2004-05-03, 1:04 pm |
| NoDot wrote:
>
>
> The problem I seem to be having in HLA, it seems, is getting the
> vtable information. I might be accessing it incorrectly. What is
> their vtable format?
>
since i'm neither a compiler programmer, nor intimately familiar with
Microsoft bastardizations, i haven't a clue.
i'm merely passing on information.
(and suggesting this may be a waste of your time.)
| |
|
| no_dot@msn.com (NoDot) écrivait
news:dfed44a6.0405011119.6837ac5b@posting.google.com:
from[color=darkred]
>
> The problem I seem to be having in HLA, it seems, is getting the
> vtable information. I might be accessing it incorrectly. What is
> their vtable format?
These are nothing but simple Tables of Pointers to
Fuctions, that you can very easily access with any
Assembler, with a quite simple Table of Displacements
Equates and with a quite simple Macro. Example with
RosAsm, for an inferface call:
; Displacements Equates:
[QueryInterface 0
AddRef 4
Release 8
Compact 12
CreateClipper 16
CreatePalette 20
CreateSurface 24
DuplicateSurface 28
EnumDisplayModes 32
EnumSurfaces 36
FlipToGDISurface 40
GetCaps 44
GetDisplayMode 48
GetFourCCCodes 52
GetGDISurface 56
GetMonitorFrequency 60
GetScanLine 64
GetVerticalBlankStatus 68
Initialize 72
RestoreDisplayMode 76
SetCooperativeLevel 80
SetDisplayMode 84
WaitForVerticalBlank 88]
; Caling Macro:
[iCall | mov eax #2 | mov eax D$eax | call D$eax+#1 #2 #3>L]
; Using:
iCall Release D$Primary
As simple as this. Of course, with HLA added confusion
this might be a bit less simple, but i am quite sure
that, when you will have understood the simplicity
of these calls you will not miss to contribute to, in
turn, misslead other beginners, with no base propaganda,
for the damage of Assembly and for the personal glory
of Master Self-Esteemed Randall Hyde.
Betov.
< http://betov.free.fr/RosAsm.html >
| |
|
| > > i don't know how much time you have on your hands, but if you want to
I'll try and create one.
[color=darkred]
> OTOH, he might also be using HLA, which allows the creation of
> object-oriented modules in assembly a breeze. :-)
HLA passes the this pointer in esi. C++ passes the this pointer on
the stack. Problem.
| |
|
| > (and suggesting this may be a waste of your time.)
How? If I make this library, then other HLA users can benifit from my
work and we can have more apps written in HLA.
| |
| Randall Hyde 2004-05-03, 1:05 pm |
|
"NoDot" <no_dot@msn.com> wrote in message
news:dfed44a6.0405020736.4f49b337@posting.google.com...
>
> HLA passes the this pointer in esi. C++ passes the this pointer on
> the stack. Problem.
If you're using HLA *classes* and the high-level HLA class invocation
mechanism, it uses ESI. However, don't forget that you can easily pass
the object pointer on the stack yourself (this is assembly language, after
all, you don't *always* have to use the high-level features in assembly
:-)).
If you like clean, HLL-like syntax for the calls, you can easily create a
macro
that does the work for you.
Cheers,
Randy Hyde
| |
| Randall Hyde 2004-05-03, 1:05 pm |
|
"NoDot" <no_dot@msn.com> wrote in message
news:dfed44a6.0405011119.6837ac5b@posting.google.com...
>
> The problem I seem to be having in HLA, it seems, is getting the
> vtable information. I might be accessing it incorrectly. What is
> their vtable format?
>
Personally, I've never worked with Direct-X, so I can't offer
any more insights into this issue. However, you might ask
Beth Stone, who has played around with Direct-X in assembly
a bit.
Cheers,
Randy Hyde
| |
| Charles Banas 2004-05-03, 1:05 pm |
| NoDot wrote:
>
>
> How? If I make this library, then other HLA users can benifit from my
> work and we can have more apps written in HLA.
>
i don't disagree with that. in fact, i completely agree.
it just seems to me to be more work than it may be worth.
| |
| NoDot 2004-05-04, 12:53 pm |
| > http://nexe.gamedev.net/ used to be NeHe's DirectX alter-ego
> so-to-speak, but its format has since changed. i don't know of anything
> else with DirectX in assembly, though i don't doubt it's possible.
> (although, it would probably be easier to write a wrapper library in C
> and use those functions from assembly than to code all of the object
> code that DirectX seems to mandate.)
The reason I'm using HLA is because my Borland C++ compiler (OK the
problem is the linker) can't handle the DirectX SDK libraries. If it
could handle them them I wouldn't be here right now asking for this
information.
| |
| Charles Banas 2004-05-04, 12:53 pm |
| NoDot wrote:
>
>
> The reason I'm using HLA is because my Borland C++ compiler (OK the
> problem is the linker) can't handle the DirectX SDK libraries. If it
> could handle them them I wouldn't be here right now asking for this
> information.
>
well, for the linker to suport DirectX, it needs the linkable libraries
to be in a format it can recognize. IIRC, Borland uses the OMF format,
as does Intel. Microsoft uses a bastardized COFF format called "PE".
GCC generally supports everything except OMF, i think.
there are libraries for GCC that support DirectX 7, and maybe 8.
but as far as HLA goes (or any non-C++ language, for that matter), you
need a pre-written library, or to write one yourself, that can load and
call all of the functions that DirectX uses.
i don't know how much time you have on your hands, but if you want to
implement an object-based library that exports DirectX calls in a usable
calling convention, then you, sir, are very talented.
(someone correct me if i'm wrong here somewhere. but i do recall
reading that the vtables format Microsoft uses in DirectX kept GCC from
supporting it for a very long time.)
| |
| Randall Hyde 2004-05-04, 12:53 pm |
|
"Charles Banas" <uce@ftc.gov> wrote in message
news:1096leqeqmeodfb@news.supernews.com...
> but as far as HLA goes (or any non-C++ language, for that matter), you
> need a pre-written library, or to write one yourself, that can load and
> call all of the functions that DirectX uses.
Hmmm... Last time I checked, the C++ language definition didn't include
DirectX as part of the language :-).
For *every* language, HLA, MASM, C++, whatever, you need the
"pre-written" library, it's call "Direct-X".
What the OP needs is a header file with the proper definitions for the
DirectX
calls, which is true, again, for nearly every language that interfaces to
external
functions. As has been pointed out, these external definitions are very
simple
to create (in HLA, as in MASM, etc.), so the best advice to the OP is to
study the Direct-X tutorials for MASM and create the appropriate external
declarations for HLA.
>
> i don't know how much time you have on your hands, but if you want to
> implement an object-based library that exports DirectX calls in a usable
> calling convention, then you, sir, are very talented.
OTOH, he might also be using HLA, which allows the creation of
object-oriented modules in assembly a breeze. :-)
>
> (someone correct me if i'm wrong here somewhere. but i do recall
> reading that the vtables format Microsoft uses in DirectX kept GCC from
> supporting it for a very long time.)
That's the beauty of assembly language.
You can interface with just about anything.
Cheers,
Randy Hyde
| |
| NoDot 2004-05-04, 12:53 pm |
| > (someone correct me if i'm wrong here somewhere. but i do recall
> reading that the vtables format Microsoft uses in DirectX kept GCC from
> supporting it for a very long time.)
The problem I seem to be having in HLA, it seems, is getting the
vtable information. I might be accessing it incorrectly. What is
their vtable format?
| |
| Charles Banas 2004-05-04, 12:53 pm |
| Randall Hyde wrote:
>
> Hmmm... Last time I checked, the C++ language definition didn't include
> DirectX as part of the language :-).
>
Thank God.
> For *every* language, HLA, MASM, C++, whatever, you need the
> "pre-written" library, it's call "Direct-X".
>
very true.
> What the OP needs is a header file with the proper definitions for the
> DirectX
> calls, which is true, again, for nearly every language that interfaces to
> external
> functions. As has been pointed out, these external definitions are very
> simple
> to create (in HLA, as in MASM, etc.), so the best advice to the OP is to
> study the Direct-X tutorials for MASM and create the appropriate external
> declarations for HLA.
>
which i submit is a difficult task given that DirectX makes copious use
of C++ classes with just about every feature known to man:
multiple-inheritance, virtual functions, etc.
wrtiting support for all of that in a language is no easy task, i'm
sure, and creates quite a bit of difficulty in calling any DirectX code.
IMHO, the solution to the issue is to create a wrapper library (written
in C++) that exports (in a C or Pascal-like calling convention) all of
the functions that one might need to write DirectX code. AFAIK, other
than OpenGL/DirectX wrappers, no such wrapper exists.
>
>
>
>
> OTOH, he might also be using HLA, which allows the creation of
> object-oriented modules in assembly a breeze. :-)
>
which, honestly, still seems like quite a feat with all fo the features
and code bloat that DirectX takes advantage of.
>
>
>
>
> That's the beauty of assembly language.
> You can interface with just about anything.
including Microsoft's COM code bloat?
the comp.lang.C++ FAQ outlines some of the problems in section [32.8,
9]. http://www.parashift.com/c++-faq-lite/
i don't deny it's possible to se DirectX from HLA. but is it worth all
of the work involved in *CREATING* the header files and libraries you need?
| |
| Charles Banas 2004-05-04, 12:53 pm |
| NoDot wrote:
>
>
> The problem I seem to be having in HLA, it seems, is getting the
> vtable information. I might be accessing it incorrectly. What is
> their vtable format?
>
since i'm neither a compiler programmer, nor intimately familiar with
Microsoft bastardizations, i haven't a clue.
i'm merely passing on information.
(and suggesting this may be a waste of your time.)
| |
| Betov 2004-05-04, 12:53 pm |
| no_dot@msn.com (NoDot) écrivait
news:dfed44a6.0405011119.6837ac5b@posting.google.com:
from[color=darkred]
>
> The problem I seem to be having in HLA, it seems, is getting the
> vtable information. I might be accessing it incorrectly. What is
> their vtable format?
These are nothing but simple Tables of Pointers to
Fuctions, that you can very easily access with any
Assembler, with a quite simple Table of Displacements
Equates and with a quite simple Macro. Example with
RosAsm, for an inferface call:
; Displacements Equates:
[QueryInterface 0
AddRef 4
Release 8
Compact 12
CreateClipper 16
CreatePalette 20
CreateSurface 24
DuplicateSurface 28
EnumDisplayModes 32
EnumSurfaces 36
FlipToGDISurface 40
GetCaps 44
GetDisplayMode 48
GetFourCCCodes 52
GetGDISurface 56
GetMonitorFrequency 60
GetScanLine 64
GetVerticalBlankStatus 68
Initialize 72
RestoreDisplayMode 76
SetCooperativeLevel 80
SetDisplayMode 84
WaitForVerticalBlank 88]
; Caling Macro:
[iCall | mov eax #2 | mov eax D$eax | call D$eax+#1 #2 #3>L]
; Using:
iCall Release D$Primary
As simple as this. Of course, with HLA added confusion
this might be a bit less simple, but i am quite sure
that, when you will have understood the simplicity
of these calls you will not miss to contribute to, in
turn, misslead other beginners, with no base propaganda,
for the damage of Assembly and for the personal glory
of Master Self-Esteemed Randall Hyde.
Betov.
< http://betov.free.fr/RosAsm.html >
| |
| NoDot 2004-05-04, 12:53 pm |
| > > i don't know how much time you have on your hands, but if you want to
I'll try and create one.
[color=darkred]
> OTOH, he might also be using HLA, which allows the creation of
> object-oriented modules in assembly a breeze. :-)
HLA passes the this pointer in esi. C++ passes the this pointer on
the stack. Problem.
| |
| NoDot 2004-05-04, 12:53 pm |
| > (and suggesting this may be a waste of your time.)
How? If I make this library, then other HLA users can benifit from my
work and we can have more apps written in HLA.
| |
| Randall Hyde 2004-05-04, 12:53 pm |
|
"NoDot" <no_dot@msn.com> wrote in message
news:dfed44a6.0405020736.4f49b337@posting.google.com...
>
> HLA passes the this pointer in esi. C++ passes the this pointer on
> the stack. Problem.
If you're using HLA *classes* and the high-level HLA class invocation
mechanism, it uses ESI. However, don't forget that you can easily pass
the object pointer on the stack yourself (this is assembly language, after
all, you don't *always* have to use the high-level features in assembly
:-)).
If you like clean, HLL-like syntax for the calls, you can easily create a
macro
that does the work for you.
Cheers,
Randy Hyde
| |
| Randall Hyde 2004-05-04, 12:53 pm |
|
"NoDot" <no_dot@msn.com> wrote in message
news:dfed44a6.0405011119.6837ac5b@posting.google.com...
>
> The problem I seem to be having in HLA, it seems, is getting the
> vtable information. I might be accessing it incorrectly. What is
> their vtable format?
>
Personally, I've never worked with Direct-X, so I can't offer
any more insights into this issue. However, you might ask
Beth Stone, who has played around with Direct-X in assembly
a bit.
Cheers,
Randy Hyde
| |
| Charles Banas 2004-05-04, 12:53 pm |
| NoDot wrote:
>
>
> How? If I make this library, then other HLA users can benifit from my
> work and we can have more apps written in HLA.
>
i don't disagree with that. in fact, i completely agree.
it just seems to me to be more work than it may be worth.
| |
|
| Betov wrote:
> NoDot wrote:
GCC[color=darkred]
> from
>
> These are nothing but simple Tables of Pointers to
> Fuctions, that you can very easily access with any
> Assembler, with a quite simple Table of Displacements
> Equates and with a quite simple Macro.
Yup; We're in complete agreement here...it's complicated by the
jargonistic nonsense Microsoft spout about "aggregating inherited
IUnknown pointers on an interface"...
> Example with
> RosAsm, for an inferface call:
>
> ; Displacements Equates:
>
> [QueryInterface 0
> AddRef 4
> Release 8
> Compact 12
> CreateClipper 16
> CreatePalette 20
> CreateSurface 24
> DuplicateSurface 28
> EnumDisplayModes 32
> EnumSurfaces 36
> FlipToGDISurface 40
> GetCaps 44
> GetDisplayMode 48
> GetFourCCCodes 52
> GetGDISurface 56
> GetMonitorFrequency 60
> GetScanLine 64
> GetVerticalBlankStatus 68
> Initialize 72
> RestoreDisplayMode 76
> SetCooperativeLevel 80
> SetDisplayMode 84
> WaitForVerticalBlank 88]
>
> ; Caling Macro:
>
> [iCall | mov eax #2 | mov eax D$eax | call D$eax+#1 #2 #3>L]
>
> ; Using:
>
> iCall Release D$Primary
>
> As simple as this.
Indeed...
> Of course, with HLA added confusion
> this might be a bit less simple, but i am quite sure
> that, when you will have understood the simplicity
> of these calls
Well, no...HLA can do it in exactly the same way...there is some
_optional_ "added confusion" of letting HLA do all that "counting up
in fours" for you using a structure, which adds all the "complex
confusion" of making it even simpler again...
[ And, for those that want it, you can add on "parameter checking" by
adding on the parameters...but if you don't add them on, HLA just
doesn't "parameter check" because there's no parameters...which
doesn't seem all that particularly confusing, really: add on
parameters, HLA checks parameters...don't add on parameters, HLA
doesn't check parameters because there are no parameters given to be
checked...kind of logical, that, really :) ]
> you will not miss to contribute to, in
> turn, misslead other beginners, with no base propaganda,
> for the damage of Assembly and for the personal glory
> of Master Self-Esteemed Randall Hyde.
As to this, it would seem that you're the one with "no base
propoganda" because HLA can _entirely duplicate_ the RosAsm method
you've just shown...it can also do a lot more besides, mind you...but,
whatever, HLA can use exactly the same method you've shown...create
some constants that "add up in fours" and a macro to automate the COM
call from those constants...using structures - as you've noted
yourself on occasion - is merely a case of getting the assembler to do
all that "counting in fours" for you to create the "offset constants"
automatically...and then you can use a macro to do it...
Hence, if HLA copying the RosAsm method is "no base propoganda for the
damage of Assembly" then so is RosAsm for using it too...
Beth :)
| |
|
| Charles Banas wrote:
> NoDot wrote:
from[color=darkred]
>
> since i'm neither a compiler programmer, nor intimately familiar
with
> Microsoft bastardizations, i haven't a clue.
Because you are neither, you are actually presenting it as far more
complicated than it really actually is...
A COM-object is a record that contains pointers to procedures...and
that's all...
You can concern yourself with all the object-orientated stuff but, as
has been contended, it's an awful lot of work for no particular reason
or benefit...considering it from a non-OOP point of view vastly
simplifies the problem without losing a sole "feature" from OOP...
For example, here's the HLA for "IUnknown" without parameter checking:
--------------- 8< ----------------
IUnknown: record
QueryInterface: procedure;
AddRef: procedure;
Release: procedure;
endrecord;
--------------- >8 ----------------
If you insist on some parameter checking, as you'd have under C++,
then merely "decorate" your procedure calls:
--------------- 8< ----------------
IUnknown: record
QueryInterface: procedure( ThisPtr: DWORD;
iid: REFIID;
ppvObject: LPLPVOID);
@stdcall; @returns("(type HRESULT eax)");
AddRef: procedure( ThisPtr: DWORD);
@stdcall; @returns("(type ULONG eax)");
Release: procedure( ThisPtr: DWORD);
@stdcall; @returns("(type ULONG eax)");
endrecord;
--------------- >8 ----------------
Note the simple addition of "ThisPtr" as the first parameter (I've
simplified the type to "DWORD" but it would actually be a
self-referential "pointer to IUnknown" if you insisted on _strict_
data typing...actually, if I recall, when I tried this myself, I had a
problem with "self-referencing" data types under HLA...something I was
going to talk to Randy about but completely plain forgot...it's
problematic so deserved a little "bug report", I thought...must have
another look at it, though, to remind myself what the exact problem
was so I can, this time, _remember_ to address it to Randy
specifically ;)...
That's really the only "OOPism" of any significance that you need
worry about : Just add "ThisPtr: DWORD" as the first parameter to any
procedure in the record (not listed in your DirectX C++-based
procedure prototypes because the OOP stuff in C++ adds it
automatically...just a case, though, of adding it manually ;)...note,
doesn't have to be called "ThisPtr"...that's just any old name I came
up with that just avoids any "clashes" with HLA's "this" keyword for
its OOP support...perhaps, for a touch of "comedy value", you could
just call it "that" instead of "this"? Or even "What-not-over-there",
if you really want to be silly about things ;)...
Also, the above assumes that the usual Windows data types are defined
("REFIID", "HRESULT", etc. ;)...but, if you don't care about your data
typing being that particularly strict, then just do the old
"everything's a DWORD" method:
--------------- 8< ----------------
IUnknown: record
QueryInterface: procedure( ThisPtr: DWORD;
iid: DWORD;
ppvObject: DWORD);
@stdcall; @returns("eax");
AddRef: procedure( ThisPtr: DWORD);
@stdcall; @returns("eax");
Release: procedure( ThisPtr: DWORD);
@stdcall; @returns("eax");
endrecord;
--------------- >8 ----------------
Works just as well, just HLA will now only be checking the size and
number of parameters, won't be checking their "formal data types" or
anything...for most ASM coders, this is good enough...
But, why not? Let's get the HLA plug in: The ability to be _more_
strict about data typing than even something like C...down to
"actually, only care that the number of parameters and sizes are
right"...all the way down to a completely undecorated "procedure"
only...is a somewhat unique HLA feature..._YOU_ decide just how much
"data typing" (including _NONE_ ;) that you want to use...
And, basically, every COM object will have its first three members as
above (that is, all COM objects are "inherited" from "IUnknown"
;)..."inheritance" can simply be tackled by either expanding it out
(really, "inheritance" in these HLLs is only just a "shorthand
macro"...an "intelligent automatic cut and paste" ;)...or,
alernatively, sticking one record inside another...
To explain, all that happens during "inheritance" is that one record
is "merged" with another...if there are no common members in both
records, this is literally a simple aggregation (in other words, you
put one after the other...yup, as simple as that ;)...the thing that
makes "inheritance" a touch different to just putting records inside
records is that any _common members_ are only listed _once_...the two
records are "merged" together...
But, with DirectX, you actually _don't need to know this_...as,
simply, all DirectX "COM interfaces" thus far have no common members
inside them at all (and this will probably always be the case...it's
"COM based" but only marginally so, in that Microsoft don't actually
use any of the wider COM / OLE "features" in actual practice at all
;)...hence, what you actually get in reality once you expand all these
"COM inheritance OOP macro" nonsense stuff out into what it really is,
is that every DirectX interface starts with those same three
"IUnknown" procedures and then you just list all the other ones for
that particular interface after it...DirectX does NOT make use of COM
"aggregation" features (you can note this in the "CreateXXX" methods
in the documentation which state "this functionality is not supported
as yet, supply NULL" for all that "lpOuter" nonsense ;)...
So, in practical terms, this means that you should just pop in the
three "QueryInterface", "AddRef" and "Release" procedures at the start
of every DirectX interface...these three are always at the start of
_ANY_ COM object because they are all to do with "COM Object
control"...for instance, you call "Release" when you finally want to
release the COM object, as you're not using it any more...you call
"AddRef" to bump up the "reference count", if you're duplicating the
pointers and need the object "held open" for both pointers...you call
"QueryInterface" in order to ask for different "interfaces" - by their
unique GUID (just a big number that's guaranteed to be unique so that
every COM interface is guaranteed to have a different GUID...and,
therefore, you can create your COM objects without fear of
"clashes"...Microsoft simply introduced this because COM objects can
be created with "CoCreateInstance" from _anywhere_ in the system, so
they needed a "naming system" which wouldn't introduce any "clashes"
or "conflicts"...for example, if they'd used ASCII names, then two
companies might both create a "IStringTable" object and - bang! - you
ask for "IStringTable" and get the _wrong_ interface...that would not
be a Good Thing at all...so, Microsoft simply use GUIDs - really big
numbers generated using a formula designed to ensure "uniqueness" (no,
no idea what that formula actually is...but, as usual, the "GUID" is
NOT a Microsoft invention so you can look around UNIX-y resources and
probably find the answer to that elsewhere) - to guarantee that if you
refer to interfaces by "GUID" then you'll always get the interface you
want because GUIDs are "guaranteed unique" so every interface -
whoever makes them - has a completely unique GUID number ;) - for this
particular object...
Other than an older DirectDraw interface where you "QueryInterface" to
get the Direct3D interface (this method, though, is now
_OBSELETE_...use a later version of DirectX, if you want Direct3D and,
again, you don't really need to know about this ;)..."AddRef" is
almost never used...that, in actual practice, the sole thing you need
care about here is calling "Release" to release your COM object when
done...the rest is "adminstration" nonsense that, in fact, you'll find
you never really have any instance to call in your DirectX code at
all...it's more there for the more complicated "OLE" stuff built on
top of COM...DirectX's COM interface just _don't_ go that far or get
that complicated...
So, basically, you don't need to know much of anything, really, in
actual practice...just pick your "interface" that you want then create
a "record" for each of the procedures with "QueryInterface", "AddRef"
and "Release" put as the first three procedures because all COM
objects start with these three "object control" procedures (if you
like, simply copy and paste the perferred one of the alternatives I
supplied above for "IUnknown" ;)...
For example, you want "IDirect3D9"? Okay...the first three procedures
in the record are going to be "QueryInterface", "AddRef" and "Release"
in that order...
Then you follow these with the "IDirect3D9" procedures...the order of
the "IDirect3D9" procedures might not be as listed in the
documentation, though...so, the easiest way? Grab the C / C++ header
file with the C / C++ definition in it (I would suggest using GREP and
then simply looking for "IDirect3D9" using GREP amongst your header
file directory...and just let GREP do all the hard work of actually
finding it for you ;)...
So, this is what we see in the C / C++ header file:
--------------- 8< ----------------
DECLARE_INTERFACE_(IDirect3D9, IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IDirect3D9 methods ***/
STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction)
PURE;
STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD
Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;
STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT
Format) PURE;
STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT
Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE;
STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT
Adapter,D3DDISPLAYMODE* pMode) PURE;
STDMETHOD(CheckDeviceType)(THIS_ UINT iAdapter,D3DDEVTYPE
DevType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,BOOL
bWindowed) PURE;
STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE
DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE
RType,D3DFORMAT CheckFormat) PURE;
STDMETHOD(CheckDeviceMultiSampleType)(TH
IS_ UINT
Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL
Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels)
PURE;
STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE
DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT
RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE;
STDMETHOD(CheckDeviceFormatConversion)(T
HIS_ UINT
Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT
TargetFormat) PURE;
STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE
DeviceType,D3DCAPS9* pCaps) PURE;
STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;
STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE
DeviceType,HWND hFocusWindow,DWORD
BehaviorFlags,D3DPRESENT_PARAMETERS*
pPresentationParameters,IDirect3DDevice9
** ppReturnedDeviceInterface)
PURE;
};
--------------- >8 ----------------
Most of this is "compatibility" nonsense so that both C and C++
compilers can read the header files without blowing up (C++ has OOP
but C does not...hence, Microsoft have created a bunch of simple
macros that expand one way for C++ and another way for C that fits in
with their OOP / non-OOP syntaxii...in fact, what I'm demonstrating
with the HLA stuff? More or less a _duplication_ of what the C version
of the macros expand into ;)...
Right, it looks a total mess but that's Microsoft trying to be
"compatible" using special "macros" everywhere...so let me try to
clear away the "junk" here for you...
The "DECLARE_INTERFACE_" expands into a "typedef struct"...note,
interestingly, that even under C++, Microsoft still use _struct_ and
not "class"...the reason? "structs" and "classes" under C++ are
identical, in fact, except for the "default access rights"...this is
"private" for "class" and "public" for "struct"...due to the
definition of COM object interfaces, they _only_ contain a series of
"public:" procedures...hence, using "struct" automatically adds a
"public:" to the whole structure and saves trying to work out some
"macro" to expand this into the definition...so, even under C++,
there's nothing dubious about my "it's all just a record" assertion
because even C++ uses "struct" here, NOT "class"...it's that OOP
jargon nonsense confusing people again...note how complex it is
explaining this stuff in OOP terms but just how clean and clear it is
to do exactly the same thing _without_ the OOP jargon and manually
using non-OOP devices...I tell you, it's a conspiracy of jargon
_designed_ so no-one can understand what's actually very easy, so that
everyone rushes out to buy "OOP" books and go on "OOP" courses to give
all these people jobs and a source of income...it really isn't that
complex "under the hood"...it's, in fact, pathetically simple stuff
that you'll probably be just as annoyed as me that all that jargon
even exists at all...
[ The only reason for using a "macro" rather than just a literal
"typedef struct IDirect3D9" - which would apply to both languages, C
and C++ - is that (for, actually, no particularly useful reason in
actual practice ;) Microsoft want to do it "properly" so as
"IDirect3D9" is technically inherited from "IUnknown", the C++ expands
to: "typedef struct IDirect3D9 : IUnknown"...seeing, though, as all
the members are actually listed out in their entireity thereafter in
the actual correct order, this actually serves no useful purpose (all
the C++ compiler does when seeing such an "inheritance" device is use
it to work out the _order_ of inherited procedures...that
"QueryInterface", "AddRef" and "Release" must be in the _same offset
positions_ as they are in "IUnknown"...this is, in fact, quite
pointless in practice because Microsoft spits out the interface
definitions in the correct order, anyway...I suppose it's useful for
_them_ to have the compiler double-check things...but this serves
_us_ - using it - absolutely no good purpose whatsoever ;)... ]
Anyway, in our HLA conversion, simply using "Name: record" will do the
trick, basically...ignore the "inheritance" nonsense, we'll just make
sure that our procedures are listed out in the correct order (which
solely means "QueryInterface", "AddRef" and "Release" come _first_, as
the first three procedures, in all COM objects and everything else
just follows it...this won't be hard to do because the C / C++ header
files you're working from, _already_ have it in the correct order,
anyway...so, literally cut and paste..."inheritance" is, as I say,
only really a "shorthand intelligent cut and paste" device in OOPLs,
anyway ;)...then, just list each of the procedures afterwards in the
same order as you see in the header file...
In fact, one simple way to do it? Cut and paste whatever's between the
opening bracket after "DECLARE_INTERFACE" and it's matching closing
bracket over to your HLA source file between your "IDirect3D9: record"
and "endrecord;" statements...avoids the chance of you making a
mistake with the ordering if you just cut and paste it directly...
So, it looks something like:
--------------- >8 ----------------
IDirect3D9: record
/*** IUnknown methods ***/
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IDirect3D9 methods ***/
STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction)
PURE;
STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD
Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;
STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT
Format) PURE;
STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT
Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE;
STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT
Adapter,D3DDISPLAYMODE* pMode) PURE;
STDMETHOD(CheckDeviceType)(THIS_ UINT iAdapter,D3DDEVTYPE
DevType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,BOOL
bWindowed) PURE;
STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE
DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE
RType,D3DFORMAT CheckFormat) PURE;
STDMETHOD(CheckDeviceMultiSampleType)(TH
IS_ UINT
Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL
Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels)
PURE;
STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE
DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT
RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE;
STDMETHOD(CheckDeviceFormatConversion)(T
HIS_ UINT
Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT
TargetFormat) PURE;
STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE
DeviceType,D3DCAPS9* pCaps) PURE;
STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;
STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE
DeviceType,HWND hFocusWindow,DWORD
BehaviorFlags,D3DPRESENT_PARAMETERS*
pPresentationParameters,IDirect3DDevice9
** ppReturnedDeviceInterface)
PURE;
endrecord;
--------------- 8< ----------------
Right, if you care nothing for "parameter checking", then literally
just clear away all the nonsense except the procedure's name and add a
":procedure" after each line...like this:
--------------- 8< ----------------
IDirect3D9: record
/*** IUnknown methods ***/
QueryInterface: procedure;
AddRef: procedure;
Release: procedure;
/*** IDirect3D9 methods ***/
RegisterSoftwareDevice: procedure;
GetAdapterCount: procedure;
GetAdapterIdentifier: procedure;
GetAdapterModeCount: procedure;
EnumAdapterModes: procedure;
GetAdapterDisplayMode: procedure;
CheckDeviceType: procedure;
CheckDeviceFormat: procedure;
CheckDeviceMultiSampleType: procedure;
CheckDepthStencilMatch: procedure;
CheckDeviceFormatConversion: procedure;
GetDeviceCaps: procedure;
GetAdapterMonitor: procedure;
CreateDevice: procedure;
endrecord;
--------------- >8 ----------------
If you _do_ care about the parameters, then...well...you've got your
DirectX documentation with the C / C++ prototypes, yes? Just
"decorate" the raw "procedure" stuff with the required parameters...
Something like:
--------------- 8< ----------------
IDirect3D9: record
/*** IUnknown methods ***/
QueryInterface: procedure( ThisPtr: DWORD;
iid: DWORD;
ppvObject: DWORD);
@stdcall; @returns("eax");
AddRef: procedure( ThisPtr: DWORD);
@stdcall; @returns("eax");
Release: procedure( ThisPtr: DWORD);
@stdcall; @returns("eax");
/*** IDirect3D9 methods ***/
RegisterSoftwareDevice: procedure(ThisPtr: DWORD;
pInitializeFunction:
DWORD);
@stdcall; @returns("eax");
GetAdapterCount: procedure(ThisPtr: DWORD);
@stdcall; @returns("eax");
GetAdapterIdentifier: procedure(ThisPtr: DWORD;
Adapter: DWORD;
Flags: DWORD;
pIdentifier: pointer to D3DADAPTER_INDENTIFIER9;
@stdcall; @returns("eax");
// ...
//
// Rest of IDirect3D9 procedures go here
// (I'm just too lazy to convert it all ;)
endrecord;
--------------- >8 ----------------
Note that the above points something else out...you'll also need to
define other records used by DirectX like "D3DADAPTER_IDENTIFIER9", if
you want to properly "type" your procedures...mind you, to a degree,
you _will_ need to define at least some of these other records which
provide parameter information to the procedures, just because DirectX
often passing around records of parameters to some of its
procedures...
Well, it's the same situation as I mentioned before, really...HLA is
happy with just "procedure" but it'll also accept you putting in
parameters and "@stdcall" and "@returns" and stuff, if you want to
"decorate" your procedure prototypes here to allow HLA to do some
"parameter checking"...also, due to the fact that HLA has strict data
typing but also the "typeless" DWORD too, you can even choose just how
"fussy" you want to be checking the "types" of your parameters...if
you don't care, then, usually under Win32, you can literally just
change it to "DWORD" because all the different types usually just
resolve into being a 32-bit DWORD...if you do care - and, with HLA, a
unique feature is you can be as _selective_ in how rigorous and strict
you want the "data typing" to be...from absolutely none at all, right
up to making C++ look like it has "loose data typing" - then simply
add in all the extra junk about parameters and calling conventions and
so forth...the "@returns" thingy allows you to write stuff like "if
(CreateDevice(parameters)==D3D_OK)" with the "HLLisms"...drop that if
you never use "IF" or "WHILE" or anything or just don't want that kind
of support from HLA...again, the uniqueness of HLA's methodology here
is that _YOU_ decide just how much stuff HLA does...it's _capable_ of
very strict data typing and "HLLisms"...but that capability is not
enforced...you can completely ignore it or only use it "partially" or
whatever...perhaps the only tool - and my support for HLA might begin
to be explained to those who don't understand - where the _CHOICE IS
IN THE PROGRAMMER'S HANDS_...every other tool has some "enforced"
scheme of "no data typing" / "strict data typing" and you have to fall
in line...HLA instead _provides the facilities_ for these things but
they are _only used_ when specifically requested...don't supply
parameters and HLA will simply not parameter check...if you do supply
them, then it will parameter check if you use the "HLLism" version of
"CALL"...if you do supply them and push parameters manually and use
"CALL" directly, it does NOT check...so, in fact, you could, say,
create a bunch of header file _with_ the parameters and everything in
place but, even then, HLA allows a programmer to _choose_ not to have
parameter checking by doing it all manually...hence, the assertion
that HLA "enforces" anything is the least applicable accusation there
is...HLA is perhaps the _only tool_ which does NOT do such a thing, be
that HLLs or ASM or whatever...the only tool to take the kind of
approach I support: "here's the facilities so if you want it, you can
have it...but, if you don't want, then don't use"...Randy is not
"copping out" when he says these things at all...he's pointing out one
of HLA's unique features that you'd be hard-pressed to find _any_ tool
providing, be that script language, HLL or ASM ;)...
And, basically, repeat for all the "COM objects" you're interesting in
using...it's _tedious_ work, rather than "difficult" work...you can,
as I've suggested, literally copy and paste the stuff out of the C++
file, trim off the macro nonsense and add ":procedure;" after each
line (which itself is always the same so write it once and then "copy
and paste" it after each line ;)...
Also, note, that there's no compulsion to use "records"...this just is
a sensible approach...but someone like Rene might insist that this is
"not assembly"...well, fair enough...you can copy the RosAsm approach
to this by converting the above structure into a list of offset
constants and use those instead...such as:
--------------- 8< ----------------
const
IDirect3D9_QueryInterface := $00000000;
IDirect3D9_AddRef := $00000004;
IDirect3D9_Release := $00000008;
IDirect3D9_RegisterSoftwareDevice := $0000000C;
IDirect3D9_GetAdapterCount := $00000010;
IDirect3D9_GetAdapterIdentifier := $00000014;
// ...
//
// Rest of IDirect3D9 procedures go here
// (I'm just too lazy to convert it all ;)
endconst;
--------------- >8 ----------------
The advantages of the "record" approach, which Rene deems
"anti-assembly", is that you can do "@size(IDirect3D9)" and get HLA to
work out the size of the entire interface rather than count it up
yourself...and that you don't need to become an expert in counting up
in fours in hexadecimal...
[ Yes, I don't really understand Rene's argument here either...how
does counting up in fours in hexadecimal make you a "real assembly
programmer", while letting the tool do it automatically some "evil
anti-assembly propoganda to aid Monsanto Nazis force Third Farmers to
kill everyone with McDonald's cheeseburgers"? Well, Rene, seems the
connection is so "clearly defined" and obvious that it only takes an
"assembly genius" of your calibre to understand the connection between
"evil camp" rule of the universe and counting up in fours in
hexadecimal...you'll have to forgive the rest of us for kind of
thinking that you're talking completely crap...but, hey, it's so
surreal - like some sketch from Monty Python - I can't help but find
it absolutely hilarious...so, keep it up, as we can all do with a
smile from time to time ;)... ]
Oh, the reason for inserting the "IDirect3D9_" stuff in front of each
constant? Well, Rene would find "scope" to be very
"anti-assembly"...hence, to avoid any "name clashes", we can throw
this in front of each constant to get much the same as "scoping"
without violating Rene's rule that it's "anti-assembly" to, ummm, let
an assembler do any of the work...I suppose it's also "anti-builders"
to let builders build things too...looks like we'll all have to build
our own houses "manually" brick-by-brick and not hire Rene to build
them, as we'd be an "evil affront" to the building trade by actually
wanting to give the experts some work to be doing...
When calling any of the procedures, of course, you must remember that
we've added that first parameter - "this" - to each procedure...so,
push the address of your interface record onto the stack as the first
parameter before making the "CALL"...this can be simplified into some
"COMCall" macro that automatically pushes the address as well as
calling the procedure offset from the same address for convenience
because it's always the same thing for any COM procedure call (that's
really the thing that the C++ compiler does "behind your back"...it
automatically adds on the "this" as the first parameter and
automatically push the "this" address on the stack as the first
parameter when you call...because this is always the same thing every
time, the C++ compiler can "automate" the process and simply hide it
from view...do I agree with this "hiding"? No, not at all...BUT
_that's what happens_, my own views aside for the moment :)...
COM objects can be simplified greatly when addressed without the
confusing OOP jargon...a "COM interface" is: a record of pointers to
procedures, where every pointer takes the address of that record as
its first parameter...the first three procedures are "QueryInterface",
"AddRef" and "Release" in that order (these are to "control" the
"lifetime" of the object...in practice, you'll just use "Release" to
close down the object when you're finished...you _might_, perhaps,
need "AddRef" if you're copying the pointer around a multi-threaded
application or something...but probably not..."QueryInterface" tends
to be useless for DirectX because, instead, you grab your first
"interface pointer" by using an ordinary API function like
"Direct3DCreate9" and then all the other COM objects tend to be
"connected" (e.g. you can create a "Direct3DDevice9" by calling the
"CreateDevice" procedure in the "IDirect3D9" you're provided...from
that interface, you can call procedures to create textures and so
forth...there also tends to be a "backlink" procedure with every
interface too, anyway...that is, the "IDirect3DDevice9::GetDirect3D"
procedure returns the "IDirect3D9" pointer that the "device" was
created from, anyhow...DirectX keeps track so you can always ask if
you "get lost" but then you're never going to "get lost" keeping track
of your pointers, anyway, are you? If you know what's going on,
there's actually very little use for these "backlink"
procedures...added, no doubt, just to support some similar API call
for VB programmers in the VB interfaces to DirectX because they tend
to have no idea what they are doing that such redundency is
"useful"...but like plotting your own graphics, there's actually often
never any legitimate need to read from the screen itself (a slow
operation)...rather read from your data and _know_ what's on the
screen instead ;)...
COM isn't overly complicated and DirectX doesn't even use all of its
feature, anyway, that using it for DirectX is even more
simplified...and there's nothing particularly "HLA specific" in the
methods mentioned here (well, other than the extra support HLA
provides for parameter checking on all the procedures...which is
optional, if you don't like or don't care :)...you can use a
"structure" in some other assembler like MASM or NASM (HLA just likes
to call this "record" instead ;)...using the constants method will
work in assemblers that find structures to be "anti-assembly"...
I Hope this begins to clarify things...there's more I could write and
I did start a bunch of HLA header files for DirectX before (well, I
know what to do so I could put together a bunch of them with all the
parameters and so forth then hand them over to Randy to put in HLA "as
standard" :)...but it's very tedious stuff to do it for _all_ of
DirectX (and I was putting in support for _all_ the versions
too...well, again, more of the same...not more "difficult", just "more
tedious" ;)...and then I got distracted doing other things and it
really is exceedingly boring to do that I couldn't get motivated
enough to be bothered to go back to it...I may eventually get around
to finishing that off so that then HLA has it "as standard"...it's not
that, magically, HLA can't do it but RosAsm can...it's a case of
RosAsm having the tireless Guga putting together all the "equates" for
Rene (a massive and tedious piece of work to do...hats off and respect
to Guga for the support...without that work being contributed to him,
Rene would not be able to smile as widely as he does ;)...where
"equates file" is just RosAsm's version of the same kind of "header
file" thing I mentioned here for HLA...Randy's a productive little
worker, indeed, but there are limits to what one person can do (and
writing all those books and articles and just getting HLA functional,
as well as work on HLA v2.0...well, he's already doing enough to make
everyone else look a touch lazy ;)...well, stuff like this - as well
as needing similar "header files" for LuxAsm - that prompted the
"okay, this is getting silly...isn't there an easier way to do this
with some automated tool rather than slogging through it all line by
line?"...a great idea but still no real response to the ConvInc
project I set up on SourceForge...I guess I should accept no-one's
interested - or won't get interested until some "version 1" has been
written - and that I should just plough on ahead by myself on
that...this is fine but, well, didn't want to march on ahead and then
have people show up all and disagreeing with what I've done
and that kind of thing...but, hey, if there's no "team", in fact, then
there's no need for me to consider "being a team player" or "the need
for teamwork" and that kind of thing...I'll just plough on ahead and
see if anyone becomes interested later once I've got something basic
working or whatever...
Beth :)
| |
|
| Randy wrote:
> Personally, I've never worked with Direct-X, so I can't offer
> any more insights into this issue. However, you might ask
> Beth Stone, who has played around with Direct-X in assembly
> a bit.
Indeed; I've posted up my assistance now...sorry about the massive
delay...too many other threads in the newsgroup going on and kind of
missed this one until now (just quickly looking over things)...Hope
I'm not so exceedingly late in reply that I've missed the original
poster completely...oops! ;)...
Beth :)
| |
|
| "Beth" <BethStone21@hotmail.NOSPICEDHAM.com> wrote in message news:<qR0nc.19$Gz6.7@newsfe5-gui.server.ntli.net>...
>
> You can concern yourself with all the object-orientated stuff but, as
> has been contended, it's an awful lot of work for no particular reason
> or benefit...considering it from a non-OOP point of view vastly
> simplifies the problem without losing a sole "feature" from OOP...
Thanks Beth. This has been a very useful article in helping me
understand some of those pesky C++ header files.
| |
|
| Kain wrote:
> Beth wrote:
as[color=darkred]
reason[color=darkred]
>
> Thanks Beth. This has been a very useful article in helping me
> understand some of those pesky C++ header files.
Pleasure...
Beth :)
| |
|
| Randy wrote:
> NoDot wrote:
on[color=darkred]
>
> If you're using HLA *classes* and the high-level HLA class
invocation
> mechanism, it uses ESI. However, don't forget that you can easily
pass
> the object pointer on the stack yourself (this is assembly language,
after
> all, you don't *always* have to use the high-level features in
assembly
> :-)).
> If you like clean, HLL-like syntax for the calls, you can easily
create a
> macro that does the work for you.
True; But as COM "objects" don't carry any data - only a "table of
pointers" - and you're already giving up on the "class invocation
mechanism" then it begins to become a case of: "Why use _any_ of the
HLA class stuff at all for COM?"...
The "record" stuff works admirably (and, in actual fact, is what C
uses, of course...because C++ has OOP but C doesn't...Microsoft use
special "macros" in their header files that expand different ways to
support the two simultaneously...mind you, incredibly messy that I'm
wondering if it wouldn't have been simpler to make separate C and C++
headers for those particular bits and then perhaps an "#ifdef", just
to select whether to include the ".h" or the ".hpp" ;)...mind you, so
does Rene using his "offset constants" stuff too...
Beth :)
| |
|
| Charles Banas wrote:
> Randy wrote:
the[color=darkred]
interfaces to[color=darkred]
very[color=darkred]
is to[color=darkred]
external[color=darkred]
>
> which i submit is a difficult task given that DirectX makes copious
use
> of C++ classes with just about every feature known to man:
> multiple-inheritance, virtual functions, etc.
To which I submit you're displaying a misunderstanding of COM itself
here...
"COM" - the "component object model" - is a _language-independent_
binary standard for object-orientation...in other words, COM is
_DESIGNED_ to have no "bias" whatsoever to any language...it's a
_binary standard_ below language considerations exactly so that OOP
can be offered by the OS to _ANY_ programming language...a COM
"interface" only consists of public procedures and no data whatsoever,
as procedures are "universal" (the target of a "CALL" instruction ;)
and have "conventions" defined across languages, whereas data and data
types vary significantly from language to language...
The header files that Microsoft produce in order to use C++ to
_interface_ with DirectX may make use of C++ classes (which is
actually somewhat inaccurate and standardised and simplified by COM's
structure, anyway)...but "DirectX" doesn't...it uses COM which is a
binary standard for object-orientation that is actually _simplified_
by this...
The jargon of "multiple inheritance" (actually, where does this happen
in DirectX specifically? All the "interfaces" I've looked at inherit
from "IUnknown" and only "IUnknown"...yes, this kind of thing happens
in the more complicated "OLE" stuff that's built atop of COM...but not
in the underlying COM binary standard itself...DirectX is COM - and a
simplistic use of it at that - not OLE) and "virtual functions"
unnecessarily complicates the matter...I really wish this jargon would
either be properly explained or just disappear...
A COM object is just a structure (or "record") of procedures, where
they take a pointer to that structure's address as their first
parameter ("this")...when a procedure has a "this" pointer to the
structure that contains it, it gets renamed a "method" just to
distinguish this property..."inheritance" is basically the practice of
_merging_ two structures together (that is, putting both members into
one structure BUT, where there are common members, these are "merged"
and listed just _once_)...a "class" is the _definition_ (the "typedef
struct" ;) of that structure, an "instance" is a variable instance of
that structure...
In the case of DirectX and COM, the "virtual functions" thing is a red
herring that complicates things...as COM is separate from the
programming language (which may or may not have OOP features in it :),
this is actually a consequence of trying to view a simple use of
structures from the viewpoint of the OOP jargon...what's actually
happening is quite simple...
A COM "interface" is a structure / record of procedures...when you get
an "interface on a pointer" (that's what Microsoft call it to confuse
the matter...this simply means "when you get a pointer to one of these
'interface' structures" :) handed to you by some API like
"Direct3DCreate9" (which is just an ordinary DLL function)...the
structure that it points to is _filled out with the actual addresses_
of the various procedures you can call...but when you're defining
these structures in your source code, you are just "reserving space"
for each procedure...you're not actually filling these out with the
actual addresses of procedures because, at this point, you don't know
what those addresses are going to be, as it's the DirectX DLLs which
supply them...
Now, ordinarily, when using C++, you define your "structure" with the
"class" keyword and then write the procedures that will be stored in
that structure...the C++ compiler automatically creates a table of the
addresses and loads this into the structure when you create an object
of that type...this is perfectly possible because you're defining the
"class" structure _and_ the procedures that will go into it at the
same time...
But this doesn't make sense when the objects are _EXTERNAL_ to the
program...their addresses must be supplied by that external DLL file
or whatever...hence, you are only making use of declaring these
procedures as "virtual methods" in order that you are only "reserving
space" for where the procedure address will go, not actually attaching
any address to it yourself (when you get a COM object structure from
the OS, the addresses will be provided then)...
To try to clarify even more obviously, this is your "interface"
definition...using MASM syntax because this syntax makes it abundently
clear what the "virtual" stuff is actually for:
----------------- 8< ---------------------
ISomeObject struct
QueryInterface dword ?
AddRef dword ?
Release dword ?
MethodOne dword ?
MethodTwo dword ?
ISomeObject ends
----------------- >8 ---------------------
The "virtual" really means the same as the "?" here...that you're only
_defining_ the structure of the interface, you're NOT yet assigning it
any actual addresses...when you get an "interface" passed to you by
DirectX, each of the "dword" entries here will actually contain an
_actual address_ for the method call...but, in your code, you define
only the _structure_ and it's DirectX that supplies the actual
addresses (that "fills out" your structure with useful data :)...
The need in C++ to put "virtual" on this is because, ordinarily, the
classes you define are your own classes defined _internally_...that
is, I'd also be including the source code for
"ISomeObject::MethodOne", "ISomeObject::MethodTwo" elsewhere in my
source code...when the compiler compiles this "class", it creates the
above structure...but it also creates a VMT ("virtual method table")
where it will create a table of procedure addresses to the "methods"
defined by this class in the correct order...in other words, this
"table" is the empty structure _filled out_ with the correct
addresses...as part of creating an object (using "new" ;), the C++
compiler inserts some code ("hidden" code ;) which copies the "VMT"
data with the actual addresses into a newly allocated structure of the
type "ISomeObject"...
Well, in the case of an object that's _external_, then we don't
actually know what those addresses are going to be yet...hence, you
declare them "virtual", which means they aren't to be alloted any
specific addresses (the use of "?" in MASM there to define the
structure without specifying it should have any initialisers
;)...those addresses will be provided when DirectX hands you an
"instance" of the structure that's properly filled out...
This is another case of the jargon and OOPL stuff actually
_complicating_ what is actually a simple matter:
DirectX hands you a table of procedure addresses (where according to
its definition, the first procedure address in the table is for
"QueryInterface" for this object, the second procedure address in the
table is for "AddRef" for this object, the third procedure in the
table is for "Release" for this object...presuming my example above,
the fourth procedure in the table is for "MethodOne" for this object,
the fifth procedure address in the table is for "MethodTwo" for this
object...and so on and so forth)...
There's only one remarkable thing about these procedures: Their first
parameter is always a pointer to the start address of this table
itself...the so-called "this" pointer...
What does the "this" pointer do? Well, you can create many instances
of this object structure (for example, you may have a "texture" object
under DirectX...well, your 3D scene requires more than one "texture"
and, thus, has one of these structures for each texture :)...on the
other hand, the procedures inside the structure are likely to all be
the same for each instance of that object so those address filled out
are likely to be exactly the same address for each procedure...hence,
all that the "this" pointer does is provide those procedures with the
address of the instance's structure so that it knows to work on the
right object...it acts as a "handle to an object", which just so
happens to be the address of its structure (being an address, it's
automatically guaranteed to be "unique" for each object because you
can't put more than one thing in the same memory at the same time ;)
so that the procedure can not only identify the object, it can jump
directly into its contents...
If you've used the C standard library, then you might have noticed
that the standard file I/O functions return you a "file handle"...but
the "type" of this "file handle" is "FILE *"...or, in fact, a "pointer
to a FILE"...what's the "FILE" data type? A structure containing all
the data that relates to a "file" for the procedures to use in
manipulating it..."fopen", "fread", "fwrite", "fclose" all take a
"FILE *" file handle as one of their parameters...to initialise the
contents of the structure with valid information, you must call
"fopen" first to open the file and this procedure fills out the
internal details into the structure..."fread", "fwrite" and "fclose"
read the contents of the "FILE" structure in order to get data from
the structure about the current file...also, the actual layout of the
"FILE" structure is implementation-dependent...you shouldn't really
need to ever look inside it or know what it's definition is
("information hiding")...
Yup, a file with these stanard library functions is really an
"object"...but just implemented without OOP...you'll note that files
are not unique in having an "open" function which returns some kind of
"handle", which you then pass onto other related functions which
manipulate the "object" in some way before handing it to some "close"
function...this layout is, in fact, so common, they invented OOP to
standardise the mechanisms...invented languages where you could use a
bunch of OOP "keywords" which would automatically layout code in this
thing "encapsulated" form...automate lots of the "hard work" and
repetitive bits of implementing something like this...
While they were at it, they also decided that if they put the
addresses of the functions like "fread", "fwrite" and "fclose" into
that "FILE" structure too then you could do some other clever stuff
like actually change the address of one of these procedures at
run-time...because another common thing was to notice that you'd often
get "common" stuff in your objects...wouldn't it be kind of to
NOT copy this _common code_ into both objects but to, well, change
that address in the structure instead? That is, we could create two
"FILE" structures but then change the "fread" and "fwrite" on one of
these "FILE" structures to use a different procedure instead...but all
the other procedures are the same...so, this changed structure kind of
"inherits" the stuff from the standard "FILE" structure but changes
things and adds new bits on...yup, "inheritance"...and, yup, putting
the addresses of the functions into the structure? "virtual
methods"...
OOP is NOT "voodoo black magic"...it _doesn't_ need all the fancy
jargon (which, to be honest, almost universally _confuses_ people more
than it clarifies things for them ;)...it was an idea based on
_practice_...programmers were noticing a common pattern of having a
bunch of data (usually in a structure, just to keep it altogether :)
that you'd allocate and then call some "Initialise" function on, which
initialised the data in the structure to initial / default
values...then there'd be a bunch of procedures that you'd call,
supplying the address of the structure of data, which would do things
and manipulate the values of that data...then, after use, they'd be
some "Uninitialise" function which closed things down and de-allocated
memory and that kind of thing...and all these things related to some
kind of "object", like "a file", "a printer", "a texture" or
whatever...some, in fact - though not Soustroupe, who reckons the
"multi-paradigm" (that you can use it OOP or non-OOP at the same time
;) stuff in C++ is one of its strong points - were even going so far
as wondering if you couldn't simply make _everything_ an "object" and
always follow this layout...
OOP was just the attempt to add on keywords and support to programming
languages to be able to automate all the bits that were always the
same when following this "object" kind of way of structuring your
program...and it is, in fact, somewhat a _betrayal_ to the initial
_PRACTICAL_ (and even slightly "hackerish") origins of OOP that it has
now been covered in impenetrable jargon and is the "academic's
darling", full of "theories" and an awful lot of that academic
bullshitting about how it's some "new philosophy for living!", "it's
the Second Coming!!" and so forth...
Nope, it's just about laying out your code in an organised and ordered
fashion, based around using "structures" (just a group of contiguous
data variables...put next to each other for convenience of doing
things like copying it all in one go ;)...I've said here before but I
would rename what "OOP" stands for: "Ordered and organised
programming"...that's all it is really about...standardising a method
of programming in an ordered and organised fashion (that all other OOP
practitioners are also following)...
> wrtiting support for all of that in a language is no easy task, i'm
> sure, and creates quite a bit of difficulty in calling any DirectX
code.
Ummm, Rene manages the support in RosAsm with a bunch of constants and
an indirect CALL!! Which is fair enough, as all "structure support"
is, is a thing for, well, automatically generating "offset constants"
(and, though TASM doesn't agree, handling "scope" and stuff ;)...
One of the main design criteria of COM was that it should be
"unbiased" and could be used in _any_ programming language...the sole
criteria that you absolutely need is to be able to "CALL" a procedure
via a "pointer variable" (an "indirect" function call ;)...if you can
do that in your language, you can use COM...it was _DESIGNED_ that
way:
"The only language requirement for COM is that code is generated in a
language that can create structures of pointers and, either explicitly
or implicitly, call functions through pointers. Object-oriented
languages such as C++ and Smalltalk provide programming mechanisms
that simplify the implementation of COM objects, but languages such as
C, Pascal, Ada, Java, and even BASIC programming environments can
create and use COM objects."
[ From Microsoft's COM documentation...actually, the _third paragraph_
in the COM documentation that you don't have to read too far into it
to find it...does _ANYONE_ "RTFM" anymore? ;) ]
Note, for the "structure of pointers", I'm disagreeing with Microsoft
that is a strict "requirement" because Rene gets by with "offset
constants" as a replacement for "structure support"...and you could
also - as all COM interfaces include _only_ procedure addresses, only
"pointers" - also consider a COM object as "an array of DWORDs" (well,
"array of pointers", which just happens to be DWORDs on an x86
machine, to be more precise to avoid the pedants ;) because all the
elements in a COM object "structure" are actually all the same
size...and it's only a logical thing between a "structure of equally
sized elements" and an "array"...
If you _IGNORE_ the C++ and OOP jargon and the other "Jackson
Pollocks" found in most documentation to confuse you, then it's
actually almost _offensive_ the degree to which they make it sound
like complex neuro-surgery with the OOP jargon, when it's quite the
opposite and, actually, exceedingly _easy_ to use and understand...
DirectX passes you an "array of procedure pointers"...each entry in
this "table" is a different procedure (the order can be determined by
looking at some DirectX header files, like the C / C++ ones Microsoft
provide...it's quite "poor show" that the DirectX documentation
doesn't _explicitly_ state the order of the entries in the
table...but, as we've seen, they don't seem interested in actually
explaining any of it in a _useful_ manner ;)...they all take the
address of the table itself as the first parameter (so the procedure
can "work out" which one of many possible similar structures it
actually is working on this time ;)...that's it in terms of the
physicality...
In terms of use, you call an ordinary API function like
"DirectSoundCreate" or whatever to get your first "table of
pointers"...after that, these tables tend to point to one another
(that is, "IDirect3D9" has a "CreateDevice" to get a
"IDirect3DDevice"...or "IDirectSound" has a "CreateBuffer" to get a
"IDirectSoundBuffer"...and so on and so forth...once you've got one of
these structures, they tend to be designed that you just use the
procedures in the structures themselves to do everything...you just
need the DLL API function to "start you off" with the first table /
record / array / structure to get yourself _into_ this "maze of
pointers" ;)...
Each "object" is responsible for its own "lifetime"...which is
actually maintained by just keeping a "reference count"...when you
create an object, the reference count goes to one...when you call
"Release" to say "there, finished.", the reference count is
decremented by one ("AddRef" does the reverse and adds one onto the
count...you can use this to "hold open" objects or when you copy
pointers around a program...you can add one onto the count - increase
it to two - to say "okay, two 'clients' are holding pointers to it at
the same time, expect two 'Release' calls before closing from each of
them" ;)...when the count is zero, the object actually de-allocates
itself..."QueryInterface"? Mostly pointless...the idea is that some
objects may have more than one type of "structure" that applies to
them, so you can use "QueryInterface" to get the other type of
structures for this object...used by OLE, not by DirectX (the idea
being that you could create an "interface" like "IStorage" which
contains "Load" and "Save" procedures inside it...well, you could
"re-use" that kind of "interface" on a whole bunch of objects...it's
like some "code re-use" stuff that is more effort than it's worth that
DirectX doesn't bother, OLE uses it a bit but, well, you can tell that
not even Microsoft are particularly impressed with "QueryInterface"
and don't bother using it much either ;)...
As for the rest of the procedures in the "interface"? Well, that all
depends on what object it is...read the DirectX documentation for that
stuff about how to do flashy 3D graphics and stuff with the
"interfaces" ;)...
> IMHO, the solution to the issue is to create a wrapper library
(written
> in C++) that exports (in a C or Pascal-like calling convention) all
of
> the functions that one might need to write DirectX code. AFAIK,
other
> than OpenGL/DirectX wrappers, no such wrapper exists.
For ASM use? Doesn't seem worth the bother...it really isn't that
complex...what you're suffering under is the stream of OOP jargonising
confusion and really badly written documentation about how it
works...DirectX hands you a "table of pointers"...you indirectly call
the right entry in the table, passing the address of the table itself
as the first parameter (also, of course, push the other parameters -
if it has any - too ;)...and...and...that's it...
The real problem is all the tons and tons of "interfaces" and
constants and flags and structures and all that...real tedious to
create your own sets of header files for these things...but, well, for
HLA, no-one has appeared to have done it yet (I was working on it but
it really is _immensely boring_ that I got bored...if I can manage to
keep my eyes open, then I might finish these and pass them onto
Randy...then, at least, only _one_ person has to go through all the
really tediously boring stuff of creating records here and records
there ;)...
There's also somewhat limited support on all the assemblers for
this...it's pretty to find, usually, a full set of Win32 API
header files...DirectX tends to be not there or it's just the earlier
DirectX 3 only or something like that...RosAsm seems to have some of
the furthest work in getting DirectX supported (well, it's "specific"
so stands to reason ;)...but even Rene has to admit to it not being
fully supported, just "mostly supported" (better than most everyone
else, though...so no "insult" intended at all there ;)...
to[color=darkred]
usable[color=darkred]
>
> which, honestly, still seems like quite a feat with all fo the
features
> and code bloat that DirectX takes advantage of.
Ah, DirectX itself might be bloated (though, it is one of Microsoft's
"finer" bits of code...basically because it does as little as
possible...just really a kind of "filter" sitting on top of the device
drivers, which actually do all the impressive work ;)...but the
interface to it isn't...
Mind you - addressing Randy now - the creation of _COM_
"object-orientated modules" ain't quite such a breeze...it _would_ be
if "this" could also be passed via the first parameter on the stack as
well as ESI, somehow...that's why, in my examples, Randy, I'm using
"record" and not "class"...it's _good_ that you've put "this" into a
register for HLA for OOP code generated in HLA itself...but, well, the
C++ / COM stuff isn't so concern for "optimised" solutions, as you
might imagine...so they stuff it onto the stack like all other HLL
function parameters...if you could allow a touch of "customisation" to
the OOP support to specify where "this" is passed?
A "compatibility" thing, really...ESI is a good place to pass it for
HLA classes...but, well, to fit in with C++ / COM classes, then you've
got to do it the same way as them to be "compatible", whether that's a
good idea generally or not...much like passing parameters in registers
is much better for lots of ASM code but you've got to put them onto
that stack when it's "STDCALL" or "CDECL" and so forth...
from[color=darkred]
>
> including Microsoft's COM code bloat?
Yes; In fact, drop the "just about"..._THAT_ is the beauty of assembly
language, you can interface with _ANYTHING_...absolutely no
"qualifier" attached at all...in assembly language, you can generate
_any_ sequence of "zeroes and ones" that you like...so - other than
some bizarre "non-binary computer" - you can interface to
_ANYTHING_...
Now, ah, whether it's "easy" to do that is another matter...I won't
make any guarantees about it being "easy"...quite the opposite...some
things would be stupidly complex to interface to...but, luckily for
you if you want to use DirectX, COM actually _isn't_ one of those
things...
> the comp.lang.C++ FAQ outlines some of the problems in section
[32.8,
> 9]. http://www.parashift.com/c++-faq-lite/
Actually, many of the "complexities" you're looking are actually about
the _reverse_...the ASM is _simple_ but the C++ - having twisted
itself up in knots with a very _particular_ method of structuring its
OOP support - has to "jump through hoops" to effectively "undo" its
own complexity...
Oh, yeah...I know...everyone tells you "ASM is complex, ASM is
difficult, ASM is impossible" and so forth...so how could ASM actually
be the one where things are _easy_ but C++ is where it is
unnecessarily complicated?
Welcome to the wonderful world of the misrepresentative "myths" about
ASM coding that are spread as gossip out there...working at the most
elemental and low-level possible can actually _SIMPLIFY_ some tasks...
> i don't deny it's possible to se DirectX from HLA. but is it worth
all
> of the work involved in *CREATING* the header files and libraries
you need?
It's not that much work...although, admittedly, I feel asleep in the
middle of trying...but that's because it's _tedious_ (grab a structure
from the C files, change the syntax, grab another, change the syntax,
grab another...and so on for far, far too many structures for one
small mind like mine to cope with ;)...it's not "difficult",
though...I gave a rough "cut and paste" method to get basic support in
one of my other posts...literally, "copy and paste", strip off macro
crap, add ":procedure;" to each line...then repeat for every
structure...in fact, using that way I might have got through it
without falling asleep but thought that "if you're going to do it, do
it properly" and added in all the parameters and stuff too...
Oh - note to Randy - there's a method in one of the Direct3D
interfaces called "Begin" and another one called "End"...keyword
clash!!! Still trying to work out what it would be best to rename them
to...but perhaps you get why I was talking about keeping "namespaces"
as "unpolluted" as possible...mind you, Microsoft's naming strategy
just isn't good for ASM, anyway...such as all that "cx" stuff (great
"role model" example of a "descriptive meaningful label name" there,
eh? How many out there, not knowing Microsoft's conventions, could
work this out as meaning "width"? Another good thing about
X-Windows...it calls the width parameter "width" (and height is
"height" ;), as you'd kind of expect, naturally enough...Microsoft
thinks "cx" says "width" to people...just exactly what planet - or
should that be solar system - are they living in? ;)...
Beth ;)
| |
|
| "Beth" <BethStone21@hotmail.NOSPICEDHAM.com> wrote in message news:<d21nc.20$6V3.5@newsfe1-win>...
> Randy wrote:
>
> Indeed; I've posted up my assistance now...sorry about the massive
> delay...too many other threads in the newsgroup going on and kind of
> missed this one until now (just quickly looking over things)...Hope
> I'm not so exceedingly late in reply that I've missed the original
> poster completely...oops! ;)...
>
> Beth :)
Beth, if your correct, then I've been right all along about the VTable
format.
That being the case, I must have another bug in the system. This is
what I've created for a micro-test:
-------------------------------------------------------------------
Program DXTest;
#asm;
includelib \masm32\directX\all-libs-except-d3dx8\d3d8.lib
#endasm;
Procedure D3DCreate;
@external("__imp__Direct3DCreate8@4");
Const
IDirect3D_Release := 8;
Begin DXTest;
pushd(31);
call(D3DCreate); // Create the Object
push(eax);
mov([eax], eax); // Load VTable
call([eax+IDirect3D_Release]);
add(8, esp); // Clean the Stack
End DXTest;
-------------------------------------------------------------------
The program ends with a terminating message in the form, "This program
has preformed an illeagal operation." blah. I'm using DirectX 8. Can
you tell me what's going on?
| |
|
| The Half a Wanna bee <shakainzulu@hotmail.com> icrivait
news:409e9f0f$1@news.broadpark.no:
[color=darkred]
> NoDot wrote:
:)) An empty answer is a bit surprising, at first look,
but after thinking of it, it seems to me the most
appropriated answer... :))
Betov.
< http://betov.free.fr/RosAsm.html >
| |
| Frank Kotler 2004-05-12, 7:19 pm |
| NoDot wrote:
> Program DXTest;
>
> #asm;
> includelib \masm32\directX\all-libs-except-d3dx8\d3d8.lib
> #endasm;
>
> Procedure D3DCreate;
> @external("__imp__Direct3DCreate8@4");
>
> Const
> IDirect3D_Release := 8;
>
> Begin DXTest;
> pushd(31);
> call(D3DCreate); // Create the Object
> push(eax);
> mov([eax], eax); // Load VTable
> call([eax+IDirect3D_Release]);
> add(8, esp); // Clean the Stack
> End DXTest;
> -------------------------------------------------------------------
>
> The program ends with a terminating message in the form, "This program
> has preformed an illeagal operation." blah. I'm using DirectX 8. Can
> you tell me what's going on?
You've performed an illegal operation. :)
Just as a wild-asmed guess - I'm not familiar with DirectX - is this
stuff stdcall like the usual API? If so, you don't want to clean the
stack. If it's C calling convention, you do. You know that, I'm sure...
best I can do...
Best,
Frank
| |
|
| Frank Kotler <fbkotler@comcast.net> wrote in message news:<409FDE13.FFDA90CB@comcast.net>...
> Just as a wild-asmed guess - I'm not familiar with DirectX - is this
> stuff stdcall like the usual API? If so, you don't want to clean the
> stack. If it's C calling convention, you do. You know that, I'm sure...
> best I can do...
>
> Best,
> Frank
Reduced the ADD to four... same problem.
Commented out the ADD... same problem.
:-(
HELP! PLEASE!
| |
|
| no_dot@msn.com (NoDot) icrivait
news:dfed44a6.0405101807.b373f2a@posting.google.com:
> Reduced the ADD to four... same problem.
> Commented out the ADD... same problem.
> :-(
> HELP! PLEASE!
Well, OK, we are far too crual with you. Sorry. ;)
So, i am going to help you: Download any Assembler.
The ones of interrest are:
NASM: < http://sourceforge.net/projects/nasm >
RosAsm: < http://betov.free.fr/RosAsm.html >
FASM: < http://flatassembler.net/ >
GoAsm: < http://www.godevtool.com/index.html >
For most -if not all-, you will find out several good
examples about how to do DX. This is very simple, and,
with an Assembler, simple things are simple to do. ;)
For RosAsm (SpAsm, more exactely), for example, you will
find a pretty good Page (dedicated to SpAsm), with quite
impressive examples, at:
< http://www.chez.com/asmgges/index.htm >
.... and/or several good demos at RosAsm Users Demos Page:
< http://betov.free.fr/UsersDemos.html >
This should help a lot. Courage, Betov.
< http://betov.free.fr/RosAsm.html >
| |
|
| NoDot wrote:
> Beth wrote:
of[color=darkred]
things)...Hope[color=darkred]
>
> Beth, if your correct, then I've been right all along about the
VTable
> format.
>
> That being the case, I must have another bug in the system. This is
> what I've created for a micro-test:
>
> -------------------------------------------------------------------
> Program DXTest;
>
> #asm;
> includelib \masm32\directX\all-libs-except-d3dx8\d3d8.lib
> #endasm;
>
> Procedure D3DCreate;
> @external("__imp__Direct3DCreate8@4");
>
> Const
> IDirect3D_Release := 8;
>
> Begin DXTest;
> pushd(31);
Right, this number "D3D_SDK_VERSION" is used as a kind of "ID number"
for the version of the SDK header files you're compiling against
(yeah, Microsoft for you...no consideration that someone won't be
compiling against the C headers ;)...the number apparently has no
meaning other than that Microsoft _CHANGE_ it every time they make a
significant change to the header files...I suppose a kind of
"subversion" number, really...
Anyway, "D3D_SDK_VERSION" is "31" - like you've written here - in the
_DirectX 9_ header files (d3d9.h) but NOT in the DirectX 8 header
files (d3d8.h)...you're using the wrong number...
Yes, this number isn't a "constant" in the usual sense...it's a
"header file ID number", basically...so, grab the value out of the
_correct_ header file for the version of DirectX you're using...
Looking into my own DX8 header files (of which I actually have
two...an older one and what should be the latest one ;) then the older
one has "120" but the newer one has "220"...I'd go with the "220" but,
if that fails, try "120" (or update your DirectX versions ;)...
> call(D3DCreate); // Create the Object
> push(eax);
Seeing as you've been passing what looks like the _wrong_
"D3D_SDK_VERSION" then the "D3DCreate" call might have failed and
returned NULL to say "no Direct3D object created"...
Regardless of this, you're steaming on ahead because you've not
checked the error return...oops!! ;)...
> mov([eax], eax); // Load VTable
> call([eax+IDirect3D_Release]);
If the return was NULL because it couldn't create the Direct3D object
(because you've supplied the "D3D_SDK_VERSION" for DirectX9, not
DirectX8 ;) then you're now doing: "mov ([NULL], eax); call([ eax +
IDirect3D_Release]);"...goodness knows what kind of sheer madness
you've just instructed Windows to perform!!!
> add(8, esp); // Clean the Stack
Frank was right, by the way; DirectX calls are all STDCALL and, thus,
they clean the stack up themselves automatically...you should remove
this instruction...and you don't need to do this with any DirectX
calls, just as you don't for any Win32 API calls...
> End DXTest;
> -------------------------------------------------------------------
>
> The program ends with a terminating message in the form, "This
program
> has preformed an illeagal operation." blah. I'm using DirectX 8.
Can
> you tell me what's going on?
Actually, you just said it: "I'm using DirectX 8"...but you've gotten
that "31" value for "D3D_SDK_VERSION" from the "d3d9.h" header file,
haven't you? Look into the "d3d8.h" header file and you'll see it's
defined as a different number ("220")...
>From Microsoft's DirectX documentation (the "remarks" for
"Direct3DCreate8" ;)...
"The D3D_SDK_VERSION identifier is passed to Direct3DCreate8 in order
to ensure that an application was built against the correct header
files. This value is incremented whenever a header or other change
would require applications to be rebuilt. If the version does not
match, Direct3DCreate8 will fail."
As you're using the DirectX9 header file's version number rather than
the DirectX8 value, the function is _FAILING_ as the documentation
specifies(!!)...when this function fails, it returns a NULL
value...you're not looking for this failure and are happily carrying
on using the returned NULL in eax, as if it was a valid pointer...
Unsurprisingly, proceeding with "NULL" ends up causing a nasty GP
fault...and up pops the "This program has performed an illegal
operation" box...
Simply, check for a "NULL" return and if it is NULL, then the object
couldn't be created so don't proceed...that is, a "cmp (eax, NULL); je
TerminateProgram;" kind of thing...I mean, you should always be
checking those return values!!
But the real problem that's _causing_ the function to fail to give you
that NULL, which is blowing up your program, is you're just using the
wrong "D3D_SDK_VERSION" for DirectX 8...this number _CHANGES_ every
time the header files change, you see...it's kind of like a
"subversion number", so to speak...the Direct3D DLL file knows all the
valid values for all the applicable header files and only creates an
object when the value is valid...in this case, the value isn't
valid...the function fails....your program starts using NULL pointers
as if they were valid pointers...and BANG! "This program has performed
an illegal operation"...
By the way, on a different note, do Microsoft realise just how
_worrying_ that particular terminology is? Along comes a "Clueless
Newbie", clicks on a program and then - BANG! - "This program has
performed an illegal operation"...
"Illegal?!? It's broken the law!! What's it done that's illegal? Has
the program just electronically robbed a bank behind my back? Is it
running some big drug smuggling operation without telling me? No, it's
probably just tried to hack into the CIA's databases! Awww, crap...the
cyber-cops will be after me now!!"...
The "Clueless Newbie" runs to the bedroom and throws all their clothes
and stuff into a suitcase...they'll have to go "on the run" and "keep
a low profile" from any cops: "bloody computers! I knew I should never
have bought the thing...they're going to | | |