Thread: Cannot find error

  1. #1
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006

    Cannot find error

    I am just begining to learn programming with DirectX. I am currently on the section on Page Flipping in the book I am reading. Anyway, I am getting an access violation fault with the program I am doing from the book. The source for it that come on the CD with the book runs fine but for the life of me I cannot find where I messed up the code. It gets as far as creating a blank screen then crashes. Here is the code that I have
    #define WIN32_LEAN_AND_MEAN 
    #define INITGUID // make sure directX guids are included
    #include <windows.h>   
    #include <windowsx.h> 
    #include <ddraw.h> 
    // DEFINES /////////////////////////////////////////////////////////////////////
    // defines for windows 
    // default screen size
    #define SCREEN_WIDTH    640  // size of screen
    #define SCREEN_HEIGHT   480  // max size 1280, 1024 w/ 32 bbp
    #define SCREEN_BPP      8    // bits per pixel
    #define MAX_COLORS      256  // maximum colors
    // TYPES ///////////////////////////////////////////////////////////////////////
    // basic unsigned types
    typedef unsigned short USHORT;
    typedef unsigned short WORD;
    typedef unsigned char  UCHAR;
    typedef unsigned char  BYTE;
    // MACROS //////////////////////////////////////////////////////////////////////
    #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
    #define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
    // initializes a direct draw struct
    #define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
    // GLOBALS /////////////////////////////////////////////////////////////////////
    HWND      main_window_handle = NULL; // globally track main window
    HINSTANCE hinstance_app      = NULL; // globally track hinstance
    int       window_closed      = 0;
    // directdraw stuff
    LPDIRECTDRAW7         lpDD               = NULL; // dd object
    LPDIRECTDRAWSURFACE7  lpDDPrimarySurface = NULL; // dd primary surface
    LPDIRECTDRAWSURFACE7  lpDDBackSurface    = NULL; // dd back surface
    LPDIRECTDRAWPALETTE   lpDDPalette        = NULL; // a pointer to the created dd palette
    LPDIRECTDRAWCLIPPER   lpDDClipper        = NULL; // dd clipper
    PALETTEENTRY          palette[256];              // color palette
    PALETTEENTRY          save_palette[256];         // used to save palettes
    DDSURFACEDESC2        DDSurfaceDesc;             // a direct draw surface description struct
    DDBLTFX               DDbltfx;                   // used to fill
    DDSCAPS2              DDSurfaceCaps;             // a direct draw surface capabilities struct
    HRESULT               DDResultVal;               // result back from dd calls
    DWORD                 start_clock_count = 0;     // used for timing
    // FUNCTIONS ///////////////////////////////////////////////////////////////////
    // this is the main message handler of the system
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
        PAINTSTRUCT      ps;                         // used in WM_PAINT
        HDC              hdc;                        // handle to a device context
        switch(msg) {	
    	    case WM_CREATE: {
    		    // do initialization stuff here
                // return success
    		} break;
        	case WM_PAINT: {
        		// simply validate the window 
       	        hdc = BeginPaint(hwnd,&ps);	 
                // end painting
                // return success
       		} break;
        	case WM_DESTROY: {
        		// kill the application, this sends a WM_QUIT message 
                // return success
    		} break;
    	    default: break;
        } // end switch
        // process any messages that we didn't take care of 
        return (DefWindowProc(hwnd, msg, wparam, lparam));
    } // end WinProc
    // this is the main loop of the game, do all your processing here
    int Game_Main(void *parms = NULL, int num_parms = 0) {
        // make sure this is not executed again
        if (window_closed) return(0);
        // for now test if user is hitting ESC and send WM_CLOSE
        if (KEYDOWN(VK_ESCAPE) ) {
            window_closed = 1;
        } // end if
        // lock the back buffer
        lpDDBackSurface->Lock(NULL, &DDSurfaceDesc, DDLOCK_SURFACEMEMORYPTR |
                                                    DDLOCK_WAIT, NULL);
        // alias pointer to back buffer surface
        UCHAR *back_buffer = (UCHAR*)DDSurfaceDesc.lpSurface;
        // now clear the back buffer out
        // linear memory?
        if (DDSurfaceDesc.lPitch == SCREEN_WIDTH) {
            memset(back_buffer, 0, SCREEN_WIDTH * SCREEN_HEIGHT);
        } else {  // non linear memory
            // make copy of video pointer
            UCHAR *dest_ptr = back_buffer;
            // clear out memory one line at a time
            for(int y = 0; y < SCREEN_HEIGHT; y++) {
                // clear the next line
                memset(dest_ptr, 0, SCREEN_WIDTH);
                // advance pointer to next line
                dest_ptr += DDSurfaceDesc.lPitch;
            } // end for
        } // end else
        // game logic here....
        // draw the next frame into the back buffer
        // plot 5000 random pixels
        for (int index = 0; index < 5000; index++) {
            int   x   = rand()%SCREEN_WIDTH;
            int   y   = rand()%SCREEN_HEIGHT;
            UCHAR col = rand()%256;
            back_buffer[x+y*DDSurfaceDesc.lPitch] = col;
        } // end for
        // unlock the back buffer
        if (FAILED(lpDDBackSurface->Unlock(NULL) ) )
        // perform the flip
        while(FAILED(lpDDPrimarySurface->Flip(NULL, DDFLIP_WAIT) ) );
        // wait a sec
        // return success or failure or your own return code here
    } // end Game_Main
    // this is called once after the initial window is created and
    // before the main event loop is entered, do all your initialization here
    int Game_Init(void *parms = NULL, int num_parms = 0) {
        // create IDirectDraw interface 7.0 object and test for error
        if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpDD, IID_IDirectDraw7, NULL) ) )
        // set cooperation to fullscreen
        if (FAILED(lpDD->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | 
                                                                 DDSCL_ALLOWMODEX |
                                                                 DDSCL_EXCLUSIVE  |
                                                                 DDSCL_ALLOWREBOOT) ) );
        // set display mode to 640x480x8
                                        0, 0) ) )
        // clear DirectDrawSurfaceDescription and set size
        // enable valid fields, surface capabilities and # of back buffers
        DDSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
        // set the back buffer count field to 1, use 2 for triple buffering
        DDSurfaceDesc.dwBackBufferCount = 1;
        // request a complex, flippable
        DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                                       DDSCAPS_COMPLEX | DDSCAPS_FLIP;
        // create the primary surface
        if (FAILED(lpDD->CreateSurface(&DDSurfaceDesc, &lpDDPrimarySurface, NULL) ) )
        // now query for attached surface from the primary surface
        // this line is needed by the call
        DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
        // get te attached back buffer surface
        if (FAILED(lpDDPrimarySurface->GetAttachedSurface(&DDSurfaceDesc.ddsCaps,
                                                          &lpDDBackSurface) ) )
        // build up the palette data array
        for (int color = 1; color < 255; color++) {
            // fill with random RGB values
            palette[color].peRed   = rand()%255;
            palette[color].peGreen = rand()%255;
            palette[color].peBlue  = rand()%255;
            // set flags field to PC_NOCOLLAPSE
            palette[color].peFlags = PC_NOCOLLAPSE;
        } // end for
        // now fill in entry 0 & 255 w/ black and white
        palette[0].peRed     = 0;
        palette[0].peGreen   = 0;
        palette[0].peBlue    = 0;
        palette[0].peFlags   = PC_NOCOLLAPSE;
        palette[255].peRed   = 255;
        palette[255].peGreen = 255;
        palette[255].peBlue  = 255;
        palette[255].peFlags = PC_NOCOLLAPSE;
        // create the palette object
        if (FAILED(lpDD->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 |
                                       palette, &lpDDPalette, NULL) ) )
        // finally, attach the palette to the primary surface
        if (FAILED(lpDDPrimarySurface->SetPalette(lpDDPalette) ) )
        // return success or failure or your own return code here
    } // end Game_Init
    // this is called after the game is exited and the main event
    // loop while is exited, do all you cleanup and shutdown here
    int Game_Shutdown(void *parms = NULL, int num_parms = 0) {
        // first the palette
        if (lpDDPalette) {
            lpDDPalette = NULL;
        } // end if
        // now the back buffer surface
        if (lpDDBackSurface) {
            lpDDBackSurface = NULL;
        } // end if
        // now the primary surface
        if (lpDDPrimarySurface) {
            lpDDPrimarySurface = NULL;
        } // end if
        // now blow away the IDirectDraw4 interface
        if (lpDD) {
            lpDD = NULL;
        } // end if
        // return success or failure or your own return code here
    } // end Game_Shutdown
    // WINMAIN
    int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance,
    					LPSTR lpcmdline, int ncmdshow) {
        WNDCLASSEX winclass; // this will hold the class we create
        HWND       hwnd;     // generic window handle
        MSG        msg;      // generic message
        HDC        hdc;      // graphics device context
        // first fill in the window class stucture
        winclass.cbSize         = sizeof(WNDCLASSEX);	        = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
        winclass.lpfnWndProc    = WindowProc;
        winclass.cbClsExtra	    = 0;
        winclass.cbWndExtra	    = 0;
        winclass.hInstance      = hinstance;
        winclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
        winclass.hCursor        = LoadCursor(NULL, IDC_ARROW); 
        winclass.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);
        winclass.lpszMenuName   = NULL;
        winclass.lpszClassName  = WINDOW_CLASS_NAME;
        winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
        // save hinstance in global
        hinstance_app = hinstance;
        // register the window class
        if (!RegisterClassEx(&winclass))
        // create the window
        if (!(hwnd = CreateWindowEx(0,                     // extended style
                                    WINDOW_CLASS_NAME,     // class
                                    "DirectDraw Initialization Demo", // title
                                    WS_POPUP | WS_VISIBLE, // fullscreen
                                    0,0,                   // initial x,y
                                    SCREEN_WIDTH, SCREEN_HEIGHT, // initial width, height
                                    NULL,                  // handle to parent 
                                    NULL,                  // handle to menu
                                    hinstance,             // instance of this application
                                    NULL) ) )              // extra creation parms
        // save main window handle
        main_window_handle = hwnd;
        // initialize game here
        // enter main event loop
        while(TRUE) {
            // test if there is a message in queue, if so get it
    	    if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { 
        	   // test if this is a quit
               if (msg.message == WM_QUIT)
    	       // translate any accelerator keys
        	   // send the message to the window proc
            } // end if
            // main game processing goes here
       	} // end while
        // closedown game here
        // return to Windows like this
    } // end WinMain
    Using DEV-C++ Under Windows XP

    "No! Do, or Do Not. There is no Try..."

  2. #2
    Software engineer
    Join Date
    Aug 2005
    Great book, but yeah errors creep up somewhere. I'll keep looking at it and find out the problem. A minor mistake: when initializing your palette, you should be giving it rand()%256 instead of rand()%255.

    What you might want to do is make a log for runtime.

    	void Log(std::string text) {
    		// Logs text to c:\\log.txt for debugging purposes.
    		std::ofstream out("c:\\log.txt", std::ios::out | std::ios::app); 
    		out << text << std::endl;
    Then check your code like this...

    hr = lpdd->CreateSurface(...);    // basically any function returns an HRESULT.
    if (FAILED(hr)) { 
       Log("Creating the surface failed.");
       return false;  // dont initialize any further.
    And... do some error checking on your Game_Init() function. Game_Init() returns true if initializion succeeded (programmed by you), or false. If false, exit the program.

    if (!Game_Init()) {    
       Log("Initializing the game failed.");
       return 0;
    You will know exactly where the problem is.

    I'm just jotting down notes on every concern I have. The next one is I tried to compile your code and it didn't even try setting the display mode because the screen was still in my desktop's resolution. So, I think it runs somewhere inside Game_Init() before the display mode.

    Ding ding! Look at your code here...

    // set display mode to 640x480x8
    0, 0) ) );

    You set the display mode with the if condition, but take a look at what that first semi-colen is doing. It doesn't return 0 if it fails. Instead, there's two things going on here. It sets the mode successfully, but then it returns 0. Your Game_Init() function thinks its done and jumps right into the main game loop. Your surfaces were never made. So, remove the first semi-colen and you'll be up and running.
    Last edited by dxfoo; 09-19-2006 at 12:30 PM.

  3. #3
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001

    This is a much better way to go about doing 2D in 3D. This is DirectX 8 so ID3DXSprite has been changed in DX9. Check the SDK for information.

    A very simple way to do blits in Direct3D:

    #pragma once
    struct TLVertexTex1
      D3DXVECTOR3 vecPos;
      float rhw;
      float u,v;
      TLVertexTex1():vecPos(D3DXVECTOR3(0.0f,0.0f,0.0f)),u(0.0f),v(0.0f),rhw(0.0f) { }
      TLVertexTex1(float x,float y,float u,float v):vecPos(D3DXVECTOR3(x,y,1.0f)),u(u),v(v),rhw(1.0f) { }
    #include "TLVertex.h"
    void CGameApp::RenderTestQuad(IDirect3DTexture9 *pTexture)
      TLVertexTex1 verts[4];
    If I coded everything correctly you should have a textured image on screen. You should be able to draw about a million of these before you get any major issues.
    Last edited by VirtualAce; 09-19-2006 at 01:45 PM.

  4. #4
    Software engineer
    Join Date
    Aug 2005
    That wasn't his question nor the problem, Bubba.
    Last edited by dxfoo; 09-19-2006 at 01:59 PM.

  5. #5
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Holy semi-colen's Batman! I did not even see that! Man, I really need to start getting more sleep.... I'll correct that and see what happens....

    Although I still don't see why that would give an access violation fault.....
    Using DEV-C++ Under Windows XP

    "No! Do, or Do Not. There is no Try..."

  6. #6
    Software engineer
    Join Date
    Aug 2005
    Heh, it's always those semi-colens! Think about it this way, SetDisplayMode() returned 1 because it was successful.

    You did this basically...

    if(1); // returned result of SetDisplayMode()
    return 0;

    There's basically two statements going on here instead of one!

    Game_Init() had no error checking on its returned result, so it continues on and starts up the main game loop. You can easily check success or failure with something like this...

    if (!Game_Init())
    return 0; // basically don't jump into the game loop but exit.

    But yeah, sleep helps

  7. #7
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    yeah, I realized that after I thought it through. After all, the computer is only as smart as you program it to be, and it only does what you tell it to do... even if you don't realize what it is you are telling it :P

    Thanx for the help!
    Using DEV-C++ Under Windows XP

    "No! Do, or Do Not. There is no Try..."

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. An error is driving me nuts!
    By ulillillia in forum C Programming
    Replies: 5
    Last Post: 04-04-2009, 09:15 PM
  2. Using VC Toolkit 2003
    By Noobwaker in forum Windows Programming
    Replies: 8
    Last Post: 03-13-2006, 07:33 AM
  3. using c++ in c code
    By hannibar in forum C Programming
    Replies: 17
    Last Post: 10-28-2005, 09:09 PM
  4. pointer to array of objects of struct
    By undisputed007 in forum C++ Programming
    Replies: 12
    Last Post: 03-02-2004, 04:49 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 01:10 AM