Hi I'm having a Problem, I'm trying to use DirectDraw in my code so I can port a 2D gfx engine I have made into DirectX/Win32 so I can use more effects because the CPU power I can use under DOS is limited by WindowsNT4/2000/XP.

DllEntry proc hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD
invoke GetModuleHandle, NULL
mov hInst,eax ;Store it in RAM
;Now determing CPU feature set
invoke LoadIcon, NULL, IDI_WINLOGO
mov iconh,eax
invoke LoadCursor, NULL, IDC_ARROW
mov curh,eax
mov wc.hCursor,eax
mov eax,iconh
mov wc.hIcon,eax
invoke StartRender, 800, 600, 32, ADDR szDisplayName, ADDR WndProc ;For debugging
xor eax,eax
cpuid ;Execute CPUID
mov esi,OFFSET vendstr ;Grab OFFSET to ESI
mov [esi],ebx ;Store first 4 letters of string
mov [esi+4],edx ;Store
mov [esi+8],ecx ;Store
xor eax,eax ;Clear out EAX
inc eax ;EAX==1
cpuid ;Execute CPUID
mov vend,eax ;Store into memory, process it
.IF EAX & 23 ;Is Bit 23 set? (MMX)
mov bl,1
mov esi,OFFSET mmx
mov [esi],bl ;Store 1 into MMX flag
.IF EAX & 25 ;Is bit 25 set? (SSE)
mov bl,1
mov esi,OFFSET sse
mov [esi],bl
mov eax,80000000h ;Check for Extended CPUID support
cpuid ;Execute CPUID
.IF EAX==NULL ;No support for Extended CPUID
mov eax,TRUE
mov eax,80000001h ;Update EAX
cpuid ;Execute CPUID
.IF EAX & 31 ;Bit 31 (3DNow!)
mov BYTE PTR k3d,1
;No need to test further :D
jmp StartRender
mov eax,TRUE
DllEntry Endp

StartRender PROC xdim:WORD,ydim:WORD,bpp:WORD,winname:DWORD,lpfunc:DWORD

mov eax,hInst
mov wc.hInstance,eax
invoke GetStockObject, BLACK_BRUSH
mov wc.hbrBackground,eax
invoke RegisterClassEx, ADDR wc
mov class,eax
movzx eax,xdim
movzx ebx,ydim
mov ecx,hInst
mov edx,hInst
invoke CreateWindowEx, NULL, ADDR szClassName, ADDR szDisplayName, WS_POPUP, 0,0, eax,ebx,NULL,NULL,edx,0
StartRender ENDP

WndProc PROC hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
pushad ;Save all registers on the stack
WndProc ENDP
END DllEntry

The problem is when I do something to set the Cooperative Level I get back aweird value in the EAX register like 80000057h or something similar. Also when I try to Create The Window it flags an Access Violation!! I passed all the right parameters and everything but I dont know what is wrong! Can someone please help me by giving me example code on how to open a DirectDraw window at say, 800x600x32 and how to set up a Pointer to the Frame Buffer? Thats all I need to pull off some fancy effects that I learned how to do :D I'll try 'em out and then I'll post it here so everyone can use and possibly someone here can optimize it so its even faster :D
Thank you everyone!
Posted on 2002-09-01 21:59:06 by x86asm
My friend...

Since you obviousely do not know much about Win32 or DirectDraw please make yourself a service and start simple, then grow up :)

Now i will suggest that you make a simple win32 application with window and stuff first...

A DLL is supposed to have a set of functions that can be used by diferent applications, haveing the code that creates a window and WndProc inside a DLL dosent make much sense to me...

If i recall corectly 80000057 is Invalid Params error for DirectDraw

To quick help you ....below is the old but functional code we useed to setup DirectDraw in Hostile Encounter game, of course you will have to change it a little (define some vars not shown here and have some include files with DD interfaces) to make it wor in you 2D engine :) . You will also need the Flip() and Lock() methods for your engine IMHO

I also remember i have posted such code in the past also so you could do a search of this board...
As you can see we use to print an debug string before starting an action and handle errors (somehow) if any action fails....

; This:
; 1. Creates a DirectDraw object.
; 2. Greedily sets the coperative level so that it's in exclusive mode.
; 3. Switches display mode to 600 by 800 /16 bits = 65.000 CLOLORS
; 4. Creates a primary surface with a back buffer
; 5. Gets a pointer to the back buffer.
; 6. Creates a plain surface in memory for transparent blitting
; ........and many others



; 1. Create a DirectDraw object.

sz007 db "007=DirectDrawCreate",13,10,0

call OutputDebugStringA,offset sz007

call DirectDrawCreate, NULL, offset lpDD,NULL

; take action if it fails
.IF eax != DD_OK
call Fail, hwndmain, offset szDirectDrawCreateFail
jmp end_loop

; 2. Greedily hehe set the coperative level
; so that it's in exclusive mode

sz008 db "008=SetCooperativeLevel Exclusive",13,10,0

call OutputDebugStringA,offset sz008

push eax

mov eax,[hwndmain]
push eax

mov eax,[lpDD]
push eax ; DD Object

mov eax,[eax] ; vtable addr
call [eax+DDO_SetCooperativeLevel] ; call address for SetCooperativeLevel

;check for error
.IF eax != DD_OK
call Fail, eax, offset szSetCooperativeLevelFail
jmp end_loop

; 3. Switch display mode to:
; screen_dx x screen_dy x screen_bpp

sz009 db "009=SetDisplayMode",13,10,0

call OutputDebugStringA,offset sz009

mov eax,screen_bpp ; bpp
push eax

mov eax,screen_dy
push eax ; cy

mov eax,screen_dx
push eax ; cx

mov eax,[lpDD] ; pointer to the instance of the DDObject
push eax

mov eax,[eax] ; get the vtable addr
call [eax + DDO_SetDisplayMode] ; Call SetDisplayMode method by indexing
; into object's virtual table
;check for error
.IF eax != DD_OK
call Fail, eax, offset szSetDisplayModeFail
jmp end_loop

; 4. Create a primary surface with a back buffer.

sz010 db "010=CreatePrimarySurface",13,10,0

call OutputDebugStringA,offset sz010

; first prepare the DDSD ie:
; DirectDrawSurfaceDescription structure
mov ddsd.dwSize, SIZE ddsd
; also has a DDS_Surf_Caps sub structure in it
mov ddsd.ddssurfCaps.dwCaps,DDSCAPS_PRIMARYSURFACE OR\


mov ddsd.dwBackBufferCount,BUFFERS ; =1

push large NULL
mov eax, offset lpDDSPrimary
push eax
mov eax, offset ddsd
push eax
mov eax,[lpDD] ;DD Object
push eax

mov eax,[eax] ; get object's vtable addr
call [eax + DDO_CreateSurface] ; call CreateSurface

.IF eax != DD_OK
call Fail, eax, offset szCreateSurfaceFail
jmp end_loop

; Get a pointer to the back buffer surface
sz011 db "011=GetPointerToBackBuffer",13,10,0

call OutputDebugStringA,offset sz011

mov ddscaps.dwCaps, DDSCAPS_BACKBUFFER ; specify the back buffer

mov eax,offset lpDDSBack ; place to store the pointer
push eax

mov eax, offset ddscaps
push eax

mov eax,[lpDDSPrimary] ; the surface the back buffer is attached to
push eax

mov eax,[eax]
call [eax + DDS_GetAttachedSurface] ; GetAttachedSurface

.IF eax != DD_OK
call Fail, eax, offset szGetAttachedSurfaceFail
jmp end_loop

; GetPixelFormat for Primary surf
dd_pixelformat01 DDPIXELFORMAT <0>
dd_lp_pixelformat01 dd 0
szGetPixelFormatFail db "GetPixelFormat Failed",0,0,0,0

sz0012 db "012=GetPixelFormatForPrimary",13,10,0

call OutputDebugStringA,offset sz0012
mov eax,size dd_pixelformat01
mov dd_pixelformat01.dwSize,eax

mov eax,offset dd_pixelformat01
push eax

mov eax,[lpDDSPrimary]
push eax

mov eax,[eax] ;vtable addr
call [eax + DDS_GetPixelFormat]

.IF eax != DD_OK
call Fail, eax, offset szGetPixelFormatFail
jmp end_loop


flag_565_pixelformat dd 0
GBitmask565 equ 7e0h
test_gmask dd 0
mov eax,dd_pixelformat01.dwGBitMask
mov [test_gmask],eax
cmp eax,GBitmask565
jnz Video_is_555
mov [flag_565_pixelformat],1


Posted on 2002-09-02 00:49:44 by BogdanOntanu
Thank you very much for the code Bogdan I really appreciate it, can I also ask a quick question, how would I structure the DLL file? Cause I want to keep all of my graphics functions in a reusable DLL that I can make a few small games because in DOS I have some functions that I can just copy and paste and write the main game code and the game is finished. Should I do this:

1. Have the main app set up DirectDraw and other stuff
2. Pass the pointer of main surface (vid memory) and back buffer

Is that OK?
Posted on 2002-09-02 12:15:34 by x86asm
Well you see do not use any DLL in HE...

but as Hiroshimator has very well pointed out it whould have been better if we used a DLL with the common functions used in both Game and Map Editor, in this way improvements in game whould have appeared faster in game editor also :)

SO to answer you questions i guess YES it is better to let applications make their own windows/class and main directdraw object. Please do not forget that in a DLL the code is shared but the .data zones are owned by each process that actually uses the DLL.

I guess you can also include the Initializations part as a helper in you DLL so if somebody dosent want to make his own DirectDraw Object but i guess makeing a window class is everybody's little work that he has to be " do it yourself" job :)

Also do not forget about "Pitch" of a locked surface or primary/seccondary on screen surfaces whrn porting any 2D stuff

Besides that choose your parameters carefully
Posted on 2002-09-02 19:59:45 by BogdanOntanu
Thank you for your guidance Bogdan, I really appreciate it :D
Posted on 2002-09-02 20:05:42 by x86asm