Ok back again, still no luck :(

The Parser correctly loads the skeleton for a while but theres still stack corruption occurring and I don't know where or why.
I've thought this through and theres another way I can tackle this problem.
I can try to build the hierarchy another way.
Instead of parsing it branch by branch, I can parse it level by level.
Let me elucidate: at the moment, our psuedocode looks similar to the following:

-check for Frame object
-while Frame,
--Create ChildFrame and Link appropriately
--check for Data object
--if Data, call self on Data
--endif
--Get Next Object
-endw


What I'm considering doing is something like this:

-check for Frame object
-while Frame,
--Create ChildFrame and Link
--shove pData into Frame so we can enumerate its children
--call Self
--Get Next Object
-endw

What I'm driving at is that we can pass just ONE parm to the procedure being the handle of OUR current object, and it can act as a vessel for the procedure input params as well as being a container for the result.

So if we (for example) find a frame with three children, we'd create three child frames, and shove the appropriate xof pointer in each one, and call self, passing only the child object handle.

It's still nested and iterative but at least we can rest assured that the xofpointer is not being corrupted on the Stack, and we reduce the local stackframe size significantly. It's got to be a Good Thing, right?
The way I'll implement it is as follows:
The FramesLoader will use the pMeshes field of the FrameNode structure as a temporary holder for that frame's xof pointer.
When a Frame is completely parsed, the pMeshes will (again) be zeroed.
If a Frame is found to contain a Mesh, we'll shove the Mesh's xof pointer into an application global and pretend it didn't happen, until all the Frames are parsed, and deal with it then. We can do this because we know we have just one Mesh.
Posted on 2003-10-10 11:53:11 by Homer
Ok screw that last post :mad:
I fired up ole faithful (OllyDebug) and got funky on this bug.
I tracked it down to my LinkedLists_AppendSiblings function, in the instance where it seeks the last sibling of a current node.
I added a new function (LinkedLists_FindLastSibling) which was effectively the SAME DAMN CODE, and replaced the offending code in AppendSiblings with a call to that instead.
I disabled all attempts to handle non Frame dataobjects.
I am now loading the Frames Hierarchy 100%.
SWEET !!

Now I have to archive the current source and then try to get it to recognize the other Object types again (frame matrices, mesh, anime, etc)

I feel better than James Brown :alright:
Posted on 2003-10-11 05:03:49 by Homer
Huh? this is weird...

I'm loading the Frames hierarchy all right .. but when I enabled handlers for the other x-entities like Mesh and FrameTransformMatrix, I am no longer detecting them during parsing AT ALL - and I was before, with the same code !!?!
If I don't get anywhere in the next few hours, I'll post the entire current SkinMesh Support source with the hope that YOU can help me get the darned parser working correctly ...
Posted on 2003-10-13 17:26:46 by Homer
I rewrote the parser based on yet another cpp example, and it still parses frames ok, but it's still not detecting ANYTHING else...

So here is my version, and below it is the cpp original, for the FrameParser function... note that I'm not handling anything except Frames in my version, but I AM trying to detect them...and not doing so :(

If you can see any critical differences in the code, please let me know.
Also, I am happy to provide source for anything not provided here, if anyone is willing to take a look into this issue with me, just let me know what you want to see and I'll post the current source in this thread.



FrameNode_Load PROC pData:DWORD, ParentFrame:DWORD, pSkinMeshOwner:DWORD
local pSubObj:DWORD
local pSubData:DWORD
local pDataRef:DWORD
local pType:LPGUID
local NameBuf[256]:BYTE
local ErrBuf[256]:BYTE
local pmeshnode:LPMESHNODE
local panimationset:LPANIMATIONNODE
local dwSize:DWORD
local hFrame:LPFRAMENODE
local pmat:LPD3DXMATRIX
local dwsize:DWORD
local hname:DWORD
;===============================================================================
;Initialize locals (DX can be finicky - some output args can also be input args !!)
;===============================================================================
xor eax,eax
mov pSubObj,eax
mov pSubData,eax
mov pDataRef,eax
mov pType,eax
mov NameBuf[0],al
mov dwSize,eax
mov hFrame,eax
mov pmeshnode,eax
mov panimationset,eax
;=======================================================================================
;Create a new Frame,fetch Name of XFile DataObject, set FrameName to same, and attach Frame to "Parent"
;=======================================================================================
mov hFrame, $invoke (LinkedLists_AppendSibling,ParentFrame,NULL, sizeof FrameNode)
.if hFrame==NULL
Errr CTXT("Error - Failed to create FrameNode")
.endif
.if $mcall (pData,IDirectXFileData_GetName, NULL, addr dwSize)!=D3D_OK
Errr CTXT("Failed to get Template Name Length")
.elseif dwSize!=0
mcall ,IDirectXFileData_GetName, addr NameBuf, addr dwSize
.endif
.if NameBuf[0]== NULL ; // Give a default name if none found
invoke lstrcpy,addr NameBuf, CTXT("$NamelessTemplate$")
.endif
invoke LinkedObjects_SetName, hFrame, addr NameBuf
;===============================================================================
; Scan XFile DataObject for embedded objects
;===============================================================================
mcall ,IDirectXFileData_GetNextObject, ADDR pSubObj
.while eax!=DXFILEERR_NOMOREOBJECTS
.if eax==DXFILEERR_BADVALUE
Errr CTXT("Parser Error - DXFILEERR_BADVALUE - in Frames Parser")
.endif
.if ($mcall (pSubObj, IDirectXFileObject_QueryInterface,addr IID_IDirectXFileData, addr pSubData)) == S_OK
invoke IdentifyTemplate,pSubData
.if eax==Frame
invoke FrameNode_Load,pSubData, hFrame,pSkinMeshOwner
.elseif eax!=Unknown
invoke MessageBox,0,CTXT("NONFRAME IDENTIFIED"),CTXT("YAYYYYYY"),MB_OK
.endif
_saferelease pSubData
.endif
.if ($mcall(pSubObj,IDirectXFileObject_QueryInterface, ADDR IID_IDirectXFileDataReference, ADDR pDataRef)) == S_OK
.if ($mcall(pDataRef,IDirectXFileDataReference_Resolve,addr pSubData))==DXFILE_OK
invoke MessageBox,0,CTXT("REFOBJECT IDENTIFIED"),CTXT("YAYYYYYY"),MB_OK
invoke FrameNode_Load,pSubData, hFrame,pSkinMeshOwner
_saferelease pSubData
.endif
_saferelease pDataRef
.endif
_saferelease pSubObj
mcall ,IDirectXFileData_GetNextObject, ADDR pSubObj
.endw
ret
FrameNode_Load ENDP





00643 HRESULT ParseFrame( LPDIRECTXFILEDATA pFileData, CD3DFileObject* pParentFrame )
00644 {
00645 DWORD dwNameLen=80;
00646 TCHAR strName[80];
00647 if( FAILED( pFileData->GetName( strName, &dwNameLen ) ) )
00648 return E_FAIL;
00649
00650 CD3DFileObject* pFrame = new CD3DFileObject( strName );
00651
00652 // Enumerate child objects.
00653 LPDIRECTXFILEOBJECT pChildObj;
00654 while( SUCCEEDED( pFileData->GetNextObject( &pChildObj ) ) )
00655 {
00656 LPDIRECTXFILEDATA pChildData;
00657 if( SUCCEEDED( pChildObj->QueryInterface( IID_IDirectXFileData,
00658 (VOID**)&pChildData ) ) )
00659 {
00660 const GUID* pGUID;
00661 pChildData->GetType( &pGUID );
00662
00663 if( TID_D3DRMFrame == *pGUID )
00664 ParseFrame( pChildData, pFrame );
00665
00666 if( TID_D3DRMMesh == *pGUID )
00667 ParseMesh( pChildData, pFrame );
00668
00669 if( TID_D3DRMFrameTransformMatrix == *pGUID )
00670 {
00671 DWORD dwSize;
00672 VOID* pData;
00673 if( FAILED( pChildData->GetData( NULL, &dwSize, &pData ) ) )
00674 {
00675 delete pFrame;
00676 return NULL;
00677 }
00678
00679 if( dwSize == sizeof(D3DMATRIX) )
00680 {
00681 // Convert from a left- to a right-handed cordinate system
00682 D3DMATRIX* pmatFrame = (D3DMATRIX*)pData;
00683 pmatFrame->_13 *= -1.0f;
00684 pmatFrame->_31 *= -1.0f;
00685 pmatFrame->_23 *= -1.0f;
00686 pmatFrame->_32 *= -1.0f;
00687 pmatFrame->_43 *= -1.0f;
00688 pFrame->SetMatrix( pmatFrame );
00689 }
00690 }
00691
00692 pChildData->Release();
00693 }
00694
00695 pChildObj->Release();
00696 }
00697
00698 pParentFrame->AddChild( pFrame );
00699 return S_OK;
00700 }
Posted on 2003-10-13 19:41:15 by Homer

I can partially understand the lack of interest if placed in the context of dx9 once more containing Frames support, however the dx9 includes I have seen for masm are far from complete, and the majority of the goodies in dx9 are not within reach of the average graphic card...

HOWEVER

The whole point of coding in asm (for me) is the speed and size benefits achieved in comparison to something more loathsome.
Maybe I am going to sound a little jaded (and even just plain old) by stating the obvious, that almost all commercial games were once hand-optimized for speed.
Even the average village idiot would agree that by optimizing the most-often called code we get to shave enough cpu cycles to put into other things like special effects.

I have stated in the past that I am willing to go it alone if I am forced to, because all the best game houses were formed by talented amateurs like myself, but I am just a little ismuth in the middle of an ocean of high level coders who can implement standard code in a fraction of the time that I can in asm.
I would sorely like to take them to task, and have spent some time developing a set of helper api and macros to this end, based on the examples set forth by some of our regs on this board, including Caleb and Scronty.

What's the problem? Do we need a "Thomas" around here to write tutorials aimed squarely at asmcoders?
The gear I base my work on is all cpp sourcecode.
I simply translate it directly and then look for optimisations.
That's one step up from one Scronty does (he has simply translated existing examples directly, without any further effort).
I don't expect to be congratulated for my work, but I kind of expected some show of interest in my optimisations because I know damn well that a lot of cpp coders waltz through here looking for a handout - and that's exactly what I have offered.
Furthermore, I don't like the masm object support code I have seen because it appears not to support dynamic arrays etc. So I coded an entire library of linked list support code because I wanted it and it wasn't available.
If you want something done (right or wrong, just at all), you have to do it yourself. I truly expected this thread to generate more interest in this forum, and I'm rather disappointed to see that most of us are still thinking in 2D terms ...


How slow are DX Math helpers, can u give us some rough numbers, I'm preparing myself for a good laugh =P

nah I wrote some 3D Matrix/vector manipulation code using the plain FPU as well, I feel there are quite slow but I would like to see how they compare to MS's code.
Posted on 2003-10-13 20:57:46 by x86asm
I can't supply benchmark figures, the benchmark tests I devised were more "feelgood" tests which gave us an idea of how the functions compared over time under actual load.
What I can say is that close up, the differences are not acute, rather like comparing say matrix rotation math to triple plane trigonometry rotation math - the difference becomes pronounced when the number of elements being processed is reasonable - let alone high.

I could quote a few relative examples, but I think you already agree without looking closer - and ultimately, why would I bother, if their code was fast enough?

Only a hardware layer coder can appreciate hand optimized binary code, but anyone can appreciate the result.

Right now though, I'm wondering if anyone is looking at the code I posted up there..
Posted on 2003-10-14 08:40:25 by Homer
Hey EvilH

Could you post the IdentifyTemplate code.

Edit

The only differences I see off hand :-

The C code initializes the dwNameLen variable to the size of the buffer. Should allow you to drop the second call to GetName in the elseif block and guarantees that the object name never exceeds the buffer size. Now it's not likely to be longer than 256 bytes but better safe than hairless.

The DX9 docs I have say the success return value is DXFILE_OK, probably the same as D3D_OK, but again better to be safe.

Maelstrom
Posted on 2003-10-14 16:31:24 by Maelstrom
My IdentifyTemplate procedure is just a wrapper to my IdentifyGUID procedure..

IdentifyTemplate PROC pxobj:DWORD
local pType:DWORD
.if ($mcall (pxobj,IDirectXFileData_GetType,addr pType))== D3D_OK
return ($invoke (IdentifyGUID, pType))
.endif
return Unknown
IdentifyTemplate ENDP

My IdentifyGUID procedure is just a wrapper to Scronty's CmpGUID procedure..

;This procedure attempts to identify a template by its guid...
;Thanks Be to Scronty for the DXGUID include ;)
;(damn hope m$ havent updated... ah well :p)
.data?
szOut db 256 dup (?)
szJoin db 256 dup(?)
Unknown equ 0
Frame equ 1
Mesh equ 2
Material equ 3
Normals equ 4
TextureCoords equ 5
FrameXFormMatrix equ 6
RMInfo equ 7
RMVector equ 8
MeshFace equ 9
MaterialArray equ 10
MeshMaterialList equ 11
RMCoords2d equ 12
Matrix44 equ 13
Animation equ 14
AnimationSet equ 15
AnimationKey equ 16
FloatKeys equ 17
AmbientColor equ 18
DiffuseColor equ 19
SpecularColor equ 20
EmissiveColor equ 21
RMMaterialPower equ 22
ColorRGBA equ 23
ColorRGB equ 24
RMGuid equ 25
RMTextureFilename equ 26
RMTextureReference equ 27
RMIndexedColor equ 28
MeshVertexColors equ 29
RMMaterialWrap equ 30
RMBoolean equ 31
MeshFaceWraps equ 32
RMBoolean2d equ 33
RMTimedFloatKeys equ 34
AnimationOptions equ 35
RMFramePosition equ 36
RMFrameVelocity equ 37
RMFrameRotation equ 38
RMLight equ 39
RMCamera equ 40
RMAppData equ 41
RMLightUmbra equ 42
RMLightRange equ 43
RMLightPenumbra equ 44
RMLightAttenuation equ 45
RMInlineData equ 46
RMUrl equ 47
RMProgressiveMesh equ 48
RMExternalVisual equ 49
RMStringProperty equ 50
RMPropertyBag equ 51
RMRightHanded equ 52
DXFileHeader equ 53
.code

IdentifyGUID PROC pType:DWORD

.if $invoke (CmpGUID, pType, ADDR TID_D3DRMFrame, 16) == 1
return Frame
.elseif $invoke (CmpGUID, pType, ADDR TID_D3DRMMesh, 16) ==1
invoke MessageBox,0,CTXT("MESH IDENTIFIED"),CTXT("YAYYYYYY"),MB_OK
return Mesh
.elseif $invoke (CmpGUID, pType, ADDR TID_D3DRMMaterial, 16 )==1
return Material
.elseif $invoke (CmpGUID, pType, ADDR TID_D3DRMMeshNormals, 16)==1
return Normals
.elseif $invoke (CmpGUID, pType, ADDR TID_D3DRMMeshTextureCoords, 16)==1
return TextureCoords
.elseif $invoke (CmpGUID, pType, ADDR TID_D3DRMFrameTransformMatrix, 16)==1
invoke MessageBox,0,CTXT("FrameXform"),CTXT("YAYYYYYYY"),MB_OK
return FrameXFormMatrix
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMInfo, 16)==1
return RMInfo
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMVector, 16)==1
return RMVector
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMeshFace, 16)==1
return MeshFace
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMaterialArray, 16)==1
return MaterialArray
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMeshMaterialList, 16)==1
return MeshMaterialList
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMCoords2d, 16)==1
return RMCoords2d
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMatrix44, 16)==1
return Matrix44
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMAnimation, 16)==1
invoke MessageBox,NULL, CTXT("ANIMATION was discovered",13,10,"SOMETHING WRONG?"), CTXT("WEIRD"), MB_OK
return Animation
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMAnimationSet, 16)==1
invoke MessageBox,NULL, CTXT("ANIMATIONSET was discovered",13,10,"SOMETHING WRONG?"), CTXT("WEIRD"), MB_OK
return AnimationSet
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMAnimationKey, 16)==1
return AnimationKey
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMFloatKeys, 16)==1
return FloatKeys
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMaterialAmbientColor, 16)==1
return AmbientColor
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMaterialDiffuseColor, 16)==1
return DiffuseColor
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMaterialSpecularColor, 16)==1
return SpecularColor
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMaterialEmissiveColor, 16)==1
return EmissiveColor
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMaterialPower, 16)==1
return RMMaterialPower
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMColorRGBA, 16)==1
return ColorRGBA
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMColorRGB, 16)==1
return ColorRGB
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMGuid, 16)==1
return RMGuid
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMTextureFilename, 16)==1
return RMTextureFilename
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMTextureReference, 16)==1
return RMTextureReference
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMIndexedColor, 16)==1
return RMIndexedColor
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMeshVertexColors, 16)==1
return MeshVertexColors
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMaterialWrap, 16)==1
return RMMaterialWrap
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMBoolean, 16)==1
return RMBoolean
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMMeshFaceWraps, 16)==1
return MeshFaceWraps
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMBoolean2d, 16)==1
return RMBoolean2d
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMTimedFloatKeys, 16)==1
return RMTimedFloatKeys
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMAnimationOptions, 16)==1
return AnimationOptions
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMFramePosition, 16)==1
return RMFramePosition
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMFrameVelocity, 16)==1
return RMFrameVelocity
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMFrameRotation, 16)==1
return RMFrameRotation
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMLight, 16)==1
return RMLight
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMCamera, 16)==1
return RMCamera
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMAppData ,16)==1
return RMAppData
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMLightUmbra, 16)==1
return RMLightUmbra
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMLightRange, 16)==1
return RMLightRange
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMLightPenumbra, 16)==1
return RMLightPenumbra
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMLightAttenuation, 16)==1
return RMLightAttenuation
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMInlineData, 16)==1
return RMInlineData
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMUrl, 16)==1
return RMUrl
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMProgressiveMesh, 16)==1
return RMProgressiveMesh
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMExternalVisual, 16)==1
return RMExternalVisual
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMStringProperty, 16)==1
return RMStringProperty
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMPropertyBag, 16)==1
return RMPropertyBag
.elseif $invoke (CmpGUID, pType,ADDR TID_D3DRMRightHanded, 16)==1
return RMRightHanded
.elseif $invoke (CmpGUID,pType,ADDR TID_DXFILEHeader,16)==1
return DXFileHeader
.else
xor ecx,ecx
.while ecx<16
push ecx
xor eax,eax
mov al,byte ptr pType
invoke wsprintf,addr szJoin,CTXT("%lX"),eax
invoke lstrcat,addr szOut, addr szJoin
pop ecx
inc ecx
.endw
invoke MessageBox,0,addr szOut,CTXT("UNKNOWN GUID"),MB_OK
return Unknown
.endif
IdentifyGUID ENDP


And finally, Scronty's CmpGUID procedure is as follows:


;-----------------------------------------------------------------------------
; Name: CmpGUID
; Desc: Compares two GUIDs and returns TRUE or FALSE.
;-----------------------------------------------------------------------------
CmpGUID proc lpfirstGUID:DWORD, lpsecondGUID:DWORD, bytestocompare:DWORD

push esi
push edi
push ebx

mov esi, lpfirstGUID ; first GUID address
mov edi, lpsecondGUID ; second GUID address
mov ecx, bytestocompare ; number of bytes to compare

@@:
push ecx
mov al, BYTE PTR
mov bl, BYTE PTR
inc esi
inc edi
.if al!=bl
jmp @F
.endif
cmp esi, ecx
pop ecx
dec ecx
jnz @B

;exit true
pop ebx
pop edi
pop esi
return 1

;exit false
@@:
pop ebx
pop edi
pop esi
return 0

CmpGUID endp


There's nothing magical or mystical about this code.
I define my returnvalues as equates, and call Scronty's Cmp procedure with a pair of pType (actually a pointer to a GUID).
If I can't find a matching GUID to the one we seek, I return 0=Unknown
In the version I have posted above, I also generate as a text string the hex value of the unidentified GUID and messagebox it.
Posted on 2003-10-15 02:28:31 by Homer
Did anyone spot anything wrong in there?
Help!!!
Posted on 2003-10-17 02:00:58 by Homer
Hey EvilH

I can't see any obvious mistakes but I haven't used C for years so it's possible I'm overlooking something :(

Correct me if I'm wrong but isn't the C code comparing the GUID pointers? Have you tried doing it this way?

Maelstrom
Posted on 2003-10-17 17:25:36 by Maelstrom
It appears to be comparing LPGUIDs yes I agree.
I have been using Scronty's CmpGUID because I assumed that he knew something which I did not - he's much better with cpp than I am.
I figured that if Scronty was comparing the data behind the pointers deliberately, there must be a good reason - like cpp performing that step internally maybe?
I don't know !! What I can say is that it works.
If I was to try an experiment comparing two LPGUIDS instead of two GUIDS by pointer, how would I go about acquiring the (dx internal) GUID pointer for comparison purposes to the LPGUID I am handed ? Bear in mind that at the moment, I am performing comparisons with guids that WE define as data strings. Therefore we know the address of OUR copy of a guid, but obviously, that pointer will never match an internal lpguid !!
As a side note, I am considering splitting my IdentifyGUID function into a range of functions dedicated to identifying a particular template, for example, we might decide to call IsTemplateMesh and IsTemplateFrame etc even though I feel the current solution (catch-all) to be preferable when we keep the most common templates at the top of the procedure and early-out on them.
Quite some time back, when I was having more success than I am now in the parsing department, my code consisted of a series of CmpGuid calls - JUST LIKE I have in the IdentifyGuid function.
Posted on 2003-10-18 00:05:30 by Homer
Hey EvilH

I threw a little test proggy together.



include adl.inc

includelib f:\sdk\dx9\lib\dxguid.lib

extern TID_D3DRMFrame:byte
extern TID_D3DRMMesh:byte

_CODE segment

_start:

lea eax, TID_D3DRMFrame
lea ebx, TID_D3DRMMesh

invoke ExitProcess, 0

_CODE ends

end _start


The pointers in EAX and EBX point to the following arrays of bytes.
The numbers match but we still need to do a byte compare since these end up in our EXE, but at least we don't need to define them ourselves.
No luck getting the internal GUIDs which I assume are inside the DLL, probably linked the DXGUID lib.



EAX : 46 AB 82 3D - DA 62 - CF 11 - AB 39 00 20 AF 71 E4 33
EBX : 44 AB 82 3D - DA 62 - CF 11 - AB 39 00 20 AF 71 E4 33

; the following GUIDs are taken from RMXFGUID.H

DEFINE_GUID(TID_D3DRMFrame, 0x3d82ab46, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
DEFINE_GUID(TID_D3DRMMesh, 0x3d82ab44, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);


As a side note, I am considering splitting my IdentifyGUID function into a range of functions dedicated to identifying a particular template, for example, we might decide to call IsTemplateMesh and IsTemplateFrame etc even though I feel the current solution (catch-all) to be preferable when we keep the most common templates at the top of the procedure and early-out on them.

I think a catch-all proc would be better but I'd probably use a LUT instead of hard coding the comparisons. I'd also integrate Scronty's CmdGUID function to elimate the call overhead since it's not likely to be called by anyone else.

Maelstrom
Posted on 2003-10-18 09:53:41 by Maelstrom
I tend to agree in general.
My GUIDS are defined in rmxfguid.inc, which is really rmxfguid.h
My include still has m$'s name on the header - so if it's good enough for them to define guids this way, I figured it would be good enough for me. Considering a guid is meant to be absolutely unique, the values should be static for these common templates, and it shouldn't matter, but if they are defined in an external lib (which I'm sure they are), then why did m$ ever release this .h file which defines them?

I won't post the file here in case someone doesn't agree with their EULA :tongue:
but it contains a crapload of statements like this:

TID_D3DRMMesh GUID {03d82ab44h, 062dah, 011cfh,<0abh, 039h, 00h, 020h, 0afh, 071h, 0e4h, 033h>}

By the way I prefer Homer to EvilH - I'm not really bad, I'm just drawn that way..

I failed to see how a LookupTable would be any faster for comparisons of 16 bytes, but I can see merit in performing four dword compares since the Length is a given - however I left Scronty's code alone since it's useful as a generic binary compare function, I figured I WOULD use it in other places than the xfile parser..
Posted on 2003-10-18 10:39:17 by Homer
I've integrated IdentifyTemplate and IdentifyGUID, and I've altered Scronty's CmpGUID to perform four DWORD compares (we now assume GUID length to be 16 bytes)
So IdentifyTemplate no longer exists.

I'm happy to post this revised source, but theres little point, since it behaves exactly as its predecessor :(
Posted on 2003-10-18 12:59:13 by Homer
Hi, EvilHomer2k. Your project is very interesting, and I'm sorry so few people here find it interesting. But I think one should have 3 qualities, to be 100% interested in it: 1) to be fluent in asm; 2) to be good in asm-oop & C++, as well as interest in 3D games' programming ; 3) to know higher maths and 3D algorithms. Also, one needs DX9, which can be a problem to some people.
1) fluency in asm - see how many people on this board are really active (less than 100)
2) oop & C++ . All of the active people here know C++, but I doubt all of them use OOP.
3) higher maths, 3D algos & games - hmm. I don't know much about this problem, I myself am first semester at uni, currently studying matrices. I think soon I'll try 3D coding myself. But I have always dreamt of making a nice 3D game or app.
4) To compete the other game creators, one needs not only coding skills, but also a good texture+models artist. Also, the latest videocards & best cpus (I assume).
in the end, there are only a few people to get your attention :(

To most people all of this is too much effort, and I personally am scared of seeing a product of mine ending like some of the games I've seen - with no customers.
I, in fact, do not know much about the world's gaming industry, but for now this is my point of view. I have a product, that doesn't have customers only because there are 2 or 3 better products in the world, no matter how much they cost.
I'd appreciate any critics :) .
Btw, my PC crashes a lot when I install DX8. (that's a reason for having labelled a CD with DX8, that I have, "in case of emergency") . I'm afraid I won't be able to install DX9.


Anyway, you have my full support for your project :alright:
I have a lot of experience in audio and 2D animation, maybe I can help sometimes ;)
Posted on 2003-10-18 13:43:43 by Ultrano
Hey Homer,

The LUT I was referring to was to replace the .if comparisons.



m_guidLut label dword
dd offset TID_D3DRMFrame, Frame
dd offset TID_D3DRMMesh, Mesh
...
dd 0


IdentifyGUID PROC pType:DWORD

lea esi, m_guidLut

_top:

cmp dword ptr [esi], 0
je _exit

invoke CmpGUID, pType, [esi], 16
test eax, eax
jnz _match

add esi, 8
jmp _top

_match:

mov eax, [esi+4]
ret

_exit:

xor eax, eax
ret

IdentifyGUID ENDP


Or something like that, it probably won't be any faster but it should be smaller.

Also, why doesn't Scronty's CmpGUID function use a rep cmpsd loop? Wouldn't that be faster? Or is that what you've done now?

Maelstrom
Posted on 2003-10-18 19:32:13 by Maelstrom
I guess like me, when coding for the masses, Scronty tends to write his code in a way which is most easily understood by the reader - I'm sure his personal code is much more optimized, as mine is.

;-----------------------------------------------------------------------------
; Name: CmpGUID
; Desc: Compares two GUIDs and returns TRUE or FALSE.
; Original code by Scronty
; Rudely optimized by Evil Homer without so much as asking
;-----------------------------------------------------------------------------
CmpGUID proc lpfirstGUID:DWORD, lpsecondGUID:DWORD

push esi
push edi
mov esi, lpfirstGUID ; first GUID address
mov edi, lpsecondGUID ; second GUID address
mov ecx, 4
repe cmpsd
jnz @F
pop edi ;exit true
pop esi
return 1

@@:
pop edi ;exit false
pop esi
return 0

CmpGUID endp
Posted on 2003-10-18 19:52:56 by Homer
Here is the revised edition of IdentifyGUID...

;This procedure attempts to identify a template by its guid...
;Thanks Be to Scronty for the DXGUID include ;)
;Thanks Be to Maelstrom for his comments concerning the codebase
;(damn hope m$ havent updated... ah well :p)

Unknown equ 0
Frame equ 1
Mesh equ 2
Material equ 3
Normals equ 4
TextureCoords equ 5
FrameXFormMatrix equ 6
RMInfo equ 7
RMVector equ 8
MeshFace equ 9
MaterialArray equ 10
MeshMaterialList equ 11
RMCoords2d equ 12
Matrix44 equ 13
Animation equ 14
AnimationSet equ 15
AnimationKey equ 16
FloatKeys equ 17
AmbientColor equ 18
DiffuseColor equ 19
SpecularColor equ 20
EmissiveColor equ 21
RMMaterialPower equ 22
ColorRGBA equ 23
ColorRGB equ 24
RMGuid equ 25
RMTextureFilename equ 26
RMTextureReference equ 27
RMIndexedColor equ 28
MeshVertexColors equ 29
RMMaterialWrap equ 30
RMBoolean equ 31
MeshFaceWraps equ 32
RMBoolean2d equ 33
RMTimedFloatKeys equ 34
AnimationOptions equ 35
RMFramePosition equ 36
RMFrameVelocity equ 37
RMFrameRotation equ 38
RMLight equ 39
RMCamera equ 40
RMAppData equ 41
RMLightUmbra equ 42
RMLightRange equ 43
RMLightPenumbra equ 44
RMLightAttenuation equ 45
RMInlineData equ 46
RMUrl equ 47
RMProgressiveMesh equ 48
RMExternalVisual equ 49
RMStringProperty equ 50
RMPropertyBag equ 51
RMRightHanded equ 52
DXFileHeader equ 53

;The LUT is sorted in the same order as the Equates above
;This avoids the need for implicitly declaring them in the table
;Note that the first value at offset 0 is illegal and we don't use it
;It's just there to maintain parity with the prior version of this code

.data
TemplateLUT dd -1 ;0=Unknown
dd offset TID_D3DRMFrame
dd offset TID_D3DRMMesh
dd offset TID_D3DRMMaterial
dd offset TID_D3DRMMeshNormals
dd offset TID_D3DRMMeshTextureCoords
dd offset TID_D3DRMFrameTransformMatrix
dd offset TID_D3DRMInfo
dd offset TID_D3DRMVector
dd offset TID_D3DRMMeshFace
dd offset TID_D3DRMMaterialArray
dd offset TID_D3DRMMeshMaterialList
dd offset TID_D3DRMCoords2d
dd offset TID_D3DRMMatrix44
dd offset TID_D3DRMAnimation
dd offset TID_D3DRMAnimationSet
dd offset TID_D3DRMAnimationKey
dd offset TID_D3DRMFloatKeys
dd offset TID_D3DRMMaterialAmbientColor
dd offset TID_D3DRMMaterialDiffuseColor
dd offset TID_D3DRMMaterialSpecularColor
dd offset TID_D3DRMMaterialEmissiveColor
dd offset TID_D3DRMMaterialPower
dd offset TID_D3DRMColorRGBA
dd offset TID_D3DRMColorRGB
dd offset TID_D3DRMGuid
dd offset TID_D3DRMTextureFilename
dd offset TID_D3DRMTextureReference
dd offset TID_D3DRMIndexedColor
dd offset TID_D3DRMMeshVertexColors
dd offset TID_D3DRMMaterialWrap
dd offset TID_D3DRMBoolean
dd offset TID_D3DRMMeshFaceWraps
dd offset TID_D3DRMBoolean2d
dd offset TID_D3DRMTimedFloatKeys
dd offset TID_D3DRMAnimationOptions
dd offset TID_D3DRMFramePosition
dd offset TID_D3DRMFrameVelocity
dd offset TID_D3DRMFrameRotation
dd offset TID_D3DRMLight
dd offset TID_D3DRMCamera
dd offset TID_D3DRMAppData
dd offset TID_D3DRMLightUmbra
dd offset TID_D3DRMLightRange
dd offset TID_D3DRMLightPenumbra
dd offset TID_D3DRMLightAttenuation
dd offset TID_D3DRMInlineData
dd offset TID_D3DRMUrl
dd offset TID_D3DRMProgressiveMesh
dd offset TID_D3DRMExternalVisual
dd offset TID_D3DRMStringProperty
dd offset TID_D3DRMPropertyBag
dd offset TID_D3DRMRightHanded
dd offset TID_DXFILEHeader
dd 0 ;Table Terminator

.code
IdentifyGUID PROC xof:DWORD
local pType:DWORD
.if ($mcall (xof,IDirectXFileData_GetType,addr pType)) != DXFILE_OK
invoke MessageBox,0,CTXT("FAILED to get template type, let alone ID it"),CTXT("Parse Error"),MB_OK+MB_ICONERROR
return Unknown
.endif
push esi
lea esi,TemplateLUT
add esi,4 ;(skip first entry since its illegal)
.while dword ptr != NULL
invoke CmpGUID, pType, dword ptr
.if eax==1 ;If we find a match, determine what it is..
sub esi, offset TemplateLUT ;first we'll subtract the start of the Table to get the Offset
shr esi,2 ;then we'll divide by 4 because the Table is based on DWORDS
mov eax,esi ;Now we have an integer value which should match our Equates above
pop esi ;We'll restore esi to its former glory
ret ;and return the value we discovered to the Caller.
.endif
add esi,4
.endw
pop esi
return Unknown
Posted on 2003-10-18 20:52:59 by Homer
w00t !!
We are detecting other types again !!
Which is Damn Strange considering how it was fixed...
Obviously, the issue was in the template identifier.
What is less obvious is that although the opcodes have changed in that procedure (we use LUT now), the methodology remains unaltered.
Here's a lite object parse function, which is handling Frames and their FrameMatrices ... I'll turn the MeshLoader and AnimationSet parser functions back on as soon as my son is done playing Morrowind...

FrameNode_Load PROC pData:DWORD, ParentFrame:DWORD, pSkinMeshOwner:DWORD
local pSubObj:DWORD
local pSubData:DWORD
local pDataRef:DWORD
local pType:LPGUID
local NameBuf[256]:BYTE
local ErrBuf[256]:BYTE
local pmeshnode:LPMESHNODE
local panimationset:LPANIMATIONNODE
local dwSize:DWORD
local hFrame:LPFRAMENODE
local pmat:LPD3DXMATRIX
local dwsize:DWORD
local hname:DWORD
;local parentframe:DWORD
;===============================================================================
;Initialize locals (DX can be finicky - some output args can also be input args !!)
;===============================================================================
xor eax,eax
mov pSubObj,eax
mov pSubData,eax
mov pDataRef,eax
mov pType,eax
mov NameBuf[0],al
mov dwSize,eax
mov hFrame,eax
mov pmeshnode,eax
mov panimationset,eax
;m2m parentframe,ParentFrame
;===============================================================================
invoke IdentifyGUID, pData
;===============================================================================
.if eax==Frame
mov hFrame, $invoke (LinkedLists_AppendSibling,ParentFrame,NULL, sizeof FrameNode)
.if hFrame==NULL
Errr CTXT("Error - Failed to create FrameNode")
.endif
.if $mcall (pData,IDirectXFileData_GetName, NULL, addr dwSize)!=D3D_OK
Errr CTXT("Failed to get Template Name Length")
.elseif dwSize!=0
mcall ,IDirectXFileData_GetName, addr NameBuf, addr dwSize
.endif
.if NameBuf[0]== NULL ; // Give a default name if none found
invoke lstrcpy,addr NameBuf, CTXT("$NamelessTemplate$")
.endif
invoke LinkedObjects_SetName, hFrame, addr NameBuf
;===============================================================================
.elseif eax==FrameXFormMatrix
; // Read the Matrix data straight into our buffer(s)
mov esi,$invoke (GlobalLock,ParentFrame)
assume esi:nothing
assume esi:ptr FrameNode
lea ebx,.OriginalMatrix
m2m pmat, ebx
mcall ,IDirectXFileData_GetData, NULL, addr dwsize, addr pmat
.if eax==DXFILE_OK
lea ebx,.TransformationMatrix
m2m pmat, ebx
mcall ,IDirectXFileData_GetData, NULL, addr dwsize, addr pmat
.if eax==DXFILE_OK
; invoke MessageBox,0,CTXT("MATRIX !!"),CTXT("Frames Loader"),MB_OK
.else
Errr CTXT ("Couldn't read frame transformation matrix from an x file")
.endif
.else
Errr CTXT ("Couldn't read frame transformation matrix from an x file")
.endif
invoke GlobalUnlock,ParentFrame
invoke MessageBox,0,CTXT("FRAMEMATRIX processed"),CTXT("Frames Loader"),MB_OK

.endif






; Scan for embedded templates

mcall ,IDirectXFileData_GetNextObject, ADDR pSubObj
.while eax!=DXFILEERR_NOMOREOBJECTS
.if eax==DXFILEERR_BADVALUE
Errr CTXT("Parser Error - DXFILEERR_BADVALUE - in Frames Parser")
.endif

.if ($mcall(pSubObj,IDirectXFileObject_QueryInterface, ADDR IID_IDirectXFileDataReference, ADDR pDataRef)) == DXFILE_OK
.if ($mcall(pDataRef,IDirectXFileDataReference_Resolve,addr pSubData))==DXFILE_OK
invoke IdentifyGUID,pSubData
invoke MessageBox,0,CTXT("REFOBJECT IDENTIFIED"),CTXT("YAYYYYYY"),MB_OK
invoke FrameNode_Load,pSubData, hFrame,pSkinMeshOwner
_saferelease pSubData
.endif
_saferelease pDataRef
.endif

.if ($mcall (pSubObj, IDirectXFileObject_QueryInterface,addr IID_IDirectXFileData, addr pSubData)) == DXFILE_OK
invoke FrameNode_Load,pSubData, hFrame,pSkinMeshOwner
_saferelease pSubData
.endif


_saferelease pSubObj
mcall ,IDirectXFileData_GetNextObject, ADDR pSubObj
.endw
ret
FrameNode_Load ENDP
Posted on 2003-10-18 21:17:08 by Homer
Hey Homer

Go on admit it, your the one playing Morrowind :grin:
I must admit that I play the game, probably the best RPG I've played altho it has its good and bad points.
I would love to write a game along similar lines.

I'm happy to hear that the code works again and I'm looking forward to seeing what you get up to next :alright:

Maelstrom
Posted on 2003-10-19 00:42:31 by Maelstrom