private void saveTileBehaviors() { ByteArrayOutputStream file = new ByteArrayOutputStream(); for (int i = 0; i < TileBehaviors.Length; i++) { file.writeUInt(TileBehaviors[i]); } if (TilesetNumber == 0) { ROM.ReplaceInlineFile(ROM.Data.File_Jyotyu_CHK, file.getArray()); } else if (TilesetNumber == 1 || TilesetNumber == 2) { TileBehaviorFile.replace(file.getArray(), this); } }
public static byte[] LZ77_Compress(byte[] data, bool header = false) { ByteArrayOutputStream res = new ByteArrayOutputStream(); if (header) { res.writeUInt(0x37375A4C); //LZ77 } res.writeInt((data.Length << 8) | 0x10); byte[] tempBuffer = new byte[16]; //Current byte to compress. int current = 0; while (current < data.Length) { int tempBufferCursor = 0; byte blockFlags = 0; for (int i = 0; i < 8; i++) { //Not sure if this is needed. The DS probably ignores this data. if (current >= data.Length) { tempBuffer[tempBufferCursor++] = 0; continue; } int searchPos = 0; int searchLen = 0; LZ77_Compress_Search(data, current, out searchPos, out searchLen); int searchDisp = current - searchPos - 1; if (searchLen > 2) //We found a big match, let's write a compressed block. { blockFlags |= (byte)(1 << (7 - i)); tempBuffer[tempBufferCursor++] = (byte)((((searchLen - 3) & 0xF) << 4) + ((searchDisp >> 8) & 0xF)); tempBuffer[tempBufferCursor++] = (byte)(searchDisp & 0xFF); current += searchLen; } else { tempBuffer[tempBufferCursor++] = data[current++]; } } res.writeByte(blockFlags); for (int i = 0; i < tempBufferCursor; i++) { res.writeByte(tempBuffer[i]); } } return(res.getArray()); }
public override void save() { ByteArrayOutputStream oo = new ByteArrayOutputStream(); for (int i = 0; i < pal.Length; i++) { oo.writeUShort(NSMBTileset.toRGB15(pal[i])); } f.replace(oo.getArray(), this); }
public virtual void save() { ByteArrayOutputStream os = new ByteArrayOutputStream(); for (int i = 0; i < f.fileSize / 2; i++) { int x = i % width; int y = i / width; os.writeUShort(tileToShort(tiles[x, y])); } f.replace(os.getArray(), this); }
public override void save() { ByteArrayOutputStream os = new ByteArrayOutputStream(); for (int i = 0; i < f.fileSize / 8; i++) { int x = (i % (width / 2)) * 2; int y = (i / (width / 2)) * 2; os.writeUShort(tileToShort(tiles[x, y])); os.writeUShort(tileToShort(tiles[x + 1, y])); os.writeUShort(tileToShort(tiles[x, y + 1])); os.writeUShort(tileToShort(tiles[x + 1, y + 1])); } f.replace(os.getArray(), this); }
public void saveObjects() { ByteArrayOutputStream eObjIndexFile = new ByteArrayOutputStream(); ByteArrayOutputStream eObjFile = new ByteArrayOutputStream(); for (int i = 0; i < Objects.Length; i++) { if (Objects[i] == null) { break; } eObjIndexFile.writeUShort((ushort)eObjFile.getPos()); eObjIndexFile.writeByte((byte)Objects[i].width); eObjIndexFile.writeByte((byte)Objects[i].height); Objects[i].save(eObjFile); } ObjFile.replace(eObjFile.getArray(), this); ObjIndexFile.replace(eObjIndexFile.getArray(), this); }
public ExportedLevel getExport() { int FilePos; // First off, save sprites. These go in the main level file so we must do them before blocks // Find out how long the block must be int SpriteBlockSize = (Sprites.Count * 12) + 4; Blocks[6] = new byte[SpriteBlockSize]; FilePos = 0; for (int SpriteIdx = 0; SpriteIdx < Sprites.Count; SpriteIdx++) { Blocks[6][FilePos] = (byte)(Sprites[SpriteIdx].Type & 0xFF); Blocks[6][FilePos + 1] = (byte)((Sprites[SpriteIdx].Type >> 8) & 0xFF); Blocks[6][FilePos + 2] = (byte)(Sprites[SpriteIdx].X & 0xFF); Blocks[6][FilePos + 3] = (byte)((Sprites[SpriteIdx].X >> 8) & 0xFF); Blocks[6][FilePos + 4] = (byte)(Sprites[SpriteIdx].Y & 0xFF); Blocks[6][FilePos + 5] = (byte)((Sprites[SpriteIdx].Y >> 8) & 0xFF); FilePos += 6; Blocks[6][FilePos + 0] = Sprites[SpriteIdx].Data[1]; Blocks[6][FilePos + 1] = Sprites[SpriteIdx].Data[0]; Blocks[6][FilePos + 2] = Sprites[SpriteIdx].Data[5]; Blocks[6][FilePos + 3] = Sprites[SpriteIdx].Data[4]; Blocks[6][FilePos + 4] = Sprites[SpriteIdx].Data[3]; Blocks[6][FilePos + 5] = Sprites[SpriteIdx].Data[2]; FilePos += 6; } Blocks[6][FilePos] = 0xFF; Blocks[6][FilePos + 1] = 0xFF; Blocks[6][FilePos + 2] = 0xFF; Blocks[6][FilePos + 3] = 0xFF; // Then save entrances int EntBlockSize = Entrances.Count * 20; Blocks[5] = new byte[EntBlockSize]; FilePos = 0; for (int EntIdx = 0; EntIdx < Entrances.Count; EntIdx++) { Blocks[5][FilePos] = (byte)(Entrances[EntIdx].X & 0xFF); Blocks[5][FilePos + 1] = (byte)((Entrances[EntIdx].X >> 8) & 0xFF); Blocks[5][FilePos + 2] = (byte)(Entrances[EntIdx].Y & 0xFF); Blocks[5][FilePos + 3] = (byte)((Entrances[EntIdx].Y >> 8) & 0xFF); Blocks[5][FilePos + 4] = (byte)(Entrances[EntIdx].CameraX & 0xFF); Blocks[5][FilePos + 5] = (byte)((Entrances[EntIdx].CameraX >> 8) & 0xFF); Blocks[5][FilePos + 6] = (byte)(Entrances[EntIdx].CameraY & 0xFF); Blocks[5][FilePos + 7] = (byte)((Entrances[EntIdx].CameraY >> 8) & 0xFF); Blocks[5][FilePos + 8] = (byte)Entrances[EntIdx].Number; Blocks[5][FilePos + 9] = (byte)Entrances[EntIdx].DestArea; Blocks[5][FilePos + 10] = (byte)Entrances[EntIdx].ConnectedPipeID; Blocks[5][FilePos + 12] = (byte)Entrances[EntIdx].DestEntrance; Blocks[5][FilePos + 13] = 0x10; Blocks[5][FilePos + 14] = (byte)Entrances[EntIdx].Type; Blocks[5][FilePos + 15] = (byte)Entrances[EntIdx].Settings; Blocks[5][FilePos + 16] = (byte)Entrances[EntIdx].Unknown1; Blocks[5][FilePos + 18] = (byte)Entrances[EntIdx].EntryView; Blocks[5][FilePos + 19] = (byte)Entrances[EntIdx].Unknown2; FilePos += 20; } // Save Paths ByteArrayOutputStream block11 = new ByteArrayOutputStream(); ByteArrayOutputStream block13 = new ByteArrayOutputStream(); foreach (NSMBPath p in Paths) { p.write(block11, block13); } Blocks[10] = block11.getArray(); //save streams Blocks[12] = block13.getArray(); // Save ProgressPaths ByteArrayOutputStream block10 = new ByteArrayOutputStream(); ByteArrayOutputStream block12 = new ByteArrayOutputStream(); foreach (NSMBPath p in ProgressPaths) { p.write(block10, block12); } Blocks[9] = block10.getArray(); //save streams Blocks[11] = block12.getArray(); // Save Views ByteArrayOutputStream Block8 = new ByteArrayOutputStream(); ByteArrayOutputStream Block2 = new ByteArrayOutputStream(); int camCount = 0; foreach (NSMBView v in Views) { v.write(Block8, Block2, camCount++); } Blocks[7] = Block8.getArray(); Blocks[1] = Block2.getArray(); //save Zones ByteArrayOutputStream Block9 = new ByteArrayOutputStream(); foreach (NSMBView v in Zones) { v.writeZone(Block9); } Blocks[8] = Block9.getArray(); //Save Extra Data (decompiled, so messy code) byte[] numArray = new byte[16 + this.ExtraData.Count * 16]; for (int index2 = 0; index2 < 16; ++index2) { numArray[index2] = this.Blocks[13][index2]; } int num2 = 16; for (int index2 = 0; index2 < this.ExtraData.Count; ++index2) { for (int index4 = 0; index4 < 16; ++index4) { numArray[num2 + index4] = this.ExtraData[index2].data[index4]; } num2 += 16; } this.Blocks[13] = numArray; // Save blocks int LevelFileSize = 8 * 14; // Find out how long the file must be for (int BlockIdx = 0; BlockIdx < 14; BlockIdx++) { LevelFileSize += Blocks[BlockIdx].Length; } // Now allocate + save it FilePos = 0; int CurBlockOffset = 8 * 14; byte[] LevelFileData = new byte[LevelFileSize]; for (int BlockIdx = 0; BlockIdx < 14; BlockIdx++) { LevelFileData[FilePos] = (byte)(CurBlockOffset & 0xFF); LevelFileData[FilePos + 1] = (byte)((CurBlockOffset >> 8) & 0xFF); LevelFileData[FilePos + 2] = (byte)((CurBlockOffset >> 16) & 0xFF); LevelFileData[FilePos + 3] = (byte)((CurBlockOffset >> 24) & 0xFF); LevelFileData[FilePos + 4] = (byte)(Blocks[BlockIdx].Length & 0xFF); LevelFileData[FilePos + 5] = (byte)((Blocks[BlockIdx].Length >> 8) & 0xFF); LevelFileData[FilePos + 6] = (byte)((Blocks[BlockIdx].Length >> 16) & 0xFF); LevelFileData[FilePos + 7] = (byte)((Blocks[BlockIdx].Length >> 24) & 0xFF); FilePos += 8; Array.Copy(Blocks[BlockIdx], 0, LevelFileData, CurBlockOffset, Blocks[BlockIdx].Length); CurBlockOffset += Blocks[BlockIdx].Length; } // Next up, objects! FilePos = 0; int BGDatFileSize = (Objects.Count * 10) + 2; byte[] BGDatFileData = new byte[BGDatFileSize]; for (int ObjIdx = 0; ObjIdx < Objects.Count; ObjIdx++) { int ObjType = Objects[ObjIdx].ObjNum | (Objects[ObjIdx].Tileset << 12); BGDatFileData[FilePos] = (byte)(ObjType & 0xFF); BGDatFileData[FilePos + 1] = (byte)((ObjType >> 8) & 0xFF); BGDatFileData[FilePos + 2] = (byte)(Objects[ObjIdx].X & 0xFF); BGDatFileData[FilePos + 3] = (byte)((Objects[ObjIdx].X >> 8) & 0xFF); BGDatFileData[FilePos + 4] = (byte)(Objects[ObjIdx].Y & 0xFF); BGDatFileData[FilePos + 5] = (byte)((Objects[ObjIdx].Y >> 8) & 0xFF); BGDatFileData[FilePos + 6] = (byte)(Objects[ObjIdx].Width & 0xFF); BGDatFileData[FilePos + 7] = (byte)((Objects[ObjIdx].Width >> 8) & 0xFF); BGDatFileData[FilePos + 8] = (byte)(Objects[ObjIdx].Height & 0xFF); BGDatFileData[FilePos + 9] = (byte)((Objects[ObjIdx].Height >> 8) & 0xFF); FilePos += 10; } BGDatFileData[FilePos] = 0xFF; BGDatFileData[FilePos + 1] = 0xFF; return(new ExportedLevel(LevelFileData, BGDatFileData, source.getLevelFileID(), source.getBGDatFileID())); }
private void importPNGButton_Click(object sender, EventArgs e) { getFiles(); if (GFXFile == null) { return; } if (PalFile == null) { return; } if (LayoutFile == null) { return; } // Create a local copy because the global variables could be overwritten while the background is importing File myGFXFile = GFXFile; File myPalFile = PalFile; File myLayoutFile = LayoutFile; int offs = bg.topLayer ? 256 : 576; int palOffs = bg.topLayer ? 8 : 10; if (bg.mappedTileset) { offs = 192; palOffs = 2; } OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = LanguageManager.Get("Filters", "png"); ofd.CheckFileExists = true; if (ofd.ShowDialog() != DialogResult.OK) { return; } string filename = ofd.FileName; Bitmap b = new Bitmap(filename); if (b.Size != new Size(512, 512)) { throw new Exception("Wrong image size"); } BgPNGImportPrompt bgPrompt = new BgPNGImportPrompt(bg.topLayer, bg.mappedTileset); if (!bgPrompt.finished) { return; } ImageTiler ti; if (bg.topLayer) { bgPrompt.bgFirstTileOffset = 0; ti = new ImageTiler(b, new Size(256, bgPrompt.fgHeightInPixels), new Size(512, 512), 50); } else { ti = new ImageTiler(b, new Size(256, bgPrompt.bgHeightInPixels), new Size(512, 512), 50); } Color[] palette = ImageIndexer.createPaletteForImage(b); ByteArrayOutputStream oo = new ByteArrayOutputStream(); for (int i = 0; i < palette.Length; i++) { oo.writeUShort(NSMBTileset.toRGB15(palette[i])); } ByteArrayOutputStream offsetBitmapData = new ByteArrayOutputStream(); for (int i = 0; i < 256 * bgPrompt.bgFirstTileOffset; i++) { offsetBitmapData.writeByte(0); } //byte[] newBitmapData = ImageIndexer.indexImageWithPalette(ti.tileBuffer, palette); byte[] newBitmapData = new byte[offsetBitmapData.getArray().Length + ImageIndexer.indexImageWithPalette(ti.tileBuffer, palette).Length]; Buffer.BlockCopy(offsetBitmapData.getArray(), 0, newBitmapData, 0, offsetBitmapData.getArray().Length); Buffer.BlockCopy(ImageIndexer.indexImageWithPalette(ti.tileBuffer, palette), 0, newBitmapData, offsetBitmapData.getArray().Length, ImageIndexer.indexImageWithPalette(ti.tileBuffer, palette).Length); myPalFile.beginEdit(this); myPalFile.replace(ROM.LZ77_Compress(oo.getArray()), this); myPalFile.endEdit(this); myGFXFile.beginEdit(this); myGFXFile.replace(ROM.LZ77_Compress(newBitmapData), this); myGFXFile.endEdit(this); b.Dispose(); ByteArrayOutputStream layout = new ByteArrayOutputStream(); for (int y = 0; y < ti.heightTileCount; y++) { for (int x = 0; x < ti.widthTileCount; x++) { layout.writeUShort((ushort)((ti.tileMap[x, y] + offs + (bgPrompt.bgFirstTileOffset * 4)) | (palOffs << 12))); } } myLayoutFile.beginEdit(this); myLayoutFile.replace(ROM.LZ77_Compress(layout.getArray()), this); myLayoutFile.endEdit(this); }