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