2
Answers

C++ to C# Slight Problem

tony

tony

16y
7.1k
1
Hi hoping someone here can help me with this slight problem i got. Basically as a personal project im converting the source code of a game written in C++ into C# and up until now everything has gone perfectly smoothly but now im just stuck big time.

Here is the original C++ code:

Class Sprite Constructor

CSprite::CSprite(HANDLE hPakFile, DXC_ddraw *pDDraw, char *cPakFileName, short sNthFile, bool bAlphaEffect)
{
    DWORD  nCount;
    int iASDstart;

    m_stBrush    = NULL;
    m_lpSurface = NULL;
    m_bIsSurfaceEmpty = TRUE;
    ZeroMemory(m_cPakFileName, sizeof(m_cPakFileName));

    m_cAlphaDegree = 1;
    m_bOnCriticalSection = FALSE;
    m_iTotalFrame = 0;
    m_pDDraw = pDDraw;
    SetFilePointer(hPakFile, 24 + sNthFile*8, NULL, FILE_BEGIN);
    ReadFile(hPakFile, &iASDstart,  4, &nCount, NULL);
    //i+100       Sprite Confirm
    SetFilePointer(hPakFile, iASDstart+100, NULL, FILE_BEGIN);
    ReadFile(hPakFile, &m_iTotalFrame,  4, &nCount, NULL);
    m_dwBitmapFileStartLoc = iASDstart  + (108 + (12*m_iTotalFrame));
    m_stBrush = new stBrush[m_iTotalFrame];
    ReadFile(hPakFile, m_stBrush, 12*m_iTotalFrame, &nCount, NULL);
    // PAK
    memcpy(m_cPakFileName, cPakFileName, strlen(cPakFileName));
    m_bAlphaEffect = bAlphaEffect;
}

Which is called from this line of code

    m_hPakFile = CreateFile("sprites\\interface2.pak", GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL);
    m_pSprite[DEF_SPRID_INTERFACE_ADDINTERFACE] = new class CSprite(m_hPakFile, &m_DDraw, "interface2", 0, FALSE);
    CloseHandle(m_hPakFile);

The problem i got resides with this bit of code in the Sprite class constructor

    m_stBrush = new stBrush[m_iTotalFrame];
    ReadFile(hPakFile, m_stBrush, 12*m_iTotalFrame, &nCount, NULL);

In the sprite.h file there is a struct as below

typedef struct stBrushtag
{
    short sx;
    short sy;
    short szx;
    short szy;
    short pvx;
    short pvy;
} stBrush;

Now what i belive the code i mentioned is causing the problem is trying to do is to create an array of m_stBrush structs for the value m_iTotalFrame which i can tell you is 22 so am i right in saying an array with 22 objects is trying to be created?

The ReadFile line of code then populates the array of objects? this is exactly where is crashes on mine giving a memory error.

Here is my code that i have converted now

Sprite class constructor

        public struct stBrush
        {
            short sx;
            short sy;
            short szx;
            short szy;
            short pvx;
            short pvy;
        }


        public Sprite(FileReader frPakFile, DXC_ddraw dDraw, string _sPakFileName, short sNthFile, bool _bAlphaEffect)
        {
            int lCount = 0;
            int iASDstart = 0;
            int _iTotalFrame;
            stBrush[] _brush;

            ddSurface = null;
            bIsSurfaceEmpty = true;
            sPakFileName = string.Empty;

            iAlphaDegree = 1;
            bOnCriticalSection = false;
            _iTotalFrame = 0;
            cDDraw = dDraw;

            Win32Functions.SetFilePointer(frPakFile.GetFileHandle(), 24 + sNthFile * 8, null, Win32Functions.EMoveMethod.Begin);

            FileReader.ReadFromFile(frPakFile.GetFileHandle(), &iASDstart, 4, &lCount, 0);

            Win32Functions.SetFilePointer(frPakFile.GetFileHandle(), iASDstart + 100, null, Win32Functions.EMoveMethod.Begin);

            FileReader.ReadFromFile(frPakFile.GetFileHandle(), &_iTotalFrame, 4, &lCount, 0);

            iBitmapFileStartLoc = iASDstart + (108 + (12 * _iTotalFrame));

            _brush = new stBrush[_iTotalFrame];

            FileReader.ReadFromFile(frPakFile.GetFileHandle(), *_brush, 12 * _iTotalFrame, &lCount, 0);

            sPakFileName = _sPakFileName;

            bAlphaEffect = _bAlphaEffect;

            iTotalFrame = _iTotalFrame;

            brush = new stBrush[_brush.Length];

            brush = _brush;
        }


This is my Win32Functions class

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using Microsoft.Win32.SafeHandles;

namespace HBOL
{
    public class Win32Functions
    {
           [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
           public static extern bool SetWindowPos(
              int hWnd,               // window handle
              int hWndInsertAfter,    // placement-order handle
              int X,                  // horizontal position
              int Y,                  // vertical position
              int cx,                 // width
              int cy,                 // height
              uint uFlags);           // window positioning flags
           public const int HWND_TOP     = 0x0;
           public const int HWND_BOTTOM     = 0x1;
           public const uint SWP_NOSIZE     = 0x1;
           public const uint SWP_NOMOVE     = 0x2;
           public const uint SWP_SHOWWINDOW = 0x40;

        [DllImport("user32.dll", EntryPoint = "GetCursorPos")]
        internal extern static bool GetCursorPos(out System.Drawing.Point lpPoint);

        public enum EMoveMethod : uint
        {
            Begin = 0,
            Current = 1,
            End = 2
        }

        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern unsafe uint SetFilePointer(
            [In] IntPtr hFile,
            [In] int lDistanceToMove,
            [Out] int* lpDistanceToMoveHigh,
            [In] EMoveMethod dwMoveMethod);

        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern uint SetFilePointer(
            [In] IntPtr hFile,
            [In] int lDistanceToMove,
            [Out] out int lpDistanceToMoveHigh,
            [In] EMoveMethod dwMoveMethod);
    }
}


This is my FileReader class

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace HBOL
{
    public class FileReader
    {
        const uint GENERIC_READ = 0x80000000;
        const uint OPEN_EXISTING = 3;
        IntPtr handle;

        [DllImport("kernel32", SetLastError = true)]
        static extern unsafe IntPtr CreateFile(
              string FileName,                    // file name
              uint DesiredAccess,                 // access mode
              uint ShareMode,                     // share mode
              uint SecurityAttributes,            // Security Attributes
              uint CreationDisposition,           // how to create
              uint FlagsAndAttributes,            // file attributes
              int hTemplateFile                   // handle to template file
              );

        [DllImport("kernel32", SetLastError = true)]
        static extern unsafe bool ReadFile(
              IntPtr hFile,                       // handle to file
              void* pBuffer,                      // data buffer
              int NumberOfBytesToRead,            // number of bytes to read
              int* pNumberOfBytesRead,            // number of bytes read
              int Overlapped                      // overlapped buffer
              );

        [DllImport("kernel32", SetLastError = true)]
        static extern unsafe bool CloseHandle(
              IntPtr hObject   // handle to object
              );

        [DllImport("kernel32.dll")] // was uint changed to int
        static extern unsafe int GetFileSize(
        IntPtr hFile, //[in] Handle to the file for size.
        object flag); //[out] Overloaded to allow passing null.

        public bool Open(string FileName)
        {
            // open the existing file for reading         
            handle = CreateFile(
                  FileName,
                  GENERIC_READ,
                  0,
                  0,
                  OPEN_EXISTING,
                  0,
                  0);

            if (handle != IntPtr.Zero)
                return true;
            else
                return false;
        }

        public unsafe int Read(byte[] buffer, int index, int count)
        {
            int n = 0;
            fixed (byte* p = buffer)
            {
                if (!ReadFile(handle, p + index, count, &n, 0))
                    return 0;
            }
            return n;
        }

        public static unsafe void ReadFromFile(IntPtr hFile, void* pBuffer, int NumberOfBytesToRead, int* pNumberOfBytesRead, int Overlapped)
        {
            ReadFile(hFile, pBuffer, NumberOfBytesToRead, pNumberOfBytesRead, Overlapped);
        }

        public bool Close()
        {
            // close file handle
            return CloseHandle(handle);
        }

        internal int aGetFileSize()
        {
            return GetFileSize(handle, null);
        }

        public IntPtr GetFileHandle()
        {
            return handle;
        }
    }
}


This is how i call the Sprite class constructor which is the same as the C++ way

            frPakFile.Open("sprites\\interface2.pak");
            cSprite[SpriteID.DEF_SPRID_INTERFACE_ADDINTERFACE] = new Sprite(frPakFile, cDDraw, "interface2", 0, false);
            frPakFile.Close();


Problem is if i create an array of stBrush's then i get this error

Error    1    Cannot take the address of, get the size of, or declare a pointer to a managed type ('HBOL.Sprite.stBrush[]')    E:\HBOL\HBOL\HBOL\Sprite.cs    66    64    HBOL


At this location

FileReader.ReadFromFile(frPakFile.GetFileHandle(), &_brush, 12 * _iTotalFrame, &lCount, 0);

If i dont create and use an array and just use a singular stBrush object then i get this error and the program just crashes

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Now i managed to narrow it down to the fact that the ReadFile call is trying to popular the stBrush object with more data than it has variables for as when i just duplicated the variables in the struct 22 times to copy the value in m_iTotalFrames then the program didnt crash and all the variables were populated. But this is not how it is meant to work as some files have more frames than others in.

Hope you understood all that and i look forward to hearing from anyone who might be able to help me

Tony
Answers (2)