/// <summary> /// Exports the v-ram as an image /// </summary> /// <param name="outputPath">The path to export to</param> /// <param name="vram">The v-ram</param> public static void ExportVram(string outputPath, PS1_VRAM vram) { Texture2D vramTex = TextureHelpers.CreateTexture2D(16 * 128, 2 * 256); for (int x = 0; x < 16 * 128; x++) { for (int y = 0; y < 2 * 256; y++) { byte val = vram.GetPixel8(0, y / 256, x, y % 256); vramTex.SetPixel(x, (2 * 256) - 1 - y, new Color(val / 255f, val / 255f, val / 255f)); } } vramTex.Apply(); Util.ByteArrayToFile(outputPath, vramTex.EncodeToPNG()); }
/// <summary> /// Fills the PS1 v-ram and returns it /// </summary> /// <param name="context">The context</param> /// <param name="mode">The blocks to fill</param> /// <returns>The filled v-ram</returns> protected override void FillVRAM(Context context, VRAMMode mode) { // Read palettes var pal4 = FileFactory.Read <ObjectArray <ARGB1555Color> >(GetPalettePath(context.Settings, 4), context, (y, x) => x.Length = y.CurrentLength / 2); var pal8 = FileFactory.Read <ObjectArray <ARGB1555Color> >(GetPalettePath(context.Settings, 8), context, (y, x) => x.Length = y.CurrentLength / 2); var palLettre = FileFactory.Read <ObjectArray <ARGB1555Color> >(GetFontPalettePath(), context, (y, x) => x.Length = y.CurrentLength / 2); // Read the files var fixGraphics = FileFactory.Read <Array <byte> >(GetAllfixSpritePath(), context, onPreSerialize: (s, a) => a.Length = s.CurrentLength); var wldGraphics = FileFactory.Read <Array <byte> >(GetWorldSpritePath(context.Settings), context, onPreSerialize: (s, a) => a.Length = s.CurrentLength); var lvlGraphics = FileFactory.Read <Array <byte> >(GetLevelSpritePath(context.Settings), context, onPreSerialize: (s, a) => a.Length = s.CurrentLength); PS1_VRAM vram = new PS1_VRAM(); // skip loading the backgrounds for now. They take up 320 (=5*64) x 256 per background // 2 backgrounds are stored underneath each other vertically, so this takes up 10 pages in total vram.currentXPage = 5; // Since skippedPagesX is uneven, and all other data takes up 2x2 pages, the game corrects this by // storing the first bit of sprites we load as 1x2 byte[] cageSprites = new byte[128 * (256 * 2)]; Array.Copy(fixGraphics.Value, 0, cageSprites, 0, cageSprites.Length); byte[] allFixSprites = new byte[fixGraphics.Value.Length - cageSprites.Length]; Array.Copy(fixGraphics.Value, cageSprites.Length, allFixSprites, 0, allFixSprites.Length); /*byte[] unknown = new byte[128 * 8]; * vram.AddData(unknown, 128);*/ vram.AddData(cageSprites, 128); vram.AddData(allFixSprites, 256); vram.AddData(wldGraphics.Value, 256); vram.AddData(lvlGraphics.Value, 256); int paletteY = 256 - 3; // 480 - 1 page height vram.AddDataAt(1, 1, 0, paletteY++, palLettre.Value.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); vram.AddDataAt(1, 1, 0, paletteY++, pal4.Value.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); vram.AddDataAt(1, 1, 0, paletteY++, pal8.Value.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); context.StoreObject("vram", vram); }
/// <summary> /// Fills the PS1 v-ram and returns it /// </summary> /// <param name="context">The context</param> /// <param name="mode">The blocks to fill</param> /// <returns>The filled v-ram</returns> protected override void FillVRAM(Context context, VRAMMode mode) { // TODO: Support BigRay + font // Read the files var allFix = mode != VRAMMode.BigRay ? FileFactory.Read <R1_PS1_AllfixFile>(GetAllfixFilePath(context.Settings), context) : null; var world = mode == VRAMMode.Level ? FileFactory.Read <R1_PS1_WorldFile>(GetWorldFilePath(context.Settings), context) : null; var levelTextureBlock = mode == VRAMMode.Level ? FileFactory.Read <R1_PS1_LevFile>(GetLevelFilePath(context.Settings), context).TextureBlock : null; var bigRay = mode == VRAMMode.BigRay ? FileFactory.Read <R1_PS1_BigRayFile>(GetBigRayFilePath(context.Settings), context) : null; var font = mode == VRAMMode.Menu ? FileFactory.Read <Array <byte> >(GetFontFilePath(context.Settings), context, (s, o) => o.Length = s.CurrentLength) : null; PS1_VRAM vram = new PS1_VRAM(); // skip loading the backgrounds for now. They take up 320 (=5*64) x 256 per background // 2 backgrounds are stored underneath each other vertically, so this takes up 10 pages in total vram.currentXPage = 5; // Reserve spot for tiles in vram if (mode == VRAMMode.Level) { IList <BaseColor> tiles = GetTileSetColors(context); int tilesetHeight = tiles.Count / 256; const int tilesetWidth = 4 * 128; int tilesetPage = (16 - 4);// Max pages - tileset width while (tilesetHeight > 0) { int thisPageHeight = Math.Min(tilesetHeight, 2 * 256); vram.ReserveBlock(tilesetPage * 128, (2 * 256) - thisPageHeight, tilesetWidth, thisPageHeight); tilesetHeight -= thisPageHeight; tilesetPage -= 4; } } if (mode != VRAMMode.BigRay) { // Since skippedPagesX is uneven, and all other data takes up 2x2 pages, the game corrects this by // storing the first bit of sprites we load as 1x2 byte[] cageSprites = new byte[(128 * 3) * (256 * 2)]; Array.Copy(allFix.TextureBlock, 0, cageSprites, 0, cageSprites.Length); byte[] allFixSprites = new byte[allFix.TextureBlock.Length - cageSprites.Length]; Array.Copy(allFix.TextureBlock, cageSprites.Length, allFixSprites, 0, allFixSprites.Length); vram.AddData(cageSprites, (128 * 3)); vram.AddData(allFixSprites, 256); } if (mode == VRAMMode.Level) { vram.AddData(world.TextureBlock, 256); vram.AddData(levelTextureBlock, 256); } else if (mode == VRAMMode.Menu) { vram.AddDataAt(10, 1, 0, 80, font.Value, 256); } else if (mode == VRAMMode.BigRay) { vram.AddDataAt(10, 0, 0, 0, bigRay.TextureBlock, 256); } int paletteY = 224; // 480 - 1 page height if (mode != VRAMMode.BigRay) { vram.AddDataAt(1, 1, 0, paletteY++, allFix.Palette2.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(1, 1, 0, paletteY++, allFix.Palette6.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(1, 1, 0, paletteY++, allFix.Palette5.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); paletteY += 26; vram.AddDataAt(1, 1, 0, paletteY++, allFix.Palette1.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); if (mode == VRAMMode.Level) { vram.AddDataAt(1, 1, 0, paletteY++, world.EventPalette2.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(1, 1, 0, paletteY++, world.EventPalette1.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); } else { vram.AddDataAt(1, 1, 0, paletteY++, allFix.Palette4.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(1, 1, 0, paletteY++, allFix.Palette3.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); } } else { paletteY += 31; // BigRay vram.AddDataAt(1, 1, 0, paletteY++, bigRay.Palette1.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(1, 1, 0, paletteY++, bigRay.Palette2.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); } context.StoreObject("vram", vram); }
/// <summary> /// Fills the PS1 v-ram and returns it /// </summary> /// <param name="context">The context</param> /// <param name="mode">The blocks to fill</param> /// <returns>The filled v-ram</returns> protected override void FillVRAM(Context context, VRAMMode mode) { // TODO: Support BigRay + font for US version // Read the files var allFix = mode != VRAMMode.BigRay ? FileFactory.Read <R1_PS1_AllfixFile>(GetAllfixFilePath(context.Settings), context) : null; var world = mode == VRAMMode.Level ? FileFactory.Read <R1_PS1_WorldFile>(GetWorldFilePath(context.Settings), context) : null; var levelTextureBlock = mode == VRAMMode.Level ? FileFactory.Read <R1_PS1_LevFile>(GetLevelFilePath(context.Settings), context).TextureBlock : null; var bigRay = mode == VRAMMode.BigRay ? FileFactory.Read <R1_PS1_BigRayFile>(GetBigRayFilePath(context.Settings), context) : null; var font = mode == VRAMMode.Menu ? FileFactory.Read <Array <byte> >(GetFontFilePath(context.Settings), context, (s, o) => o.Length = s.CurrentLength) : null; //var bgPath = GetLevelBackgroundFilePath(context.Settings, true); //ARGB1555Color[][] bgPalette = new ARGB1555Color[0][]; //if (bgPath != null) // bgPalette = FileFactory.Read<PS1_R1_BackgroundVignetteFile>(bgPath, context).ParallaxPalettes; PS1_VRAM vram = new PS1_VRAM(); // skip loading the backgrounds for now. They take up 320 (=5*64) x 256 per background // 2 backgrounds are stored underneath each other vertically, so this takes up 10 pages in total vram.currentXPage = 5; if (mode != VRAMMode.BigRay) { // Since skippedPagesX is uneven, and all other data takes up 2x2 pages, the game corrects this by // storing the first bit of sprites we load as 1x2 byte[] cageSprites = new byte[128 * (256 * 2 - 8)]; Array.Copy(allFix.TextureBlock, 0, cageSprites, 0, cageSprites.Length); byte[] allFixSprites = new byte[allFix.TextureBlock.Length - cageSprites.Length]; Array.Copy(allFix.TextureBlock, cageSprites.Length, allFixSprites, 0, allFixSprites.Length); byte[] unknown = new byte[128 * 8]; vram.AddData(unknown, 128); vram.AddData(cageSprites, 128); vram.AddData(allFixSprites, 256); } if (mode == VRAMMode.Level) { vram.AddData(world.TextureBlock, 256); vram.AddData(levelTextureBlock, 256); } else if (mode == VRAMMode.Menu) { if (context.Settings.GameModeSelection == GameModeSelection.RaymanPS1US) { vram.AddDataAt(10, 1, 0, 80, font.Value, 256); } else { vram.AddDataAt(10, 0, 0, 226, font.Value, 256); } } else if (mode == VRAMMode.BigRay) { vram.AddDataAt(10, 0, 0, 0, bigRay.TextureBlock, 256); } // Palettes start at y = 256 + 234 (= 490), so page 1 and y=234 int paletteY = 234; if (mode != VRAMMode.BigRay) { /*vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette3.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); * vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette4.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512);*/ if (mode == VRAMMode.Level) { vram.AddDataAt(12, 1, 0, paletteY++, world.EventPalette1.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, world.EventPalette2.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); } else { vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette3.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette4.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); } vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette1.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette5.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette6.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette2.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); // TODO: How are these aligned? Seems different for every background... //// Add background parallax palettes //foreach (var p in bgPalette.Reverse()) // vram.AddDataAt(12, 1, 0, paletteY++, p.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); if (mode == VRAMMode.Level) { paletteY += 13 - world.TilePalettes.Length; // Add tile palettes foreach (var p in world.TilePalettes) { vram.AddDataAt(12, 1, 0, paletteY++, p.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); } } } else { // BigRay vram.AddDataAt(12, 1, 0, paletteY++, bigRay.Palette1.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, bigRay.Palette2.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); } context.StoreObject("vram", vram); }
/// <summary> /// Fills the PS1 v-ram and returns it /// </summary> /// <param name="context">The context</param> /// <param name="mode">The blocks to fill</param> /// <returns>The filled v-ram</returns> protected override void FillVRAM(Context context, VRAMMode mode) { // Read the files var fixGraphics = FileFactory.Read <Array <byte> >(FixGraphicsPath, context, onPreSerialize: (s, a) => a.Length = s.CurrentLength); var lvlGraphics = FileFactory.Read <Array <byte> >(GetLevelGraphicsPath(context.Settings), context, onPreSerialize: (s, a) => a.Length = s.CurrentLength); var palettes = FileFactory.Read <ObjectArray <RGBA5551Color> >(SpritePalettesPath, context, onPreSerialize: (s, a) => a.Length = s.CurrentLength / 2); var tilePalettes = new ObjectArray <RGBA5551Color> [4]; for (int i = 0; i < MapCount; i++) { tilePalettes[i] = FileFactory.Read <ObjectArray <RGBA5551Color> >(GetSubMapPalettePath(i), context, onPreSerialize: (s, a) => a.Length = s.CurrentLength / 2); } PS1_VRAM vram = new PS1_VRAM(); // skip loading the backgrounds for now. They take up 320 (=5*64) x 256 per background // 2 backgrounds are stored underneath each other vertically, so this takes up 10 pages in total vram.currentXPage = 5; // Since skippedPagesX is uneven, and all other data takes up 2x2 pages, the game corrects this by // storing the first bit of sprites we load as 1x2 byte[] cageSprites = new byte[128 * (256 * 2)]; Array.Copy(fixGraphics.Value, 0, cageSprites, 0, cageSprites.Length); byte[] allFixSprites = new byte[fixGraphics.Value.Length - cageSprites.Length]; Array.Copy(fixGraphics.Value, cageSprites.Length, allFixSprites, 0, allFixSprites.Length); /*byte[] unknown = new byte[128 * 8]; * vram.AddData(unknown, 128);*/ vram.AddData(cageSprites, 128); vram.AddData(allFixSprites, 256); vram.AddData(lvlGraphics.Value, 256); // Palettes start at y = 256 + 234 (= 490), so page 1 and y=234 int paletteY = 240; vram.AddDataAt(0, 0, 0, paletteY, palettes.Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); paletteY = 248; vram.AddDataAt(12, 1, 0, paletteY++, tilePalettes[3].Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, tilePalettes[2].Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, tilePalettes[2].Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, tilePalettes[2].Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, tilePalettes[2].Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, tilePalettes[1].Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, tilePalettes[0].Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); vram.AddDataAt(12, 1, 0, paletteY++, tilePalettes[0].Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); /*vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette3.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); * vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette4.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512);*/ /*vram.AddDataAt(12, 1, 0, paletteY++, world.EventPalette1.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); * vram.AddDataAt(12, 1, 0, paletteY++, world.EventPalette2.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); * vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette1.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); * vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette5.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); * vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette6.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); * vram.AddDataAt(12, 1, 0, paletteY++, allFix.Palette2.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512); * * paletteY += 13 - world.TilePalettes.Length; * * foreach (var p in world.TilePalettes) * vram.AddDataAt(12, 1, 0, paletteY++, p.SelectMany(c => BitConverter.GetBytes(c.Color1555)).ToArray(), 512);*/ vram.AddDataAt(0, 0, 0, paletteY, palettes.Value.SelectMany(c => BitConverter.GetBytes(c.Color5551)).ToArray(), 512); context.StoreObject("vram", vram); //PaletteHelpers.ExportVram(context.Settings.GameDirectory + "vram.png", vram); }