mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-16 11:06:44 -04:00
Added FSO.Files for use with the API server
Don't ask me. FreeSO is the prime example of dependency hell.
This commit is contained in:
parent
4b5e584eeb
commit
8fec258215
104 changed files with 14653 additions and 163 deletions
299
server/tso.files/Formats/IFF/Chunks/SPR.cs
Executable file
299
server/tso.files/Formats/IFF/Chunks/SPR.cs
Executable file
|
@ -0,0 +1,299 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using FSO.Files.Utils;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FSO.Common.Utils;
|
||||
using FSO.Common;
|
||||
using FSO.Common.Rendering;
|
||||
|
||||
namespace FSO.Files.Formats.IFF.Chunks
|
||||
{
|
||||
/// <summary>
|
||||
/// This chunk type holds a number of paletted sprites that share a common color palette and lack z-buffers and
|
||||
/// alpha buffers. SPR# chunks can be either big-endian or little-endian, which must be determined by comparing
|
||||
/// the first two bytes to zero (since no version number uses more than two bytes).
|
||||
/// </summary>
|
||||
public class SPR : IffChunk
|
||||
{
|
||||
public List<SPRFrame> Frames { get; internal set; }
|
||||
public ushort PaletteID;
|
||||
private List<uint> Offsets;
|
||||
public ByteOrder ByteOrd;
|
||||
public bool WallStyle;
|
||||
|
||||
/// <summary>
|
||||
/// Reads a SPR chunk from a stream.
|
||||
/// </summary>
|
||||
/// <param name="iff">An Iff instance.</param>
|
||||
/// <param name="stream">A Stream object holding a SPR chunk.</param>
|
||||
public override void Read(IffFile iff, Stream stream)
|
||||
{
|
||||
using (var io = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN))
|
||||
{
|
||||
var version1 = io.ReadUInt16();
|
||||
var version2 = io.ReadUInt16();
|
||||
uint version = 0;
|
||||
|
||||
if (version1 == 0)
|
||||
{
|
||||
io.ByteOrder = ByteOrder.BIG_ENDIAN;
|
||||
version = (uint)(((version2|0xFF00)>>8) | ((version2&0xFF)<<8));
|
||||
}
|
||||
else
|
||||
{
|
||||
version = version1;
|
||||
}
|
||||
ByteOrd = io.ByteOrder;
|
||||
|
||||
var spriteCount = io.ReadUInt32();
|
||||
PaletteID = (ushort)io.ReadUInt32();
|
||||
|
||||
Frames = new List<SPRFrame>();
|
||||
if (version != 1001)
|
||||
{
|
||||
var offsetTable = new List<uint>();
|
||||
for (var i = 0; i < spriteCount; i++)
|
||||
{
|
||||
offsetTable.Add(io.ReadUInt32());
|
||||
}
|
||||
Offsets = offsetTable;
|
||||
for (var i = 0; i < spriteCount; i++)
|
||||
{
|
||||
var frame = new SPRFrame(this);
|
||||
io.Seek(SeekOrigin.Begin, offsetTable[i]);
|
||||
var guessedSize = ((i + 1 < offsetTable.Count) ? offsetTable[i + 1] : (uint)stream.Length) - offsetTable[i];
|
||||
frame.Read(version, io, guessedSize);
|
||||
Frames.Add(frame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (io.HasMore)
|
||||
{
|
||||
var frame = new SPRFrame(this);
|
||||
frame.Read(version, io, 0);
|
||||
Frames.Add(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The frame (I.E sprite) of a SPR chunk.
|
||||
/// </summary>
|
||||
public class SPRFrame : ITextureProvider
|
||||
{
|
||||
public static PALT DEFAULT_PALT = new PALT(Color.Black);
|
||||
|
||||
public uint Version;
|
||||
private SPR Parent;
|
||||
private Texture2D PixelCache;
|
||||
private byte[] ToDecode;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new SPRFrame instance.
|
||||
/// </summary>
|
||||
/// <param name="parent">A SPR parent.</param>
|
||||
public SPRFrame(SPR parent)
|
||||
{
|
||||
this.Parent = parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a SPRFrame from a stream.
|
||||
/// </summary>
|
||||
/// <param name="iff">An Iff instance.</param>
|
||||
/// <param name="stream">A Stream object holding a SPRFrame.</param>
|
||||
public void Read(uint version, IoBuffer io, uint guessedSize)
|
||||
{
|
||||
if (version == 1001)
|
||||
{
|
||||
var spriteFersion = io.ReadUInt32();
|
||||
|
||||
var size = io.ReadUInt32();
|
||||
this.Version = spriteFersion;
|
||||
|
||||
if (IffFile.RETAIN_CHUNK_DATA) ReadDeferred(1001, io);
|
||||
else ToDecode = io.ReadBytes(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Version = version;
|
||||
if (IffFile.RETAIN_CHUNK_DATA) ReadDeferred(1000, io);
|
||||
else ToDecode = io.ReadBytes(guessedSize);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadDeferred(uint version, IoBuffer io)
|
||||
{
|
||||
var reserved = io.ReadUInt32();
|
||||
var height = io.ReadUInt16();
|
||||
var width = io.ReadUInt16();
|
||||
this.Init(width, height);
|
||||
this.Decode(io);
|
||||
}
|
||||
|
||||
public void DecodeIfRequired()
|
||||
{
|
||||
if (ToDecode != null)
|
||||
{
|
||||
using (IoBuffer buf = IoBuffer.FromStream(new MemoryStream(ToDecode), Parent.ByteOrd))
|
||||
{
|
||||
ReadDeferred(Version, buf);
|
||||
}
|
||||
|
||||
ToDecode = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes this SPRFrame.
|
||||
/// </summary>
|
||||
/// <param name="io">IOBuffer used to read a SPRFrame.</param>
|
||||
private void Decode(IoBuffer io)
|
||||
{
|
||||
var palette = Parent.ChunkParent.Get<PALT>(Parent.PaletteID);
|
||||
if (palette == null)
|
||||
{
|
||||
palette = DEFAULT_PALT;
|
||||
}
|
||||
|
||||
var y = 0;
|
||||
var endmarker = false;
|
||||
|
||||
while (!endmarker){
|
||||
var command = io.ReadByte();
|
||||
var count = io.ReadByte();
|
||||
|
||||
switch (command){
|
||||
/** Start marker **/
|
||||
case 0x00:
|
||||
case 0x10:
|
||||
break;
|
||||
/** Fill row with pixel data **/
|
||||
case 0x04:
|
||||
var bytes = count - 2;
|
||||
var x = 0;
|
||||
|
||||
while (bytes > 0){
|
||||
var pxCommand = io.ReadByte();
|
||||
var pxCount = io.ReadByte();
|
||||
bytes -= 2;
|
||||
|
||||
switch (pxCommand){
|
||||
/** Next {n} pixels are transparent **/
|
||||
case 0x01:
|
||||
x += pxCount;
|
||||
break;
|
||||
/** Next {n} pixels are the same palette color **/
|
||||
case 0x02:
|
||||
var index = io.ReadByte();
|
||||
var padding = io.ReadByte();
|
||||
bytes -= 2;
|
||||
|
||||
var color = palette.Colors[index];
|
||||
for (var j=0; j < pxCount; j++){
|
||||
this.SetPixel(x, y, color);
|
||||
x++;
|
||||
}
|
||||
break;
|
||||
/** Next {n} pixels are specific palette colours **/
|
||||
case 0x03:
|
||||
for (var j=0; j < pxCount; j++){
|
||||
var index2 = io.ReadByte();
|
||||
var color2 = palette.Colors[index2];
|
||||
this.SetPixel(x, y, color2);
|
||||
x++;
|
||||
}
|
||||
bytes -= pxCount;
|
||||
if (pxCount % 2 != 0){
|
||||
//Padding
|
||||
io.ReadByte();
|
||||
bytes--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
y++;
|
||||
break;
|
||||
/** End marker **/
|
||||
case 0x05:
|
||||
endmarker = true;
|
||||
break;
|
||||
/** Leave next rows transparent **/
|
||||
case 0x09:
|
||||
y += count;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Color[] Data;
|
||||
public int Width { get; internal set; }
|
||||
public int Height { get; internal set; }
|
||||
|
||||
protected void Init(int width, int height)
|
||||
{
|
||||
this.Width = width;
|
||||
this.Height = height;
|
||||
Data = new Color[Width * Height];
|
||||
}
|
||||
|
||||
public Color GetPixel(int x, int y)
|
||||
{
|
||||
return Data[(y * Width) + x];
|
||||
}
|
||||
|
||||
public void SetPixel(int x, int y, Color color)
|
||||
{
|
||||
Data[(y * Width) + x] = color;
|
||||
}
|
||||
|
||||
public Texture2D GetTexture(GraphicsDevice device)
|
||||
{
|
||||
DecodeIfRequired();
|
||||
if (PixelCache == null)
|
||||
{
|
||||
var mip = !Parent.WallStyle && FSOEnvironment.Enable3D && FSOEnvironment.EnableNPOTMip;
|
||||
var tc = FSOEnvironment.TexCompress;
|
||||
|
||||
if (Width * Height > 0)
|
||||
{
|
||||
var w = Math.Max(1, Width);
|
||||
var h = Math.Max(1, Height);
|
||||
if (mip && TextureUtils.OverrideCompression(w, h)) tc = false;
|
||||
if (tc)
|
||||
{
|
||||
PixelCache = new Texture2D(device, ((w+3)/4)*4, ((h+3)/4)*4, mip, SurfaceFormat.Dxt5);
|
||||
if (mip)
|
||||
TextureUtils.UploadDXT5WithMips(PixelCache, w, h, device, Data);
|
||||
else
|
||||
PixelCache.SetData<byte>(TextureUtils.DXT5Compress(Data, w, h).Item1);
|
||||
}
|
||||
else
|
||||
{
|
||||
PixelCache = new Texture2D(device, w, h, mip, SurfaceFormat.Color);
|
||||
if (mip)
|
||||
TextureUtils.UploadWithMips(PixelCache, device, Data);
|
||||
else
|
||||
PixelCache.SetData<Color>(this.Data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PixelCache = new Texture2D(device, Math.Max(1, Width), Math.Max(1, Height), mip, SurfaceFormat.Color);
|
||||
PixelCache.SetData<Color>(new Color[] { Color.Transparent });
|
||||
}
|
||||
|
||||
PixelCache.Tag = new TextureInfo(PixelCache, Width, Height);
|
||||
if (!IffFile.RETAIN_CHUNK_DATA) Data = null;
|
||||
}
|
||||
return PixelCache;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue