Jump to content
  • Advertisement
Sign in to follow this  
Kenneth Alexander

Can't lock surface :(

This topic is 4993 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

“First I get “ BASIC caused an invalid page fault in module BASIC.EXE at 016f:0040b974. Registers: EAX=cccccccc CS=016f EIP=0040b974 EFLGS=00010202 EBX=00580000 SS=0177 ESP=0068fbd2 EBP=0068fbde ECX=00000000 DS=0177 ESI=0068fc48 FS=2c3f EDX=006a5f34 ES=0000 EDI=00680068 GS=0000 Bytes at CS:EIP: 66 c5 75 0c 0f b6 55 18 0f b6 5d 10 66 83 fa 00 Stack dump: 00000177 0068fc48 0068fc2c fc9cfc2c fc480068 00000068 cccc0058 cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc There are two basic causes for an invalid page fault in the Windows 95 environment: · Something unexpected has happened within the Windows environment, typically an improper memory address. For example, an application or a Windows component might read or write to a memory location that has not been allocated to it (memory that it does not own), potentially overwriting and corrupting other program code in that area of memory. · Parameters that are not valid have been passed between applications and the Windows environment. Invalid parameters can cause invalid instructions to be executed, resulting in page faults. This is usually the result of the application's internal program code incorrectly passing specific data that could not be correctly interpreted by Windows or a Windows-based application. “Then the next time I run the code I get : DDERR_CANTLOCKSURFACE” “windowed directx code I use for trouble shooting that returns error during lock function!” “ an help would be great! J” DX_Error_result=(lpdd7->SetCooperativeLevel(hwnd, DDSCL_NORMAL)); if (FAILED(DX_Error_result)){ Error_Engine -> Get_Error(DX_Error_result); MessageBox(NULL, "NORMAL Coopertive Operation Failed","Exit", MB_OK|MB_ICONEXCLAMATION); exit(1); }// end if failed DDRAW_INIT_STRUCT(ddsd); DDRAW_INIT_STRUCT(ddpixelformat); memset(ddsd_ptr,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.dwBackBufferCount = 0; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; DX_Error_result=(lpdd7->CreateSurface(&ddsd, &lpddsprimary, NULL)); if (FAILED(DX_Error_result)){ Error_Engine -> Get_Error(DX_Error_result); MessageBox(NULL, "Create Primary Surface Failed","Exit", MB_OK|MB_ICONEXCLAMATION); exit(1); }// end if failed DX_Error_result=(lpddsprimary->GetPixelFormat(&ddpixelformat)); if (FAILED(DX_Error_result)){ Error_Engine -> Get_Error(DX_Error_result); MessageBox(NULL, "Get Pixel Format Failed","Exit", MB_OK|MB_ICONEXCLAMATION); exit(1); }// end if failed Color_Depth = ddpixelformat.dwRGBBitCount; Depth_modifier = (Color_Depth / 8); Color_Modified_Size = Vid_Buff_Size * Depth_modifier; GetWindowRect(hwnd,lpRect); result = lpddsprimary->IsLost(); if (FAILED(result)){ Error_Engine -> Get_Error(result); MessageBox(NULL, "Surface Lost","Exit", MB_OK|MB_ICONEXCLAMATION); exit(1); }// end if failed else{ MessageBox(NULL, "Surface not Lost","Exit", MB_OK|MB_ICONEXCLAMATION); } result = (lpddsprimary->Lock(NULL, ddsd_ptr, DDLOCK_WAIT, NULL)); if (FAILED(result)){ Error_Engine -> Get_Error(result); MessageBox(NULL, "LOCK Operation Failed","Exit", MB_OK|MB_ICONEXCLAMATION); exit(1); }// end if failed else{ Screen_Engine->BackBuffAddress = (unsigned char far*)ddsd_ptr->lpSurface;// Asign the Back Buffer address here Screen_Engine->mempitch = (ddsd_ptr->lPitch); if (Screen_Engine->mempitch == 0){ W = Vid_Scr_W * Vid_Scr_H; H = 0; } else { W = Vid_Scr_W; H = Vid_Scr_H; } //MOVE(unsigned char far* BuffDestAddress, unsigned char far* BuffSrcAddress, unsigned int LPitch, unsigned int W, unsigned int H); MOVE(Screen_Engine->BackBuffAddress, Screen_Engine->SrcBuffAddress, Screen_Engine->mempitch, Screen_Engine->W, Screen_Engine->H); //MOVE(BackBuffAddress, SrcBuffAddress, Color_Modified_Size); if(FAILED(lpddsprimary->Unlock(NULL))){ //ERROR } } Accessing the Frame-Buffer Directly Pixel format??????hmmm…..L NT Kernal Built in Kernel Debugging Extensions !locks !locks [Options] [Address] !locks displays information about kernel ERESOURCE locks. Parameters Options This parameter is optional. The following options can be specified to control the information output. -V Maximum output about each lock should be displayed. -P Performance lock information should be displayed Address This parameter is optional. Displays information about the ERESOURCE lock at the specified address. If Address is not specified, then information about all ERESOURCE locks in the system will be displayed. Platforms Power PC, Alpha, MIPS, x86 [Edited by - Kenneth Alexander on April 9, 2005 1:16:40 PM]

Share this post

Link to post
Share on other sites
I've seen you have a ddsd and a ddsd_ptr, but as you didn't paste the creation of those, I think maybe it has something to do with the ddsd_ptr.

Or maybe something else that could be is that you didn't set a clipper for the window with lpddclipper->setHWnd(0, window_handle); lpddsprimary->setClipper(lpddclipper).

Or maybe you don't have enough video memory or something like that; try a different color depth from windows.

Hope this helps.

Share this post

Link to post
Share on other sites
Original post by Kenneth Alexander
And, lock is suppose to lock the memory even on the video card for writting purposes.

Even the primary surface; which is, what is written to in windowed mode... ie a rectangle on the screen.
Thanks for the correction, I removed my post so it doesn't lead to confusion. I wrote a program which basically does the same as yours: creates a DirectDraw7 object, sets cooperative level to normal, creates a primary surface, attempts to lock the primary surface. And I get the errors which you describe when running through the debugger. The following is what I think is the cause of the error, excerpt from MSDN: "Unless you include the DDLOCK_NOSYSLOCK flag when you call the Lock method, locking the surface typically causes DirectDraw to take the Win16Mutex. During the Win16Mutex all other applications, including Windows, cease execution. Since the Win16Mutex stops applications from executing, standard debuggers cannot be used while the lock is held. Kernel debuggers can be used during this period. DirectDraw always takes the Win16Mutex when locking the primary surface."
Do you think this could be the cause in your case? Because of this I tried to build the executable and ran it outside the debugger (so it wouldn't stop execution) and then the primary surface was successfully locked and I could write pixels to it. I did expect the window client area to be locked but the whole screen was locked so one probably has to get the correct rectangle using ClientToScreen and GetClientRect or similar.

\Jimmy H

Share this post

Link to post
Share on other sites
sorry, i don't have help relating to your problem. i wanted to point out that in the forum faq it tells you how to post code like this...

code here blah blah

makes large code posts smaller and easier to read :)

ok so how the hell u do show people those tags in a post anyway

Share this post

Link to post
Share on other sites
Have you tried doing a "Rebuild All"?

Other than that, this caught my attention: EAX=cccccccc. EAX is the register commonly used for return values and values that are just about to be used, and cccccccc is the value the debugger fills uninitialised variables with. So, that implies to me that some value that's just about to be used hasn't been initialized yet.
My guess is the surface you're locking isn't valid, which would imply that CreateSurface() failed. But you check for that in your code, and besides - that'd cause GetPixelFormat() to fail first.

The NOSYSLOCK thing hasn't ever been a problem for me, that just means that you can't use the debugger within the lock (in theory - I've always been able to. Perhaps this only happens with Win9x?). It won't cause any actual errors like this.

ok so how the hell u do show people those tags in a post anyway
See Here [smile]
And yes, [source] [/source] tags would make it nicer on the eyes [smile]

Share this post

Link to post
Share on other sites
Original post by Kenneth Alexander
Never fully remove code -> comment it out, it makes going back over your steps easier without eliminating something from view or back stepping too much.

Yeah, I've done that a few times.
"Well, I'll change it all anyway. I'll delete this function"
(5 mins later)
"Right, where's my code to do this?"
"Oh crap. I deleted it >_<"

I usually keep things commented out until I know for *sure* I won't need them. Which often means a lot of crap cluttering up my source till near the end of the project [smile]

Share this post

Link to post
Share on other sites
Well.... that explains alot.
If MSCV6, which I am using, is using bp to access the parameters, then messing with it is a bad idea.
The code was originaly external and linked in as an OBJ when I used Borland 4.5 so pushing bp and moving sp to bp is a standard operation, but with inline code I'm playing with others so to speak :)

Almost all external Assembly subroutines use:

push bp
mov bp,sp
pop bp

to access the stack for parameters / data passed to the function.

So either I'm going to have to access the stack directly or use the compiler and leave bp alone.

It is one or the other not both. :)

Thanks Steve,


Share this post

Link to post
Share on other sites
First that mov bp,sp in the move function was an error. stop.
But, it is not alone. stop.
teletype days :)

I must have an errant pointer or array some where :(

Because, after review, that is the only explanation left.

And it is writing into Display-Frame or the Lock function or their variables or members.
Resulting in a wide array of failures including coruption of the call stack.

You can see in the following:

Clear function

0040B650 push ebp // This is a dissassembly of the compiler
0040B651 mov ebp,esp // code
0040B653 sub esp,44h
0040B656 push ebx
0040B657 push esi
0040B658 push edi
0040B659 push ecx
0040B65A lea edi,[ebp-44h]
0040B65D mov ecx,11h
0040B662 mov eax,0CCCCCCCCh
0040B667 rep stos dword ptr [edi]
0040B669 pop ecx
0040B66A mov dword ptr [ebp-4],ecx

---------my code----------------------

0040B6BD pop edi
0040B6BE pop esi
0040B6BF pop ebx
0040B6C0 add esp,44h
0040B6C3 cmp ebp,esp
0040B6C5 call __chkesp (004125d0)
0040B6CA mov esp,ebp
0040B6CC pop ebp
0040B6CD ret 14h

This is normal exit and entry of functions in MSVC(Debug mode, Steve points out release is lighter :) )
I need to look more into this but am out of time.

[Edited by - Kenneth Alexander on April 12, 2005 1:47:34 PM]

Share this post

Link to post
Share on other sites

Got it Steve, and do I feel stupid :(
Again, that mov bp,sp would cause some problems.
But it is not alone.

First, for those who don't know and are "listening in", just a small note on registers for those new to using inline assembly in "c/c++". You can find this under help "inline assembly" :)


"When using __asm to write assembly language in C/C++ functions, you don't need to preserve the EAX, EBX, ECX, EDX, ESI, or EDI registers. For example, in the POWER2.C example in Writing Functions with Inline Assembly, the power2 function doesn't preserve the value in the EAX register. However, using these registers will affect code quality because the register allocator cannot use them to store values across __asm blocks. In addition, by using EBX, ESI or EDI in inline assembly code, you force the compiler to save and restore those registers in the function prologue and epilogue.

You should preserve other registers you use (such as DS, SS, SP, BP, and flags registers) for the scope of the __asm block. You should preserve the ESP and EBP registers unless you have some reason to change them (to switch stacks, for example). Also see Optimizing Inline Assembly.

Note If your inline assembly code changes the direction flag using the STD or CLD instructions, you must restore the flag to its original value." - MS

Back to the problem :)
I say again:
Got it, and do I feel stupid :(

If you look at the Clear function you will find a line:(not show in the thread)
mov edi, BuffDestAddress ;// Load start address of destination buffer in di

This used to be:
les di, BuffDestAddress ;// Load start address of destination buffer in es:di

Until I found Load ES/DS with pointer caused a Page fault.
I forgot, I changed that a month ago.
Something to due, I think, with the cpu running in
Protected Mode.
The opcode is either illegal out of the os's ring "0"
or it is not passing the right address.

This needs to be changed:
379: les di, BuffDestAddress ;// Load start address of destination buffer in es:di
0040B712 les di,dword ptr [ebp+8]
380: lds si, BuffSrcAddress ;// Load start address of source buffer in ds:si
0040B716 lds si,dword ptr [ebp+0Ch]

mov edi, BuffDestAddress ;// Load start address of destination buffer in es:di
mov esi, BuffSrcAddress ;// Load start address of source buffer in ds:si

The page fault, I believe, caused colateral damage resulting in a cascade of errors.

It still needs additional work, but it is closer.

The "Lock" fuction still gets corrupted in debug mode....
I don't know why.

fails -1


I then need to reboot the computer to get the surface free again.

Oh well, at least I'm making progress.

If anyone knows or has additional information please "chime in"
hope this helps,
Still at it,

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!