/// <summary> /// Split a game.com image that contains multiple banks into individual bank images. /// </summary> /// <param name="image"></param> /// <returns></returns> public static List <GameComImage> Split(GameComImage image) { List <GameComImage> list = new List <GameComImage>(); int b = 0; // Todo: This implementation is kinda lazy. // It should /not/ be using LINQ. // In the future replace this with a proper rectangle copy. // Would be nice to have a constructor for this object that takes another instance, and rectangle coordinates or a Rectangle object. // Which should also use an unsafe context for copying the image data instead of creating an image clone. // Using LINQ might actually be slower than just using the image, and generating the bytes again too. // This implementation really is awful. for (int y = 0; y < image.Bitmap.Height; y += 256) { for (int x = 0; x < image.Bitmap.Width; x += 256) { Bitmap imageTemp = image.Bitmap.Clone(new Rectangle(x, y, 256, 256), PixelFormat.Format24bppRgb); list.Add(new GameComImage(image.RawBytes.Skip(b).Take(GameComBank.SizeInBytes).ToArray(), imageTemp)); b += GameComBank.SizeInBytes; } GC.Collect(); } return(list); }
/// <summary> /// Create from bytes. /// </summary> /// <param name="bytes"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="byteStart"></param> public GameComBank(byte[] bytes, int x, int y, int byteStart) { Image = new GameComImage(bytes); X = x; Y = y; ByteStart = byteStart; }
/// <summary> /// Create from bitmap image. /// </summary> /// <param name="image"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="byteStart"></param> public GameComBank(Bitmap image, int x, int y, int byteStart) { Image = new GameComImage(image); X = x; Y = y; ByteStart = byteStart; }
/// <summary> /// Create from game.com image. /// </summary> /// <param name="image"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="byteStart"></param> public GameComBank(GameComImage image, int x, int y, int byteStart) { Image = image; X = x; Y = y; ByteStart = byteStart; }
/// <summary> /// Dispose this instance. /// </summary> public void Dispose() { FullImage.Dispose(); MemoryBanks.Clear(); FullImage = null; MemoryBanks = null; GC.SuppressFinalize(this); }
/// <summary> /// Create rom object from file. /// </summary> /// <param name="filePath"></param> public GameComRom(string filePath) { // Create an image out of the entire rom, for the HDK. FullImage = new GameComImage(File.ReadAllBytes(filePath)); // Then split the large image up into 256x256 pixel banks. MemoryBanks = GameComImage.SplitBanks(FullImage); // Search for the header location, and grab header data! GrabHeaderData(SearchForHeader()); FilePath = filePath; }
/// <summary> /// Replace one of the banks with a new Image. /// </summary> /// <param name="bankIndex"></param> /// <param name="image"></param> public void ReplaceBank(int bankIndex, GameComImage image) { // Grab the bank object for convenience. GameComBank bank = MemoryBanks[bankIndex]; // Draw the new bank to the full rom image. using (Graphics g = Graphics.FromImage(FullImage.Bitmap)) g.DrawImage(image.Bitmap, bank.X, bank.Y); // Then apply the changes to the bytes. for (int i = 0; i < image.RawBytes.Length; i++) { FullImage.RawBytes[bank.ByteStart + i] = image.RawBytes[i]; } }
/// <summary> /// Split a game.com image that contains multiple banks into individual bank objects. /// </summary> /// <param name="image"></param> /// <returns></returns> public static List <GameComBank> SplitBanks(GameComImage image) { List <GameComBank> list = new List <GameComBank>(); // Todo: This implementation is kinda lazy. // It should /not/ be using LINQ. // In the future replace this with a proper rectangle copy. // Would be nice to have a constructor for this object that takes another instance, and rectangle coordinates or a Rectangle object. // Which should also use an unsafe context for copying the image data instead of creating an image clone. // Using LINQ might actually be slower than just using the image, and generating the bytes again too. // This implementation really is awful. int b = 0; for (int y = 0; y < image.Bitmap.Height; y += 256) { for (int x = 0; x < image.Bitmap.Width; x += 256) { // Clone the image with a crop region. Bitmap imageTemp = image.Bitmap.Clone(new Rectangle(x, y, 256, 256), PixelFormat.Format24bppRgb); // Create the gcom bank and image objects in a really slow awful way. // Do not do this. // And lets hope that it's replaced by the next couple commits hot diggity damn. list.Add(new GameComBank(new GameComImage(image.RawBytes.Skip(b).Take(GameComBank.SizeInBytes).ToArray(), imageTemp), x, y, b)); // Keep track of what byte position we're at for the linq commands. // Yeah I know, I hate this as much as you do. b += GameComBank.SizeInBytes; } // Force a garbage collection heap because ooh boy there's a lot to clean. // When rewriting this function, this won't be neccesary. GC.Collect(); } // After the worlds worst use of query commands, return the list of banks. return(list); }