• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 649
  • Last Modified:

Memory access violation while locking and clearing surfaces.

I wrote a simple program to draw a bitmap on the screen using directdraw and everything worked. After that I tried to put my code into functions, to make it more readable, but I got this error:

The instruction at "0x00406981" referenced memory at "0x00000000." The memory could not be written.

If I replace the call to back.Lock (see code) by the actual code back.Lock contains (see comment in code), it works, but I want to do it with the method Lock.

Do you know how I can solve this?

This is my code (main.cpp, functies.cpp and functies.h):

I know It's a lot of code, but only some parts have something to do with the error.

The parts that are important are:

the part in main.cpp, where the error occurs (you can recognize it by the comments in capitals).
the class definition of DDBack in functies.h
the methods of DDBack and the clearSurfaceMemory function in functies.cpp

////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////  main.cpp  /////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN

#include <windows.h>   // include alle windows headers
#include <windowsx.h>  // include bruikbare macro's
#include <stdio.h>
#include <ddraw.h>
#include <stdlib.h>
#include <time.h>
#include <io.h>

#include "functies.h"

#define WINDOW_CLASS_NAME "WINCLASS1"
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define BITDEPT 32


HINSTANCE hinstance_app;
HWND main_window_handle;

DD7Object DD7;
DDPrimary primary;
DDBack back;
DDOffscreenSurface bitmapsurface;
DDSURFACEDESC2      ddsd;    // surface description

bool window_gesloten=0;

BITMAP_FILE  bitmap;                // holds the bitmap

///////////////////////////////////////////////////////////

int Game_Init()
{

DD7.SetFullscreen(main_window_handle);
DD7.SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,BITDEPT);
primary.Init(DD7.lpdd,1);
back.Init(primary.lpdds);

bitmapsurface.Init(DD7.lpdd,640,480,1);

if(!Set_Pixel_Format(primary.lpdds)){return(0);}

if (!Load_Bitmap_File(&bitmap,"bitmap24.bmp",BITDEPT))
{
      DisplayError("Load_Bitmap_File error");
      return(0);
}

bitmapsurface.Lock();

if(!clearSurfaceMemory(bitmapsurface.memory, bitmapsurface.mempitch, SCREEN_WIDTH, SCREEN_HEIGHT, BITDEPT)){return(0);}

if(!loadBitmapToSurface(&bitmap, bitmapsurface.memory, bitmapsurface.mempitch, BITDEPT, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0))
{
      DisplayError("loadBitmapToSurface error");
      return(0);
}

bitmapsurface.Unlock();
// return success or failure or your own return code here
return(1);

} // end Game_Init

/////////////////////////////////////////////////////////////

int Game_Main()
{
// this is the main loop of the game, do all your processing
// here

if(window_gesloten){return (0);}

// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
      {
      SendMessage(main_window_handle,WM_CLOSE,0,0);
      window_gesloten=1;
      }

// IF I CHANGE THE FOLLOWING THREE LINES BY THE COMMENT UNDER IT, THE CODE WORKS !!!
back.Lock();
int mempitch = back.mempitch;
UCHAR* video_buffer = back.memory;

/*
DDRAW_INIT_STRUCT(ddsd);
if (FAILED(back.lpdds->Lock(NULL, &ddsd,
                         DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
                         NULL)))
   {
   // error
   return(0);
   } // end if

int mempitch        = (int)ddsd.lPitch;
UCHAR *video_buffer = (UCHAR *)ddsd.lpSurface;

*/

// IT'S IN THIS FUNCTIONS THAT MY DEBUGGER TELLS THE ERROR IS !!!!!!!!!!!!!!!!!!!!!!!!!!

if(!clearSurfaceMemory(video_buffer,mempitch,SCREEN_WIDTH,SCREEN_HEIGHT,BITDEPT)){return(0);}

back.Unlock();

back.lpdds->Blt(NULL, // pointer to dest RECT
                bitmapsurface.lpdds,    // pointer to source surface
                NULL, // pointer to source RECT
                DDBLT_WAIT,   // control flags
                NULL); // pointer to DDBLTFX holding info

primary.Flip();

// sleep a bit
Sleep(50);

// return success or failure or your own return code here
return(1);

} // end Game_Main

////////////////////////////////////////////////////////////

int Game_Shutdown()
{
// this is called after the game is exited and the main event
// loop while is exited; do all you cleanup and shutdown here
// unload the bitmap file, we no longer need it
Unload_Bitmap_File(&bitmap);

// return success or failure or your own return code here
return(1);

} // end Game_Shutdown

// WINMAIN ////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hinstance,
            HINSTANCE hprevinstance,
            LPSTR lpcmdline,
            int ncmdshow)
{

WNDCLASSEX winclass; // this holds the class we create
HWND       hwnd;     // generic window handle
MSG          msg;      // generic message

// first fill in the window class structure
winclass.cbSize         = sizeof(WNDCLASSEX);
winclass.style            = 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))
    return(0);

// create the window
if (!(hwnd = CreateWindowEx(NULL,                  // extended style
                            WINDOW_CLASS_NAME,     // class
                           "T3D Game Console Version 1.0", // titleWS_OVERLAPPEDWINDOW | WS_VISIBLE
                           WS_POPUP|WS_VISIBLE,
                           0,0,           // initial x,y
                           400,300,   // initial width, height
                           NULL,       // handle to parent
                           NULL,       // handle to menu
                           hinstance, // instance of this application
                           NULL)))    // extra creation parms
return(0);

// save main window handle
main_window_handle = hwnd;

// initialize game here
if(!Game_Init())
   return (0);

// enter main event loop
while(TRUE)
      {
      DWORD start_time = GetTickCount();
    // 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)
           break;

       // translate any accelerator keys
       TranslateMessage(&msg);

       // send the message to the window proc
       DispatchMessage(&msg);
       } // end if

       // main game processing goes here
       if(!Game_Main())
         {return (0);}
         while((GetTickCount() - start_time) < 33);
      } // end while

// closedown game here
if(!Game_Shutdown())
    return (0);

// return to Windows like this
return(msg.wParam);

} // end WinMain
///////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////// functies.h ///////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

// basic unsigned types
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char  UCHAR;
typedef unsigned char  BYTE;

typedef struct BITMAP_FILE_TAG
        {
        BITMAPFILEHEADER bitmapfileheader;  // this contains the
                                            // bitmapfile header
        BITMAPINFOHEADER bitmapinfoheader;  // this is all the info
                                            // including the palette
        PALETTEENTRY     palette[256];// we will store the palette here
        UCHAR            *buffer;    // this is a pointer to the data

        } BITMAP_FILE, *BITMAP_FILE_PTR;

// macro's /////////////////////////////////////////////

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

#define DDRAW_INIT_STRUCT(ddstruct){ memset(&ddstruct,0,sizeof(ddstruct));ddstruct.dwSize=sizeof(ddstruct); }

#define BITMAP_ID            0x4D42 // universal id for a bitmap
#define MAX_COLORS_PALETTE  256
#define DD_PIXEL_FORMAT555      15
#define DD_PIXEL_FORMAT565      16

#define RGB16BIT565(red, green, blue) ( ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3))
#define RGB16BIT555(red, green, blue) ( ((red >> 3) << 10) | ((green >> 3) << 5) | (blue >> 3))

#define RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))

// functies //////////////////////////////////////////////

LRESULT CALLBACK WindowProc(HWND hwnd,
                  UINT msg,
                                                WPARAM wparam,
                                                LPARAM lparam);

int Load_Bitmap_File(BITMAP_FILE_PTR bitmap,
                               char *filename,
            int bitdept);

int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);

int Set_Pixel_Format(LPDIRECTDRAWSURFACE7 lpdds);

int loadBitmapToSurface(BITMAP_FILE_PTR bitmap,
                                    UCHAR*videoMemory,
                                    int memPitch,
                                    int bits,
                                    int width,
                                    int height,
                                    int x,
                                    int y);

int clearSurfaceMemory(UCHAR*videoMemory,
                                 int memPitch,
                                 int width,
                                 int height,
                                 int bits);

void DisplayError (char*error);

class DD7Object
{
      HWND* window_handle;
      bool fullscreen;
      int width;
      int height;
      int bitdept;
      bool state;
public:
      LPDIRECTDRAW7 lpdd;
      DD7Object();
      ~DD7Object();
      SetFullscreen(HWND Pwindow_handle);
      SetDisplayMode(int Pwidth, int Pheight, int Pbitdept);
};

class DDPrimary
{
      int backbuffers;
      DDSURFACEDESC2 ddsd;
      bool state;
public:
      UCHAR* memory;
      int mempitch;
      LPDIRECTDRAWSURFACE7 lpdds;
      DDPrimary();
      ~DDPrimary();
      Init(LPDIRECTDRAW7 lpdd, int Pbackbuffers);
      Flip();
};

class DDBack
{
      DDSURFACEDESC2 ddsd;
      bool state;
public:
      UCHAR* memory;
      int mempitch;
      LPDIRECTDRAWSURFACE7 lpdds;
      DDBack();
      ~DDBack();
      Init(LPDIRECTDRAWSURFACE7 lpdds);
      Lock();
      Unlock();
};

class DDOffscreenSurface
{
      DDSURFACEDESC2 ddsd;
      bool state;
public:
      int width;
      int height;
      UCHAR* memory;
      int mempitch;
      LPDIRECTDRAWSURFACE7 lpdds;
      DDOffscreenSurface();
      ~DDOffscreenSurface();
      Init(LPDIRECTDRAW7 lpdd, int Pwidth, int Pheight,bool videogeheugen);
      Lock();
      Unlock();
};

/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// functies.cpp ///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN  

#include <windows.h>  
#include <windowsx.h>  
#include <stdio.h>
#include <ddraw.h>
#include <stdlib.h>
#include <time.h>
#include <io.h>
#include <cstdio>
#include <fstream.h>

#include "functies.h"

int dd_pixel_format;
int bitdept;

////////////////////// WindowProc ////////////////////////////////////////////////////////

//De standaard berichtenverwerker

LRESULT CALLBACK WindowProc(HWND hwnd,
                                        UINT msg,
                            WPARAM wparam,
                            LPARAM lparam)
{
// hier worden alle berichten verwerkt
PAINTSTRUCT    ps;    // wordt gebruikt in WM_PAINT
HDC            hdc;  // handle naar een device context

// wat is het bericht?
switch(msg)
    {
    case WM_CREATE:
        {
    // initializeer hier

        // zeg dat alles goed ging
    return(0);
    } break;

    case WM_PAINT:
    {
            // valideer het venster
    hdc = BeginPaint(hwnd,&ps);
    // hier gebeurt al het tekenen
        EndPaint(hwnd,&ps);

        // zeg dat alles goed ging
    return(0);
    } break;
    case WM_DESTROY:
    {
    // sluit de toepassing, dit verstuurt een WM_QUIT bericht
    PostQuitMessage(0);

        // zeg dat alles goed ging
    return(0);
    } break;

    default:break;

    } // einde van de switch

// stuur alle berichten die we niet behandeld hebben door
return (DefWindowProc(hwnd, msg, wparam, lparam));

} // einde WinProc

///////////////////////////////// Set_Pixel_Format /////////////////////////

int Set_Pixel_Format(LPDIRECTDRAWSURFACE7 lpdds)
{
// get the pixel format of the primary surface
DDPIXELFORMAT ddpf; // used to get pixel format

// initialize structure
DDRAW_INIT_STRUCT(ddpf);

// query the format from primary surface
if(FAILED(lpdds->GetPixelFormat(&ddpf)))
{
      return(0);
}

dd_pixel_format = ddpf.dwRGBBitCount;
return(1);
}

///////////////////////// Load_Bitmap_File /////////////////////////////////////

int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename,int bitdept)
{
// this function opens a bitmap file and loads the data into bitmap

FILE *in;

    //open the file for reading in binary mode    
    in=fopen(filename,"rb");

fread(&bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER),1,in);

// test if this is a bitmap file
if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
   {
   // close the file
   fclose(in);

   // return error
   return(0);
   } // end if

// now we know this is a bitmap, so read in all the sections

fread(&bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER),1,in);

//load the palette for 8 bits per pixel
if(bitmap->bitmapinfoheader.biBitCount == 8) {
   
    fread(&bitmap->palette,sizeof(PALETTEENTRY),MAX_COLORS_PALETTE,in);

         for (int index=0; index < MAX_COLORS_PALETTE; index++)
       {
       // reverse the red and green fields
       int temp_color                = bitmap->palette[index].peRed;
       bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
       bitmap->palette[index].peBlue = temp_color;
       
       // always set the flags word to this
       bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
       } // end for index
}

DWORD size;

size=bitmap->bitmapfileheader.bfSize-bitmap->bitmapfileheader.bfOffBits;

BYTE *tempPixelData;

tempPixelData=new BYTE[size];

if(tempPixelData==NULL) {
    fclose(in);
      return(0);
}
fread(tempPixelData,sizeof(BYTE),size,in);

fclose(in);

//byteWidth is the width of the actual image in bytes
//padWidth is the width of the image plus the extra padding
LONG byteWidth,padWidth;
long width  = bitmap->bitmapinfoheader.biWidth;
long height = bitmap->bitmapinfoheader.biHeight;
//initially set both to the width of the image
byteWidth=padWidth=(LONG)((float)width*(float)bitmap->bitmapinfoheader.biBitCount/8.0);

//add any extra space to bring each line to a DWORD boundary
while(padWidth%4!=0) {
   padWidth++;
}

      int offset;

      DWORD diff=height*byteWidth;
      BYTE *tempPixelData2;
      tempPixelData2=new BYTE[diff];

      // flip the bitmap
      if(height>0)
      {
          offset=0;
          do {
              memcpy((tempPixelData2+(((height-1)-offset)*byteWidth)),
                     (tempPixelData+(offset*padWidth)),
                      byteWidth);
              offset++;
          } while(offset<height);
      }
      else
      {
            height=height*-1;
          offset=0;
          do {
              memcpy((tempPixelData2+(offset*byteWidth)),
                     (tempPixelData+(offset*padWidth)),
                      byteWidth);
              offset++;
          } while(offset<height);
      }
      delete tempPixelData;

if(bitmap->bitmapinfoheader.biBitCount==8)
{
      bitmap->buffer=new BYTE[diff];
      memcpy(bitmap->buffer,tempPixelData2,diff);
      delete tempPixelData2;
}
else if((bitmap->bitmapinfoheader.biBitCount==24)&&(bitdept==16))
{
      bitmap->buffer=new BYTE[height*width*2];
      int index;

   // now convert each 24 bit RGB value into a 16 bit value
   for (index=0; index < height*width; index++)
       {
       // build up 16 bit color word
       USHORT color;
       
       // build pixel based on format of directdraw surface
       if (dd_pixel_format==DD_PIXEL_FORMAT555)
           {
           // extract RGB components (in BGR order), note the scaling
           UCHAR blue  = (tempPixelData2[index*3 + 0]),
                 green = (tempPixelData2[index*3 + 1]),
                 red   = (tempPixelData2[index*3 + 2]);
           // use the 555 macro
           color = RGB16BIT555(red,green,blue);
           } // end if 555
       else
       if (dd_pixel_format==DD_PIXEL_FORMAT565)
          {
          // extract RGB components (in BGR order), note the scaling
           UCHAR blue  = (tempPixelData2[index*3 + 0]),
                 green = (tempPixelData2[index*3 + 1]),
                 red   = (tempPixelData2[index*3 + 2]);

           // use the 565 macro
           color = RGB16BIT565(red,green,blue);

          } // end if 565

       // write color to buffer
       ((USHORT *)bitmap->buffer)[index] = color;

       } // end for index

   // finally write out the correct number of bits
   bitmap->bitmapinfoheader.biBitCount=16;


      delete tempPixelData2;
}
else if((bitmap->bitmapinfoheader.biBitCount==24)&&(bitdept==32))
{
      bitmap->buffer=new BYTE[height*width*4];
      int index;

   // now convert each 24 bit RGB value into a 16 bit value
   for (index=0; index < height*width; index++)
       {
       // build up 16 bit color word
       DWORD color;
       
       // build pixel based on format of directdraw surface
     
           // extract RGB components (in BGR order), note the scaling
           UCHAR blue  = (tempPixelData2[index*3 + 0]),
                 green = (tempPixelData2[index*3 + 1]),
                 red   = (tempPixelData2[index*3 + 2]);
           // use the 555 macro
           color = RGB32BIT(0,red,green,blue);
               // write color to buffer
       ((DWORD *)bitmap->buffer)[index] = color;

            }
   // finally write out the correct number of bits
   bitmap->bitmapinfoheader.biBitCount=32;


      delete tempPixelData2;
}
else
{return(0);}

// return success
return(1);
} // end Load_Bitmap_File

//////////////////////////// Unload_Bitmap_File //////////////////////////

int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
{
// this function releases all memory associated with "bitmap"
if (bitmap->buffer)
   {
   // release memory
   delete bitmap->buffer;

   // reset pointer
   bitmap->buffer = NULL;

   } // end if

// return success
return(1);

} // end Unload_Bitmap_File

//////////////////////// loadBitmapToSurface ////////////////////////////////

int loadBitmapToSurface(BITMAP_FILE_PTR bitmap,UCHAR*videoMemory,int memPitch,int bits,int width,int height,int x, int y)
{
    int imagebits = bitmap->bitmapinfoheader.biBitCount;
      if(imagebits!=bits){return(0);}
      int bytesPerPixel = bits>>3;

      int imagewidth = bitmap->bitmapinfoheader.biWidth;
      int imageheight = bitmap->bitmapinfoheader.biHeight;

      if(((x + imagewidth)>width)||((y + imageheight)>height)||(x<0)||(y<0)){return(0);}

UCHAR *bitmap_buffer = videoMemory;
bitmap_buffer+=memPitch*y+bytesPerPixel*x;

// test if memory is linear
if ((memPitch == bytesPerPixel*width)&&(x==0)&&(width==imagewidth))
   {
   // copy memory from double buffer to primary buffer
   memcpy((void *)bitmap_buffer, (void *)bitmap->buffer, bytesPerPixel*width*imageheight);
   } // end if
else
   { // non-linear

   // make copy of source and destination addresses
   UCHAR *dest_ptr = bitmap_buffer;
   UCHAR *src_ptr  = bitmap->buffer;

   // memory is non-linear, copy line by line
   for (int ywaarde=0; ywaarde < imageheight; ywaarde++)
       {
       // copy line
       memcpy((void *)dest_ptr, (void *)src_ptr, bytesPerPixel*imagewidth);

       // advance pointers to next line
       dest_ptr+=memPitch;
       src_ptr +=(bytesPerPixel*imagewidth);
       } // end for

   } // end else

return(1);
}


///////////////////////////// clearSurfaceMemory /////////////////////////////////

int clearSurfaceMemory(UCHAR*Memory,int memPitch, int width, int height, int bits)
{
int bpp = bits>>3;

// now clear the back buffer out

// linear memory?
if (memPitch == bpp*width)
    memset(Memory,0,bpp*width*height);
else
   {
   // non-linear memory

   // make copy of video pointer
   UCHAR *dest_ptr = Memory;

   // clear out memory one line at a time
   for (int y=0; y<height; y++)
       {
       // clear next line
       memset(dest_ptr,0,bpp*width);

       // advance pointer to next line
       dest_ptr+=memPitch;

       } // end for y

   } // end else

return(1);
}

//////////////////////////// DisplayError ///////////////////////////////

void DisplayError (char*error)
{
        ofstream examplefile ("error.txt");
        if (examplefile.is_open())
            {
                  examplefile << error << "\n";
                examplefile.close();
            }
}

///////////////////////// DD7Object methods ///////////////////////////////

DD7Object::DD7Object()
{
      lpdd = NULL;
      window_handle = NULL;
      fullscreen = true;
      width = 0;
      height = 0;
      bitdept = 0;
      state = true;
      if(FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
      {DisplayError("DirectDrawCreateEx FAILED");}
}
DD7Object::~DD7Object()
{
      if (lpdd)
   {
   lpdd->Release();
   lpdd = NULL;
   } // end if
      state = false;
}
DD7Object::SetFullscreen(HWND Pwindow_handle)
{
      if (state)
      {
            fullscreen = true;
            window_handle = &Pwindow_handle;
            if(FAILED(lpdd->SetCooperativeLevel(*window_handle,
                                                                  DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |
                                                                  DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
            {DisplayError("lpdd->SetCooperativeLevel FAILED");}
      }else{DisplayError("DD7Object::SetFullscreen error state = 0");}
}
DD7Object::SetDisplayMode(int Pwidth, int Pheight, int Pbitdept)
{
      if (state)
      {
            width = Pwidth;
            height = Pheight;
            bitdept = Pbitdept;
            if(FAILED(lpdd->SetDisplayMode(width, height, bitdept,0,0)))
            {DisplayError("lpdd->SetDisplayMode FAILED");}
      }else{DisplayError("DD7Object::SetDisplayMode error state = 0");}
}

///////////////////////////////// DDPrimary methods ///////////////////////////

DDPrimary::DDPrimary()
{
      backbuffers=0;
      state=false;
      memory=NULL;
      mempitch=0;
      lpdds=NULL;
}
DDPrimary::~DDPrimary()
{
      if (lpdds)
   {
   lpdds->Release();
   lpdds = NULL;
   } // end if
      state = false;
}
DDPrimary::Init(LPDIRECTDRAW7 lpdd,int Pbackbuffers)
{
      backbuffers=Pbackbuffers;
      state=true;
      if(backbuffers==1)
      {
            DDRAW_INIT_STRUCT(ddsd);

            // enable valid fields
            ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
      
            ddsd.dwBackBufferCount = 1;

            // request primary surface
            ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                                  DDSCAPS_COMPLEX | DDSCAPS_FLIP;
      
            // create the primary surface
            if (FAILED(lpdd->CreateSurface(&ddsd, &lpdds, NULL)))
            {
               DisplayError("FAILED CreateSurface error primary");
            } // end if
      }
}
DDPrimary::Flip()
{
      if(state)
      {
            while (FAILED(lpdds->Flip(NULL, DDFLIP_WAIT)));
      }
}

///////////////////////////////// DDBack methods //////////////////////////////

DDBack::DDBack()
{
      state=false;
      memory=NULL;
      mempitch=0;
      lpdds=NULL;
}
DDBack::~DDBack()
{
      if (lpdds)
   {
   lpdds->Release();
   lpdds = NULL;
   } // end if
      state = false;
}
DDBack::Init(LPDIRECTDRAWSURFACE7 lpddsback)
{
      state=true;

      DDRAW_INIT_STRUCT(ddsd);

      // this line is needed by the call
      ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

      // get the attached back buffer surface
      if (FAILED(lpddsback->GetAttachedSurface(&ddsd.ddsCaps, &lpdds)))
      {
            DisplayError("FAILED CreateSurface error back");
      }
}
DDBack::Lock()
{
      DDRAW_INIT_STRUCT(ddsd);
      if (FAILED(lpdds->Lock(NULL, &ddsd,
                                 DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
                                 NULL)))
         {
         // error
         DisplayError("FAILED Lock error back");
         } // end if

      mempitch        = (int)ddsd.lPitch;
      memory                  = (UCHAR *)ddsd.lpSurface;
}
DDBack::Unlock()
{
      if (FAILED(lpdds->Unlock(NULL)))
      {
            DisplayError("FAILED Unlock error back");
      }
      mempitch=0;
      memory=NULL;
}

//////////////////// DDOffscreenSurface methods ////////////////////////////

DDOffscreenSurface::DDOffscreenSurface()
{
      state=false;
      memory=NULL;
      mempitch=0;
      lpdds=NULL;
      width=0;
      height=0;
}
DDOffscreenSurface::~DDOffscreenSurface()
{
      if (lpdds)
   {
   lpdds->Release();
   lpdds = NULL;
   } // end if
      state = false;
}
DDOffscreenSurface::Init(LPDIRECTDRAW7 lpdd,int Pwidth,int Pheight, bool videogeheugen)
{
      state = true;
      width = Pwidth;
      height = Pheight;

      DDRAW_INIT_STRUCT(ddsd);
      
      // set to access caps, width, and height
      ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
      
      // set dimensions of the new bitmap surface
      ddsd.dwWidth  =  width;
      ddsd.dwHeight =  height;
      
      // set surface to offscreen plain
      if (videogeheugen)
      {
            ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
      }else{
            ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
      }
      // create the surface
      if (FAILED(lpdd->CreateSurface(&ddsd,&lpdds,NULL)))
      {
            DisplayError("FAILED CreateSurface error offscreen");
      }
}
DDOffscreenSurface::Lock()
{
      DDRAW_INIT_STRUCT(ddsd);
      if (FAILED(lpdds->Lock(NULL, &ddsd,
                                 DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
                                 NULL)))
         {
         // error
         DisplayError("FAILED Lock error offscreen");
         } // end if

      mempitch        = (int)ddsd.lPitch;
      memory                  = (UCHAR *)ddsd.lpSurface;
}
DDOffscreenSurface::Unlock()
{
      if (FAILED(lpdds->Unlock(NULL)))
      {
            DisplayError("FAILED Unlock error offscreen");
      }
      mempitch=0;
      memory=NULL;
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

That's it.

Thanks in advance to anyone who helps me with this one.

Jasper
0
bockske
Asked:
bockske
  • 5
  • 3
  • 2
1 Solution
 
esorfCommented:
I couldn't see how just that change would result in failure.  One complicating factor is that you refer to ddsd (a global) within the method Lock().  In general, you should refer only to member variables and method parameters within a member function.

In order to diagnose the problem and make the program easier to maintain, I recommend that you move the globals at the top of the file into the Main() routine.  Then pass only those variables that are actually used by subroutines into the subroutines.

- Frank
0
 
SirHandoCommented:
The exception that you are getting seems to me to indicate a NULL pointer being used.

You should add assertions to check that you have valid pointers at run time, and then narrow down from there.

Regards,

SirHando
0
 
bockskeAuthor Commented:
@ esorf:
Yes, that's also my problem, I can't see the difference between the codes, I mean, It's the same.
And ddsd isn't a global, it's also a member variable as you can see in the class definition of DDBack.

@ SirHando:
what's an assertion? (I'm from Belgium, so my English isn't realy good)


0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
SirHandoCommented:
You can use the assert macro to perfrom basic validation at runtime.

I suggest you search for assert on msdn, but basically it works like this.

1) Include the header

#include <assert>

2) Use the macro in your code to check for valid conditions, especially NULL pointers, e.g.

DDOffscreenSurface::Lock()
{
     assert( lpdds != NULL );   // Check we have a valid dds pointer

     DDRAW_INIT_STRUCT(ddsd);
     if (FAILED(lpdds->Lock(NULL, &ddsd,
                              DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
                              NULL)))
        {
        // error
        DisplayError("FAILED Lock error offscreen");
        } // end if

     mempitch        = (int)ddsd.lPitch;
     memory               = (UCHAR *)ddsd.lpSurface;
}

In this case if lpdds == NULL the debugger will let you know, and you can then furhter track backwards from there.

Ciao

SirHando
0
 
esorfCommented:
I suspect that you don't need the DDRAW_INIT_STRUCT() in the Lock() method.  You've already intialized the structure in the Init() method.

Would you provide the #define of DDRAW_INIT_STRUCT so that we can check?

- Frank
0
 
bockskeAuthor Commented:
the #define of DDRAW_INIT_STRUCT is in functies.h in my question
0
 
esorfCommented:
Ok.  I withdraw my suggestion not to call DDRAW_INIT_STRUCT().  It appears that ddsd is used for parameter passing and doesn't really store anything across multiple calls.  In which case, I recommend highly to
 1. Not have a Global ddsd
 2. Not have member variable ddsd
Just create them locally when you need them if they are transient.
0
 
esorfCommented:
So, if the call that gives you trouble is
   int clearSurfaceMemory(UCHAR*Memory,int memPitch, int width, int height, int bits)
then let's see what you're getting there.

If you add a trace, like
   printf("mem: %p, pitch: %d, wid: %d, height: %d, bits: %d\n", Memory, memPitch, width, height, bits);
to the top of clearSurfaceMemory(), what do you get?
0
 
bockskeAuthor Commented:
that Memory and memPitch are both NULL, that's the same I got with SirHando's method.
0
 
esorfCommented:
Try restructuring the code.  Rather than calling DDBack.Lock() and then knowing you can get pitch and video-buffer out of the member variables, try encapsulating this functionality into a method.

DDBack::ClearSurface(int width, height, bitdepth)
{
    Lock();
    if( !clearSurfaceMemory(memory,mempitch,width,height,bitdepth)) {
        return(0);
    }
    Unlock();
}

Then you can focus your investigation within the confines of the class without worrying about exposing values to the main program.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 5
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now