Ok, after quitting the idea of using directx 9 for the lack of the include files necessary for the job for one side and because of the complexity to get them working for the other, my mind started to think in the possibility of make a mix of c and asm. The idea was to use c functions called from asm code just to invoke all the stuff in the directx 9 libraries. The problem with this idea, as aw27 mentioned in somewhere, is that that will mean that the 80% or maybe 90% will have to be written in c, because in the games made with directx 9 (AFAIK) you only need windows and messages to set up the basic stuff and then you ignore all the other messages. That's why i have created this simple demo of how mix the asm code (main program) which creates the window for the game and handles the winproc. And from this main program we call 3 c functions: to initialize direcxt 9 objects, to use them (the game action) and to clean all the obects when finishing the game. But that's all. I don't want to program in c... :lol: But you can check out this, maybe as help, maybe as curiosity, maybe to see the game loop (this particular implementation)... :idea:
Attached is the .exe, the c code (ignore the .cpp extension) and the .obj files. The assembly code is here:
.686
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\gdi32.lib
Game_Init proto c :dword ; The c functions that deals with directx9 calls.
Game_Run proto c :dword
Game_End proto c :dword
SCREEN_WIDTH equ 1024 ; Kind of old standard
SCREEN_HEIGHT equ 768 ; resolution.
.data
align 1
class_name byte "main window class",0
wnd_name byte "DIRECTX9 TEST",0
.data?
align 4
hinstance dword ?
hwindow dword ?
bye dword ?
.code
align 4
start:
push ebp
mov ebp,esp
push NULL ; Get a handle for the program instance.
call GetModuleHandle
mov hinstance,eax
sub esp,76 ; WNDCLASSEX and MSG.
mov dword ptr[ebp-48],48 ; The size of the structure.
mov dword ptr[ebp-44],CS_HREDRAW or CS_VREDRAW ; The style of the class.
mov [ebp-40],wndproc
mov dword ptr[ebp-36],0 ; No extra
mov dword ptr[ebp-32],0 ; bytes.
mov eax,hinstance
mov [ebp-28],eax
mov dword ptr[ebp-24],NULL ; No icon.
push IDC_ARROW ; The system cursor.
push NULL
call LoadCursor
mov [ebp-20],eax ; hCursor.
push WHITE_BRUSH ; Typical background color for a window.
call GetStockObject ; Get the handle of the brush.
mov [ebp-16],eax ; hBrush.
mov dword ptr[ebp-12],NULL ; No menu.
mov [ebp-8],offset class_name
mov dword ptr[ebp-4],NULL ; Use the same app icon for the small one.
lea eax,[ebp-48] ; WNDCLASSEX.
push eax
call RegisterClassEx
push NULL ; No value passed to the window.
push hinstance
push NULL ; No menu.
push NULL ; No parent of the window.
push SCREEN_HEIGHT ; Old standar
push SCREEN_WIDTH ; resolution.
push CW_USEDEFAULT ; Default position
push CW_USEDEFAULT ; of the window.
push WS_EX_TOPMOST or WS_VISIBLE or WS_POPUP ; Game window style.
push offset wnd_name ; Name of the game window.
push offset class_name
push WS_EX_TOPMOST ; Some extension of the style.
call CreateWindowEx
mov hwindow,eax
push SW_SHOWNORMAL ; Displaying the window for the first time.
push eax
call ShowWindow
push hwindow
call UpdateWindow ; Update the client area.
push hwindow
call Game_Init ; Initialize direct3d objects.
add esp,4
lea esi,[ebp-76] ; MSG.
mov bye,0 ; Flag to stop the game loop.
align 4
msgloop:
push PM_REMOVE ; Pull out messages.
push 0 ; Retrieve all
push 0 ; available messages.
push NULL ; Messages of any window of this thread.
push esi ; MSG.
call PeekMessage
cmp eax,0
je no_msg ; No messages yet. Give the game the resources.
push esi
call TranslateMessage ; Translate keyboard to messages.
push esi
call DispatchMessage ; Dispatch messages to wndproc.
cmp bye,1
je end_program ; Check if the game is over.
align 4
no_msg:
push hwindow
call Game_Run ; All the action of the game.
add esp,4
push VK_ESCAPE
call GetAsyncKeyState ; The esc key turns off the game.
test eax,80000000h
jz keep_rolling ; If is not pressed keep playing.
push 0
push 0
push WM_DESTROY
push hwindow
call PostMessage ; If pressed let start to shutdown the game.
align 4
keep_rolling:
jmp msgloop ; All again.
align 4
end_program:
mov eax,[ebp-68] ; wParam (exit code).
mov esp,ebp
pop ebp
push eax
call ExitProcess ; End the program.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 4
wndproc: ; The window procedure for the main window class.
push ebp
mov ebp,esp
cmp dword ptr[ebp+12],WM_DESTROY ; Game over.
jne do_the_default
push hwindow
call Game_End ; Clean the direct3d objects.
add esp,4
push 0 ; Exit code (wParam in WM_QUIT).
call PostQuitMessage ; Notify to windows that is the end of the application.
mov bye,1 ; To stop the game loop.
xor eax,eax
mov esp,ebp
pop ebp
ret 16
align 4
do_the_default:
push dword ptr[ebp+20] ; lParam.
push dword ptr[ebp+16] ; wParam.
push dword ptr[ebp+12] ; The message.
push dword ptr[ebp+8] ; Handle of the window.
call DefWindowProc ; Default processing for all the other messages.
mov esp,ebp
pop ebp
ret 16
end start
Btw i'm 100% agreed if you want to RE all the .exes that i upload. This is because if you want to be sure (paranoid? not necessarily, is good to be sure) than the .exe is what the code is. And also specially in this mix scenario where we can see how the directx 9 are called :icon14:.
I haven't do to much research about com and directx in general, but it seems that you need to call methods from objects. Is it possible to do this usign the functions loadlibrary and getproc address (i think)? If so, will this need special (directx include) files too? Any help here will be appreciated :icon14:.
Some details of the process of creation of this simple demo (just a painted window in fullscreen :redface:): Was created with visual studio 2010 :dazzled: :P. Using ml 10 from there. That facilitated the linking process. And the compile of the c module.
Aside note: Siekmanski is talking about quantum physics out there in this forum, so i will not comment there to avoid embarrassing... :icon_redface: :lol: :greenclp:
Btw, to exit the program (the full screen window painted green) press the esc key...
Why would you mix asm and c++ for DirectX?
You can use 1 of those languages to make it work.
Quote from: Siekmanski on April 17, 2018, 07:27:24 AM
Why would you mix asm and c++ for DirectX?
You can use 1 of those languages to make it work.
Agreed. He took the easy way out.
Felipe, you and I both started our DirectX journey in ASM at about the same time. Should have stuck with it dude. You'd have been better off for it.
I have learned much valuable information from Siekmanski that I can now apply to any COM interface.
Quote from: Lonewolff on April 17, 2018, 07:35:01 AM
Agreed. He took the easy way out.
:biggrin:
This sounds very interesting. Good luck with game development. :t
It is legitimate to mix C, or any high-level language, with ASM, actually it is the almost the only way ASM is used in the real World these days.
Of course, we can also make standalone DirectX ASM applications. However, things are difficult without using a set of macros to help with indirection and location of methods inside interfaces. People that fabricated those macros learned a lot in the process, but users tend to use a finished product like a black box. Sure, a few will dig inside the macros, but most will not.
Quote from: aw27 on April 17, 2018, 01:51:06 PM
It is legitimate to mix C, or any high-level language, with ASM, actually it is the almost the only way ASM is used in the real World these days.
Of course, we can also make standalone DirectX ASM applications. However, things are difficult without using a set of macros to help with indirection and location of methods inside interfaces. People that fabricated those macros learned a lot in the process, but users tend to use a finished product like a black box. Sure, a few will dig inside the macros, but most will not.
Depends on what Felipe wants to do.
If he wants to ship a game in a timely fashion then maybe GameMaker would be more suitable.
If he wants to learn ASM, then mixing up languages to 'Frankenstein' something together because he doesn't want to understand one of the steps, doesn't seem like the way to go to me.
But, each to their own. We all do things for our own purposes. :t
Felipe is learning ASM at a fast pace because he choose not to go through the easy fast lane. I am not seeing him pose basic questions, like "others" do. :t
Quote from: aw27 on April 17, 2018, 02:20:47 PM
Felipe is learning ASM at a fast pace because he choose not to go through the easy fast lane. I am not seeing him pose basic questions, like "others" do. :t
"others" being me you mean?
I started ASM 10 days ago and have already ported DirectX 11 :t
Sure, 99% of ASM is still new to me, that's why I ask basic questions. Is that not what this forum is for? Learning in a supposed 'friendly' environment?
You have very firm opinions about how things should be for someone that has no definite idea of the whole picture.
Quote
I started ASM 10 days ago and have already ported DirectX 11
I meet genius of that sort everyday.
OK
You should not use unusual abbreviations like OP because most people here is neither yankee nor frequent online chats all the time.
And I have nothing else to add. :biggrin:
PS: You changed the post to a mere OK, to make it appear that OP is a typo. I can confirm once again that you are a genius.
Is this some kind of joke? c0der is you again? :badgrin:
Quote from: Lonewolff on April 17, 2018, 02:11:12 PMIf he wants to learn ASM, then mixing up languages to 'Frankenstein' something together because he doesn't want to understand one of the steps, doesn't seem like the way to go to me.
This is an old conflict between "fans of the bare metal" and "macro freaks" that pops up every n months. The purists insist that a 100 lines hand-made proc ending with a push push call WriteLine is much better than a print "hello world". Then the macro freaks invite the purists not to use a dirty WinAPI call to WriteLine but rather to code a direct pure way to shift bits into the video card ;)
Quote from: jj2007 on April 17, 2018, 04:45:17 PM
This is an old conflict between "fans of the bare metal" and "macro freaks" that pops up every n months. The purists insist that a 100 lines hand-made proc ending with a push push call WriteLine is much better than a print "hello world". Then the macro freaks invite the purists not to use a dirty WinAPI call to WriteLine but rather to code a direct pure way to shift bits into the video card ;)
It's not that at all.
To make something usable, he will need to do a hell of a lot of 'wrapping' of function calls in C/C++. And even then the function will always be limited to his implementation.
What if he decides he wants to enable vSnyc?
Triple buffering to avoid tearing?
FSAA?
Change the FVF formats.
Fixed function or pure?
Lights (spot, directional, ambient).
The list (and wrapping) is literally endless.
This will require rewrites of the external library or additional functions written. That's the danger of relying on writing wrapper libraries rather than using a native implementation.
DirectX is massive (granted 9.0c less so - but it is still huge). You will never cover all bases trying to make a wrapper for it.
What would I know though. I'm just the noob here. :biggrin:
Quote from: aw27 on April 17, 2018, 02:59:58 PM
You should not use unusual abbreviations like OP because most people here is neither yankee nor frequent online chats all the time.
And I have nothing else to add. :biggrin:
PS: You changed the post to a mere OK, to make it appear that OP is a typo. I can confirm once again that you are a genius.
Not sure why you are trying to cause a fight here. I have been friendly and openly thankful of all help I have received in my endeavours to learn ASM.
You go and call me out for posting basic questions in 'The Campus'. Isn't that what it is for? "A friendly safe environment"? Sorry Sir, but I am not a fan of your attitude towards newcomers.
I don't know what 'OP' means where you come from, but it is a common internet term for 'Original Poster'.
http://onlineslangdictionary.com/meaning-definition-of/op
Quote from: Lonewolff on April 17, 2018, 08:44:48 PMTo make something usable, he will need to do a hell of a lot of 'wrapping' of function calls in C/C++. And even then the function will always be limited to his implementation.
What if he decides he wants to enable vSnyc?
Triple buffering to avoid tearing?
FSAA?
Change the FVF formats.
Fixed function or pure?
Lights (spot, directional, ambient).
The list (and wrapping) is literally endless.
You are right, actually: When working with a complex library, it's not a good idea to wrap everything. What you can and should do, though, is use some macros that make using the library easier. Example: GNU Scientific Library (http://masm32.com/board/index.php?topic=4680.msg50508#msg50508); doing such calls by hand would hardly produce quick results.
Quote
Not sure why you are trying to cause a fight here
I am not fighting. Firstly I contested you ideas about Felipe's Frankenstein code (is it terror code?), secondly I applauded your genius twice and now I am feeling sad for your new role of victim. :(
Quote from: Lonewolff on April 17, 2018, 08:44:48 PM
What if he decides he wants to...
Why you enjoy talk about what i want or not. I even have been very clear in respect of direcxt in all the posts you linked here, saying you were very sure about what were you saying because i admited defeat in all that posts (The post you edited later, to a merely "ok"). You have been relying on others (like on the siekmaski's work) or in my case to point things of me which are not my interests. I will be pleased if you read what i posted here and stop speculating in what i want or not. If i say phuk directx i hope you can still feel like a usefull programmer and if not, just leave it like that. This is not high level religion. You really don't see the big picture, assembly language is not the same as the microsoft's interfaces. I actually did a question here about accesing to the directx dll using loadlibrary and getproaddress, but i haven't read an answer of that. That doesn't matter either because in this forum good people help in a volunteer basis. :icon_exclaim:
Quote from: Lonewolff on April 17, 2018, 02:36:03 PM
I started ASM 10 days ago and have already ported DirectX 11 :t
Sure, 99% of ASM is still new to me, that's why I ask basic questions. Is that not what this forum is for? Learning in a supposed 'friendly' environment?
I'm still a little angry with you, so i will ask you one more time: is this some kind of joke? Or just a lie? :eusa_snooty::
http://masm32.com/board/index.php?topic=5220.msg56044#msg56044 (http://masm32.com/board/index.php?topic=5220.msg56044#msg56044) And please don't edit all your posts. :eusa_naughty:
I am sorry to have upset you, that was never my intention. From your previous posts it seemed you were giving up. I see now that your perspective on your project has just shifted and you are taking a different route by interfacing C with ASM.
The post you linked cleared says [edit] where I have provided additional information. Any forums I have been a member of generally prefer this in opposed to bumping topics two or three times in quick succession.
If bumping topics is the preferred method on this board, I will do that from now on. :t
Quote from: Lonewolff on April 18, 2018, 07:44:47 AM
I see now that your perspective on your project has just shifted and you are taking a different route by interfacing C with ASM.
You really have lecture problems.
Quote from: Lonewolff on April 18, 2018, 07:44:47 AM
The post you linked cleared says [edit] where I have provided additional information. Any forums I have been a member of generally prefer this in opposed to bumping topics two or three times in quick succession.
If bumping topics is the preferred method on this board, I will do that from now on. :t
You said in this topic:
Quote from: Lonewolff on April 17, 2018, 02:36:03 PM
I started ASM 10 days ago and have already ported DirectX 11 :t
So you were lying i assume now.
Come on Guys, be friendly. :t
As far as I understand you Filipe, you like to get the d3d9.dll via LoadLibrary and the function "Direct3DCreate9" via GetProcAddress?
And if possible without MACROS calling the COM interfaces?
Quote from: felipe on April 18, 2018, 07:54:43 AM
You said in this topic:
Quote from: Lonewolff on April 17, 2018, 02:36:03 PM
I started ASM 10 days ago and have already ported DirectX 11 :t
So you were lying i assume now.
Why would you assume I am lying?
Quote from: Siekmanski on April 18, 2018, 08:16:32 AM
Come on Guys, be friendly. :t
I'm never other than friendly. :biggrin:
It does get challenging though when you have one guy calling me a derogatory names and the other calling me a liar.
With that, I wish you all the best with your project, Felipe. :t
Sorry siekmanski.
Quote from: Lonewolff on April 18, 2018, 08:24:08 AM
and the other calling me a liar.
How can that be possible not a lie, if you have been in this forum, learning assembly for at least 1 year bye now?. Sorry if i offend you but you looks to me like a liar.
Quote from: felipe on April 18, 2018, 08:43:19 AM
How can that be possible not a lie, if you have been in this forum, learning assembly for at least 1 year bye now?. Sorry if i offend you but you looks to me like a liar.
You mean because I have been a member of the forum for more than a year?
This doesn't mean I have actively been learning assembly. AW27 will vouch that I know nothing.
Ask Siekmanski, when I started wrapping up DX11.
Quote from: Lonewolff on April 18, 2018, 08:49:49 AM
Quote from: felipe on April 18, 2018, 08:43:19 AM
How can that be possible not a lie, if you have been in this forum, learning assembly for at least 1 year bye now?. Sorry if i offend you but you looks to me like a liar.
You mean because I have been a member of the forum for more than a year?
This doesn't mean I have actively been learning assembly. AW27 will vouch that I know nothing.
Ask Siekmanski, when I started wrapping up DX11.
:biggrin: I will not ask him that sh*t. I really don't give a ph*k what you have done in your entire life. Just stop of using my name in this forum as some prototype of the misadventures of the game development, specially from the high level perspective you have. I'm not in your game development team and i don't have any ph*king project to develop a ph*cking game. If i can use directx with the assembly language that i write, that's fine, if i can't that's fine for me too. Is clear as water to you lonewolff?
:t
Sorry siekmanski if that last answer summary a little my original (interrupted-not posted) answer. I don't want to bother nobody here, especially you. You have helped me, but probably because directx 9 is too old, i haven't been able to use those macros and even to assemble those programs. My favorite choice is without macros of course, but if there are only macros (hopefully not bloated macros who calls too many other macros) with the assembly code, that could be good starting point i guess. But as i stated doesn't matter if this is not possible for me now or ever, period. If there are more guidelines out there, that is fine, if not, fine too. Thanks for any help with a possible approach using LoadLibrary and GetProcAddress. :icon14:
Quote from: Lonewolff on April 18, 2018, 09:21:23 AM
Quotei don't have any ph*king project to develop a ph*cking game.
You do realise you posted that in 'Game development', right? :eusa_clap:
:biggrin: This is lovely lonewolff but i already have a girlfriend... :badgrin:
'Toddler's Corner' is down the bottom :t
Hi Felipe,
No worries, I will put something together tomorrow.
Loading "d3d9.dll" via LoadLibrary and get the function "Direct3DCreate9" via GetProcAddress.
And calling the COM interfaces without MACROS . :t
Ok siekmanski, thanks a lot. I f you can do that probably you are a genius. :greenclp:
Quote from: Lonewolff on April 18, 2018, 09:30:13 AM
'Toddler's Corner' is down the bottom :t
You are really a lonewolff, right? :badgrin:
Quote from: felipe on April 18, 2018, 09:25:28 AM:biggrin: This is lovely lonewolff but i already have a girlfriend... :badgrin:
Maybe you should dedicate more time to her. Or to coding 8)
To give you a starting point: Forum search (http://masm32.com/board/index.php?action=search;advanced;search=) yields almost 100
threads for
loadlibrary getprocaddress. If that is not enough, there are almost 200 threads at the old forum (http://www.masmforum.com/board/index.php?action=search;advanced). The term
coinvoke is less popular, 36 threads in the new forum, less than 100 in the old one, but still, there is enough learning material for you. And certainly, if you post
code, many people here will be willing to help you.
Quote from: jj2007 on April 18, 2018, 11:10:47 AM
Maybe you should dedicate more time to her. Or to coding 8)
jj2007: Is that an inclusive OR? Because if not, from what you have typed can be inferred that there are too many resources to learn, even more than there is time to code. Which in fact may be true. So in what do you think i waste my time? If you mean fighting i agree. But i'm really not the kind of guy who likes to fight. I just do what i have to do to remain free, as possible, and hopefully, happy :idea:.
Btw, thanks for the tips :icon14:.
guys, guys, come on! Peace!
Another approach to get DirectX 9 running without using static libs and without the coinvoke MACRO.
And for Felipe also a com call code procedure without using a ComCall MACRO.
Of course I made a new "DX9call" MACRO for myself and everybody else who wants to use it.
Had to rewrite all d3d9 com interface code in the include files.
d3d9.inc, d3d9caps.inc and d3d9types are translated and ready to use.
The other include files for the d3d9x wrapper lib are not translated yet.
I'll leave that job for Felipe.
How to load and scan the computer for 1 of the many d3d9x wrapper libs, have a look at my PixelShader compiler code.
http://masm32.com/board/index.php?topic=6904.0
Cheers, Siekmanski
; Hi Felipe, because you didn't want to use the coinvoke MACRO to call the COM Interfaces,
; all COM Interfaces like the one below have to be rewritten like "IDirect3D9 Interface methods".
; coinvoke version:
;_vtIDirect3D9 MACRO CastName:REQ
; _vtIUnknown CastName
; &CastName&_RegisterSoftwareDevice comethod2 ?
; &CastName&_GetAdapterCount comethod1 ?
; &CastName&_GetAdapterIdentifier comethod4 ?
; &CastName&_GetAdapterModeCount comethod3 ?
; &CastName&_EnumAdapterModes comethod5 ?
; &CastName&_GetAdapterDisplayMode comethod3 ?
; &CastName&_CheckDeviceType comethod6 ?
; &CastName&_CheckDeviceFormat comethod7 ?
; &CastName&_CheckDeviceMultiSampleType comethod7 ?
; &CastName&_CheckDepthStencilMatch comethod6 ?
; &CastName&_CheckDeviceFormatConversion comethod5 ?
; &CastName&_GetDeviceCaps comethod4 ?
; &CastName&_GetAdapterMonitor comethod2 ?
; &CastName&_CreateDevice comethod7 ?
;ENDM
;
;IDirect3D9 struct
; _vtIDirect3D9 IDirect3D9
;IDirect3D9 ends
;
; LPDIRECT3D9 typedef PTR IDirect3D9
; PDIRECT3D9 typedef PTR IDirect3D9
; Interfaces are now addressed in this manner:
; Keep the interface methods as in the original SDK order!( see the DX9 SDK *.h includes for the right order )
; Don't place the interface methods in alphabetical order as in the "DirectX9_c.chm"
; Start with address offset 12 and add 4 for the next method.
; IDirect3D9 Interface methods
IDirect3D9_RegisterSoftwareDevice equ 12
IDirect3D9_GetAdapterCount equ 16
IDirect3D9_GetAdapterIdentifier equ 20
IDirect3D9_GetAdapterModeCount equ 24
IDirect3D9_EnumAdapterModes equ 28
IDirect3D9_GetAdapterDisplayMode equ 32
IDirect3D9_CheckDeviceType equ 36
IDirect3D9_CheckDeviceFormat equ 40
IDirect3D9_CheckDeviceMultiSampleType equ 44
IDirect3D9_CheckDepthStencilMatch equ 48
IDirect3D9_CheckDeviceFormatConversion equ 52
IDirect3D9_GetDeviceCaps equ 56
IDirect3D9_GetAdapterMonitor equ 60
IDirect3D9_CreateDevice equ 64
LPDIRECT3D9 typedef PTR DWORD
PDIRECT3D9 typedef PTR DWORD
The COM call code:
push 0 ; push the parameters
push FLT4(1.0)
push BackgroundColor
push D3DCLEAR_TARGET
push NULL
push 0
mov eax,g_pD3DDevice ; load the com interface
push eax ; push it
mov eax,[eax] ; get the pointer from the interface pointer
call dword ptr[eax+IDirect3DDevice9_Clear] ; call the com interface method
;DX9call g_pD3DDevice,IDirect3DDevice9_Clear,0,NULL,D3DCLEAR_TARGET,BackgroundColor,FLT4(1.0),0
; The "DX9call" MACRO produces the same code as the manual code above
Siekmanski you are a genius! Thanks a lot! This time all worked correctly, i was able of run the program and to assemble and link the code (i first deleted the .exe) and all worked without problems. This is a great learning resource for me. I really appreciate it. I will use and work with all this and will create all the includes that remains (and of course i will post everything too). :greenclp:
:greenclp:
:bgrin:
Now the fun starts :t
Quote from: Siekmanski on April 19, 2018, 06:38:34 AM
push FLT4(1.0)
Remember felipe is allergic against macros :eusa_naughty:
:biggrin: I'm not.
He can now start with DirectX9 in his own favorite coding style, I can understand that very well.
Afterall, we all have our own coding styles, I like mine the most. :bgrin:
I'm waiting till he discovers all the macros for the color conversions etc.
It is almost impossible not to use macros to keep it a bit maintainable.
And another thing, my DX9call macro is now faster then the coinvoke macro. ( one less memory read )
Without Felipe I never had spotted that one + I can use edx again in the parameters.
Nice job!
A couple of years ago I was studying a way to use the Desktop Duplication API to transfer changed screen rectangles to a remote computer. It requires DirectX 11/DXGI 1.2. I have also made an article about that (https://www.codeproject.com/Articles/1114240/Desktop-Duplication-API-in-Delphi). Although I know how to save rectangles to bitmaps and send them across the network, of course, I ended up not pursuing the project because my current implementation is already very fast and at the time I could not figure out a good way to handle it on the receiver side.
Quote from: jj2007 on April 19, 2018, 10:19:21 AM
Quote from: Siekmanski on April 19, 2018, 06:38:34 AM
push FLT4(1.0)
Remember felipe is allergic against macros :eusa_naughty:
:biggrin: This macro code actually helped me to see that i can't move directly a float to a register, i mean like an immediate operand. I didn't knew that. Seems like we need to initialize all of them.
Siekmanski thanks again very much, this has been actually, i think, a great contribution to the masm32 sdk. I have to go to sleep now (i was too excited to wait until tomorrow to try to code with this great help). From tomorrow i will start to learn more about directx9. Here is the same "idea" that i posted here (the first reply) but without c code:
.686
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\gdi32.lib
include \masm32\include\DX9Includes\d3d9.inc
SCREEN_WIDTH equ 1024 ; Kind of old standard
SCREEN_HEIGHT equ 768 ; resolution.
.data
align 1
class_name byte "main window class",0
wnd_name byte "DIRECTX9 TEST",0
d3d9_lib byte "d3d9.dll",0
dx9func0 byte "Direct3DCreate9",0
align 4
float4 dword 1.0
.data?
align 4
hinstance dword ?
hwindow dword ?
bye dword ?
hdll dword ?
proc_add dword ?
inter_add dword ?
d3dpp D3DPRESENT_PARAMETERS <?>
d3ddev dword ?
.code
align 4
start:
push ebp
mov ebp,esp
push NULL ; Get a handle for the program instance.
call GetModuleHandle
mov hinstance,eax
sub esp,76 ; WNDCLASSEX and MSG.
mov dword ptr[ebp-48],48 ; The size of the structure.
mov dword ptr[ebp-44],CS_HREDRAW or CS_VREDRAW ; The style of the class.
mov [ebp-40],wndproc
mov dword ptr[ebp-36],0 ; No extra
mov dword ptr[ebp-32],0 ; bytes.
mov eax,hinstance
mov [ebp-28],eax
mov dword ptr[ebp-24],NULL ; No icon.
push IDC_ARROW ; The system cursor.
push NULL
call LoadCursor
mov [ebp-20],eax ; hCursor.
push WHITE_BRUSH ; Typical background color for a window.
call GetStockObject ; Get the handle of the brush.
mov [ebp-16],eax ; hBrush.
mov dword ptr[ebp-12],NULL ; No menu.
mov [ebp-8],offset class_name
mov dword ptr[ebp-4],NULL ; Use the same app icon for the small one.
lea eax,[ebp-48] ; WNDCLASSEX.
push eax
call RegisterClassEx
push NULL ; No value passed to the window.
push hinstance
push NULL ; No menu.
push NULL ; No parent of the window.
push SCREEN_HEIGHT ; Old standar
push SCREEN_WIDTH ; resolution.
push CW_USEDEFAULT ; Default position
push CW_USEDEFAULT ; of the window.
push WS_EX_TOPMOST or WS_VISIBLE or WS_POPUP ; Game window style.
push offset wnd_name ; Name of the game window.
push offset class_name
push WS_EX_TOPMOST ; Some extension of the style.
call CreateWindowEx
mov hwindow,eax
push SW_SHOWNORMAL ; Displaying the window for the first time.
push eax
call ShowWindow
push hwindow
call UpdateWindow ; Update the client area.
push offset d3d9_lib
call LoadLibrary ; Load d3d9.dll to the address space of this program.
mov hdll,eax ; Handle to the module loaded.
push offset dx9func0 ; Direct3DCreate9.
push eax ; hdll.
call GetProcAddress ; Get the address of the dx9 function.
mov proc_add,eax ; Save the address of the funtion Direct3DCreate9.
push D3D_SDK_VERSION
call eax ; Call the function Direct3DCreate9.
mov inter_add,eax ; Safe the com interface address.
mov esi,offset d3dpp
mov ecx,14 ; There are 14 dword members in this structure.
align 4
fill_struc:
mov dword ptr[esi],0
add esi,4 ; Next field.
loop fill_struc ; Fill the structure with 0.
mov esi,offset d3dpp
mov dword ptr[esi+0],SCREEN_WIDTH ; Backbuffer width.
mov dword ptr[esi+4],SCREEN_HEIGHT ; Backbuffer height.
mov dword ptr[esi+8],D3DFMT_X8R8G8B8 ; Backbuffer format.
mov dword ptr[esi+12],1 ; Backbuffer count.
mov dword ptr[esi+24],D3DSWAPEFFECT_DISCARD ; Swap effect.
mov eax,hwindow
mov dword ptr[esi+28],eax ; device window.
mov dword ptr[esi+32],FALSE ; Not windowe, we want fullscreen.
push offset d3ddev
push offset d3dpp
push D3DCREATE_SOFTWARE_VERTEXPROCESSING
push eax ; hwindow
push D3DDEVTYPE_HAL
push D3DADAPTER_DEFAULT
mov eax,inter_add ; Com interface address.
push eax
mov eax,[eax]
call dword ptr[eax+IDirect3D9_CreateDevice] ; Call com interface method CreateDevice.
lea esi,[ebp-76] ; MSG.
mov bye,0 ; Flag to stop the game loop.
align 4
msgloop:
push PM_REMOVE ; Pull out messages.
push 0 ; Retrieve all
push 0 ; available messages.
push NULL ; Messages of any window of this thread.
push esi ; MSG.
call PeekMessage
cmp eax,0
je no_msg ; No messages yet. Give the game the resources.
push esi
call TranslateMessage ; Translate keyboard to messages.
push esi
call DispatchMessage ; Dispatch messages to wndproc.
cmp bye,1
je end_program ; Check if the game is over.
align 4
no_msg:
push 0
push float4
push 00ff0000h ; Color.
push D3DCLEAR_TARGET
push NULL
push 0
mov eax,d3ddev ; Com interface address.
push eax
mov eax,[eax]
call dword ptr[eax+IDirect3DDevice9_Clear] ; Call the com interface method.
mov eax,d3ddev
push eax
mov eax,[eax]
call dword ptr[eax+IDirect3DDevice9_BeginScene]
mov eax,d3ddev
push eax
mov eax,[eax]
call dword ptr[eax+IDirect3DDevice9_EndScene]
push NULL
push NULL
push NULL
push NULL
mov eax,d3ddev
push eax
mov eax,[eax]
call dword ptr[eax+IDirect3DDevice9_Present]
push VK_ESCAPE
call GetAsyncKeySt ; The esc key turns off the game.
test eax,80000000h
jz keep_rolling ; If is not pressed keep playing.
push 0
push 0
push WM_DESTROY
push hwindow
call PostMessage ; If pressed let start to shutdown the game.
align 4
keep_rolling:
jmp msgloop ; All again.
align 4
end_program:
mov eax,[ebp-68] ; wParam (exit code).
mov esp,ebp
pop ebp
push eax
call ExitProcess ; End the program.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 4
wndproc: ; The window procedure for the main window class.
push ebp
mov ebp,esp
cmp dword ptr[ebp+12],WM_DESTROY ; Game over.
jne do_the_default
cmp d3ddev,NULL
je skip_cleaning
mov eax,d3ddev
push eax
mov eax,[eax]
call dword ptr[eax+IUnknown_Release]
cmp inter_add,NULL
je skip_cleaning
mov eax,inter_add
push eax
mov eax,[eax]
call dword ptr[eax+IUnknown_Release]
align 4
skip_cleaning:
push 0 ; Exit code (wParam in WM_QUIT).
call PostQuitMessage ; Notify to windows that is the end of the application.
mov bye,1 ; To stop the game loop.
xor eax,eax
mov esp,ebp
pop ebp
ret 16
align 4
do_the_default:
push dword ptr[ebp+20] ; lParam.
push dword ptr[ebp+16] ; wParam.
push dword ptr[ebp+12] ; The message.
push dword ptr[ebp+8] ; Handle of the window.
call DefWindowProc ; Default processing for all the other messages.
mov esp,ebp
pop ebp
ret 16
end start
The .exe is attached. Remember to escape the fullscreen with the esc key.
:icon_mrgreen: I'm very happy.
Quote from: Siekmanski on April 19, 2018, 10:23:36 AM
Afterall, we all have our own coding styles, I like mine the most. :bgrin:
Is true. Your coding style is very clear. I'm trying to improve mine. But in the code above i didn't do too much effort to refine it because i was very hurry trying to probe it. I have a lot to learn. What i couldn't understand yet is why we need to push the address of the com interface always, before we get the value of the first method (i think?). Well tomorrow more research now to the bed... :icon_mrgreen:
:greenclp: :icon14:
Quote
What i couldn't understand yet is why we need to push the address of the com interface always
Since you are not using macros you might be able to save a few bytes and cycles across repeated calls, namely here:
mov eax,g_pD3DDevice ; load the com interface
and here:
mov eax,[eax] ; get the pointer from the interface pointer
However, people that like macros trades that for its convenient automatism.
Quote from: aw27 on April 19, 2018, 08:12:29 PMSince you are not using macros you might be able to save a few bytes and cycles across repeated calls
Now you make me curious, José! How exactly can you save bytes, or gain speed, as compared to a coinvoke macro?
You save two instructions on a second call:
1st call
push 0 ; push the parameters
push FLT4(1.0)
push BackgroundColor
push D3DCLEAR_TARGET
push NULL
push 0
mov edi,g_pD3DDevice ; load the com interface
push edi ; push it
mov ebx,[edi] ; get the pointer from the interface pointer
call dword ptr[ebx+IDirect3DDevice9_Clear] ; call the com interface method
2nd call
push 0 ; push the parameters
push FLT4(1.0)
push BackgroundColor
push D3DCLEAR_TARGET
push NULL
push 0
; NOT NEEDED NOW mov edi,g_pD3DDevice ; load the com interface
push edi ; push it
;NOT NEEDED NOW mov ebx,[edi] ; get the pointer from the interface pointer
call dword ptr[ebx+IDirect3DDevice9_Clear] ; call the com interface method
OK, I see. I've tested another example with my current CoInvoke macro:
pInterface equ esi
INT 3
CoInvoke pInterface, IWebBrowserVtbl.put_MenuBar, VARIANT_TRUE ; false = no menu
nops 4
This translates to:
int3
push 0FFFF ; VARIANT_TRUE
push esi ; pInterface
mov eax, [esi]
call near [eax+0C4] ; method
nop
So, when using the interface a second time, one could save the mov eax, [esi] step and use once mov ebx, [esi] instead. That saves two bytes, but you need a non-volatile register like ebx, so two bytes for push+pop. Which means you can save two bytes each for the third, fourth, ... use of the interface. In short: You are right, one can save some bytes by coding this stuff by hand :t
This technique is commonly used in the Demo scene to save bytes when coding size limited executables.
Group everything that's possible and use one pointer for the same interface. 8)
Not every COM model is the same.
ASIO audio COM interface wants the pointer from the interface pointer in ECX
mov ecx,pASIO_Device
mov ecx,[ecx]
mov eax,[ecx]
call dword ptr[eax+Function]
I guess i understand what you say aw27, but my question still remains in this form:
;1st call
mov edi,g_pD3DDevice ; load the com interface
push edi ; push it here because is not a parameter for this method.
push 0 ; push the parameters
push FLT4(1.0)
push BackgroundColor
push D3DCLEAR_TARGET
push NULL
push 0
mov ebx,[edi] ; get the pointer from the interface pointer
call dword ptr[ebx+IDirect3DDevice9_Clear] ; call the com interface method
;2nd call
; NOT NEEDED NOW mov edi,g_pD3DDevice ; load the com interface
;push edi ; No need to push it here, if you don't trash the register.
push 0 ; push the parameters
push FLT4(1.0)
push BackgroundColor
push D3DCLEAR_TARGET
push NULL
push 0
;NOT NEEDED NOW mov ebx,[edi] ; get the pointer from the interface pointer
call dword ptr[ebx+IDirect3DDevice9_Clear] ; call the com interface method
Isn't this right? What i'm missing of the call to the methods here?
Quote
push it here because is not a parameter for this method.
No, no, you are not pushing it to preserve edi. You can do that elsewhere, in the beginning of the function for example, or don't preserve at all if you know what you are doing because it is a standalone ASM application not called from anywhere.
It is indeed a parameter for the method as you can see from the http://masm32.com/board/index.php?topic=7078.msg76110#msg76110
mov eax,g_pD3DDevice ; load the com interface
push eax
I replaced eax with edi because I know that the call to the interface method will not corrupt edi since it has the obligation to preserve non-volatile registers.
It's a little confusing this documentation from the directx 9 sdk (this method call as an example):
Quote
IDirect3DDevice9::BeginScene Method
Begins a scene.
Syntax
HRESULT BeginScene();
Parameters
This method has no parameters.
Return Value
HRESULT
And siekmanski code even confirm the no parameters for this method call:
Quote
; no parameters
mov eax,g_pD3DDevice ; load the com interface
push eax ; push it
mov eax,[eax] ; get the pointer from the interface pointer
call dword ptr[eax+IDirect3DDevice9_BeginScene] ; call the com interface method
And in this sdk documentation i haven't seen the pointer to the interface as a parameter yet in any method call. It's something only know to assembly language programmers :biggrin:? I can't find the explanation of this in that link either. Thanks for all the help, seriously. :greenclp:
Is something related to the headers file from the sdk? I'm not well versed in that idiom, but i have found lines like this (probably for every method):
Quote#define IDirect3D9_CreateDevice(p,a,b,c,d,e,f) (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f)
So that p is the pointer defined implicitly?
You need pass a "THIS" pointer, so you need as a minimum (according to my example, 2nd call):
push edi ; push it
call dword ptr[ebx+IDirect3DDevice9_BeginScene] ; call the com interface method
Have a look here and see if it makes some light (http://yanaware.com/com4me/accesscom.php-author=Ernie%20MURPHY&mail=ernie@surfree.com&url=http---here.is-ComInAsm&idTute=38.htm). If not, keep trying this is not easy at all.
Ernie explains lots of things. If you have less time, try Mysteries of COM (http://masm32.com/board/index.php?topic=6313.msg76146#msg76146) 8)
I have seen Hitchhikers 1k demos in old forum, so to be able to save size I could make a minimum .inc file like that, so I could be able to post some real d3d9-11 game, so instead of having large lib files included in 512kb I have place for textures instead
but what about you initialize dx adresses to your .data section with most used first and least used last, the 20 most used
:greenclp: Now this comment:
Quote; get the pointer from the interface pointer
has finally perfectly sense to me. :bgrin:
Quote from: jj2007 on April 20, 2018, 03:40:19 AM
Now one might ask the developers of COM why CoCreateInstance needs the address of a variable to deliver pInterface, instead of simply returning it in eax. The answer will be "it's by design" or "why do something simple if there is a more complicated way?". Redmond speaking... 8)
I was asking me the same from the article above. Well now, thanks to the genius programmers from the best forum in the world, it really doesn't matter. :greensml:
I should have commented it like this,
mov eax,g_pD3DDevice ; load the com interface
push eax ; push it
mov eax,[eax] ; get the vtable pointer from the interface pointer
call dword ptr[eax+IDirect3DDevice9_BeginScene] ; call the com interface method function.
Hi daydreamer,
You have to set up the screen first and it delivers you the interface address in return.
Setting up the video device, same story etc.
No need to use CoCreateInstance in DX.
For the function Direct3DCreate9 there is no GUID available to get the interface address with CoCreateInstance.
QuoteI have seen Hitchhikers 1k demos in old forum, so to be able to save size I could make a minimum .inc file like that, so I could be able to post some real d3d9-11 game, so instead of having large lib files included in 512kb I have place for textures instead
but what about you initialize dx adresses to your .data section with most used first and least used last, the 20 most used
We don't use static libs anymore.
Do you trust Microsoft the addresses will be the same in next operating systems?
Quote from: Siekmanski on April 20, 2018, 05:18:08 AM
Hi daydreamer,
You have to set up the screen first and it delivers you the interface address in return.
Setting up the video device, same story etc.
No need to use CoCreateInstance in DX.
For the function Direct3DCreate9 there is no GUID available to get the interface address with CoCreateInstance.
QuoteI have seen Hitchhikers 1k demos in old forum, so to be able to save size I could make a minimum .inc file like that, so I could be able to post some real d3d9-11 game, so instead of having large lib files included in 512kb I have place for textures instead
but what about you initialize dx adresses to your .data section with most used first and least used last, the 20 most used
We don't use static libs anymore.
Do you trust Microsoft the addresses will be the same in next operating systems?
when and how often the adresses change is exactly what I want to know, if its possible to initalize d3d9 and the most used calls adresses stored easy,maybe the 3 registers that are kept untouched by could hold the 3 most used dxadresses?
and few others pushed on stack
so if I keep adresses on the stack, could those calls simple be called by a RET?
1:do they change on the fly suddenly when running a game?I dont know
2:do they change when user installs a newer GFX and/or GFX driver?probably why it can change
3:do they change when a different dx9 version gets installed?probably can do
4:if I have directx caps on older version than newest ,I wonder if it is because I have a old legacy game installed on newest computer, like Baldurs Gate, is that the reason I can run ancient ddraw code, but others with win10 can't?
but sometimes democoders dont care about it runs on every computer, like RGBA elevated 4k demo is so specialized it only run on one graphics card
1: No, once initialized, they stay the same.
2: Don't know how DX internally communicates with all different GPU drivers, do the COM interfaces gives us the same address values of all interfaces from all different GPU drivers? I don't know.
3: Never checked it.
Demo coders use all the tricks known to get the smallest and fastest demos.
Before entering the competition, they know on what system their demos will run.
Probably also what monitor resolutions are available.
Also for DX they know before, which DX wrapper lib is installed on the demo party sytem.
This is why there often are different release versions of the same demo:
- party release
- final release, should run at least on more sytems.
My philosophy on this is, if you don't enter a demo competition, stay away from all the trickery.
I always "try" to get my proggys running from XP up to Win10.
This is the reason I use Direct3D9 and not the higher versions.
Quote from: jj2007 on April 19, 2018, 10:19:21 AM
Quote from: Siekmanski on April 19, 2018, 06:38:34 AM
push FLT4(1.0)
Remember felipe is allergic against macros :eusa_naughty:
Hi Felipe, I understand your style is bound to a more straight asm coding. Just allow me to suggest you have a look at how macros work so you get the barebones of it.
It's a very powerful feature of MASM and it's there for many reasons, and they are all for our benefit.
Since this is the Game forum, I believe it would be very very very hard to make a medium-large game without macros (as it would be for C without inline functions). It would be insane and actually slower..
My game has already more than 6.000 lines. Without macros where suitable... I'd say I couldn't clean any of my own mess.
Again, it's solely a friend's suggestion for reflection.
Just as a introductory recall:In relation with we were talking, about why we needed to push the object address before calling some Directx 9 functions, even if in the sdk documentation didn't appear that parameter...
Quote from: felipe on April 20, 2018, 02:26:25 AM
Is something related to the headers file from the sdk? I'm not well versed in that idiom, but i have found lines like this (probably for every method):
Quote#define IDirect3D9_CreateDevice(p,a,b,c,d,e,f) (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f)
So that p is the pointer defined implicitly?
Quote from: aw27 on April 20, 2018, 02:55:01 AM
You need pass a "THIS" pointer, so you need as a minimum (according to my example, 2nd call):
push edi ; push it
call dword ptr[ebx+IDirect3DDevice9_BeginScene] ; call the com interface method
Have a look here and see if it makes some light (http://yanaware.com/com4me/accesscom.php-author=Ernie%20MURPHY&mail=ernie@surfree.com&url=http---here.is-ComInAsm&idTute=38.htm). If not, keep trying this is not easy at all.
aw27 you were right and me too. I was reading another book for develop games using directx 9. This book uses c++ and in related to functions of some classes says this:
Quote...and WndProc is now a static function
cWindow::WndProc. The function is static because non-static class functions have a hidden first variable passed in (the
this pointer) that is not compatible with the WndProc function declaration.
This high level languages, they just love to hide things... :biggrin: