I am creating a game manager for Skyrim and have run into a problem. When I create a SaveGame object myself, the raster part of the save works correctly. However, when I call this method in a loop, the bitmap assumes an erroneous value, basically the same as another save game.
TL DR - Why is my form displayed in the list showing the correct information for saving a character, except for the inline image? Instead of choosing the right image, he seems to choose the last processed one. How does this process differ from the open file selected in the dialog box?
Edit: update. I looked at the bitmaps saved with each SaveGame object and found that while creating SaveGames in scanDirectoryForSave, it somehow messed it up. Is there a problem with the bitmap object and using a byte pointer that I don't know about?
Here is the code for my saved static factory game object:
public string Name { get; private set; }
public int SaveNumber { get; private set; }
public int PictureWidth { get; private set; }
public int PictureHeight { get; private set; }
public Bitmap Picture { get; private set; }
public DateTime SaveDate { get; private set; }
public string FileName { get; private set; }
public static SaveGame ReadSaveGame(string Filename)
{
SaveGame save = new SaveGame();
save.FileName = Filename;
byte[] file = File.ReadAllBytes(Filename);
int headerWidth = BitConverter.ToInt32(file, 13);
save.SaveNumber = BitConverter.ToInt32(file, 21);
short nameWidth = BitConverter.ToInt16(file, 25);
save.Name = System.Text.Encoding.UTF8.GetString(file, 27, nameWidth);
save.PictureWidth = BitConverter.ToInt32(file, 13 + headerWidth - 4);
save.PictureHeight = BitConverter.ToInt32(file, 13 + headerWidth);
save.readPictureData(file, 13 + headerWidth + 4, save.PictureWidth, save.PictureHeight);
save.SaveDate = DateTime.FromFileTime((long)BitConverter.ToUInt64(file, 13 + headerWidth - 12));
return save;
}
private void readPictureData(byte[] file, int startIndex, int width, int height)
{
IntPtr pointer = Marshal.UnsafeAddrOfPinnedArrayElement(file, startIndex);
Picture = new Bitmap(width, height, 3 * width, System.Drawing.Imaging.PixelFormat.Format24bppRgb, pointer);
}
In my form, I use a method to read all save files in a specific directory, create SaveGame objects from them and save them in a dictionary based on the symbol name.
private Dictionary<string, List<SaveGame>> scanDirectoryForSaves(string directory)
{
Dictionary<string, List<SaveGame>> saves = new Dictionary<string, List<SaveGame>>();
DirectoryInfo info = new DirectoryInfo(directory);
foreach (FileInfo file in info.GetFiles())
{
if (file.Name.ToLower().EndsWith(".ess") || file.Name.ToLower().EndsWith(".bak"))
{
string filepath = String.Format(@"{0}\{1}", directory, file.Name);
SaveGame save = SaveGame.ReadSaveGame(filepath);
if (!saves.ContainsKey(save.Name))
{
saves.Add(save.Name, new List<SaveGame>());
}
saves[save.Name].Add(save);
}
}
foreach (List<SaveGame> saveList in saves.Values)
{
saveList.Sort();
}
return saves;
}
I am adding keys to the list. When a name is displayed in the list, the last save for the symbol is displayed on the form. The name, date and other fields are true for each character, but a bitmap is a variation of certain characters that preserve the image of the game.
, .
private void updateLabels(SaveGame save)
{
nameLabel.Text = "Name: " + save.Name;
filenameLabel.Text = "File: " + save.FileName;
saveNumberLabel.Text = "Save Number: " + save.SaveNumber;
saveDateLabel.Text = "Save Date: " + save.SaveDate;
saveGamePictureBox.Image = save.Picture;
saveGamePictureBox.Image = ScaleImage(
saveGamePictureBox.Image, saveGamePictureBox.Width, saveGamePictureBox.Height);
saveGamePictureBox.Invalidate();
}