CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Mar 2005
    Location
    Canada Alberta
    Posts
    80

    Calculating memory address

    Code:
     1: void __fastcall fastpixel(long* surface) 
     2:  {
     3:    int iCount = 1152*864;
     4:    __asm
     5:    {
     6:    // Assign pointers to register
     7:    push edi;
     8:    push ecx;
     9:    push eax;
    10:    mov edi, [surface] ; //put dest addr to edi reg
    11:    mov ecx, [iCount] ;// put count to ecx reg
    12:
    13:    codeloop:
    14:    mov eax, [edi] ; //mov a byte of src data to low
    15:    xor eax, 0x00ffffff ;
    16:    mov [edi], eax ;
    17:    add edi,4;
    18:    dec ecx ; //decrement count by 1
    19:    jnz codeloop ; //jump to codeloop if not 0
    20:    pop edi;
    21:    pop ecx;
    22:    pop eax;
    23:    }
    24: }
    Ok so I've got this lovely bit of code that I've constructed and I need a few clerifications:

    in theory I should have been able to replace lines 14 to 16 with this:

    first:
    xor [edi], 0x00FFFFFF

    how ever this just turns my screen blue :\

    second:
    I seem to need to use add edi,4 instead of just inc because inc only seems to move it 1 byte forward, is there a way to fix this?

    third:
    This is in the help docs for MASM32 but I have no clue what idex, scale, and displacement are reffering to.

    [ Base Address + Index * Scale + Displacement ]

    [ebx + ecx * 4 + 8]

    ebx is the base address.
    ecx is the index.
    4 is the scale based on the data size.
    8 is the displacement in BYTES.
    In C, you merely shoot yourself in the foot.

    In C++, you accidentally create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical care is impossible, because you can't tell which are bitwise copies and which are just pointing at others and saying, "That's me, over there."

  2. #2
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    Re: Calculating memory address

    Your function could look like:
    Code:
    void fastpixel(long* surface) 
     {
       int iCount = 1152*864;
       __asm
       {
       // Assign pointers to register
       push edi;
       push ecx;
       push eax;
       mov edi, [surface] ; //put dest addr to edi reg
       mov ecx, [iCount] ;// put count to ecx reg
    
       codeloop:
       //mov eax, [edi] ; //mov a byte of src data to low
       //xor eax, 0x00ffffff ;
       //mov [edi], eax ;
    
       xor DWORD PTR [edi+ecx*4-4], 0x00ffffff;
       
       //inc edi
       //add edi,4;
       dec ecx ; //decrement count by 1
       jnz codeloop ; //jump to codeloop if not 0
       pop edi;
       pop ecx;
       pop eax;
       }
    }
    As you see, there is no need to modify EDI, although increasing it by 4 is not worse than increasing by 1, compilers create instructions like 'add reg data_type_size' when processing arrays. You also lack type specifier, thats why your 'xor [edi], long_num' did not work. And, in added line, you have example of addresing with index,scale and displacement.
    Unfortunately, at this moment I have no time to explain these changes, but if you do not understand them, I will do it today evening (evening of CET+1h ).
    Hope it helps
    Hob
    Last edited by Hobson; April 9th, 2005 at 07:52 AM.
    B+!
    'There is no cat' - A. Einstein

    Use [code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  3. #3
    Join Date
    Mar 2005
    Location
    Canada Alberta
    Posts
    80

    Re: Calculating memory address

    hmm thanks that did help, I'm having another problem though, I have this asm code which for some reason does not work for writing 8bit video memory, instead the middle of my screen generates this image
    (resolution is to big to post so you'lk need to use the link, and possibly paint )
    http://img.photobucket.com/albums/v5...ul/ASMprob.png

    all of those objectes are supposed to be a single thing in the middle not all spread out like that. (9 objects)

    Code:
         //index = (X-1+((Y-1)*1152));
         __asm
         {
         mov eax, [X];//this ASM replaces the index calulation
         sub eax, 1;
         mov ecx, [Y];
         sub ecx, 1;
         imul ecx, 1152;
         add ecx,eax;
         //mov ecx, [index]; //index
         mov edi, [surface]; //put dest addr to edi reg
         mov al, [edi+ecx]; //mov a byte of src data to low
         xor al, 0xF;
         mov [edi+ecx], al;
    Last edited by barrensoul; April 9th, 2005 at 04:40 PM.
    In C, you merely shoot yourself in the foot.

    In C++, you accidentally create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical care is impossible, because you can't tell which are bitwise copies and which are just pointing at others and saying, "That's me, over there."

  4. #4
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    Re: Calculating memory address

    Those ideas are not tested, because I have no compiler here, let me know if it helped:

    1. Always when you are reading or storing a value from memory, use size specifier. This does not affect the program, and you will be sure that everything is ok.
    2. This code seems to be time-critical for you, or you just like to mess around with assembler. In both cases you could replace 'imul val, 1152' with
    Code:
    mov val, reg1;
    mov val, reg2;
    shl reg1, 10;
    shl reg2, 7;
    add reg1, reg2
    Rumours say that xMUL is slower than set of movs/shifts/adds, but i do not know hows that with modern procesors. Besides, IMUL is a bit tricky with it source/dest operands.
    Instead 'sub reg,1' you could use 'dec reg'.

    Thats all what I can help without compiler, Ill check it for more when i am back home.

    Hob
    B+!
    'There is no cat' - A. Einstein

    Use [code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  5. #5
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    Re: Calculating memory address

    I checked your code with compiler and it works in correct way (X and Y should be declared as DWORDS). Probably not index calculation code is your problem. I forgot to mention earlier:
    Is 'surface' variable a pointer to memory of DirectX screen surface? If so, you should know that width of DirectX screen surface is NOT equal to its horizontal resolution. In your index calculationd you should use not 1152 (resolution value) but its pitch value.
    If its not a DX screen buffer, then your problem is probably located not in index calculation routine. I would expect that X and Y variables are declared as WORD, and in assembly code they are used as DWORD. Just use size specifiers EVERYWHERE where possible. If your problem still persists, attach your project and I will check it (if its not too complicated for me).

    Hob.
    B+!
    'There is no cat' - A. Einstein

    Use [code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  6. #6
    Join Date
    Mar 2005
    Location
    Canada Alberta
    Posts
    80

    Re: Calculating memory address

    it is a pointer to the screen memory (void pointer), I'm well aware of pitch (surface.lPitch) how ever I have specified a 8 bit screen thus making the pitch 1, on the other prog I use the *4 in the index cause that was 32bit mode, thus I should not need to specify an index multiplier.
    Last edited by barrensoul; April 11th, 2005 at 12:19 PM.
    In C, you merely shoot yourself in the foot.

    In C++, you accidentally create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical care is impossible, because you can't tell which are bitwise copies and which are just pointing at others and saying, "That's me, over there."

  7. #7
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    Re: Calculating memory address

    So if its not pitch, then I'd expect some size mismatch between declaration of coords and their usage in asm code.

    By 'size specifier' I did not mean index multiplier. In this case it should be indeed set to 1. I just mean that your function prototype could look like
    Code:
    void setpixel(void* surf, WORD X, WORD Y)
    while in asm snippet you use
    Code:
    mov eax, [X]
    what moves into eax 32-bit value.
    If it is also not a reason, then I think that trouble is not located at code posted by you.

    If you attach your project, it does not need some specific libs and can be compiled under VC 6.0, I might to take look at it.

    Hob
    Last edited by Hobson; April 11th, 2005 at 02:35 PM.
    B+!
    'There is no cat' - A. Einstein

    Use [code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  8. #8
    Join Date
    Mar 2005
    Location
    Canada Alberta
    Posts
    80
    Code:
    #include <windows.h>
    #include <ddraw.h>
    
    HINSTANCE ghinst = 0;
    HDC hdc;
    HWND mainwindow = 0;
    static DDSCAPS ddscaps;
    static LPDIRECTDRAW lpDD = 0;
    static LPDIRECTDRAWSURFACE lpDDSPrimary; 
    static LPDIRECTDRAWSURFACE lpDDSBack; 
    static DDSURFACEDESC ddsd;
    static PAINTSTRUCT ps; 
    static HDC whdc;
    static DDSURFACEDESC DDSurfDesc;
    static BYTE on_off[999364];                      
    static BYTE off_on[999364];
    bool drawnow = 0;
    bool CreatePrimarySurface();
    bool DirectDrawInit();
    void __forceinline updateFrame( void );
    void suicide ();
    
    long FAR PASCAL WndProc (HWND myhwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
     switch (message)
     {
      case WM_CHAR:
       if (wParam == VK_ESCAPE) // VK key code for exit key
    	  PostQuitMessage(0);
       else if (wParam == VK_SPACE)
        drawnow = 1;
       break;
      case WM_DESTROY: 
       PostQuitMessage(0);
       break;
     }         
     return(DefWindowProc(myhwnd,message,wParam,lParam));
    }
    int FAR PASCAL WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
     {
     char buffer[10];
     WNDCLASS wc;
     HWND myhwnd=0;
     MSG msg;
     ghinst = hInst;
     wc.style = CS_HREDRAW|CS_VREDRAW;
     wc.lpfnWndProc = WndProc;
     wc.hInstance = ghinst;
     wc.cbClsExtra = 0;
     wc.cbWndExtra = 0;
     wc.hIcon = 0;
     wc.lpszMenuName = 0;
     wc.hCursor = LoadCursor(0,IDC_ARROW);
     wc.hbrBackground = (HBRUSH__ *)GetStockObject(BLACK_BRUSH);
     wc.lpszClassName = "DDClass";
     if (!RegisterClass(&wc)){MessageBox(mainwindow,"RegisterClass","error",MB_OK); return(1);}
    
     bool mainloop = 1;
     if (!DirectDrawInit())
     {
      suicide();
      MessageBox(mainwindow,"DDinit","error",MB_OK);
      exit(0); 
     }
     CreatePrimarySurface();
     long* colour = 0;
     BYTE setpixel = 1;
     BYTE neighbour = 0;
     unsigned int index = 0;
     unsigned int Y = 0;                                     //     x
     unsigned int X = 0;                                     //    xxxooo
     ZeroMemory(on_off,sizeof(on_off));                      //     xx
     //on_off[576+(432*1154)] = 1;
     on_off[577+(433*1154)] = 1;  //x rabit
     on_off[576+(433*1154)] = 1;  //xxx
     on_off[578+(433*1154)] = 1;  // x
     on_off[577+(434*1154)] = 1;
     on_off[576+(432*1154)] = 1;
    
     on_off[580+(432*1154)] = 1; //xxx
     on_off[581+(432*1154)] = 1; // x
     on_off[582+(432*1154)] = 1; 
     on_off[581+(433*1154)] = 1;
    
    
     /*switchen
     on_off[566+(431*1154)] = 1;  //575 is middle 431 is middle
     on_off[565+(431*1154)] = 1;
     on_off[564+(431*1154)] = 1;
     on_off[565+(430*1154)] = 1;
     on_off[564+(428*1154)] = 1;
     on_off[562+(430*1154)] = 1;
     on_off[561+(429*1154)] = 1;
     on_off[562+(428*1154)] = 1;
    
     on_off[587+(433*1154)] = 1;
     on_off[588+(433*1154)] = 1;
     on_off[587+(434*1154)] = 1;
     */
     unsigned long counter = 0; 
     ZeroMemory(buffer,10);
     DDBLTFX ddbltfx;
     /*---------------------- MAIN LOOP ------------------------*/
     while (mainloop)
     {
     while (PeekMessage(&msg,0,0,0,PM_REMOVE))
     {
      if (msg.message == WM_QUIT)
      {mainloop = 0;}
      TranslateMessage(&msg); 
      DispatchMessage(&msg);
     }
     ZeroMemory( &DDSurfDesc, sizeof( DDSurfDesc ));
     DDSurfDesc.dwSize = sizeof( DDSurfDesc );
     lpDDSBack->Lock( 0, &DDSurfDesc, DDLOCK_WAIT, 0 );
     long* surface = reinterpret_cast<long*>(DDSurfDesc.lpSurface);      
     for(Y = 1; Y<865; ++Y)
      {
      for(X= 1; X<1153; ++X)
       {
       neighbour += on_off[(X-1)+((Y-1)*1154)];
       neighbour += on_off[(X+1)+((Y-1)*1154)];
       neighbour += on_off[(X-1)+((Y+1)*1154)];
       neighbour += on_off[(X+1)+((Y+1)*1154)];
       neighbour += on_off[(X-1)+(Y*1154)];
       neighbour += on_off[(X+1)+(Y*1154)];
       neighbour += on_off[X+((Y+1)*1154)];
       neighbour += on_off[X+((Y-1)*1154)];
       if(neighbour)
        {
        if(((neighbour == 2)&&(on_off[X+(Y*1154)]))||((neighbour == 3)))
         {
         //index = (X-1+((Y-1)*1152));
         __asm
         {
         mov eax,DWORD PTR [X];
         dec eax;
         mov ecx,DWORD PTR [Y];
         dec ecx;
         imul ecx, 1152; //integer multiplication
         add ecx,eax;
         xor eax,eax;
         //mov ecx, [index]; //index
         mov edi, [surface]; //put dest addr to edi reg
         mov al, BYTE PTR [edi+ecx]; //mov a byte of src data to low
         xor al,BYTE PTR 255;
         mov BYTE PTR [edi+ecx], al;
    
         //off_on[X+(Y*1154)] = 1;
         mov ecx, [Y];
         imul ecx, 1154;
         lea edi, off_on;
         add ecx,[X];
         mov [edi+ecx], 1;
         }
         }        
        }
       neighbour = 0;
       }
      }
     lpDDSBack->GetDC(&hdc);
     itoa(++counter,buffer,10);
     SetBkColor(hdc, RGB(0, 0, 0)); 
     SetTextColor(hdc, RGB(255, 255, 255)); 
     TextOut(hdc, 500, 0, buffer, lstrlen(buffer)); 
     lpDDSBack->ReleaseDC(hdc);                   
     lpDDSBack->Unlock(DDSurfDesc.lpSurface);
     lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
     for(X = 0; X<1154; ++X)
      {
      off_on[X] = 0;
      off_on[X+(865*1154)] = 0;
      }
     for(Y = 0; Y<866; ++Y)
      {
      off_on[Y*1154] = 0;
      off_on[1153+(Y*1154)] = 0;
      }
     CopyMemory(on_off,off_on,sizeof(off_on));
     ZeroMemory(off_on,sizeof(off_on));
     ddbltfx.dwSize = sizeof(ddbltfx); 
     ddbltfx.dwFillColor = 0x00;
     lpDDSBack->Blt(NULL,NULL,NULL,DDBLT_COLORFILL, &ddbltfx); 
     }
     suicide();
     return(1);
    }
    void suicide ()
    {
     if (lpDD)
     {
      if (lpDDSPrimary)   
      {
       lpDDSPrimary->Release();
       lpDDSPrimary = 0;
      }
      lpDD->Release(); lpDD = 0;
     }
     if (mainwindow)
     {
      DestroyWindow(mainwindow);
      mainwindow = 0;
     }
    }
    
    
    bool DirectDrawInit()
    {
        HDC hdc = GetDC(0);
        mainwindow = CreateWindow("DDClass","Escapetoexit",WS_VISIBLE | WS_POPUP,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),0,0,ghinst,0);   
        ReleaseDC(0,hdc);
        ShowCursor(0);
        HRESULT ddrval;
    
        ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
        if( ddrval != DD_OK )
        {
            MessageBox(mainwindow,"Direct Draw Creation","error",MB_OK);
            return(false);
        }
    
        ddrval = lpDD->SetCooperativeLevel( mainwindow, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
        if( ddrval != DD_OK )
        {
            lpDD->Release();
            MessageBox(mainwindow,"Coop Level","error",MB_OK);
            return(false);
        }
        ddrval = lpDD->SetDisplayMode( 1152, 864, 8);
        if( ddrval != DD_OK )
        {
            lpDD->Release();
            MessageBox(mainwindow,"Display Mode","error",MB_OK);
            return(false);
        }
    
        return(true);
    }
    bool CreatePrimarySurface()
    {
        HRESULT ddrval;
        ZeroMemory(&ddsd,sizeof(ddsd));
        ddsd.dwSize = sizeof(ddsd);
    
        ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
        ddsd.dwBackBufferCount = 1;
    
        ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
        if( ddrval != DD_OK )
        {
            MessageBox(mainwindow,"Creat Surface","error",MB_OK);
            lpDD->Release();
            return(false);
        }
        ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
        ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
        if( ddrval != DD_OK )
        {
            MessageBox(mainwindow,"Get Attached Surface","error",MB_OK);
            lpDDSPrimary->Release();
            lpDD->Release();
            return(false);
        }
    
        return true;
    }
    well here it is, you'll need the directX SDK so you can link the directx libs n stuff (don't get the most recent one if your using VC++6.0 because it dosn't support VC++6.0 any more, you'll need to find last months)
    link: user32.lib ddraw.lib gdi32.lib
    In C, you merely shoot yourself in the foot.

    In C++, you accidentally create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical care is impossible, because you can't tell which are bitwise copies and which are just pointing at others and saying, "That's me, over there."

  9. #9
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    Re: Calculating memory address

    This is DDSurfaceDesc.lPitch value in your app. For some reason, it is NOT equal 1. You need to multiply all coords by this pitch, instead of 1152. If you have problem with changes, msg me.
    Remember, that lPitch can vary depending on Graphic hardware driver, and it should be read every time it will be used.

    Hob
    Attached Images Attached Images  
    Last edited by Hobson; April 12th, 2005 at 07:48 AM.
    B+!
    'There is no cat' - A. Einstein

    Use &#91;code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  10. #10
    Join Date
    Mar 2005
    Location
    Canada Alberta
    Posts
    80

    Re: Calculating memory address

    I will try pitch as soon as I get home, how ever it seems either you implimented my prog without the same rules or something went wrong because the straight line in your program should not exist, this link shows what you should see starting in the middle of my screen if it works correctly:

    http://www.radicaleye.com/lifepage/p...s/rabbits.html

    and I thank you for taking the time to help this stubourn noobie although I like ASM quite a bit, I'd have to say I love C++/ASM hybrid prorgamming alot.
    Last edited by barrensoul; April 12th, 2005 at 10:40 AM.
    In C, you merely shoot yourself in the foot.

    In C++, you accidentally create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical care is impossible, because you can't tell which are bitwise copies and which are just pointing at others and saying, "That's me, over there."

  11. #11
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    Re: Calculating memory address

    Straight line is made by me, for testing purposes. Your life of rabbits is working correctly, just now you need to change ALL occurences of 1152 to pitch, what will fix coords, because now pixels are spread around whole screen. And i'd suggest not hardcode pitch value, just read it each time when ddsdesc is obtained.
    Always to help

    Hob
    B+!
    'There is no cat' - A. Einstein

    Use &#91;code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  12. #12
    Join Date
    Mar 2005
    Location
    Canada Alberta
    Posts
    80

    Re: Calculating memory address

    heh heh yeah I made a cardinal sin in DirX I realised that after a computer at school was experiencing the same glitch in the 32bit working version
    In C, you merely shoot yourself in the foot.

    In C++, you accidentally create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical care is impossible, because you can't tell which are bitwise copies and which are just pointing at others and saying, "That's me, over there."

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured