commit 4d124ad9595c01cbf60988dca568f7139411db6f Author: Tim Sarbin Date: Thu Nov 22 00:18:42 2018 -0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f00a0eba --- /dev/null +++ b/.gitignore @@ -0,0 +1,334 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ \ No newline at end of file diff --git a/OpenDiablo2.Common/Attributes/SceneAttribute.cs b/OpenDiablo2.Common/Attributes/SceneAttribute.cs new file mode 100644 index 00000000..97de4d1e --- /dev/null +++ b/OpenDiablo2.Common/Attributes/SceneAttribute.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Attributes +{ + [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] + public sealed class SceneAttribute : Attribute + { + public SceneAttribute(string sceneName) => SceneName = sceneName; + public string SceneName { get; } + } +} diff --git a/OpenDiablo2.Common/Enums/eMPQFormatVersion.cs b/OpenDiablo2.Common/Enums/eMPQFormatVersion.cs new file mode 100644 index 00000000..96547f2e --- /dev/null +++ b/OpenDiablo2.Common/Enums/eMPQFormatVersion.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Enums +{ + public enum eMPQFormatVersion + { + Format1, + Format2, + Format3, + Format4 + } +} diff --git a/OpenDiablo2.Common/Interfaces/IGameEngine.cs b/OpenDiablo2.Common/Interfaces/IGameEngine.cs new file mode 100644 index 00000000..173471e4 --- /dev/null +++ b/OpenDiablo2.Common/Interfaces/IGameEngine.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Interfaces +{ + public interface IGameEngine : IDisposable + { + void Run(); + } +} diff --git a/OpenDiablo2.Common/Interfaces/IMPQProvider.cs b/OpenDiablo2.Common/Interfaces/IMPQProvider.cs new file mode 100644 index 00000000..2f3210fc --- /dev/null +++ b/OpenDiablo2.Common/Interfaces/IMPQProvider.cs @@ -0,0 +1,14 @@ +using OpenDiablo2.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; + +namespace OpenDiablo2.Common.Interfaces +{ + public interface IMPQProvider + { + IEnumerable GetMPQs(); + IEnumerable> GetTextFile(string fileName); + Stream GetStream(string fileName); + } +} diff --git a/OpenDiablo2.Common/Interfaces/IPaletteProvider.cs b/OpenDiablo2.Common/Interfaces/IPaletteProvider.cs new file mode 100644 index 00000000..55315534 --- /dev/null +++ b/OpenDiablo2.Common/Interfaces/IPaletteProvider.cs @@ -0,0 +1,10 @@ +using OpenDiablo2.Common.Models; +using System.Collections.Generic; + +namespace OpenDiablo2.Common.Interfaces +{ + public interface IPaletteProvider + { + Dictionary PaletteTable { get; } + } +} diff --git a/OpenDiablo2.Common/Interfaces/IRenderTarget.cs b/OpenDiablo2.Common/Interfaces/IRenderTarget.cs new file mode 100644 index 00000000..9744d014 --- /dev/null +++ b/OpenDiablo2.Common/Interfaces/IRenderTarget.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Interfaces +{ + public interface IRenderTarget + { + void Draw(ISprite sprite); + } +} diff --git a/OpenDiablo2.Common/Interfaces/IRenderWindow.cs b/OpenDiablo2.Common/Interfaces/IRenderWindow.cs new file mode 100644 index 00000000..9dec77f6 --- /dev/null +++ b/OpenDiablo2.Common/Interfaces/IRenderWindow.cs @@ -0,0 +1,20 @@ +using OpenDiablo2.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Interfaces +{ + public interface IRenderWindow : IDisposable + { + bool IsRunning { get; } + void Update(); + void Clear(); + void Sync(); + ISprite LoadSprite(ImageSet source); + void Draw(ISprite sprite); + } +} diff --git a/OpenDiablo2.Common/Interfaces/IScene.cs b/OpenDiablo2.Common/Interfaces/IScene.cs new file mode 100644 index 00000000..88732b44 --- /dev/null +++ b/OpenDiablo2.Common/Interfaces/IScene.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Interfaces +{ + public interface IScene : IDisposable + { + void Update(long ms); + void Render(); + } +} diff --git a/OpenDiablo2.Common/Interfaces/ISprite.cs b/OpenDiablo2.Common/Interfaces/ISprite.cs new file mode 100644 index 00000000..622a69fa --- /dev/null +++ b/OpenDiablo2.Common/Interfaces/ISprite.cs @@ -0,0 +1,15 @@ +using OpenDiablo2.Common.Models; +using System; +using System.Drawing; + +namespace OpenDiablo2.Common.Interfaces +{ + public interface ISprite : IDisposable + { + Point Location { get; set; } + Size FrameSize { get; set; } + int Frame { get; set; } + int TotalFrames { get; } + Palette CurrentPalette { get; set; } + } +} diff --git a/OpenDiablo2.Common/Models/BitStream.cs b/OpenDiablo2.Common/Models/BitStream.cs new file mode 100644 index 00000000..e79ac503 --- /dev/null +++ b/OpenDiablo2.Common/Models/BitStream.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; + +namespace OpenDiablo2.Common.Models +{ + /// + /// A utility class for reading groups of bits from a stream + /// + internal class BitStream + { + private Stream _baseStream; + private int _current; + private int _bitCount; + + public BitStream(Stream sourceStream) + { + _baseStream = sourceStream; + } + + public int ReadBits(int bitCount) + { + if (bitCount > 16) + throw new ArgumentOutOfRangeException("BitCount", "Maximum BitCount is 16"); + if (EnsureBits(bitCount) == false) return -1; + int result = _current & (0xffff >> (16 - bitCount)); + WasteBits(bitCount); + return result; + } + + public int PeekByte() + { + if (EnsureBits(8) == false) return -1; + return _current & 0xff; + } + + public bool EnsureBits(int bitCount) + { + if (bitCount <= _bitCount) return true; + + if (_baseStream.Position >= _baseStream.Length) return false; + int nextvalue = _baseStream.ReadByte(); + _current |= nextvalue << _bitCount; + _bitCount += 8; + return true; + } + + private bool WasteBits(int bitCount) + { + _current >>= bitCount; + _bitCount -= bitCount; + return true; + } + } +} diff --git a/OpenDiablo2.Common/Models/GlobalConfiguration.cs b/OpenDiablo2.Common/Models/GlobalConfiguration.cs new file mode 100644 index 00000000..e13c2570 --- /dev/null +++ b/OpenDiablo2.Common/Models/GlobalConfiguration.cs @@ -0,0 +1,7 @@ +namespace OpenDiablo2.Common.Models +{ + public sealed class GlobalConfiguration + { + public string BaseDataPath { get; set; } + } +} diff --git a/OpenDiablo2.Common/Models/ImageSet.cs b/OpenDiablo2.Common/Models/ImageSet.cs new file mode 100644 index 00000000..d82fd223 --- /dev/null +++ b/OpenDiablo2.Common/Models/ImageSet.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Models +{ + + public class ImageFrame + { + public UInt32 Flip; + public UInt32 Width; + public UInt32 Height; + public Int32 OffsetX; + public Int32 OffsetY; // from bottom border, not up + public UInt32 Unknown; + public UInt32 NextBlock; + public UInt32 Length; + public Int16[,] ImageData; + + public Color GetColor(int x, int y, Palette palette) + { + var index = ImageData[x, y]; + if (index == -1) + return Color.Transparent; + + var color = palette.Colors[(int)index]; + + return Color.FromArgb(255, color.R, color.G, color.B); + } + } + + public sealed class ImageSet + { + private UInt32 version; + private UInt32 unknown1; // 01 00 00 00 ??? + private UInt32 unknown2; // 00 00 00 00 ??? + private UInt32 termination; // EE EE EE EE or CD CD CD CD ??? + private UInt32[] framePointers; + public ImageFrame[] Frames { get; private set; } + + public UInt32 Directions { get; private set; } + public UInt32 FramesPerDirection { get; private set; } + + public static ImageSet LoadFromStream(Stream stream) + { + var br = new BinaryReader(stream); + var result = new ImageSet + { + version = br.ReadUInt32(), + unknown1 = br.ReadUInt32(), + unknown2 = br.ReadUInt32(), + termination = br.ReadUInt32(), + Directions = br.ReadUInt32(), + FramesPerDirection = br.ReadUInt32() + }; + + result.framePointers = new uint[result.Directions * result.FramesPerDirection]; + for (var i = 0; i < result.Directions * result.FramesPerDirection; i++) + result.framePointers[i] = br.ReadUInt32(); + + result.Frames = new ImageFrame[result.Directions * result.FramesPerDirection]; + for (var i = 0; i < result.Directions * result.FramesPerDirection; i++) + { + stream.Seek(result.framePointers[i], SeekOrigin.Begin); + + var frame = new ImageFrame + { + Flip = br.ReadUInt32(), + Width = br.ReadUInt32(), + Height = br.ReadUInt32(), + OffsetX = br.ReadInt32(), + OffsetY = br.ReadInt32(), + Unknown = br.ReadUInt32(), + NextBlock = br.ReadUInt32(), + Length = br.ReadUInt32() + }; + + frame.ImageData = new Int16[frame.Width, frame.Height]; + for (int ty = 0; ty < frame.Height; ty++) + for (int tx = 0; tx < frame.Width; tx++) + frame.ImageData[tx, ty] = -1; + + + int x = 0; + int y = (int)frame.Height - 1; + while (true) + { + var b = br.ReadByte(); + if (b == 0x80) + { + if (y == 0) + break; + + y--; + x = 0; + continue; + } + + if ((b & 0x80) > 0) + { + var transparentPixelsToWrite = b & 0x7F; + for (int p = 0; p < transparentPixelsToWrite; p++) + { + frame.ImageData[x++, y] = -1; + } + continue; + } + + + for (int p = 0; p < b; p++) + { + frame.ImageData[x++, y] = br.ReadByte(); + } + + } + result.Frames[i] = frame; + } + + + return result; + } + } +} diff --git a/OpenDiablo2.Common/Models/MPQ.cs b/OpenDiablo2.Common/Models/MPQ.cs new file mode 100644 index 00000000..44f9a852 --- /dev/null +++ b/OpenDiablo2.Common/Models/MPQ.cs @@ -0,0 +1,364 @@ +using OpenDiablo2.Common.Enums; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Models +{ + public sealed class MPQ : IDisposable + { + private const string HEADER_SIGNATURE = "MPQ\x1A"; + private const string USERDATA_SIGNATURE = "MPQ\x1B"; + private const string LISTFILE_NAME = "(listfile)"; + private const int MPQ_HASH_FILE_KEY = 3; + private const int MPQ_HASH_TABLE_OFFSET = 0; + private const int MPQ_HASH_NAME_A = 1; + private const int MPQ_HASH_NAME_B = 2; + private const UInt32 MPQ_HASH_ENTRY_EMPTY = 0xFFFFFFFF; + private const UInt32 MPQ_HASH_ENTRY_DELETED = 0xFFFFFFFE; + + internal struct HeaderRecord + { + public UInt32 HeaderSize; + public UInt32 ArchiveSize; + public UInt16 FormatVersion; + public Byte BlockSize; + public UInt32 HashTablePos; + public UInt32 BlockTablePos; + public UInt32 HashTableSize; + public UInt32 BlockTableSize; + // Other properties are for >0 MPQ version + } + + [Flags] + internal enum eBlockRecordFlags : UInt32 + { + IsFile = 0x80000000, // Block is a file, and follows the file data format; otherwise, block is free space or unused. If the block is not a file, all other flags should be cleared, and FileSize should be 0. + SingleUnit = 0x01000000, // File is stored as a single unit, rather than split into sectors. + KeyAdjusted = 0x00020000, // The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted. + IsEncrypted = 0x00010000, // File is encrypted. + IsCompressed = 0x00000200, // File is compressed. File cannot be imploded. + IsImploded = 0x00000100 // File is imploded. File cannot be compressed. + } + + internal struct BlockRecord + { + public UInt32 BlockOffset; + public UInt32 BlockSize; + public UInt32 FileSize; + public UInt32 Flags; + public uint EncryptionSeed { get; set; } + public string FileName { get; internal set; } + + public bool IsFile => (Flags & (UInt32)eBlockRecordFlags.IsFile) != 0; + public bool SingleUnit => (Flags & (UInt32)eBlockRecordFlags.SingleUnit) != 0; + public bool KeyAdjusted => (Flags & (UInt32)eBlockRecordFlags.KeyAdjusted) != 0; + public bool IsEncrypted => (Flags & (UInt32)eBlockRecordFlags.IsEncrypted) != 0; + public bool IsCompressed => (Flags & (UInt32)eBlockRecordFlags.IsCompressed) != 0; + public bool IsImploded => (Flags & (UInt32)eBlockRecordFlags.IsImploded) != 0; + } + + internal struct HashRecord + { + public UInt32 FilePathHashA; + public UInt32 FilePathHashB; + public UInt16 Language; + public UInt16 Platform; + public UInt32 FileBlockIndex; + } + + internal static UInt32[] cryptTable = new UInt32[0x500]; + internal HeaderRecord Header; + private List blockTable = new List(); + private List hashTable = new List(); + internal Stream fileStream; + + public UInt16 LanguageId = 0; + public const byte Platform = 0; + + public string Path { get; private set; } + public eMPQFormatVersion FormatVersion => (eMPQFormatVersion)Header.FormatVersion; + public List Files => GetFilePaths(); + + private List GetFilePaths() + { + var stream = OpenFile("(listfile)"); + if (stream == null) + { + return new List(); + } + + var sr = new StreamReader(stream); + var text = sr.ReadToEnd(); + + return text.Split('\n').Where(x => !String.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).ToList(); + } + + static MPQ() + { + InitializeCryptTable(); + } + + public MPQ(string path) + { + this.Path = path; + + fileStream = new FileStream(path, FileMode.Open); + + using (var br = new BinaryReader(fileStream, Encoding.Default, true)) + { + var header = Encoding.ASCII.GetString(br.ReadBytes(4)); + if (header != HEADER_SIGNATURE) + throw new ApplicationException($"Unknown header signature '{header}' detected while processing '{Path}'!"); + + ParseMPQHeader(br); + } + + } + + private static void InitializeCryptTable() + { + UInt32 seed = 0x00100001; + UInt32 index1 = 0; + UInt32 index2 = 0; + int i; + + for (index1 = 0; index1 < 0x100; index1++) + { + for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100) + { + seed = (seed * 125 + 3) % 0x2AAAAB; + var temp = (seed & 0xFFFF) << 0x10; + + seed = (seed * 125 + 3) % 0x2AAAAB; + + cryptTable[index2] = (temp | (seed & 0xFFFF)); + } + } + } + + internal static void DecryptBlock(uint[] data, uint seed1) + { + uint seed2 = 0xeeeeeeee; + + for (int i = 0; i < data.Length; i++) + { + seed2 += cryptTable[0x400 + (seed1 & 0xff)]; + uint result = data[i]; + result ^= seed1 + seed2; + + seed1 = ((~seed1 << 21) + 0x11111111) | (seed1 >> 11); + seed2 = result + seed2 + (seed2 << 5) + 3; + data[i] = result; + } + } + + internal static void DecryptBlock(byte[] data, uint seed1) + { + uint seed2 = 0xeeeeeeee; + + // NB: If the block is not an even multiple of 4, + // the remainder is not encrypted + for (int i = 0; i < data.Length - 3; i += 4) + { + seed2 += cryptTable[(int)(0x400 + (seed1 & 0xff))]; + + uint result = BitConverter.ToUInt32(data, i); + result ^= (seed1 + seed2); + + seed1 = ((~seed1 << 21) + 0x11111111) | (seed1 >> 11); + seed2 = result + seed2 + (seed2 << 5) + 3; + + data[i + 0] = ((byte)(result & 0xff)); + data[i + 1] = ((byte)((result >> 8) & 0xff)); + data[i + 2] = ((byte)((result >> 16) & 0xff)); + data[i + 3] = ((byte)((result >> 24) & 0xff)); + } + } + + + private void ParseMPQHeader(BinaryReader br) + { + Header = new HeaderRecord + { + HeaderSize = br.ReadUInt32(), + ArchiveSize = br.ReadUInt32(), + FormatVersion = br.ReadUInt16(), + BlockSize = (byte)br.ReadInt16(), + HashTablePos = br.ReadUInt32(), + BlockTablePos = br.ReadUInt32(), + HashTableSize = br.ReadUInt32(), + BlockTableSize = br.ReadUInt32() + }; + + if (FormatVersion != eMPQFormatVersion.Format1) + throw new ApplicationException($"Unsupported MPQ format version of {Header.FormatVersion} detected for '{Path}'!"); + + if (br.BaseStream.Position != Header.HeaderSize) + throw new ApplicationException($"Invalid header size detected for '{Path}'. Expected to be at offset {Header.HeaderSize} but we are at offset {br.BaseStream.Position} instead!"); + + br.BaseStream.Seek(Header.BlockTablePos, SeekOrigin.Begin); + + // Process the block table + var bData = br.ReadBytes((int)(16 * Header.BlockTableSize)); + DecryptBlock(bData, HashString("(block table)", MPQ_HASH_FILE_KEY)); + using (var ms = new MemoryStream(bData)) + using (var dr = new BinaryReader(new MemoryStream(bData))) + for (var index = 0; index < Header.BlockTableSize; index++) + { + blockTable.Add(new BlockRecord + { + BlockOffset = dr.ReadUInt32(), + BlockSize = dr.ReadUInt32(), + FileSize = dr.ReadUInt32(), + Flags = dr.ReadUInt32() + }); + } + + // Process the hash table + br.BaseStream.Seek(Header.HashTablePos, SeekOrigin.Begin); + bData = br.ReadBytes((int)(16 * Header.HashTableSize)); + DecryptBlock(bData, HashString("(hash table)", MPQ_HASH_FILE_KEY)); + using (var ms = new MemoryStream(bData)) + using (var dr = new BinaryReader(new MemoryStream(bData))) + for (var index = 0; index < Header.HashTableSize; index++) + { + hashTable.Add(new HashRecord + { + FilePathHashA = dr.ReadUInt32(), + FilePathHashB = dr.ReadUInt32(), + Language = dr.ReadUInt16(), + Platform = dr.ReadUInt16(), + FileBlockIndex = dr.ReadUInt32() + }); + } + + } + + private uint CalculateEncryptionSeed(BlockRecord record) + { + if (record.FileName == null) return 0; + + uint seed = HashString(System.IO.Path.GetFileName(record.FileName), MPQ_HASH_FILE_KEY); + if (record.KeyAdjusted) + seed = (seed + record.BlockOffset) ^ record.FileSize; + return seed; + } + + private static UInt32 HashString(string inputString, UInt32 hashType) + { + if (hashType > MPQ_HASH_FILE_KEY) + throw new ApplicationException($"Unknown hash type {hashType} for input string {inputString}"); + + UInt32 seed1 = 0x7FED7FED; + UInt32 seed2 = 0xEEEEEEEE; + + foreach (var ch in inputString) + { + var chInt = (UInt32)char.ToUpper(ch); + seed1 = cryptTable[(hashType * 0x100) + chInt] ^ (seed1 + seed2); + seed2 = chInt + seed1 + seed2 + (seed2 << 5) + 3; + } + return seed1; + } + + private static UInt32 ComputeFileKey(string filePath, BlockRecord blockRecord, UInt32 archiveOffset) + { + var fileName = filePath.Split('\\').Last(); + + // Hash the name to get the base key + var fileKey = HashString(fileName, MPQ_HASH_FILE_KEY); + + // Offset-adjust the key if necessary + if (blockRecord.KeyAdjusted) + fileKey = (fileKey + blockRecord.BlockOffset) ^ blockRecord.FileSize; + + return fileKey; + } + + private bool FindFileInHashTable(string filePath, out UInt32 fileHashEntry) + { + fileHashEntry = 0; + + // Find the home entry in the hash table for the file + UInt32 initEntry = HashString(filePath, MPQ_HASH_TABLE_OFFSET) & (UInt32)(Header.HashTableSize - 1); + + // Is there anything there at all? + if (hashTable[(int)initEntry].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY) + return false; + + // Compute the hashes to compare the hash table entry against + var nNameHashA = HashString(filePath, MPQ_HASH_NAME_A); + var nNameHashB = HashString(filePath, MPQ_HASH_NAME_B); + var iCurEntry = initEntry; + + // Check each entry in the hash table till a termination point is reached + do + { + if (hashTable[(int)iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_DELETED) + { + if (hashTable[(int)iCurEntry].FilePathHashA == nNameHashA + && hashTable[(int)iCurEntry].FilePathHashB == nNameHashB + && hashTable[(int)iCurEntry].Language == LanguageId + && hashTable[(int)iCurEntry].Platform == (UInt16)PlatformID.Win32S) + { + fileHashEntry = iCurEntry; + + return true; + } + } + + iCurEntry = (iCurEntry + 1) & (UInt32)(Header.HashTableSize - 1); + } while (iCurEntry != initEntry && hashTable[(int)iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_EMPTY); + + return false; + } + + private bool GetHashRecord(string fileName, out HashRecord hash) + { + uint index = HashString(fileName, 0); + index &= Header.HashTableSize - 1; + uint name1 = HashString(fileName, MPQ_HASH_NAME_A); + uint name2 = HashString(fileName, MPQ_HASH_NAME_B); + + for (uint i = index; i < hashTable.Count(); ++i) + { + hash = hashTable[(int)i]; + if (hash.FilePathHashA == name1 && hash.FilePathHashB == name2) + return true; + } + + for (uint i = 0; i < index; i++) + { + hash = hashTable[(int)i]; + if (hash.FilePathHashA == name1 && hash.FilePathHashB == name2) + return true; + } + + hash = new HashRecord(); + return false; + } + + public MPQStream OpenFile(string filename) + { + HashRecord hash; + BlockRecord block; + + if (!GetHashRecord(filename, out hash)) + throw new FileNotFoundException("File not found: " + filename); + + block = blockTable[(int)hash.FileBlockIndex]; + block.FileName = filename.ToLower(); + block.EncryptionSeed = CalculateEncryptionSeed(block); + return new MPQStream(this, block); + } + + public void Dispose() + { + fileStream?.Dispose(); + } + } +} diff --git a/OpenDiablo2.Common/Models/MPQHuffman.cs b/OpenDiablo2.Common/Models/MPQHuffman.cs new file mode 100644 index 00000000..fdf2e408 --- /dev/null +++ b/OpenDiablo2.Common/Models/MPQHuffman.cs @@ -0,0 +1,404 @@ +// +// MpqHuffman.cs +// +// Authors: +// Foole (fooleau@gmail.com) +// +// (C) 2006 Foole (fooleau@gmail.com) +// Based on code from StormLib by Ladislav Zezula and ShadowFlare +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Collections; + +namespace OpenDiablo2.Common.Models +{ + // A node which is both hierachcical (parent/child) and doubly linked (next/prev) + internal class LinkedNode + { + public int DecompressedValue; + public int Weight; + public LinkedNode Parent; + public LinkedNode Child0; + + public LinkedNode Child1 + { get { return Child0.Prev; } } + + public LinkedNode Next; + public LinkedNode Prev; + + public LinkedNode(int decompVal, int weight) + { + DecompressedValue = decompVal; + this.Weight = weight; + } + + // TODO: This would be more efficient as a member of the other class + // ie avoid the recursion + public LinkedNode Insert(LinkedNode other) + { + // 'Next' should have a lower weight + // we should return the lower weight + if (other.Weight <= Weight) + { + // insert before + if (Next != null) + { + Next.Prev = other; + other.Next = Next; + } + Next = other; + other.Prev = this; + return other; + } + else + { + if (Prev == null) + { + // Insert after + other.Prev = null; + Prev = other; + other.Next = this; + } + else + { + Prev.Insert(other); + } + } + return this; + } + } + + /// + /// A decompressor for MPQ's huffman compression + /// + internal static class MpqHuffman + { + private static readonly byte[][] sPrime = + { + // Compression type 0 + new byte[] + { + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + }, + // Compression type 1 + new byte[] + { + 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05, + 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, + 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, + 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, + 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, + 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, + 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03, + 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, + 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B, + }, + // Compression type 2 + new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04, + 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02, + 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A, + 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01 + }, + // Compression type 3 + new byte[] + { + 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03, + 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, + 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03, + 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03, + 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01, + 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, + }, + // Compression type 4 + new byte[] + { + 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17, + }, + // Compression type 5 + new byte[] + { + 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82, + 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37, + 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D, + 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18 + }, + // Compression type 6 + new byte[] + { + 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7A, 0x46 + }, + // Compression type 7 + new byte[] + { + 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x6C + }, + // Compression type 8 + new byte[] + { + 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10, + 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11, + 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5F, 0x9E + } + }; + + public static MemoryStream Decompress(Stream data) + { + int comptype = data.ReadByte(); + + if (comptype == 0) + throw new NotImplementedException("Compression type 0 is not currently supported"); + + LinkedNode tail = BuildList(sPrime[comptype]); + LinkedNode head = BuildTree(tail); + + MemoryStream outputstream = new MemoryStream(); + BitStream bitstream = new BitStream(data); + int decoded; + do + { + LinkedNode node = Decode(bitstream, head); + decoded = node.DecompressedValue; + switch (decoded) + { + case 256: + break; + case 257: + int newvalue = bitstream.ReadBits(8); + outputstream.WriteByte((byte)newvalue); + tail = InsertNode(tail, newvalue); + break; + default: + outputstream.WriteByte((byte)decoded); + break; + } + } while (decoded != 256); + + outputstream.Seek(0, SeekOrigin.Begin); + return outputstream; + } + + private static LinkedNode Decode(BitStream input, LinkedNode head) + { + LinkedNode node = head; + + while (node.Child0 != null) + { + int bit = input.ReadBits(1); + if (bit == -1) + throw new Exception("Unexpected end of file"); + + node = bit == 0 ? node.Child0 : node.Child1; + } + return node; + } + + private static LinkedNode BuildList(byte[] primeData) + { + LinkedNode root; + + root = new LinkedNode(256, 1); + root = root.Insert(new LinkedNode(257, 1)); + + for (int i = 0; i < primeData.Length; i++) + { + if (primeData[i] != 0) + root = root.Insert(new LinkedNode(i, primeData[i])); + } + return root; + } + + private static LinkedNode BuildTree(LinkedNode tail) + { + LinkedNode current = tail; + + while (current != null) + { + LinkedNode child0 = current; + LinkedNode child1 = current.Prev; + if (child1 == null) break; + + LinkedNode parent = new LinkedNode(0, child0.Weight + child1.Weight); + parent.Child0 = child0; + child0.Parent = parent; + child1.Parent = parent; + + current.Insert(parent); + current = current.Prev.Prev; + } + return current; + } + + private static LinkedNode InsertNode(LinkedNode tail, int decomp) + { + LinkedNode parent = tail; + LinkedNode result = tail.Prev; // This will be the new tail after the tree is updated + + LinkedNode temp = new LinkedNode(parent.DecompressedValue, parent.Weight); + temp.Parent = parent; + + LinkedNode newnode = new LinkedNode(decomp, 0); + newnode.Parent = parent; + + parent.Child0 = newnode; + + tail.Next = temp; + temp.Prev = tail; + newnode.Prev = temp; + temp.Next = newnode; + + AdjustTree(newnode); + // TODO: For compression type 0, AdjustTree should be called + // once for every value written and only once here + AdjustTree(newnode); + return result; + } + + // This increases the weight of the new node and its antecendants + // and adjusts the tree if needed + private static void AdjustTree(LinkedNode newNode) + { + LinkedNode current = newNode; + + while (current != null) + { + current.Weight++; + LinkedNode insertpoint; + LinkedNode prev; + // Go backwards thru the list looking for the insertion point + insertpoint = current; + while (true) + { + prev = insertpoint.Prev; + if (prev == null) break; + if (prev.Weight >= current.Weight) break; + insertpoint = prev; + } + + // No insertion point found + if (insertpoint == current) + { + current = current.Parent; + continue; + } + + // The following code basicly swaps insertpoint with current + + // remove insert point + if (insertpoint.Prev != null) insertpoint.Prev.Next = insertpoint.Next; + insertpoint.Next.Prev = insertpoint.Prev; + + // Insert insertpoint after current + insertpoint.Next = current.Next; + insertpoint.Prev = current; + if (current.Next != null) current.Next.Prev = insertpoint; + current.Next = insertpoint; + + // remove current + current.Prev.Next = current.Next; + current.Next.Prev = current.Prev; + + // insert current after prev + LinkedNode temp = prev.Next; + current.Next = temp; + current.Prev = prev; + temp.Prev = current; + prev.Next = current; + + // Set up parent/child links + LinkedNode currentparent = current.Parent; + LinkedNode insertparent = insertpoint.Parent; + + if (currentparent.Child0 == current) + currentparent.Child0 = insertpoint; + + if (currentparent != insertparent && insertparent.Child0 == insertpoint) + insertparent.Child0 = current; + + current.Parent = insertparent; + insertpoint.Parent = currentparent; + + current = current.Parent; + } + } + } +} \ No newline at end of file diff --git a/OpenDiablo2.Common/Models/MPQStream.cs b/OpenDiablo2.Common/Models/MPQStream.cs new file mode 100644 index 00000000..70be2d40 --- /dev/null +++ b/OpenDiablo2.Common/Models/MPQStream.cs @@ -0,0 +1,374 @@ +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static OpenDiablo2.Common.Models.MPQ; + + +namespace OpenDiablo2.Common.Models +{ + public sealed class MPQStream : Stream + { + private readonly MPQ mpq; + private readonly BlockRecord blockRecord; + private uint[] blockPositions; + private long position; + private byte[] _currentData; + private int _currentBlockIndex = -1; + private int blockSize; + + internal MPQStream(MPQ mpq, BlockRecord blockRecord) + { + this.mpq = mpq; + this.blockRecord = blockRecord; + this.blockSize = 0x200 << mpq.Header.BlockSize; + + if (blockRecord.IsCompressed && !blockRecord.SingleUnit) + LoadBlockOffsets(); + + } + + private void LoadBlockOffsets() + { + + int blockposcount = (int)((blockRecord.FileSize + blockSize - 1) / blockSize) + 1; + blockPositions = new uint[blockposcount]; + + lock (mpq.fileStream) + { + mpq.fileStream.Seek(blockRecord.BlockOffset, SeekOrigin.Begin); + var br = new BinaryReader(mpq.fileStream); + for (int i = 0; i < blockposcount; i++) + blockPositions[i] = br.ReadUInt32(); + + } + + uint blockpossize = (uint)blockposcount * 4; + + if (blockRecord.IsEncrypted) + { + MPQ.DecryptBlock(blockPositions, blockRecord.EncryptionSeed - 1); + + if (blockPositions[0] != blockpossize) + throw new ApplicationException("Decryption failed"); + if (blockPositions[1] > blockSize + blockpossize) + throw new ApplicationException("Decryption failed"); + } + + } + + public override bool CanRead => true; + + public override bool CanSeek => true; + + public override bool CanWrite => false; + + public override long Length => blockRecord.FileSize; + + public override long Position + { + get => position; + set => Seek(value, SeekOrigin.Begin); + } + + public override void Flush() { } + + public override int Read(byte[] buffer, int offset, int count) + { + if (blockRecord.SingleUnit) + return ReadInternalSingleUnit(buffer, offset, count); + + int toread = count; + int readtotal = 0; + + while (toread > 0) + { + int read = ReadInternal(buffer, offset, toread); + if (read == 0) break; + readtotal += read; + offset += read; + toread -= read; + } + return readtotal; + } + + private int ReadInternalSingleUnit(byte[] buffer, int offset, int count) + { + if (position >= Length) + return 0; + + if (_currentData == null) + LoadSingleUnit(); + + int bytestocopy = Math.Min((int)(_currentData.Length - position), count); + + Array.Copy(_currentData, position, buffer, offset, bytestocopy); + + position += bytestocopy; + return bytestocopy; + } + + private void LoadSingleUnit() + { + // Read the entire file into memory + byte[] filedata = new byte[blockSize]; + lock (mpq.fileStream) + { + mpq.fileStream.Seek(mpq.Header.HeaderSize + blockRecord.BlockOffset, SeekOrigin.Begin); + int read = mpq.fileStream.Read(filedata, 0, filedata.Length); + if (read != filedata.Length) + throw new ApplicationException("Insufficient data or invalid data length"); + } + + if (blockSize == blockRecord.FileSize) + _currentData = filedata; + else + _currentData = DecompressMulti(filedata, (int)blockRecord.FileSize); + } + + private int ReadInternal(byte[] buffer, int offset, int count) + { + // OW: avoid reading past the contents of the file + if (position >= Length) + return 0; + + BufferData(); + + int localposition = (int)(position % blockSize); + int bytestocopy = Math.Min(_currentData.Length - localposition, count); + if (bytestocopy <= 0) return 0; + + Array.Copy(_currentData, localposition, buffer, offset, bytestocopy); + + position += bytestocopy; + return bytestocopy; + } + + public override int ReadByte() + { + if (position >= Length) return -1; + + if (blockRecord.SingleUnit) + return ReadByteSingleUnit(); + + BufferData(); + + int localposition = (int)(position % blockSize); + position++; + return _currentData[localposition]; + } + + private int ReadByteSingleUnit() + { + if (_currentData == null) + LoadSingleUnit(); + + return _currentData[position++]; + } + + private void BufferData() + { + int requiredblock = (int)(position / blockSize); + if (requiredblock != _currentBlockIndex) + { + int expectedlength = (int)Math.Min(Length - (requiredblock * blockSize), blockSize); + _currentData = LoadBlock(requiredblock, expectedlength); + _currentBlockIndex = requiredblock; + } + } + + private byte[] LoadBlock(int blockIndex, int expectedLength) + { + uint offset; + int toread; + uint encryptionseed; + + if (blockRecord.IsCompressed) + { + offset = blockPositions[blockIndex]; + toread = (int)(blockPositions[blockIndex + 1] - offset); + } + else + { + offset = (uint)(blockIndex * blockSize); + toread = expectedLength; + } + offset += blockRecord.BlockOffset; + + byte[] data = new byte[toread]; + lock (mpq.fileStream) + { + mpq.fileStream.Seek(offset, SeekOrigin.Begin); + int read = mpq.fileStream.Read(data, 0, toread); + if (read != toread) + throw new ApplicationException("Insufficient data or invalid data length"); + } + + if (blockRecord.IsEncrypted && blockRecord.FileSize > 3) + { + if (blockRecord.EncryptionSeed == 0) + throw new ApplicationException("Unable to determine encryption key"); + + encryptionseed = (uint)(blockIndex + blockRecord.EncryptionSeed); + MPQ.DecryptBlock(data, encryptionseed); + } + + if (blockRecord.IsCompressed && (toread != expectedLength)) + { + //if ((blockRecord.Flags & MpqFileFlags.CompressedMulti) != 0) + if (!blockRecord.SingleUnit) + data = DecompressMulti(data, expectedLength); + else + data = PKDecompress(new MemoryStream(data), expectedLength); + } + + return data; + } + + private static byte[] DecompressMulti(byte[] input, int outputLength) + { + Stream sinput = new MemoryStream(input); + + byte comptype = (byte)sinput.ReadByte(); + + switch (comptype) + { + case 1: // Huffman + return MpqHuffman.Decompress(sinput).ToArray(); + case 2: // ZLib/Deflate + return ZlibDecompress(sinput, outputLength); + case 8: // PKLib/Impode + return PKDecompress(sinput, outputLength); + case 0x10: // BZip2 + return BZip2Decompress(sinput, outputLength); + case 0x80: // IMA ADPCM Stereo + return MpqWavCompression.Decompress(sinput, 2); + case 0x40: // IMA ADPCM Mono + return MpqWavCompression.Decompress(sinput, 1); + + case 0x12: + throw new ApplicationException("LZMA compression is not yet supported"); + // Combos + case 0x22: + // TODO: sparse then zlib + throw new ApplicationException("Sparse compression + Deflate compression is not yet supported"); + case 0x30: + // TODO: sparse then bzip2 + throw new ApplicationException("Sparse compression + BZip2 compression is not yet supported"); + case 0x41: + sinput = MpqHuffman.Decompress(sinput); + return MpqWavCompression.Decompress(sinput, 1); + case 0x48: + { + byte[] result = PKDecompress(sinput, outputLength); + return MpqWavCompression.Decompress(new MemoryStream(result), 1); + } + case 0x81: + sinput = MpqHuffman.Decompress(sinput); + return MpqWavCompression.Decompress(sinput, 2); + case 0x88: + { + byte[] result = PKDecompress(sinput, outputLength); + return MpqWavCompression.Decompress(new MemoryStream(result), 2); + } + default: + throw new ApplicationException("Compression is not yet supported: 0x" + comptype.ToString("X")); + } + } + + private static byte[] BZip2Decompress(Stream data, int expectedLength) + { + using (var output = new MemoryStream(expectedLength)) + { + new Ionic.BZip2.BZip2InputStream(data) + .CopyTo(output); + return output.ToArray(); + } + } + + private static byte[] PKDecompress(Stream data, int expectedLength) + { + PKLibDecompress pk = new PKLibDecompress(data); + return pk.Explode(expectedLength); + } + + private static byte[] ZlibDecompress(Stream data, int expectedLength) + { + // This assumes that Zlib won't be used in combination with another compression type + byte[] Output = new byte[expectedLength]; + Stream s = new InflaterInputStream(data); + int Offset = 0; + while (expectedLength > 0) + { + int size = s.Read(Output, Offset, expectedLength); + if (size == 0) break; + Offset += size; + expectedLength -= size; + } + return Output; + } + + public override long Seek(long offset, SeekOrigin origin) + { + long target; + + switch (origin) + { + case SeekOrigin.Begin: + target = offset; + break; + case SeekOrigin.Current: + target = Position + offset; + break; + case SeekOrigin.End: + target = Length + offset; + break; + default: + throw new ArgumentException("Origin", "Invalid SeekOrigin"); + } + + if (target < 0) + throw new ArgumentOutOfRangeException("Attmpted to Seek before the beginning of the stream"); + if (target >= Length) + throw new ArgumentOutOfRangeException("Attmpted to Seek beyond the end of the stream"); + + position = target; + + return position; + } + + internal static uint DetectFileSeed(uint value0, uint value1, uint decrypted) + { + uint temp = (value0 ^ decrypted) - 0xeeeeeeee; + + for (int i = 0; i < 0x100; i++) + { + uint seed1 = temp - MPQ.cryptTable[0x400 + i]; + uint seed2 = 0xeeeeeeee + MPQ.cryptTable[0x400 + (seed1 & 0xff)]; + uint result = value0 ^ (seed1 + seed2); + + if (result != decrypted) + continue; + + uint saveseed1 = seed1; + + // Test this result against the 2nd value + seed1 = ((~seed1 << 21) + 0x11111111) | (seed1 >> 11); + seed2 = result + seed2 + (seed2 << 5) + 3; + + seed2 += MPQ.cryptTable[0x400 + (seed1 & 0xff)]; + result = value1 ^ (seed1 + seed2); + + if ((result & 0xfffc0000) == 0) + return saveseed1; + } + return 0; + } + + public override void SetLength(long value) => throw new NotImplementedException(); + public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException(); + } +} diff --git a/OpenDiablo2.Common/Models/MPQWavCompression.cs b/OpenDiablo2.Common/Models/MPQWavCompression.cs new file mode 100644 index 00000000..923b56a4 --- /dev/null +++ b/OpenDiablo2.Common/Models/MPQWavCompression.cs @@ -0,0 +1,125 @@ +using System.IO; + +namespace OpenDiablo2.Common.Models +{ + /// + /// An IMA ADPCM decompress for Mpq files + /// + internal static class MpqWavCompression + { + private static readonly int[] sLookup = + { + 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, + 0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, + 0x0022, 0x0025, 0x0029, 0x002D, 0x0032, 0x0037, 0x003C, 0x0042, + 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076, 0x0082, 0x008F, + 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133, + 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, + 0x02D4, 0x031C, 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, + 0x0610, 0x06AB, 0x0756, 0x0812, 0x08E0, 0x09C3, 0x0ABD, 0x0BD0, + 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, 0x1706, 0x1954, + 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B, + 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, + 0x7FFF + }; + + private static readonly int[] sLookup2 = + { + -1, 0, -1, 4, -1, 2, -1, 6, + -1, 1, -1, 5, -1, 3, -1, 7, + -1, 1, -1, 5, -1, 3, -1, 7, + -1, 2, -1, 4, -1, 6, -1, 8 + }; + + public static byte[] Decompress(Stream data, int channelCount) + { + int[] Array1 = new int[] { 0x2c, 0x2c }; + int[] Array2 = new int[channelCount]; + + BinaryReader input = new BinaryReader(data); + MemoryStream outputstream = new MemoryStream(); + BinaryWriter output = new BinaryWriter(outputstream); + + input.ReadByte(); + byte shift = input.ReadByte(); + + for (int i = 0; i < channelCount; i++) + { + short temp = input.ReadInt16(); + Array2[i] = temp; + output.Write(temp); + } + + int channel = channelCount - 1; + while (data.Position < data.Length) + { + byte value = input.ReadByte(); + + if (channelCount == 2) channel = 1 - channel; + + if ((value & 0x80) != 0) + { + switch (value & 0x7f) + { + case 0: + if (Array1[channel] != 0) Array1[channel]--; + output.Write((short)Array2[channel]); + break; + case 1: + Array1[channel] += 8; + if (Array1[channel] > 0x58) Array1[channel] = 0x58; + if (channelCount == 2) channel = 1 - channel; + break; + case 2: + break; + default: + Array1[channel] -= 8; + if (Array1[channel] < 0) Array1[channel] = 0; + if (channelCount == 2) channel = 1 - channel; + break; + } + } + else + { + int temp1 = sLookup[Array1[channel]]; + int temp2 = temp1 >> shift; + + if ((value & 1) != 0) + temp2 += (temp1 >> 0); + if ((value & 2) != 0) + temp2 += (temp1 >> 1); + if ((value & 4) != 0) + temp2 += (temp1 >> 2); + if ((value & 8) != 0) + temp2 += (temp1 >> 3); + if ((value & 0x10) != 0) + temp2 += (temp1 >> 4); + if ((value & 0x20) != 0) + temp2 += (temp1 >> 5); + + int temp3 = Array2[channel]; + if ((value & 0x40) != 0) + { + temp3 -= temp2; + if (temp3 <= short.MinValue) temp3 = short.MinValue; + } + else + { + temp3 += temp2; + if (temp3 >= short.MaxValue) temp3 = short.MaxValue; + } + Array2[channel] = temp3; + output.Write((short)temp3); + + Array1[channel] += sLookup2[value & 0x1f]; + + if (Array1[channel] < 0) + Array1[channel] = 0; + else + if (Array1[channel] > 0x58) Array1[channel] = 0x58; + } + } + return outputstream.ToArray(); + } + } +} diff --git a/OpenDiablo2.Common/Models/PKLibDecompress.cs b/OpenDiablo2.Common/Models/PKLibDecompress.cs new file mode 100644 index 00000000..f44ea447 --- /dev/null +++ b/OpenDiablo2.Common/Models/PKLibDecompress.cs @@ -0,0 +1,229 @@ +// +// MpqLibDecompress.cs +// +// Authors: +// Foole (fooleau@gmail.com) +// +// (C) 2006 Foole (fooleau@gmail.com) +// Based on code from StormLib by Ladislav Zezula +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; + +namespace OpenDiablo2.Common.Models +{ + enum CompressionType + { + Binary = 0, + Ascii = 1 + } + /// + /// A decompressor for PKLib implode/explode + /// + public class PKLibDecompress + { + private BitStream _bitstream; + private CompressionType _compressionType; + private int _dictSizeBits; // Dictionary size in bits + + private static byte[] sPosition1; + private static byte[] sPosition2; + + private static readonly byte[] sLenBits = + { + 3, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7 + }; + + private static readonly byte[] sLenCode = + { + 5, 3, 1, 6, 10, 2, 12, 20, 4, 24, 8, 48, 16, 32, 64, 0 + }; + + private static readonly byte[] sExLenBits = + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8 + }; + + private static readonly UInt16[] sLenBase = + { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106 + }; + + private static readonly byte[] sDistBits = + { + 2, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 + }; + + private static readonly byte[] sDistCode = + { + 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, + 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, + 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, + 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 + }; + + static PKLibDecompress() + { + sPosition1 = GenerateDecodeTable(sDistBits, sDistCode); + sPosition2 = GenerateDecodeTable(sLenBits, sLenCode); + } + + public PKLibDecompress(Stream input) + { + _bitstream = new BitStream(input); + + _compressionType = (CompressionType)input.ReadByte(); + if (_compressionType != CompressionType.Binary && _compressionType != CompressionType.Ascii) + throw new InvalidDataException("Invalid compression type: " + _compressionType); + + _dictSizeBits = input.ReadByte(); + // This is 6 in test cases + if (4 > _dictSizeBits || _dictSizeBits > 6) + throw new InvalidDataException("Invalid dictionary size: " + _dictSizeBits); + } + + public byte[] Explode(int expectedSize) + { + byte[] outputbuffer = new byte[expectedSize]; + Stream outputstream = new MemoryStream(outputbuffer); + + int instruction; + while ((instruction = DecodeLit()) != -1) + { + if (instruction < 0x100) + { + outputstream.WriteByte((byte)instruction); + } + else + { + // If instruction is greater than 0x100, it means "Repeat n - 0xFE bytes" + int copylength = instruction - 0xFE; + int moveback = DecodeDist(copylength); + if (moveback == 0) break; + + int source = (int)outputstream.Position - moveback; + // We can't just outputstream.Write the section of the array + // because it might overlap with what is currently being written + while (copylength-- > 0) + outputstream.WriteByte(outputbuffer[source++]); + } + } + + if (outputstream.Position == expectedSize) + { + return outputbuffer; + } + else + { + // Resize the array + byte[] result = new byte[outputstream.Position]; + Array.Copy(outputbuffer, 0, result, 0, result.Length); + return result; + } + } + + // Return values: + // 0x000 - 0x0FF : One byte from compressed file. + // 0x100 - 0x305 : Copy previous block (0x100 = 1 byte) + // -1 : EOF + private int DecodeLit() + { + switch (_bitstream.ReadBits(1)) + { + case -1: + return -1; + + case 1: + // The next bits are position in buffers + int pos = sPosition2[_bitstream.PeekByte()]; + + // Skip the bits we just used + if (_bitstream.ReadBits(sLenBits[pos]) == -1) return -1; + + int nbits = sExLenBits[pos]; + if (nbits != 0) + { + // TODO: Verify this conversion + int val2 = _bitstream.ReadBits(nbits); + if (val2 == -1 && (pos + val2 != 0x10e)) return -1; + + pos = sLenBase[pos] + val2; + } + return pos + 0x100; // Return number of bytes to repeat + + case 0: + if (_compressionType == CompressionType.Binary) + return _bitstream.ReadBits(8); + + // TODO: Text mode + throw new NotImplementedException("Text mode is not yet implemented"); + default: + return 0; + } + } + + private int DecodeDist(int length) + { + if (_bitstream.EnsureBits(8) == false) return 0; + int pos = sPosition1[_bitstream.PeekByte()]; + byte skip = sDistBits[pos]; // Number of bits to skip + + // Skip the appropriate number of bits + if (_bitstream.ReadBits(skip) == -1) return 0; + + if (length == 2) + { + if (_bitstream.EnsureBits(2) == false) return 0; + pos = (pos << 2) | _bitstream.ReadBits(2); + } + else + { + if (_bitstream.EnsureBits(_dictSizeBits) == false) return 0; + pos = ((pos << _dictSizeBits)) | _bitstream.ReadBits(_dictSizeBits); + } + + return pos + 1; + } + + private static byte[] GenerateDecodeTable(byte[] bits, byte[] codes) + { + byte[] result = new byte[256]; + + for (int i = bits.Length - 1; i >= 0; i--) + { + UInt32 idx1 = codes[i]; + UInt32 idx2 = (UInt32)1 << bits[i]; + + do + { + result[idx1] = (byte)i; + idx1 += idx2; + } while (idx1 < 0x100); + } + return result; + } + } +} \ No newline at end of file diff --git a/OpenDiablo2.Common/Models/Palette.cs b/OpenDiablo2.Common/Models/Palette.cs new file mode 100644 index 00000000..19cba0cb --- /dev/null +++ b/OpenDiablo2.Common/Models/Palette.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Models +{ + public struct PaletteEntry + { + public int R; + public int G; + public int B; + } + + public struct Palette + { + public string Name { get; set; } + public PaletteEntry[] Colors; + + public static Palette LoadFromStream(Stream stream) + { + var result = new Palette + { + Colors = new PaletteEntry[256] + }; + + var br = new BinaryReader(stream); + for (var i = 0; i <= 255; i++) + result.Colors[i] = new PaletteEntry + { + B = br.ReadByte(), + G = br.ReadByte(), + R = br.ReadByte() + }; + + return result; + } + } +} diff --git a/OpenDiablo2.Common/Models/SoundEntry.cs b/OpenDiablo2.Common/Models/SoundEntry.cs new file mode 100644 index 00000000..90c0b3ce --- /dev/null +++ b/OpenDiablo2.Common/Models/SoundEntry.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Models +{ + public struct SoundEntry + { + public string Handle { get; set; } + public int Index { get; set; } + public string FileName { get; set; } + public byte Volume { get; set; } + public int GroupSize { get; set; } + public bool Loop { get; set; } + public int FadeIn { get; set; } + public int FadeOut { get; set; } + public int DeferInst { get; set; } + public int StopInst { get; set; } + public int Duration { get; set; } + public int Compound { get; set; } + public bool Reverb { get; set; } + public int Falloff { get; set; } + public int Cache { get; set; } + public bool AsyncOnly { get; set; } + public int Priority { get; set; } + public int Stream { get; set; } + public int Stereo { get; set; } + public int Tracking { get; set; } + public int Solo { get; set; } + public int MusicVol { get; set; } + public int Block1 { get; set; } + public int Block2 { get; set; } + public int Block3 { get; set; } + } + + public static class SoundEntryHelper + { + public static SoundEntry ToSoundEntry(this string source) + { + var props = source.Split('\t'); + return new SoundEntry + { + Handle = props[0], + Index = Convert.ToInt32(props[1]), + FileName = props[2], + Volume = Convert.ToByte(props[3]), + GroupSize = Convert.ToInt32(props[4]), + Loop = Convert.ToInt32(props[5]) == 1, + FadeIn = Convert.ToInt32(props[6]), + FadeOut = Convert.ToInt32(props[7]), + DeferInst = Convert.ToInt32(props[8]), + StopInst = Convert.ToInt32(props[9]), + Duration = Convert.ToInt32(props[10]), + Compound = Convert.ToInt32(props[11]), + Reverb = Convert.ToInt32(props[12]) == 1, + Falloff = Convert.ToInt32(props[13]), + Cache = Convert.ToInt32(props[14]), + AsyncOnly = Convert.ToInt32(props[15]) == 1, + Priority = Convert.ToInt32(props[16]), + Stream = Convert.ToInt32(props[17]), + Stereo = Convert.ToInt32(props[18]), + Tracking = Convert.ToInt32(props[19]), + Solo = Convert.ToInt32(props[20]), + MusicVol = Convert.ToInt32(props[21]), + Block1 = Convert.ToInt32(props[22]), + Block2 = Convert.ToInt32(props[23]), + Block3 = Convert.ToInt32(props[24]), + }; + } + } +} diff --git a/OpenDiablo2.Common/OpenDiablo2.Common.csproj b/OpenDiablo2.Common/OpenDiablo2.Common.csproj new file mode 100644 index 00000000..f1b3198b --- /dev/null +++ b/OpenDiablo2.Common/OpenDiablo2.Common.csproj @@ -0,0 +1,94 @@ + + + + + Debug + AnyCPU + {B743160E-A0BB-45DC-9998-967A85E50562} + Library + Properties + OpenDiablo2.Common + OpenDiablo2.Common + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\DotNetZip.1.12.0\lib\net20\DotNetZip.dll + + + ..\packages\NetSword.Common.ICSharpCode.SharpZipLib.0.84.0\lib\ICSharpCode.SharpZipLib.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenDiablo2.Common/Properties/AssemblyInfo.cs b/OpenDiablo2.Common/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..5a64b7b6 --- /dev/null +++ b/OpenDiablo2.Common/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenDiablo2.Common")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenDiablo2.Common")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b743160e-a0bb-45dc-9998-967a85e50562")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenDiablo2.Common/packages.config b/OpenDiablo2.Common/packages.config new file mode 100644 index 00000000..72fad29a --- /dev/null +++ b/OpenDiablo2.Common/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/OpenDiablo2.Core/AutofacModule.cs b/OpenDiablo2.Core/AutofacModule.cs new file mode 100644 index 00000000..49b05724 --- /dev/null +++ b/OpenDiablo2.Core/AutofacModule.cs @@ -0,0 +1,23 @@ +using Autofac; +using OpenDiablo2.Common.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Core +{ + public sealed class AutofacModule : Module + { + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected override void Load(ContainerBuilder builder) + { + log.Info("Configuring OpenDiablo2.Core service implementations."); + + builder.RegisterType().AsImplementedInterfaces().SingleInstance(); + builder.RegisterType().As().SingleInstance(); + } + } +} diff --git a/OpenDiablo2.Core/GameEngine.cs b/OpenDiablo2.Core/GameEngine.cs new file mode 100644 index 00000000..4fd127b5 --- /dev/null +++ b/OpenDiablo2.Core/GameEngine.cs @@ -0,0 +1,97 @@ +using OpenDiablo2.Common.Interfaces; +using OpenDiablo2.Common.Models; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenDiablo2.Core +{ + public sealed class GameEngine : IGameEngine, IPaletteProvider + { + static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private readonly IMPQProvider mpqProvider; + private readonly IRenderWindow renderWindow; + private readonly Func getScene; + private IScene currentScene; + + private readonly MPQ[] MPQs; + + private Dictionary soundTable = new Dictionary(); + public Dictionary PaletteTable { get; private set; } = new Dictionary(); + private Stopwatch sw = new Stopwatch(); + + + public GameEngine(IMPQProvider mpqProvider, IRenderWindow renderWindow, Func getScene) + { + this.mpqProvider = mpqProvider; + this.renderWindow = renderWindow; + this.getScene = getScene; + + MPQs = mpqProvider.GetMPQs().ToArray(); + } + + private void LoadPalettes() + { + log.Info("Loading palettes"); + var paletteFiles = MPQs.SelectMany(x => x.Files).Where(x => x.StartsWith("data\\global\\palette\\") && x.EndsWith(".dat")); + foreach (var paletteFile in paletteFiles) + { + var paletteNameParts = paletteFile.Split('\\'); + var paletteName = paletteNameParts[paletteNameParts.Count() - 2]; + PaletteTable[paletteName] = Palette.LoadFromStream(mpqProvider.GetStream(paletteFile)); + } + } + + private void LoadSoundData() + { + log.Info("Loading sound configuration data"); + foreach (var soundDescFile in mpqProvider.GetTextFile("data\\global\\excel\\Sounds.txt")) + { + foreach (var row in soundDescFile.Skip(1).Where(x => !String.IsNullOrWhiteSpace(x))) + { + var soundEntry = row.ToSoundEntry(); + soundTable[soundEntry.Handle] = soundEntry; + } + } + } + + public void Run() + { + LoadPalettes(); + LoadSoundData(); + + currentScene = getScene("Main Menu"); + sw.Start(); + while (renderWindow.IsRunning) + { + while (sw.ElapsedMilliseconds < 16) + Thread.Sleep(1); // Oh yes we did + + var ms = sw.ElapsedMilliseconds; + + // Prevent falco-punch updates + if (ms > 1000) + { + sw.Restart(); + continue; + } + sw.Restart(); + renderWindow.Update(); + currentScene.Update(ms); + + currentScene.Render(); + } + } + + public void Dispose() + { + + } + } +} diff --git a/OpenDiablo2.Core/MPQProvider.cs b/OpenDiablo2.Core/MPQProvider.cs new file mode 100644 index 00000000..7d4f22aa --- /dev/null +++ b/OpenDiablo2.Core/MPQProvider.cs @@ -0,0 +1,40 @@ +using OpenDiablo2.Common.Interfaces; +using OpenDiablo2.Common.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Core +{ + public sealed class MPQProvider : IMPQProvider + { + private readonly GlobalConfiguration globalConfiguration; + private readonly MPQ[] mpqs; + + public MPQProvider(GlobalConfiguration globalConfiguration) + { + this.globalConfiguration = globalConfiguration; + this.mpqs = Directory + .EnumerateFiles(globalConfiguration.BaseDataPath, "*.mpq") + .Where(x => !Path.GetFileName(x).StartsWith("patch")) + .Select(file => new MPQ(file)) + .ToArray(); + } + + public IEnumerable GetMPQs() => mpqs; + + public Stream GetStream(string fileName) + => mpqs.First(x => x.Files.Any(z =>z.ToLower() == fileName.ToLower())).OpenFile(fileName); + + public IEnumerable> GetTextFile(string fileName) + { + foreach (var stream in mpqs.Where(x => x.Files.Contains(fileName)).Select(x => x.OpenFile(fileName))) + yield return new StreamReader(stream).ReadToEnd().Split('\n').Select(x => x.Trim()); + } + + + } +} diff --git a/OpenDiablo2.Core/OpenDiablo2.Core.csproj b/OpenDiablo2.Core/OpenDiablo2.Core.csproj new file mode 100644 index 00000000..9b87a6fa --- /dev/null +++ b/OpenDiablo2.Core/OpenDiablo2.Core.csproj @@ -0,0 +1,90 @@ + + + + + Debug + AnyCPU + {8FC6BF7D-835A-47C1-A6B2-125495FA0900} + Library + Properties + OpenDiablo2.Core + OpenDiablo2.Core + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\Autofac.4.8.1\lib\net45\Autofac.dll + + + ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + ..\packages\Xabe.FFmpeg.3.1.4\lib\netstandard2.0\Xabe.FFmpeg.dll + + + + + + + + + + + {b743160e-a0bb-45dc-9998-967a85e50562} + OpenDiablo2.Common + + + + + + + \ No newline at end of file diff --git a/OpenDiablo2.Core/Properties/AssemblyInfo.cs b/OpenDiablo2.Core/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..c0f14f78 --- /dev/null +++ b/OpenDiablo2.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenDiablo2.Core")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenDiablo2.Core")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8fc6bf7d-835a-47c1-a6b2-125495fa0900")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenDiablo2.Core/packages.config b/OpenDiablo2.Core/packages.config new file mode 100644 index 00000000..d6d64ebf --- /dev/null +++ b/OpenDiablo2.Core/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/OpenDiablo2.SDL2/AutofacModule.cs b/OpenDiablo2.SDL2/AutofacModule.cs new file mode 100644 index 00000000..638efc0b --- /dev/null +++ b/OpenDiablo2.SDL2/AutofacModule.cs @@ -0,0 +1,18 @@ +using Autofac; +using OpenDiablo2.Common.Interfaces; + +namespace OpenDiablo2.SDL2_ +{ + public sealed class AutofacModule : Module + { + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected override void Load(ContainerBuilder builder) + { + log.Info("Configuring OpenDiablo2.Core service implementations."); + + builder.RegisterType().AsImplementedInterfaces().SingleInstance(); + + } + } +} diff --git a/OpenDiablo2.SDL2/OpenDiablo2.SDL2.csproj b/OpenDiablo2.SDL2/OpenDiablo2.SDL2.csproj new file mode 100644 index 00000000..4724008b --- /dev/null +++ b/OpenDiablo2.SDL2/OpenDiablo2.SDL2.csproj @@ -0,0 +1,96 @@ + + + + + Debug + AnyCPU + {1F8731D5-393B-4561-9CEA-887A2F466576} + Library + Properties + OpenDiablo2.SDL2 + OpenDiablo2.SDL2 + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + true + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\Autofac.4.8.1\lib\net45\Autofac.dll + + + ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + {b743160e-a0bb-45dc-9998-967a85e50562} + OpenDiablo2.Common + + + + + PreserveNewest + + + + \ No newline at end of file diff --git a/OpenDiablo2.SDL2/Properties/AssemblyInfo.cs b/OpenDiablo2.SDL2/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..fc056aef --- /dev/null +++ b/OpenDiablo2.SDL2/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenDiablo2.SDL2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenDiablo2.SDL2")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1f8731d5-393b-4561-9cea-887a2f466576")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenDiablo2.SDL2/SDL2-CS/LPUtf8StrMarshaler.cs b/OpenDiablo2.SDL2/SDL2-CS/LPUtf8StrMarshaler.cs new file mode 100644 index 00000000..6e875e6c --- /dev/null +++ b/OpenDiablo2.SDL2/SDL2-CS/LPUtf8StrMarshaler.cs @@ -0,0 +1,106 @@ +/* SDL2# - C# Wrapper for SDL2 + * + * Copyright (c) 2013-2015 Ethan Lee. + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * Ethan "flibitijibibo" Lee + * + */ + +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace SDL2 +{ + internal unsafe class LPUtf8StrMarshaler : ICustomMarshaler + { + public const string LeaveAllocated = "LeaveAllocated"; + + private static ICustomMarshaler + _leaveAllocatedInstance = new LPUtf8StrMarshaler(true), + _defaultInstance = new LPUtf8StrMarshaler(false); + + public static ICustomMarshaler GetInstance(string cookie) + { + switch (cookie) + { + case "LeaveAllocated": + return _leaveAllocatedInstance; + default: + return _defaultInstance; + } + } + + private bool _leaveAllocated; + + public LPUtf8StrMarshaler(bool leaveAllocated) + { + _leaveAllocated = leaveAllocated; + } + + public object MarshalNativeToManaged(IntPtr pNativeData) + { + if (pNativeData == IntPtr.Zero) + return null; + var ptr = (byte*)pNativeData; + while (*ptr != 0) + { + ptr++; + } + var bytes = new byte[ptr - (byte*)pNativeData]; + Marshal.Copy(pNativeData, bytes, 0, bytes.Length); + return Encoding.UTF8.GetString(bytes); + } + + public IntPtr MarshalManagedToNative(object ManagedObj) + { + if (ManagedObj == null) + return IntPtr.Zero; + var str = ManagedObj as string; + if (str == null) + { + throw new ArgumentException("ManagedObj must be a string.", "ManagedObj"); + } + var bytes = Encoding.UTF8.GetBytes(str); + var mem = SDL.SDL_malloc((IntPtr) (bytes.Length + 1)); + Marshal.Copy(bytes, 0, mem, bytes.Length); + ((byte*)mem)[bytes.Length] = 0; + return mem; + } + + public void CleanUpManagedData(object ManagedObj) + { + } + + public void CleanUpNativeData(IntPtr pNativeData) + { + if (!_leaveAllocated) + { + SDL.SDL_free(pNativeData); + } + } + + public int GetNativeDataSize () + { + return -1; + } + } +} diff --git a/OpenDiablo2.SDL2/SDL2-CS/SDL2.cs b/OpenDiablo2.SDL2/SDL2-CS/SDL2.cs new file mode 100644 index 00000000..56fa31a5 --- /dev/null +++ b/OpenDiablo2.SDL2/SDL2-CS/SDL2.cs @@ -0,0 +1,5683 @@ +#region License +/* SDL2# - C# Wrapper for SDL2 + * + * Copyright (c) 2013-2015 Ethan Lee. + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * Ethan "flibitijibibo" Lee + * + */ +#endregion + +#region Using Statements +using System; +using System.Runtime.InteropServices; +#endregion + +namespace SDL2 +{ + /// + /// Entry point for all SDL-related (non-extension) types and methods + /// + public static class SDL + { + #region SDL2# Variables + + /// + /// Used by DllImport to load the native library. + /// + private const string nativeLibName = "SDL2.dll"; + + #endregion + + #region SDL_stdinc.h + + public static uint SDL_FOURCC(byte A, byte B, byte C, byte D) + { + return (uint) (A | (B << 8) | (C << 16) | (D << 24)); + } + + public enum SDL_bool + { + SDL_FALSE = 0, + SDL_TRUE = 1 + } + + /* malloc/free are used by the marshaler! -flibit */ + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr SDL_malloc(IntPtr size); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + internal static extern void SDL_free(IntPtr memblock); + + #endregion + + #region SDL_rwops.h + + /* Note about SDL2# and Internal RWops: + * These functions are currently not supported for public use. + * They are only meant to be used internally in functions marked with + * the phrase "THIS IS AN RWops FUNCTION!" + */ + + /// + /// Use this function to create a new SDL_RWops structure for reading from and/or writing to a named file. + /// + /// a UTF-8 string representing the filename to open + /// an ASCII string representing the mode to be used for opening the file; see Remarks for details + /// Returns a pointer to the SDL_RWops structure that is created, or NULL on failure; call SDL_GetError() for more information. + [DllImport(nativeLibName, EntryPoint = "SDL_RWFromFile", CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr INTERNAL_SDL_RWFromFile( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string file, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string mode + ); + + /* These are the public RWops functions. They should be used by + * functions marked with the phrase "THIS IS A PUBLIC RWops FUNCTION!" + */ + + /* IntPtr refers to an SDL_RWops */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_RWFromMem(byte[] mem, int size); + + #endregion + + #region SDL_main.h + + /// + /// Use this function to circumvent failure of SDL_Init() when not using SDL_main() as an entry point. + /// + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetMainReady(); + + #endregion + + #region SDL.h + + public const uint SDL_INIT_TIMER = 0x00000001; + public const uint SDL_INIT_AUDIO = 0x00000010; + public const uint SDL_INIT_VIDEO = 0x00000020; + public const uint SDL_INIT_JOYSTICK = 0x00000200; + public const uint SDL_INIT_HAPTIC = 0x00001000; + public const uint SDL_INIT_GAMECONTROLLER = 0x00002000; + public const uint SDL_INIT_NOPARACHUTE = 0x00100000; + public const uint SDL_INIT_EVERYTHING = ( + SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | + SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | + SDL_INIT_GAMECONTROLLER + ); + + /// + /// Use this function to initialize the SDL library. + /// This must be called before using any other SDL function. + /// + /// subsystem initialization flags; see Remarks for details + /// Returns 0 on success or a negative error code on failure. + /// Call for more information. + /// The Event Handling, File I/O, and Threading subsystems are initialized by default. + /// You must specifically initialize other subsystems if you use them in your application. + /// Unless the SDL_INIT_NOPARACHUTE flag is set, it will install cleanup signal handlers + /// for some commonly ignored fatal signals (like SIGSEGV). + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_Init(uint flags); + + /// + /// Use this function to initialize specific SDL subsystems. + /// + /// any of the flags used by SDL_Init(); see Remarks for details + /// Returns 0 on success or a negative error code on failure. + /// Call for more information. + /// After SDL has been initialized with you may initialize + /// uninitialized subsystems with . + /// If you want to initialize subsystems separately you would call + /// followed by with the desired subsystem flag. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_InitSubSystem(uint flags); + + /// + /// Use this function to clean up all initialized subsystems. + /// You should call it upon all exit conditions. + /// + /// You should call this function even if you have already shutdown each initialized + /// subsystem with . + /// If you start a subsystem using a call to that subsystem's init function (for example + /// ) instead of or , + /// then you must use that subsystem's quit function () to shut it down + /// before calling . + /// You can use this function with atexit() to ensure that it is run when your application is + /// shutdown, but it is not wise to do this from a library or other dynamically loaded code. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_Quit(); + + /// + /// Use this function to shut down specific SDL subsystems. + /// + /// any of the flags used by ; see Remarks for details + /// If you start a subsystem using a call to that subsystem's init function (for example + /// ) instead of or , + /// then you must use that subsystem's quit function () to shut it down + /// before calling . + /// You can use this function with atexit() to en + /// You still need to call even if you close all open subsystems with SDL_QuitSubSystem(). + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_QuitSubSystem(uint flags); + + /// + /// Use this function to return a mask of the specified subsystems which have previously been initialized. + /// + /// any of the flags used by ; see Remarks for details + /// If flags is 0 it returns a mask of all initialized subsystems, otherwise it returns the + /// initialization status of the specified subsystems. The return value does not include SDL_INIT_NOPARACHUTE. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_WasInit(uint flags); + + #endregion + + #region SDL_platform.h + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetPlatform(); + + #endregion + + #region SDL_hints.h + + public const string SDL_HINT_FRAMEBUFFER_ACCELERATION = + "SDL_FRAMEBUFFER_ACCELERATION"; + public const string SDL_HINT_RENDER_DRIVER = + "SDL_RENDER_DRIVER"; + public const string SDL_HINT_RENDER_OPENGL_SHADERS = + "SDL_RENDER_OPENGL_SHADERS"; + public const string SDL_HINT_RENDER_DIRECT3D_THREADSAFE = + "SDL_RENDER_DIRECT3D_THREADSAFE"; + public const string SDL_HINT_RENDER_VSYNC = + "SDL_RENDER_VSYNC"; + public const string SDL_HINT_VIDEO_X11_XVIDMODE = + "SDL_VIDEO_X11_XVIDMODE"; + public const string SDL_HINT_VIDEO_X11_XINERAMA = + "SDL_VIDEO_X11_XINERAMA"; + public const string SDL_HINT_VIDEO_X11_XRANDR = + "SDL_VIDEO_X11_XRANDR"; + public const string SDL_HINT_GRAB_KEYBOARD = + "SDL_GRAB_KEYBOARD"; + public const string SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS = + "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"; + public const string SDL_HINT_IDLE_TIMER_DISABLED = + "SDL_IOS_IDLE_TIMER_DISABLED"; + public const string SDL_HINT_ORIENTATIONS = + "SDL_IOS_ORIENTATIONS"; + public const string SDL_HINT_XINPUT_ENABLED = + "SDL_XINPUT_ENABLED"; + public const string SDL_HINT_GAMECONTROLLERCONFIG = + "SDL_GAMECONTROLLERCONFIG"; + public const string SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS = + "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"; + public const string SDL_HINT_ALLOW_TOPMOST = + "SDL_ALLOW_TOPMOST"; + public const string SDL_HINT_TIMER_RESOLUTION = + "SDL_TIMER_RESOLUTION"; + public const string SDL_HINT_RENDER_SCALE_QUALITY = + "SDL_RENDER_SCALE_QUALITY"; + + /* Only available in SDL 2.0.1 or higher */ + public const string SDL_HINT_VIDEO_HIGHDPI_DISABLED = + "SDL_VIDEO_HIGHDPI_DISABLED"; + + /* Only available in SDL 2.0.2 or higher */ + public const string SDL_HINT_CTRL_CLICK_EMULATE_RIGHT_CLICK = + "SDL_CTRL_CLICK_EMULATE_RIGHT_CLICK"; + public const string SDL_HINT_VIDEO_WIN_D3DCOMPILER = + "SDL_VIDEO_WIN_D3DCOMPILER"; + public const string SDL_HINT_MOUSE_RELATIVE_MODE_WARP = + "SDL_MOUSE_RELATIVE_MODE_WARP"; + public const string SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT = + "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT"; + public const string SDL_HINT_VIDEO_ALLOW_SCREENSAVER = + "SDL_VIDEO_ALLOW_SCREENSAVER"; + public const string SDL_HINT_ACCELEROMETER_AS_JOYSTICK = + "SDL_ACCELEROMETER_AS_JOYSTICK"; + public const string SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES = + "SDL_VIDEO_MAC_FULLSCREEN_SPACES"; + + public enum SDL_HintPriority + { + SDL_HINT_DEFAULT, + SDL_HINT_NORMAL, + SDL_HINT_OVERRIDE + } + + /// + /// Use this function to clear all hints. + /// + /// This function is automatically called during . + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_ClearHints(); + + /// + /// Use this function to get the value of a hint. + /// + /// the hint to query; see the list of hints on + /// CategoryHints for details + /// Returns the string value of a hint or NULL if the hint isn't set. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetHint( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string name + ); + + /// + /// Use this function to set a hint with normal priority. + /// + /// the hint to query; see the list of hints on + /// CategoryHints for details + /// the value of the hint variable + /// Returns SDL_TRUE if the hint was set, SDL_FALSE otherwise. + /// Hints will not be set if there is an existing override hint or environment + /// variable that takes precedence. You can use to set the hint with + /// override priority instead. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_SetHint( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string name, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string value + ); + + /// + /// Use this function to set a hint with a specific priority. + /// + /// the hint to query; see the list of hints on + /// CategoryHints for details + /// the value of the hint variable + /// the level for the hint + /// Returns SDL_TRUE if the hint was set, SDL_FALSE otherwise. + /// The priority controls the behavior when setting a hint that already has a value. + /// Hints will replace existing hints of their priority and lower. Environment variables are + /// considered to have override priority. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_SetHintWithPriority( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string name, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string value, + SDL_HintPriority priority + ); + + #endregion + + #region SDL_error.h + + /// + /// Use this function to clear any previous error message. + /// + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_ClearError(); + + /// + /// Use this function to retrieve a message about the last error that occurred. + /// + /// Returns a message with information about the specific error that occurred, + /// or an empty string if there hasn't been an error since the last call to . + /// Without calling , the message is only applicable when an SDL function + /// has signaled an error. You must check the return values of SDL function calls to determine + /// when to appropriately call . + /// This string is statically allocated and must not be freed by the application. + /// It is possible for multiple errors to occur before calling SDL_GetError(). Only the last error is returned. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetError(); + + /// + /// Use this function to set the SDL error string. + /// + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + /// Calling this function will replace any previous error message that was set. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetError( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + #endregion + + #region SDL_log.h + + /* Begin nameless enum SDL_LOG_CATEGORY */ + public const int SDL_LOG_CATEGORY_APPLICATION = 0; + public const int SDL_LOG_CATEGORY_ERROR = 1; + public const int SDL_LOG_CATEGORY_ASSERT = 2; + public const int SDL_LOG_CATEGORY_SYSTEM = 3; + public const int SDL_LOG_CATEGORY_AUDIO = 4; + public const int SDL_LOG_CATEGORY_VIDEO = 5; + public const int SDL_LOG_CATEGORY_RENDER = 6; + public const int SDL_LOG_CATEGORY_INPUT = 7; + public const int SDL_LOG_CATEGORY_TEST = 8; + + /* Reserved for future SDL library use */ + public const int SDL_LOG_CATEGORY_RESERVED1 = 9; + public const int SDL_LOG_CATEGORY_RESERVED2 = 10; + public const int SDL_LOG_CATEGORY_RESERVED3 = 11; + public const int SDL_LOG_CATEGORY_RESERVED4 = 12; + public const int SDL_LOG_CATEGORY_RESERVED5 = 13; + public const int SDL_LOG_CATEGORY_RESERVED6 = 14; + public const int SDL_LOG_CATEGORY_RESERVED7 = 15; + public const int SDL_LOG_CATEGORY_RESERVED8 = 16; + public const int SDL_LOG_CATEGORY_RESERVED9 = 17; + public const int SDL_LOG_CATEGORY_RESERVED10 = 18; + + /* Beyond this point is reserved for application use, e.g. + enum { + LOG_CATEGORY_AWESOME1 = SDL_LOG_CATEGORY_CUSTOM, + LOG_CATEGORY_AWESOME2, + LOG_CATEGORY_AWESOME3, + ... + }; + */ + public const int SDL_LOG_CATEGORY_CUSTOM = 19; + /* End nameless enum SDL_LOG_CATEGORY */ + + /// + /// An enumeration of the predefined log priorities. + /// + public enum SDL_LogPriority + { + SDL_LOG_PRIORITY_VERBOSE = 1, + SDL_LOG_PRIORITY_DEBUG, + SDL_LOG_PRIORITY_INFO, + SDL_LOG_PRIORITY_WARN, + SDL_LOG_PRIORITY_ERROR, + SDL_LOG_PRIORITY_CRITICAL, + SDL_NUM_LOG_PRIORITIES + } + + /// + /// Used as a callback for and + /// + /// what was passed as userdata to + /// the category of the message; see Remarks for details + /// the priority of the message; see Remarks for details + /// the message being output + /// The category can be one of SDL_LOG_CATEGORY* + /// The priority can be one of SDL_LOG_PRIORITY* + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void SDL_LogOutputFunction( + IntPtr userdata, // void* + int category, + SDL_LogPriority priority, + IntPtr message // const char* + ); + + /// + /// Use this function to log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO. + /// + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_Log( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to log a message with SDL_LOG_PRIORITY_VERBOSE. + /// + /// the category of the message; see Remarks for details + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + /// The category can be one of SDL_LOG_CATEGORY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogVerbose( + int category, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to log a message with SDL_LOG_PRIORITY_DEBUG. + /// + /// the category of the message; see Remarks for details + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + /// The category can be one of SDL_LOG_CATEGORY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogDebug( + int category, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to log a message with SDL_LOG_PRIORITY_INFO. + /// + /// the category of the message; see Remarks for details + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + /// The category can be one of SDL_LOG_CATEGORY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogInfo( + int category, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to log a message with SDL_LOG_PRIORITY_WARN. + /// + /// the category of the message; see Remarks for details + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + /// The category can be one of SDL_LOG_CATEGORY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogWarn( + int category, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to log a message with SDL_LOG_PRIORITY_ERROR. + /// + /// the category of the message; see Remarks for details + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + /// The category can be one of SDL_LOG_CATEGORY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogError( + int category, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to log a message with SDL_LOG_PRIORITY_CRITICAL. + /// + /// the category of the message; see Remarks for details + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + /// The category can be one of SDL_LOG_CATEGORY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogCritical( + int category, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to log a message with the specified category and priority. + /// + /// the category of the message; see Remarks for details + /// the priority of the message; see Remarks for details + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + /// The category can be one of SDL_LOG_CATEGORY* + /// The priority can be one of SDL_LOG_PRIORITY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogMessage( + int category, + SDL_LogPriority priority, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to log a message with the specified category and priority. + /// This version of uses a stdarg variadic argument list. + /// + /// the category of the message; see Remarks for details + /// the priority of the message; see Remarks for details + /// a printf() style message format string + /// additional parameters matching % tokens in the fmt string, if any + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogMessageV( + int category, + SDL_LogPriority priority, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string fmt, + __arglist + ); + + /// + /// Use this function to get the priority of a particular log category. + /// + /// the category to query; see Remarks for details + /// Returns the for the requested category; see Remarks for details. + /// The category can be one of SDL_LOG_CATEGORY* + /// The returned priority will be one of SDL_LOG_PRIORITY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_LogPriority SDL_LogGetPriority( + int category + ); + + /// + /// Use this function to set the priority of a particular log category. + /// + /// the category to query; see Remarks for details + /// the of the message; see Remarks for details + /// The category can be one of SDL_LOG_CATEGORY* + /// The priority can be one of SDL_LOG_PRIORITY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogSetPriority( + int category, + SDL_LogPriority priority + ); + + /// + /// Use this function to set the priority of all log categories. + /// + /// the of the message; see Remarks for details + /// The priority can be one of SDL_LOG_PRIORITY* + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogSetAllPriority( + SDL_LogPriority priority + ); + + /// + /// Use this function to reset all priorities to default. + /// + /// This is called in . + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogResetPriorities(); + + /// + /// Use this function to get the current log output function. + /// + /// a pointer filled in with the current log callback; see Remarks for details + /// a pointer filled in with the pointer that is passed to callback (refers to void*) + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogGetOutputFunction( + out SDL_LogOutputFunction callback, + out IntPtr userdata + ); + + /* userdata refers to a void* */ + /// + /// Use this function to replace the default log output function with one of your own. + /// + /// the function to call instead of the default; see Remarks for details + /// a pointer that is passed to callback (refers to void*) + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LogSetOutputFunction( + SDL_LogOutputFunction callback, + IntPtr userdata + ); + + #endregion + + #region SDL_messagebox.h + + [Flags] + public enum SDL_MessageBoxFlags : uint + { + SDL_MESSAGEBOX_ERROR = 0x00000010, + SDL_MESSAGEBOX_WARNING = 0x00000020, + SDL_MESSAGEBOX_INFORMATION = 0x00000040 + } + + [Flags] + public enum SDL_MessageBoxButtonFlags : uint + { + SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 0x00000001, + SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 0x00000002 + } + + [StructLayout(LayoutKind.Sequential)] + private struct INTERNAL_SDL_MessageBoxButtonData + { + public SDL_MessageBoxButtonFlags flags; + public int buttonid; + public IntPtr text; /* The UTF-8 button text */ + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_MessageBoxButtonData + { + public SDL_MessageBoxButtonFlags flags; + public int buttonid; + public string text; /* The UTF-8 button text */ + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_MessageBoxColor + { + public byte r, g, b; + } + + public enum SDL_MessageBoxColorType + { + SDL_MESSAGEBOX_COLOR_BACKGROUND, + SDL_MESSAGEBOX_COLOR_TEXT, + SDL_MESSAGEBOX_COLOR_BUTTON_BORDER, + SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND, + SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED, + SDL_MESSAGEBOX_COLOR_MAX + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_MessageBoxColorScheme + { + [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = (int)SDL_MessageBoxColorType.SDL_MESSAGEBOX_COLOR_MAX)] + public SDL_MessageBoxColor[] colors; + } + + [StructLayout(LayoutKind.Sequential)] + private struct INTERNAL_SDL_MessageBoxData + { + public SDL_MessageBoxFlags flags; + public IntPtr window; /* Parent window, can be NULL */ + public IntPtr title; /* UTF-8 title */ + public IntPtr message; /* UTF-8 message text */ + public int numbuttons; + public IntPtr buttons; + public IntPtr colorScheme; /* Can be NULL to use system settings */ + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_MessageBoxData + { + public SDL_MessageBoxFlags flags; + public IntPtr window; /* Parent window, can be NULL */ + public string title; /* UTF-8 title */ + public string message; /* UTF-8 message text */ + public int numbuttons; + public SDL_MessageBoxButtonData[] buttons; + public SDL_MessageBoxColorScheme? colorScheme; /* Can be NULL to use system settings */ + } + + /// + /// + /// + /// + /// + /// + [DllImport(nativeLibName, EntryPoint = "SDL_ShowMessageBox", CallingConvention = CallingConvention.Cdecl)] + private static extern int INTERNAL_SDL_ShowMessageBox([In()] ref INTERNAL_SDL_MessageBoxData messageboxdata, out int buttonid); + + /// + /// + /// + /// + /// + /// + public static unsafe int SDL_ShowMessageBox([In()] ref SDL_MessageBoxData messageboxdata, out int buttonid) + { + var utf8 = LPUtf8StrMarshaler.GetInstance(null); + + var data = new INTERNAL_SDL_MessageBoxData() + { + flags = messageboxdata.flags, + window = messageboxdata.window, + title = utf8.MarshalManagedToNative(messageboxdata.title), + message = utf8.MarshalManagedToNative(messageboxdata.message), + numbuttons = messageboxdata.numbuttons, + }; + + var buttons = new INTERNAL_SDL_MessageBoxButtonData[messageboxdata.numbuttons]; + for (int i = 0; i < messageboxdata.numbuttons; i++) + { + buttons[i] = new INTERNAL_SDL_MessageBoxButtonData() + { + flags = messageboxdata.buttons[i].flags, + buttonid = messageboxdata.buttons[i].buttonid, + text = utf8.MarshalManagedToNative(messageboxdata.buttons[i].text), + }; + } + + if (messageboxdata.colorScheme != null) + { + data.colorScheme = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SDL_MessageBoxColorScheme))); + Marshal.StructureToPtr(messageboxdata.colorScheme.Value, data.colorScheme, false); + } + + int result; + fixed (INTERNAL_SDL_MessageBoxButtonData* buttonsPtr = &buttons[0]) + { + data.buttons = (IntPtr)buttonsPtr; + result = INTERNAL_SDL_ShowMessageBox(ref data, out buttonid); + } + + Marshal.FreeHGlobal(data.colorScheme); + for (int i = 0; i < messageboxdata.numbuttons; i++) + { + utf8.CleanUpNativeData(buttons[i].text); + } + utf8.CleanUpNativeData(data.message); + utf8.CleanUpNativeData(data.title); + + return result; + } + + /// + /// Use this function to display a simple message box. + /// + /// An ; see Remarks for details; + /// UTF-8 title text + /// UTF-8 message text + /// the parent window, or NULL for no parent (refers to a + /// 0 on success or a negative error code on failure; call SDL_GetError() for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_ShowSimpleMessageBox( + SDL_MessageBoxFlags flags, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string title, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string message, + IntPtr window + ); + + #endregion + + #region SDL_version.h, SDL_revision.h + + /* Similar to the headers, this is the version we're expecting to be + * running with. You will likely want to check this somewhere in your + * program! + */ + public const int SDL_MAJOR_VERSION = 2; + public const int SDL_MINOR_VERSION = 0; + public const int SDL_PATCHLEVEL = 3; + + public static readonly int SDL_COMPILEDVERSION = SDL_VERSIONNUM( + SDL_MAJOR_VERSION, + SDL_MINOR_VERSION, + SDL_PATCHLEVEL + ); + + /// + /// A structure that contains information about the version of SDL in use. + /// + /// Represents the library's version as three levels: + /// major revision (increments with massive changes, additions, and enhancements) + /// minor revision (increments with backwards-compatible changes to the major revision), and + /// patchlevel (increments with fixes to the minor revision) + /// can be used to populate this structure with information + [StructLayout(LayoutKind.Sequential)] + public struct SDL_version + { + public byte major; + public byte minor; + public byte patch; + } + + /// + /// Use this macro to determine the SDL version your program was compiled against. + /// + /// an structure to initialize + public static void SDL_VERSION(out SDL_version x) + { + x.major = SDL_MAJOR_VERSION; + x.minor = SDL_MINOR_VERSION; + x.patch = SDL_PATCHLEVEL; + } + + /// + /// Use this macro to convert separate version components into a single numeric value. + /// + /// major version; reported in thousands place + /// minor version; reported in hundreds place + /// update version (patchlevel); reported in tens and ones places + /// + /// This assumes that there will never be more than 100 patchlevels. + /// Example: SDL_VERSIONNUM(1,2,3) -> (1203) + public static int SDL_VERSIONNUM(int X, int Y, int Z) + { + return (X * 1000) + (Y * 100) + Z; + } + + /// + /// Use this macro to determine whether the SDL version compiled against is at least as new as the specified version. + /// + /// major version + /// minor version + /// update version (patchlevel) + /// This macro will evaluate to true if compiled with SDL version at least X.Y.Z. + public static bool SDL_VERSION_ATLEAST(int X, int Y, int Z) + { + return (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)); + } + + /// + /// Use this function to get the version of SDL that is linked against your program. + /// + /// the structure that contains the version information + /// This function may be called safely at any time, even before SDL_Init(). + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GetVersion(out SDL_version ver); + + /// + /// Use this function to get the code revision of SDL that is linked against your program. + /// + /// Returns an arbitrary string, uniquely identifying the exact revision + /// of the SDL library in use. + /// The revision is a string including sequential revision number that is + /// incremented with each commit, and a hash of the last code change. + /// Example: hg-5344:94189aa89b54 + /// This value is the revision of the code you are linked with and may be + /// different from the code you are compiling with, which is found in the constant SDL_REVISION. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetRevision(); + + /// + /// Use this function to get the revision number of SDL that is linked against your program. + /// + /// Returns a number uniquely identifying the exact revision of the SDL library in use. + /// This is an incrementing number based on commits to hg.libsdl.org. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetRevisionNumber(); + + #endregion + + #region SDL_video.h + + /* Actually, this is from SDL_blendmode.h */ + /// + /// An enumeration of blend modes used in SDL_RenderCopy() and drawing operations. + /// + [Flags] + public enum SDL_BlendMode + { + SDL_BLENDMODE_NONE = 0x00000000, + SDL_BLENDMODE_BLEND = 0x00000001, + SDL_BLENDMODE_ADD = 0x00000002, + SDL_BLENDMODE_MOD = 0x00000004 + } + + /// + /// An enumeration of OpenGL configuration attributes. + /// + public enum SDL_GLattr + { + SDL_GL_RED_SIZE, + SDL_GL_GREEN_SIZE, + SDL_GL_BLUE_SIZE, + SDL_GL_ALPHA_SIZE, + SDL_GL_BUFFER_SIZE, + SDL_GL_DOUBLEBUFFER, + SDL_GL_DEPTH_SIZE, + SDL_GL_STENCIL_SIZE, + SDL_GL_ACCUM_RED_SIZE, + SDL_GL_ACCUM_GREEN_SIZE, + SDL_GL_ACCUM_BLUE_SIZE, + SDL_GL_ACCUM_ALPHA_SIZE, + SDL_GL_STEREO, + SDL_GL_MULTISAMPLEBUFFERS, + SDL_GL_MULTISAMPLESAMPLES, + SDL_GL_ACCELERATED_VISUAL, + SDL_GL_RETAINED_BACKING, + SDL_GL_CONTEXT_MAJOR_VERSION, + SDL_GL_CONTEXT_MINOR_VERSION, + SDL_GL_CONTEXT_EGL, + SDL_GL_CONTEXT_FLAGS, + SDL_GL_CONTEXT_PROFILE_MASK, + SDL_GL_SHARE_WITH_CURRENT_CONTEXT, + SDL_GL_FRAMEBUFFER_SRGB_CAPABLE + } + + /// + /// An enumeration of OpenGL profiles. + /// + [Flags] + public enum SDL_GLprofile + { + SDL_GL_CONTEXT_PROFILE_CORE = 0x0001, + SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002, + SDL_GL_CONTEXT_PROFILE_ES = 0x0004 + } + + /// + /// This enumeration is used in conjunction with SDL_GL_SetAttribute + /// and SDL_GL_CONTEXT_FLAGS. Multiple flags can be OR'd together. + /// + [Flags] + public enum SDL_GLcontext + { + SDL_GL_CONTEXT_DEBUG_FLAG = 0x0001, + SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002, + SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG = 0x0004, + SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008 + } + + /// + /// An enumeration of window events. + /// + public enum SDL_WindowEventID : byte + { + SDL_WINDOWEVENT_NONE, + SDL_WINDOWEVENT_SHOWN, + SDL_WINDOWEVENT_HIDDEN, + SDL_WINDOWEVENT_EXPOSED, + SDL_WINDOWEVENT_MOVED, + SDL_WINDOWEVENT_RESIZED, + SDL_WINDOWEVENT_SIZE_CHANGED, + SDL_WINDOWEVENT_MINIMIZED, + SDL_WINDOWEVENT_MAXIMIZED, + SDL_WINDOWEVENT_RESTORED, + SDL_WINDOWEVENT_ENTER, + SDL_WINDOWEVENT_LEAVE, + SDL_WINDOWEVENT_FOCUS_GAINED, + SDL_WINDOWEVENT_FOCUS_LOST, + SDL_WINDOWEVENT_CLOSE, + } + + /// + /// An enumeration of window states. + /// + [Flags] + public enum SDL_WindowFlags : uint + { + SDL_WINDOW_FULLSCREEN = 0x00000001, + SDL_WINDOW_OPENGL = 0x00000002, + SDL_WINDOW_SHOWN = 0x00000004, + SDL_WINDOW_HIDDEN = 0x00000008, + SDL_WINDOW_BORDERLESS = 0x00000010, + SDL_WINDOW_RESIZABLE = 0x00000020, + SDL_WINDOW_MINIMIZED = 0x00000040, + SDL_WINDOW_MAXIMIZED = 0x00000080, + SDL_WINDOW_INPUT_GRABBED = 0x00000100, + SDL_WINDOW_INPUT_FOCUS = 0x00000200, + SDL_WINDOW_MOUSE_FOCUS = 0x00000400, + SDL_WINDOW_FULLSCREEN_DESKTOP = + (SDL_WINDOW_FULLSCREEN | 0x00001000), + SDL_WINDOW_FOREIGN = 0x00000800, + SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000 /* Only available in 2.0.1 */ + } + + public const int SDL_WINDOWPOS_UNDEFINED_MASK = 0x1FFF0000; + public const int SDL_WINDOWPOS_CENTERED_MASK = 0x2FFF0000; + public const int SDL_WINDOWPOS_UNDEFINED = 0x1FFF0000; + public const int SDL_WINDOWPOS_CENTERED = 0x2FFF0000; + + public static int SDL_WINDOWPOS_UNDEFINED_DISPLAY(int X) + { + return (SDL_WINDOWPOS_UNDEFINED_MASK | X); + } + + public static bool SDL_WINDOWPOS_ISUNDEFINED(int X) + { + return (X & 0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK; + } + + public static int SDL_WINDOWPOS_CENTERED_DISPLAY(int X) + { + return (SDL_WINDOWPOS_CENTERED_MASK | X); + } + + public static bool SDL_WINDOWPOS_ISCENTERED(int X) + { + return (X & 0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK; + } + + /// + /// A structure that describes a display mode. + /// + [StructLayout(LayoutKind.Sequential)] + public struct SDL_DisplayMode + { + public uint format; + public int w; + public int h; + public int refresh_rate; + public IntPtr driverdata; // void* + } + + /// + /// Use this function to create a window with the specified position, dimensions, and flags. + /// + /// the title of the window, in UTF-8 encoding + /// the x position of the window, SDL_WINDOWPOS_CENTERED, or SDL_WINDOWPOS_UNDEFINED + /// the y position of the window, SDL_WINDOWPOS_CENTERED, or SDL_WINDOWPOS_UNDEFINED + /// the width of the window + /// the height of the window + /// 0, or one or more OR'd together; + /// see Remarks for details + /// Returns the window that was created or NULL on failure; call + /// for more information. (refers to an ) + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateWindow( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string title, + int x, + int y, + int w, + int h, + SDL_WindowFlags flags + ); + + /// + /// Use this function to create a window and default renderer. + /// + /// The width of the window + /// The height of the window + /// The flags used to create the window (see ) + /// A pointer filled with the window, or NULL on error () + /// A pointer filled with the renderer, or NULL on error + /// Returns 0 on success, or -1 on error; call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_CreateWindowAndRenderer( + int width, + int height, + SDL_WindowFlags window_flags, + out IntPtr window, + out IntPtr renderer + ); + + /// + /// Use this function to create an SDL window from an existing native window. + /// + /// a pointer to driver-dependent window creation data, typically your native window cast to a void* + /// Returns the window () that was created or NULL on failure; + /// call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateWindowFrom(IntPtr data); + + /// + /// Use this function to destroy a window. + /// + /// the window to destroy () + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_DestroyWindow(IntPtr window); + + /// + /// Use this function to prevent the screen from being blanked by a screen saver. + /// + /// If you disable the screensaver, it is automatically re-enabled when SDL quits. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_DisableScreenSaver(); + + /// + /// Use this function to allow the screen to be blanked by a screen saver. + /// + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_EnableScreenSaver(); + + /* IntPtr refers to an SDL_DisplayMode. Just use closest. */ + /// + /// Use this function to get the closest match to the requested display mode. + /// + /// the index of the display to query + /// an structure containing the desired display mode + /// an structure filled in with + /// the closest match of the available display modes + /// Returns the passed in value closest or NULL if no matching video mode was available; + /// (refers to a ) + /// call for more information. + /// The available display modes are scanned and closest is filled in with the closest mode + /// matching the requested mode and returned. The mode format and refresh rate default to the desktop + /// mode if they are set to 0. The modes are scanned with size being first priority, format being + /// second priority, and finally checking the refresh rate. If all the available modes are too small, + /// then NULL is returned. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetClosestDisplayMode( + int displayIndex, + ref SDL_DisplayMode mode, + out SDL_DisplayMode closest + ); + + /// + /// Use this function to get information about the current display mode. + /// + /// the index of the display to query + /// an structure filled in with the current display mode + /// Returns 0 on success or a negative error code on failure; + /// call for more information. + /// There's a difference between this function and when SDL + /// runs fullscreen and has changed the resolution. In that case this function will return the + /// current display mode, and not the previous native display mode. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetCurrentDisplayMode( + int displayIndex, + out SDL_DisplayMode mode + ); + + /// + /// Use this function to return the name of the currently initialized video driver. + /// + /// Returns the name of the current video driver or NULL if no driver has been initialized. + /// There's a difference between this function and when SDL + /// runs fullscreen and has changed the resolution. In that case this function will return the + /// previous native display mode, and not the current display mode. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetCurrentVideoDriver(); + + /// + /// Use this function to get information about the desktop display mode. + /// + /// the index of the display to query + /// an structure filled in with the current display mode + /// Returns 0 on success or a negative error code on failure; + /// call for more information. + /// There's a difference between this function and when SDL + /// runs fullscreen and has changed the resolution. In that case this function will return the + /// previous native display mode, and not the current display mode. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetDesktopDisplayMode( + int displayIndex, + out SDL_DisplayMode mode + ); + + /// + /// Use this function to get the desktop area represented by a display, with the primary display located at 0,0. + /// + /// the index of the display to query + /// the structure filled in with the display bounds + /// Returns 0 on success or a negative error code on failure; + /// call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetDisplayBounds( + int displayIndex, + out SDL_Rect rect + ); + + /// + /// Use this function to get information about a specific display mode. + /// + /// the index of the display to query + /// the index of the display mode to query + /// an structure filled in with the mode at modeIndex + /// Returns 0 on success or a negative error code on failure; + /// call for more information. + /// The display modes are sorted in this priority: + /// bits per pixel -> more colors to fewer colors + /// width -> largest to smallest + /// height -> largest to smallest + /// refresh rate -> highest to lowest + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetDisplayMode( + int displayIndex, + int modeIndex, + out SDL_DisplayMode mode + ); + + /// + /// Use this function to return the number of available display modes. + /// + /// the index of the display to query + /// Returns a number >= 1 on success or a negative error code on failure; + /// call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetNumDisplayModes( + int displayIndex + ); + + /// + /// Use this function to return the number of available video displays. + /// + /// Returns a number >= 1 or a negative error code on failure; + /// call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetNumVideoDisplays(); + + /// + /// Use this function to get the number of video drivers compiled into SDL. + /// + /// Returns a number >= 1 on success or a negative error code on failure; + /// call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetNumVideoDrivers(); + + /// + /// Use this function to get the name of a built in video driver. + /// + /// the index of a video driver + /// Returns the name of the video driver with the given index. + /// The video drivers are presented in the order in which they are normally checked during initialization. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetVideoDriver( + int index + ); + + /// + /// Use this function to get the brightness (gamma correction) for a window. + /// + /// the window to query () + /// Returns the brightness for the window where 0.0 is completely dark and 1.0 is normal brightness. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern float SDL_GetWindowBrightness( + IntPtr window + ); + + /// + /// Use this function to retrieve the data pointer associated with a window. + /// + /// the window to query () + /// the name of the pointer + /// Returns the value associated with name. (void*) + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetWindowData( + IntPtr window, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string name + ); + + /// + /// Use this function to get the index of the display associated with a window. + /// + /// the window to query () + /// Returns the index of the display containing the center of the window + /// on success or a negative error code on failure; + /// call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetWindowDisplayIndex( + IntPtr window + ); + + /// + /// Use this function to fill in information about the display mode to use when a window is visible at fullscreen. + /// + /// the window to query () + /// an structure filled in with the fullscreen display mode + /// Returns 0 on success or a negative error code on failure; + /// call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetWindowDisplayMode( + IntPtr window, + out SDL_DisplayMode mode + ); + + /// + /// Use this function to get the window flags. + /// + /// the window to query () + /// Returns a mask of the associated with window; see Remarks for details. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_GetWindowFlags(IntPtr window); + + /// + /// Use this function to get a window from a stored ID. + /// + /// the ID of the window + /// Returns the window associated with id or NULL if it doesn't exist (); + /// call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetWindowFromID(uint id); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetWindowGammaRamp( + IntPtr window, + [Out()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2, SizeConst = 256)] + ushort[] red, + [Out()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2, SizeConst = 256)] + ushort[] green, + [Out()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2, SizeConst = 256)] + ushort[] blue + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_GetWindowGrab(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_GetWindowID(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_GetWindowPixelFormat( + IntPtr window + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GetWindowMaximumSize( + IntPtr window, + out int max_w, + out int max_h + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GetWindowMinimumSize( + IntPtr window, + out int min_w, + out int min_h + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GetWindowPosition( + IntPtr window, + out int x, + out int y + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GetWindowSize( + IntPtr window, + out int w, + out int h + ); + + /* IntPtr refers to an SDL_Surface*, window to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetWindowSurface(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetWindowTitle( + IntPtr window + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GL_BindTexture( + IntPtr texture, + out float texw, + out float texh + ); + + /* IntPtr and window refer to an SDL_GLContext and SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GL_CreateContext(IntPtr window); + + /* context refers to an SDL_GLContext */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GL_DeleteContext(IntPtr context); + + /* IntPtr refers to a function pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GL_GetProcAddress( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string proc + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_GL_ExtensionSupported( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string extension + ); + + /* Only available in SDL 2.0.2 or higher */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GL_ResetAttributes(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GL_GetAttribute( + SDL_GLattr attr, + out int value + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GL_GetSwapInterval(); + + /* window and context refer to an SDL_Window* and SDL_GLContext */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GL_MakeCurrent( + IntPtr window, + IntPtr context + ); + + /* IntPtr refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GL_GetCurrentWindow(); + + /* IntPtr refers to an SDL_Context */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GL_GetCurrentContext(); + + /* window refers to an SDL_Window*, This function is only available in SDL 2.0.1 */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GL_GetDrawableSize( + IntPtr window, + out int w, + out int h + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GL_SetAttribute( + SDL_GLattr attr, + int value + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GL_SetSwapInterval(int interval); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GL_SwapWindow(IntPtr window); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GL_UnbindTexture(IntPtr texture); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_HideWindow(IntPtr window); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_IsScreenSaverEnabled(); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_MaximizeWindow(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_MinimizeWindow(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_RaiseWindow(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_RestoreWindow(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetWindowBrightness( + IntPtr window, + float brightness + ); + + /* IntPtr and userdata are void*, window is an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_SetWindowData( + IntPtr window, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string name, + IntPtr userdata + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetWindowDisplayMode( + IntPtr window, + ref SDL_DisplayMode mode + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetWindowFullscreen( + IntPtr window, + uint flags + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetWindowGammaRamp( + IntPtr window, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2, SizeConst = 256)] + ushort[] red, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2, SizeConst = 256)] + ushort[] green, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2, SizeConst = 256)] + ushort[] blue + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetWindowGrab( + IntPtr window, + SDL_bool grabbed + ); + + /* window refers to an SDL_Window*, icon to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetWindowIcon( + IntPtr window, + IntPtr icon + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetWindowMaximumSize( + IntPtr window, + int max_w, + int max_h + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetWindowMinimumSize( + IntPtr window, + int min_w, + int min_h + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetWindowPosition( + IntPtr window, + int x, + int y + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetWindowSize( + IntPtr window, + int w, + int h + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetWindowBordered( + IntPtr window, + SDL_bool bordered + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetWindowTitle( + IntPtr window, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string title + ); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_ShowWindow(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_UpdateWindowSurface(IntPtr window); + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_UpdateWindowSurfaceRects( + IntPtr window, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] + SDL_Rect[] rects, + int numrects + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_VideoInit( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string driver_name + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_VideoQuit(); + + #endregion + + #region SDL_render.h + + [Flags] + public enum SDL_RendererFlags : uint + { + SDL_RENDERER_SOFTWARE = 0x00000001, + SDL_RENDERER_ACCELERATED = 0x00000002, + SDL_RENDERER_PRESENTVSYNC = 0x00000004, + SDL_RENDERER_TARGETTEXTURE = 0x00000008 + } + + [Flags] + public enum SDL_RendererFlip + { + SDL_FLIP_NONE = 0x00000000, + SDL_FLIP_HORIZONTAL = 0x00000001, + SDL_FLIP_VERTICAL = 0x00000002 + } + + public enum SDL_TextureAccess + { + SDL_TEXTUREACCESS_STATIC, + SDL_TEXTUREACCESS_STREAMING, + SDL_TEXTUREACCESS_TARGET + } + + [Flags] + public enum SDL_TextureModulate + { + SDL_TEXTUREMODULATE_NONE = 0x00000000, + SDL_TEXTUREMODULATE_HORIZONTAL = 0x00000001, + SDL_TEXTUREMODULATE_VERTICAL = 0x00000002 + } + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct SDL_RendererInfo + { + public IntPtr name; // const char* + public uint flags; + public uint num_texture_formats; + public fixed uint texture_formats[16]; + public int max_texture_width; + public int max_texture_height; + } + + /* IntPtr refers to an SDL_Renderer*, window to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateRenderer( + IntPtr window, + int index, + SDL_RendererFlags flags + ); + + /* IntPtr refers to an SDL_Renderer*, surface to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateSoftwareRenderer(IntPtr surface); + + /* IntPtr refers to an SDL_Texture*, renderer to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateTexture( + IntPtr renderer, + uint format, + int access, + int w, + int h + ); + + /* IntPtr refers to an SDL_Texture* + * renderer refers to an SDL_Renderer* + * surface refers to an SDL_Surface* + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateTextureFromSurface( + IntPtr renderer, + IntPtr surface + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_DestroyRenderer(IntPtr renderer); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_DestroyTexture(IntPtr texture); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetNumRenderDrivers(); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetRenderDrawBlendMode( + IntPtr renderer, + out SDL_BlendMode blendMode + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetRenderDrawColor( + IntPtr renderer, + out byte r, + out byte g, + out byte b, + out byte a + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetRenderDriverInfo( + int index, + out SDL_RendererInfo info + ); + + /* IntPtr refers to an SDL_Renderer*, window to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetRenderer(IntPtr window); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetRendererInfo( + IntPtr renderer, + out SDL_RendererInfo info + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetRendererOutputSize( + IntPtr renderer, + out int w, + out int h + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetTextureAlphaMod( + IntPtr texture, + out byte alpha + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetTextureBlendMode( + IntPtr texture, + out SDL_BlendMode blendMode + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetTextureColorMod( + IntPtr texture, + out byte r, + out byte g, + out byte b + ); + + /// + /// Use this function to lock a portion of the texture for write-only pixel access. + /// + /// the texture to lock for access, which was created with + /// SDL_TEXTUREACCESS_STREAMING (refers to a SDL_Texture*) + /// an SDL_Rect structure representing the area to lock for access; + /// NULL to lock the entire texture + /// this is filled in with a pointer to the locked pixels, appropriately + /// offset by the locked area (refers to a void*) + /// this is filled in with the pitch of the locked pixels + /// Returns 0 on success or a negative error code if the texture is not valid or + /// was not created with SDL_TEXTUREACCESS_STREAMING; call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_LockTexture( + IntPtr texture, + ref SDL_Rect rect, + out IntPtr pixels, + out int pitch + ); + + /// + /// Use this function to lock a portion of the texture for write-only pixel access. This overload + /// allows for passing an IntPtr.Zero (null) rect value to lock the entire texture. + /// + /// the texture to lock for access, which was created with + /// SDL_TEXTUREACCESS_STREAMING (refers to a SDL_Texture*) + /// an SDL_Rect structure representing the area to lock for access; + /// NULL to lock the entire texture + /// this is filled in with a pointer to the locked pixels, appropriately + /// offset by the locked area (refers to a void*) + /// this is filled in with the pitch of the locked pixels + /// Returns 0 on success or a negative error code if the texture is not valid or + /// was not created with SDL_TEXTUREACCESS_STREAMING; call for more information. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_LockTexture( + IntPtr texture, + IntPtr rect, + out IntPtr pixels, + out int pitch + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_QueryTexture( + IntPtr texture, + out uint format, + out int access, + out int w, + out int h + ); + + /* texture refers to an SDL_Texture, pixels to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_QueryTexturePixels( + IntPtr texture, + out IntPtr pixels, + out int pitch + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderClear(IntPtr renderer); + + /* renderer refers to an SDL_Renderer*, texture to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderCopy( + IntPtr renderer, + IntPtr texture, + ref SDL_Rect srcrect, + ref SDL_Rect dstrect + ); + + /* renderer refers to an SDL_Renderer*, texture to an SDL_Texture*. + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for srcrect. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderCopy( + IntPtr renderer, + IntPtr texture, + IntPtr srcrect, + ref SDL_Rect dstrect + ); + + /* renderer refers to an SDL_Renderer*, texture to an SDL_Texture*. + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for dstrect. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderCopy( + IntPtr renderer, + IntPtr texture, + ref SDL_Rect srcrect, + IntPtr dstrect + ); + + /* renderer refers to an SDL_Renderer*, texture to an SDL_Texture*. + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for both SDL_Rects. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderCopy( + IntPtr renderer, + IntPtr texture, + IntPtr srcrect, + IntPtr dstrect + ); + + /* renderer refers to an SDL_Renderer*, texture to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderCopyEx( + IntPtr renderer, + IntPtr texture, + ref SDL_Rect srcrect, + ref SDL_Rect dstrect, + double angle, + ref SDL_Point center, + SDL_RendererFlip flip + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderDrawLine( + IntPtr renderer, + int x1, + int y1, + int x2, + int y2 + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderDrawLines( + IntPtr renderer, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] + SDL_Point[] points, + int count + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderDrawPoint( + IntPtr renderer, + int x, + int y + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderDrawPoints( + IntPtr renderer, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] + SDL_Point[] points, + int count + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderDrawRect( + IntPtr renderer, + ref SDL_Rect rect + ); + + /* renderer refers to an SDL_Renderer*, rect to an SDL_Rect*. + * This overload allows for IntPtr.Zero (null) to be passed for rect. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderDrawRect( + IntPtr renderer, + IntPtr rect + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderDrawRects( + IntPtr renderer, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] + SDL_Rect[] rects, + int count + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderFillRect( + IntPtr renderer, + ref SDL_Rect rect + ); + + /* renderer refers to an SDL_Renderer*, rect to an SDL_Rect*. + * This overload allows for IntPtr.Zero (null) to be passed for rect. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderFillRect( + IntPtr renderer, + IntPtr rect + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderFillRects( + IntPtr renderer, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] + SDL_Rect[] rects, + int count + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_RenderGetClipRect( + IntPtr renderer, + out SDL_Rect rect + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_RenderGetLogicalSize( + IntPtr renderer, + out int w, + out int h + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_RenderGetScale( + IntPtr renderer, + out float scaleX, + out float scaleY + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderGetViewport( + IntPtr renderer, + out SDL_Rect rect + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_RenderPresent(IntPtr renderer); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderReadPixels( + IntPtr renderer, + ref SDL_Rect rect, + uint format, + IntPtr pixels, + int pitch + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderSetClipRect( + IntPtr renderer, + ref SDL_Rect rect + ); + + /* renderer refers to an SDL_Renderer* + * This overload allows for IntPtr.Zero (null) to be passed for rect. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderSetClipRect( + IntPtr renderer, + IntPtr rect + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderSetLogicalSize( + IntPtr renderer, + int w, + int h + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderSetScale( + IntPtr renderer, + float scaleX, + float scaleY + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_RenderSetViewport( + IntPtr renderer, + ref SDL_Rect rect + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetRenderDrawBlendMode( + IntPtr renderer, + SDL_BlendMode blendMode + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetRenderDrawColor( + IntPtr renderer, + byte r, + byte g, + byte b, + byte a + ); + + /* renderer refers to an SDL_Renderer*, texture to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetRenderTarget( + IntPtr renderer, + IntPtr texture + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetTextureAlphaMod( + IntPtr texture, + byte alpha + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetTextureBlendMode( + IntPtr texture, + SDL_BlendMode blendMode + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetTextureColorMod( + IntPtr texture, + byte r, + byte g, + byte b + ); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_UnlockTexture(IntPtr texture); + + /* texture refers to an SDL_Texture* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_UpdateTexture( + IntPtr texture, + ref SDL_Rect rect, + IntPtr pixels, + int pitch + ); + + /* renderer refers to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_RenderTargetSupported( + IntPtr renderer + ); + + /* IntPtr refers to an SDL_Texture*, renderer to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetRenderTarget(IntPtr renderer); + + #endregion + + #region SDL_pixels.h + + public static uint SDL_DEFINE_PIXELFOURCC(byte A, byte B, byte C, byte D) + { + return SDL_FOURCC(A, B, C, D); + } + + public static uint SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM type, + SDL_PIXELORDER_ENUM order, + SDL_PACKEDLAYOUT_ENUM layout, + byte bits, + byte bytes + ) { + return (uint) ( + (1 << 28) | + (((byte) type) << 24) | + (((byte) order) << 20) | + (((byte) layout) << 16) | + (bits << 8) | + (bytes) + ); + } + + public static byte SDL_PIXELFLAG(uint X) + { + return (byte) ((X >> 28) & 0x0F); + } + + public static byte SDL_PIXELTYPE(uint X) + { + return (byte) ((X >> 24) & 0x0F); + } + + public static byte SDL_PIXELORDER(uint X) + { + return (byte) ((X >> 20) & 0x0F); + } + + public static byte SDL_PIXELLAYOUT(uint X) + { + return (byte) ((X >> 16) & 0x0F); + } + + public static byte SDL_BITSPERPIXEL(uint X) + { + return (byte) ((X >> 8) & 0x0F); + } + + public static byte SDL_BYTESPERPIXEL(uint X) + { + if (SDL_ISPIXELFORMAT_FOURCC(X)) + { + if ( (X == SDL_PIXELFORMAT_YUY2) || + (X == SDL_PIXELFORMAT_UYVY) || + (X == SDL_PIXELFORMAT_YVYU) ) + { + return 2; + } + return 1; + } + return (byte) (X & 0xFF); + } + + public static bool SDL_ISPIXELFORMAT_INDEXED(uint format) + { + if (SDL_ISPIXELFORMAT_FOURCC(format)) + { + return false; + } + SDL_PIXELTYPE_ENUM pType = + (SDL_PIXELTYPE_ENUM) SDL_PIXELTYPE(format); + return ( + pType == SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX1 || + pType == SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX4 || + pType == SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX8 + ); + } + + public static bool SDL_ISPIXELFORMAT_ALPHA(uint format) + { + if (SDL_ISPIXELFORMAT_FOURCC(format)) + { + return false; + } + SDL_PIXELORDER_ENUM pOrder = + (SDL_PIXELORDER_ENUM) SDL_PIXELORDER(format); + return ( + pOrder == SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ARGB || + pOrder == SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_RGBA || + pOrder == SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ABGR || + pOrder == SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_BGRA + ); + } + + public static bool SDL_ISPIXELFORMAT_FOURCC(uint format) + { + return (format == 0) && (SDL_PIXELFLAG(format) != 1); + } + + public enum SDL_PIXELTYPE_ENUM + { + SDL_PIXELTYPE_UNKNOWN, + SDL_PIXELTYPE_INDEX1, + SDL_PIXELTYPE_INDEX4, + SDL_PIXELTYPE_INDEX8, + SDL_PIXELTYPE_PACKED8, + SDL_PIXELTYPE_PACKED16, + SDL_PIXELTYPE_PACKED32, + SDL_PIXELTYPE_ARRAYU8, + SDL_PIXELTYPE_ARRAYU16, + SDL_PIXELTYPE_ARRAYU32, + SDL_PIXELTYPE_ARRAYF16, + SDL_PIXELTYPE_ARRAYF32 + } + + public enum SDL_PIXELORDER_ENUM + { + /* BITMAPORDER */ + SDL_BITMAPORDER_NONE, + SDL_BITMAPORDER_4321, + SDL_BITMAPORDER_1234, + /* PACKEDORDER */ + SDL_PACKEDORDER_NONE = 0, + SDL_PACKEDORDER_XRGB, + SDL_PACKEDORDER_RGBX, + SDL_PACKEDORDER_ARGB, + SDL_PACKEDORDER_RGBA, + SDL_PACKEDORDER_XBGR, + SDL_PACKEDORDER_BGRX, + SDL_PACKEDORDER_ABGR, + SDL_PACKEDORDER_BGRA, + /* ARRAYORDER */ + SDL_ARRAYORDER_NONE = 0, + SDL_ARRAYORDER_RGB, + SDL_ARRAYORDER_RGBA, + SDL_ARRAYORDER_ARGB, + SDL_ARRAYORDER_BGR, + SDL_ARRAYORDER_BGRA, + SDL_ARRAYORDER_ABGR + } + + public enum SDL_PACKEDLAYOUT_ENUM + { + SDL_PACKEDLAYOUT_NONE, + SDL_PACKEDLAYOUT_332, + SDL_PACKEDLAYOUT_4444, + SDL_PACKEDLAYOUT_1555, + SDL_PACKEDLAYOUT_5551, + SDL_PACKEDLAYOUT_565, + SDL_PACKEDLAYOUT_8888, + SDL_PACKEDLAYOUT_2101010, + SDL_PACKEDLAYOUT_1010102 + } + + public static readonly uint SDL_PIXELFORMAT_UNKNOWN = 0; + public static readonly uint SDL_PIXELFORMAT_INDEX1LSB = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX1, + SDL_PIXELORDER_ENUM.SDL_BITMAPORDER_4321, + 0, + 1, 0 + ); + public static readonly uint SDL_PIXELFORMAT_INDEX1MSB = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX1, + SDL_PIXELORDER_ENUM.SDL_BITMAPORDER_1234, + 0, + 1, 0 + ); + public static readonly uint SDL_PIXELFORMAT_INDEX4LSB = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX4, + SDL_PIXELORDER_ENUM.SDL_BITMAPORDER_4321, + 0, + 4, 0 + ); + public static readonly uint SDL_PIXELFORMAT_INDEX4MSB = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX4, + SDL_PIXELORDER_ENUM.SDL_BITMAPORDER_1234, + 0, + 4, 0 + ); + public static readonly uint SDL_PIXELFORMAT_INDEX8 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX8, + 0, + 0, + 8, 1 + ); + public static readonly uint SDL_PIXELFORMAT_RGB332 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED8, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_XRGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_332, + 8, 1 + ); + public static readonly uint SDL_PIXELFORMAT_RGB444 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_XRGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_4444, + 12, 2 + ); + public static readonly uint SDL_PIXELFORMAT_RGB555 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_XRGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_1555, + 15, 2 + ); + public static readonly uint SDL_PIXELFORMAT_BGR555 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_INDEX1, + SDL_PIXELORDER_ENUM.SDL_BITMAPORDER_4321, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_1555, + 15, 2 + ); + public static readonly uint SDL_PIXELFORMAT_ARGB4444 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ARGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_4444, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_RGBA4444 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_RGBA, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_4444, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_ABGR4444 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ABGR, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_4444, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_BGRA4444 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_BGRA, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_4444, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_ARGB1555 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ARGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_1555, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_RGBA5551 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_RGBA, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_5551, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_ABGR1555 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ABGR, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_1555, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_BGRA5551 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_BGRA, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_5551, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_RGB565 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_XRGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_565, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_BGR565 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED16, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_XBGR, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_565, + 16, 2 + ); + public static readonly uint SDL_PIXELFORMAT_RGB24 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_ARRAYU8, + SDL_PIXELORDER_ENUM.SDL_ARRAYORDER_RGB, + 0, + 24, 3 + ); + public static readonly uint SDL_PIXELFORMAT_BGR24 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_ARRAYU8, + SDL_PIXELORDER_ENUM.SDL_ARRAYORDER_BGR, + 0, + 24, 3 + ); + public static readonly uint SDL_PIXELFORMAT_RGB888 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_XRGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_8888, + 24, 4 + ); + public static readonly uint SDL_PIXELFORMAT_RGBX8888 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_RGBX, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_8888, + 24, 4 + ); + public static readonly uint SDL_PIXELFORMAT_BGR888 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_XBGR, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_8888, + 24, 4 + ); + public static readonly uint SDL_PIXELFORMAT_BGRX8888 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_BGRX, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_8888, + 24, 4 + ); + public static readonly uint SDL_PIXELFORMAT_ARGB8888 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ARGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_8888, + 32, 4 + ); + public static readonly uint SDL_PIXELFORMAT_RGBA8888 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_RGBA, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_8888, + 32, 4 + ); + public static readonly uint SDL_PIXELFORMAT_ABGR8888 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ABGR, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_8888, + 32, 4 + ); + public static readonly uint SDL_PIXELFORMAT_BGRA8888 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_BGRA, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_8888, + 32, 4 + ); + public static readonly uint SDL_PIXELFORMAT_ARGB2101010 = + SDL_DEFINE_PIXELFORMAT( + SDL_PIXELTYPE_ENUM.SDL_PIXELTYPE_PACKED32, + SDL_PIXELORDER_ENUM.SDL_PACKEDORDER_ARGB, + SDL_PACKEDLAYOUT_ENUM.SDL_PACKEDLAYOUT_2101010, + 32, 4 + ); + public static readonly uint SDL_PIXELFORMAT_YV12 = + SDL_DEFINE_PIXELFOURCC( + (byte) 'Y', (byte) 'V', (byte) '1', (byte) '2' + ); + public static readonly uint SDL_PIXELFORMAT_IYUV = + SDL_DEFINE_PIXELFOURCC( + (byte) 'I', (byte) 'Y', (byte) 'U', (byte) 'V' + ); + public static readonly uint SDL_PIXELFORMAT_YUY2 = + SDL_DEFINE_PIXELFOURCC( + (byte) 'Y', (byte) 'U', (byte) 'Y', (byte) '2' + ); + public static readonly uint SDL_PIXELFORMAT_UYVY = + SDL_DEFINE_PIXELFOURCC( + (byte) 'U', (byte) 'Y', (byte) 'V', (byte) 'Y' + ); + public static readonly uint SDL_PIXELFORMAT_YVYU = + SDL_DEFINE_PIXELFOURCC( + (byte) 'Y', (byte) 'V', (byte) 'Y', (byte) 'U' + ); + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_Color + { + public byte r; + public byte g; + public byte b; + public byte a; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_Palette + { + public int ncolors; + public IntPtr colors; + public int version; + public int refcount; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_PixelFormat + { + public uint format; + public IntPtr palette; // SDL_Palette* + public byte BitsPerPixel; + public byte BytesPerPixel; + public uint Rmask; + public uint Gmask; + public uint Bmask; + public uint Amask; + public byte Rloss; + public byte Gloss; + public byte Bloss; + public byte Aloss; + public byte Rshift; + public byte Gshift; + public byte Bshift; + public byte Ashift; + public int refcount; + public IntPtr next; // SDL_PixelFormat* + } + + /* IntPtr refers to an SDL_PixelFormat* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_AllocFormat(uint pixel_format); + + /* IntPtr refers to an SDL_Palette* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_AllocPalette(int ncolors); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_CalculateGammaRamp( + float gamma, + [Out()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U2, SizeConst = 256)] + ushort[] ramp + ); + + /* format refers to an SDL_PixelFormat* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_FreeFormat(IntPtr format); + + /* palette refers to an SDL_Palette* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_FreePalette(IntPtr palette); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetPixelFormatName( + uint format + ); + + /* format refers to an SDL_PixelFormat* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GetRGB( + uint pixel, + IntPtr format, + out byte r, + out byte g, + out byte b + ); + + /* format refers to an SDL_PixelFormat* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GetRGBA( + uint pixel, + IntPtr format, + out byte r, + out byte g, + out byte b, + out byte a + ); + + /* format refers to an SDL_PixelFormat* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_MapRGB( + IntPtr format, + byte r, + byte g, + byte b + ); + + /* format refers to an SDL_PixelFormat* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_MapRGBA( + IntPtr format, + byte r, + byte g, + byte b, + byte a + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_MasksToPixelFormatEnum( + int bpp, + uint Rmask, + uint Gmask, + uint Bmask, + uint Amask + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_PixelFormatEnumToMasks( + uint format, + out int bpp, + out uint Rmask, + out uint Gmask, + out uint Bmask, + out uint Amask + ); + + /* palette refers to an SDL_Palette* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetPaletteColors( + IntPtr palette, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct)] + SDL_Color[] colors, + int firstcolor, + int ncolors + ); + + /* format and palette refer to an SDL_PixelFormat* and SDL_Palette* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetPixelFormatPalette( + IntPtr format, + IntPtr palette + ); + + #endregion + + #region SDL_rect.h + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_Point + { + public int x; + public int y; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_Rect + { + public int x; + public int y; + public int w; + public int h; + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_EnclosePoints( + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 1)] + SDL_Point[] points, + int count, + ref SDL_Rect clip, + out SDL_Rect result + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_HasIntersection( + ref SDL_Rect A, + ref SDL_Rect B + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_IntersectRect( + ref SDL_Rect A, + ref SDL_Rect B, + out SDL_Rect result + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_IntersectRectAndLine( + ref SDL_Rect rect, + ref int X1, + ref int Y1, + ref int X2, + ref int Y2 + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_RectEmpty(ref SDL_Rect rect); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_RectEquals( + ref SDL_Rect A, + ref SDL_Rect B + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_UnionRect( + ref SDL_Rect A, + ref SDL_Rect B, + out SDL_Rect result + ); + + #endregion + + #region SDL_surface.h + + public const uint SDL_SWSURFACE = 0x00000000; + public const uint SDL_PREALLOC = 0x00000001; + public const uint SDL_RLEACCEL = 0x00000002; + public const uint SDL_DONTFREE = 0x00000004; + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_Surface + { + public uint flags; + public IntPtr format; // SDL_PixelFormat* + public int w; + public int h; + public int pitch; + public IntPtr pixels; // void* + public IntPtr userdata; // void* + public int locked; + public IntPtr lock_data; // void* + public SDL_Rect clip_rect; + public IntPtr map; // SDL_BlitMap* + public int refcount; + } + + /* surface refers to an SDL_Surface* */ + public static bool SDL_MUSTLOCK(IntPtr surface) + { + SDL_Surface sur; + sur = (SDL_Surface) Marshal.PtrToStructure( + surface, + typeof(SDL_Surface) + ); + return (sur.flags & SDL_RLEACCEL) != 0; + } + + /* src and dst refer to an SDL_Surface* */ + [DllImport(nativeLibName, EntryPoint = "SDL_UpperBlit", CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_BlitSurface( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + /* src and dst refer to an SDL_Surface* + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for srcrect. + */ + [DllImport(nativeLibName, EntryPoint = "SDL_UpperBlit", CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_BlitSurface( + IntPtr src, + IntPtr srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + /* src and dst refer to an SDL_Surface* + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for dstrect. + */ + [DllImport(nativeLibName, EntryPoint = "SDL_UpperBlit", CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_BlitSurface( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + IntPtr dstrect + ); + + /* src and dst refer to an SDL_Surface* + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for both SDL_Rects. + */ + [DllImport(nativeLibName, EntryPoint = "SDL_UpperBlit", CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_BlitSurface( + IntPtr src, + IntPtr srcrect, + IntPtr dst, + IntPtr dstrect + ); + + /* src and dst refer to an SDL_Surface* */ + [DllImport(nativeLibName, EntryPoint = "SDL_UpperBlitScaled", CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_BlitScaled( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + /* src and dst refer to an SDL_Surface* + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for srcrect. + */ + [DllImport(nativeLibName, EntryPoint = "SDL_UpperBlitScaled", CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_BlitScaled( + IntPtr src, + IntPtr srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + /* src and dst refer to an SDL_Surface* + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for dstrect. + */ + [DllImport(nativeLibName, EntryPoint = "SDL_UpperBlitScaled", CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_BlitScaled( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + IntPtr dstrect + ); + + /* src and dst refer to an SDL_Surface* + * Internally, this function contains logic to use default values when + * source and destination rectangles are passed as NULL. + * This overload allows for IntPtr.Zero (null) to be passed for both SDL_Rects. + */ + [DllImport(nativeLibName, EntryPoint = "SDL_UpperBlitScaled", CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_BlitScaled( + IntPtr src, + IntPtr srcrect, + IntPtr dst, + IntPtr dstrect + ); + + /* src and dst are void* pointers */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_ConvertPixels( + int width, + int height, + uint src_format, + IntPtr src, + int src_pitch, + uint dst_format, + IntPtr dst, + int dst_pitch + ); + + /* IntPtr refers to an SDL_Surface* + * src refers to an SDL_Surface* + * fmt refers to an SDL_PixelFormat* + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_ConvertSurface( + IntPtr src, + IntPtr fmt, + uint flags + ); + + /* IntPtr refers to an SDL_Surface*, src to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_ConvertSurfaceFormat( + IntPtr src, + uint pixel_format, + uint flags + ); + + /* IntPtr refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateRGBSurface( + uint flags, + int width, + int height, + int depth, + uint Rmask, + uint Gmask, + uint Bmask, + uint Amask + ); + + /* IntPtr refers to an SDL_Surface*, pixels to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateRGBSurfaceFrom( + IntPtr pixels, + int width, + int height, + int depth, + int pitch, + uint Rmask, + uint Gmask, + uint Bmask, + uint Amask + ); + + /* dst refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_FillRect( + IntPtr dst, + ref SDL_Rect rect, + uint color + ); + + /* dst refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_FillRects( + IntPtr dst, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] + SDL_Rect[] rects, + int count, + uint color + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_FreeSurface(IntPtr surface); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GetClipRect( + IntPtr surface, + out SDL_Rect rect + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetColorKey( + IntPtr surface, + out uint key + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetSurfaceAlphaMod( + IntPtr surface, + out byte alpha + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetSurfaceBlendMode( + IntPtr surface, + out SDL_BlendMode blendMode + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetSurfaceColorMod( + IntPtr surface, + out byte r, + out byte g, + out byte b + ); + + /* These are for SDL_LoadBMP, which is a macro in the SDL headers. */ + /* IntPtr refers to an SDL_Surface* */ + /* THIS IS AN RWops FUNCTION! */ + [DllImport(nativeLibName, EntryPoint = "SDL_LoadBMP_RW", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr INTERNAL_SDL_LoadBMP_RW( + IntPtr src, + int freesrc + ); + public static IntPtr SDL_LoadBMP(string file) + { + IntPtr rwops = INTERNAL_SDL_RWFromFile(file, "rb"); + return INTERNAL_SDL_LoadBMP_RW(rwops, 1); + } + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_LockSurface(IntPtr surface); + + /* src and dst refer to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_LowerBlit( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + /* src and dst refer to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_LowerBlitScaled( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + /* These are for SDL_SaveBMP, which is a macro in the SDL headers. */ + /* IntPtr refers to an SDL_Surface* */ + /* THIS IS AN RWops FUNCTION! */ + [DllImport(nativeLibName, EntryPoint = "SDL_SaveBMP_RW", CallingConvention = CallingConvention.Cdecl)] + private static extern int INTERNAL_SDL_SaveBMP_RW( + IntPtr surface, + IntPtr src, + int freesrc + ); + public static int SDL_SaveBMP(IntPtr surface, string file) + { + IntPtr rwops = INTERNAL_SDL_RWFromFile(file, "wb"); + return INTERNAL_SDL_SaveBMP_RW(surface, rwops, 1); + } + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_SetClipRect( + IntPtr surface, + ref SDL_Rect rect + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetColorKey( + IntPtr surface, + int flag, + uint key + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetSurfaceAlphaMod( + IntPtr surface, + byte alpha + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetSurfaceBlendMode( + IntPtr surface, + SDL_BlendMode blendMode + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetSurfaceColorMod( + IntPtr surface, + byte r, + byte g, + byte b + ); + + /* surface refers to an SDL_Surface*, palette to an SDL_Palette* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetSurfacePalette( + IntPtr surface, + IntPtr palette + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetSurfaceRLE( + IntPtr surface, + int flag + ); + + /* src and dst refer to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SoftStretch( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_UnlockSurface(IntPtr surface); + + /* src and dst refer to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_UpperBlit( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + /* src and dst refer to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_UpperBlitScaled( + IntPtr src, + ref SDL_Rect srcrect, + IntPtr dst, + ref SDL_Rect dstrect + ); + + #endregion + + #region SDL_clipboard.h + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_HasClipboardText(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetClipboardText(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetClipboardText( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string text + ); + + #endregion + + #region SDL_events.h + + /* General keyboard/mouse state definitions. */ + public const byte SDL_PRESSED = 1; + public const byte SDL_RELEASED = 0; + + /* Default size is according to SDL2 default. */ + public const int SDL_TEXTEDITINGEVENT_TEXT_SIZE = 32; + public const int SDL_TEXTINPUTEVENT_TEXT_SIZE = 32; + + /* The types of events that can be delivered. */ + public enum SDL_EventType : uint + { + SDL_FIRSTEVENT = 0, + + /* Application events */ + SDL_QUIT = 0x100, + + /* Window events */ + SDL_WINDOWEVENT = 0x200, + SDL_SYSWMEVENT, + + /* Keyboard events */ + SDL_KEYDOWN = 0x300, + SDL_KEYUP, + SDL_TEXTEDITING, + SDL_TEXTINPUT, + + /* Mouse events */ + SDL_MOUSEMOTION = 0x400, + SDL_MOUSEBUTTONDOWN, + SDL_MOUSEBUTTONUP, + SDL_MOUSEWHEEL, + + /* Joystick events */ + SDL_JOYAXISMOTION = 0x600, + SDL_JOYBALLMOTION, + SDL_JOYHATMOTION, + SDL_JOYBUTTONDOWN, + SDL_JOYBUTTONUP, + SDL_JOYDEVICEADDED, + SDL_JOYDEVICEREMOVED, + + /* Game controller events */ + SDL_CONTROLLERAXISMOTION = 0x650, + SDL_CONTROLLERBUTTONDOWN, + SDL_CONTROLLERBUTTONUP, + SDL_CONTROLLERDEVICEADDED, + SDL_CONTROLLERDEVICEREMOVED, + SDL_CONTROLLERDEVICEREMAPPED, + + /* Touch events */ + SDL_FINGERDOWN = 0x700, + SDL_FINGERUP, + SDL_FINGERMOTION, + + /* Gesture events */ + SDL_DOLLARGESTURE = 0x800, + SDL_DOLLARRECORD, + SDL_MULTIGESTURE, + + /* Clipboard events */ + SDL_CLIPBOARDUPDATE = 0x900, + + /* Drag and drop events */ + SDL_DROPFILE = 0x1000, + + /* Render events */ + /* Only available in SDL 2.0.2 or higher */ + SDL_RENDER_TARGETS_RESET = 0x2000, + + /* Events SDL_USEREVENT through SDL_LASTEVENT are for + * your use, and should be allocated with + * SDL_RegisterEvents() + */ + SDL_USEREVENT = 0x8000, + + /* The last event, used for bouding arrays. */ + SDL_LASTEVENT = 0xFFFF + } + + /* Fields shared by every event */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_GenericEvent + { + public SDL_EventType type; + public UInt32 timestamp; + } + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Window state change event data (event.window.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_WindowEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public UInt32 windowID; + public SDL_WindowEventID windowEvent; // event, lolC# + private byte padding1; + private byte padding2; + private byte padding3; + public Int32 data1; + public Int32 data2; + } +#pragma warning restore 0169 + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Keyboard button event structure (event.key.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_KeyboardEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public UInt32 windowID; + public byte state; + public byte repeat; /* non-zero if this is a repeat */ + private byte padding2; + private byte padding3; + public SDL_Keysym keysym; + } +#pragma warning restore 0169 + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct SDL_TextEditingEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public UInt32 windowID; + public fixed byte text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; + public Int32 start; + public Int32 length; + } + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct SDL_TextInputEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public UInt32 windowID; + public fixed byte text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; + } + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Mouse motion event structure (event.motion.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_MouseMotionEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public UInt32 windowID; + public UInt32 which; + public byte state; /* bitmask of buttons */ + private byte padding1; + private byte padding2; + private byte padding3; + public Int32 x; + public Int32 y; + public Int32 xrel; + public Int32 yrel; + } +#pragma warning restore 0169 + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Mouse button event structure (event.button.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_MouseButtonEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public UInt32 windowID; + public UInt32 which; + public byte button; /* button id */ + public byte state; /* SDL_PRESSED or SDL_RELEASED */ + public byte clicks; /* 1 for single-click, 2 for double-click, etc. */ + private byte padding1; + public Int32 x; + public Int32 y; + } +#pragma warning restore 0169 + + /* Mouse wheel event structure (event.wheel.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_MouseWheelEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public UInt32 windowID; + public UInt32 which; + public Int32 x; /* amount scrolled horizontally */ + public Int32 y; /* amount scrolled vertically */ + } + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Joystick axis motion event structure (event.jaxis.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_JoyAxisEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public Int32 which; /* SDL_JoystickID */ + public byte axis; + private byte padding1; + private byte padding2; + private byte padding3; + public Int16 axisValue; /* value, lolC# */ + public UInt16 padding4; + } +#pragma warning restore 0169 + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Joystick trackball motion event structure (event.jball.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_JoyBallEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public Int32 which; /* SDL_JoystickID */ + public byte ball; + private byte padding1; + private byte padding2; + private byte padding3; + public Int16 xrel; + public Int16 yrel; + } +#pragma warning restore 0169 + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Joystick hat position change event struct (event.jhat.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_JoyHatEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public Int32 which; /* SDL_JoystickID */ + public byte hat; /* index of the hat */ + public byte hatValue; /* value, lolC# */ + private byte padding1; + private byte padding2; + } +#pragma warning restore 0169 + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Joystick button event structure (event.jbutton.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_JoyButtonEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public Int32 which; /* SDL_JoystickID */ + public byte button; + public byte state; /* SDL_PRESSED or SDL_RELEASED */ + private byte padding1; + private byte padding2; + } +#pragma warning restore 0169 + + /* Joystick device event structure (event.jdevice.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_JoyDeviceEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public Int32 which; /* SDL_JoystickID */ + } + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Game controller axis motion event (event.caxis.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_ControllerAxisEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public Int32 which; /* SDL_JoystickID */ + public byte axis; + private byte padding1; + private byte padding2; + private byte padding3; + public Int16 axisValue; /* value, lolC# */ + private UInt16 padding4; + } +#pragma warning restore 0169 + +// Ignore private members used for padding in this struct +#pragma warning disable 0169 + /* Game controller button event (event.cbutton.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_ControllerButtonEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public Int32 which; /* SDL_JoystickID */ + public byte button; + public byte state; + private byte padding1; + private byte padding2; + } +#pragma warning restore 0169 + + /* Game controller device event (event.cdevice.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_ControllerDeviceEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public Int32 which; /* joystick id for ADDED, else + instance id */ + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_TouchFingerEvent + { + public UInt32 type; + public UInt32 timestamp; + public Int64 touchId; // SDL_TouchID + public Int64 fingerId; // SDL_GestureID + public float x; + public float y; + public float dx; + public float dy; + public float pressure; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_MultiGestureEvent + { + public UInt32 type; + public UInt32 timestamp; + public Int64 touchId; // SDL_TouchID + public float dTheta; + public float dDist; + public float x; + public float y; + public UInt16 numFingers; + public UInt16 padding; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_DollarGestureEvent + { + public UInt32 type; + public UInt32 timestamp; + public Int64 touchId; // SDL_TouchID + public Int64 gestureId; // SDL_GestureID + public UInt32 numFingers; + public float error; + public float x; + public float y; + } + + /* File open request by system (event.drop.*), disabled by + * default + */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_DropEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public IntPtr file; /* char* filename, to be freed */ + } + + /* The "quit requested" event */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_QuitEvent + { + public SDL_EventType type; + public UInt32 timestamp; + } + + /* A user defined event (event.user.*) */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_UserEvent + { + public UInt32 type; + public UInt32 timestamp; + public UInt32 windowID; + public Int32 code; + public IntPtr data1; /* user-defined */ + public IntPtr data2; /* user-defined */ + } + + /* A video driver dependent event (event.syswm.*), disabled */ + [StructLayout(LayoutKind.Sequential)] + public struct SDL_SysWMEvent + { + public SDL_EventType type; + public UInt32 timestamp; + public IntPtr msg; /* SDL_SysWMmsg*, system-dependent*/ + } + + /* General event structure */ + // C# doesn't do unions, so we do this ugly thing. */ + [StructLayout(LayoutKind.Explicit)] + public struct SDL_Event + { + [FieldOffset(0)] + public SDL_EventType type; + [FieldOffset(0)] + public SDL_WindowEvent window; + [FieldOffset(0)] + public SDL_KeyboardEvent key; + [FieldOffset(0)] + public SDL_TextEditingEvent edit; + [FieldOffset(0)] + public SDL_TextInputEvent text; + [FieldOffset(0)] + public SDL_MouseMotionEvent motion; + [FieldOffset(0)] + public SDL_MouseButtonEvent button; + [FieldOffset(0)] + public SDL_MouseWheelEvent wheel; + [FieldOffset(0)] + public SDL_JoyAxisEvent jaxis; + [FieldOffset(0)] + public SDL_JoyBallEvent jball; + [FieldOffset(0)] + public SDL_JoyHatEvent jhat; + [FieldOffset(0)] + public SDL_JoyButtonEvent jbutton; + [FieldOffset(0)] + public SDL_JoyDeviceEvent jdevice; + [FieldOffset(0)] + public SDL_ControllerAxisEvent caxis; + [FieldOffset(0)] + public SDL_ControllerButtonEvent cbutton; + [FieldOffset(0)] + public SDL_ControllerDeviceEvent cdevice; + [FieldOffset(0)] + public SDL_QuitEvent quit; + [FieldOffset(0)] + public SDL_UserEvent user; + [FieldOffset(0)] + public SDL_SysWMEvent syswm; + [FieldOffset(0)] + public SDL_TouchFingerEvent tfinger; + [FieldOffset(0)] + public SDL_MultiGestureEvent mgesture; + [FieldOffset(0)] + public SDL_DollarGestureEvent dgesture; + [FieldOffset(0)] + public SDL_DropEvent drop; + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int SDL_EventFilter( + IntPtr userdata, // void* + IntPtr sdlevent // SDL_Event* event, lolC# + ); + + /* Pump the event loop, getting events from the input devices*/ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_PumpEvents(); + + public enum SDL_eventaction + { + SDL_ADDEVENT, + SDL_PEEKEVENT, + SDL_GETEVENT + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_PeepEvents( + [Out()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 1)] + SDL_Event[] events, + int numevents, + SDL_eventaction action, + SDL_EventType minType, + SDL_EventType maxType + ); + + /* Checks to see if certain events are in the event queue */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_HasEvent(SDL_EventType type); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_HasEvents( + SDL_EventType minType, + SDL_EventType maxType + ); + + /* Clears events from the event queue */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_FlushEvent(SDL_EventType type); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_FlushEvents( + SDL_EventType min, + SDL_EventType max + ); + + /* Polls for currently pending events */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_PollEvent(out SDL_Event _event); + + /* Waits indefinitely for the next event */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_WaitEvent(out SDL_Event _event); + + /* Waits until the specified timeout (in ms) for the next event + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_WaitEventTimeout(out SDL_Event _event, int timeout); + + /* Add an event to the event queue */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_PushEvent(ref SDL_Event _event); + + /* userdata refers to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetEventFilter( + SDL_EventFilter filter, + IntPtr userdata + ); + + /* userdata refers to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_GetEventFilter( + out SDL_EventFilter filter, + out IntPtr userdata + ); + + /* userdata refers to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_AddEventWatch( + SDL_EventFilter filter, + IntPtr userdata + ); + + /* userdata refers to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_DelEventWatch( + SDL_EventFilter filter, + IntPtr userdata + ); + + /* userdata refers to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_FilterEvents( + SDL_EventFilter filter, + IntPtr userdata + ); + + /* These are for SDL_EventState() */ + public const int SDL_QUERY = -1; + public const int SDL_IGNORE = 0; + public const int SDL_DISABLE = 0; + public const int SDL_ENABLE = 1; + + /* This function allows you to enable/disable certain events */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern byte SDL_EventState(SDL_EventType type, int state); + + /* Get the state of an event */ + public static byte SDL_GetEventState(SDL_EventType type) + { + return SDL_EventState(type, SDL_QUERY); + } + + /* Allocate a set of user-defined events */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 SDL_RegisterEvents(int numevents); + #endregion + + #region SDL_scancode.h + + /* Scancodes based off USB keyboard page (0x07) */ + public enum SDL_Scancode + { + SDL_SCANCODE_UNKNOWN = 0, + + SDL_SCANCODE_A = 4, + SDL_SCANCODE_B = 5, + SDL_SCANCODE_C = 6, + SDL_SCANCODE_D = 7, + SDL_SCANCODE_E = 8, + SDL_SCANCODE_F = 9, + SDL_SCANCODE_G = 10, + SDL_SCANCODE_H = 11, + SDL_SCANCODE_I = 12, + SDL_SCANCODE_J = 13, + SDL_SCANCODE_K = 14, + SDL_SCANCODE_L = 15, + SDL_SCANCODE_M = 16, + SDL_SCANCODE_N = 17, + SDL_SCANCODE_O = 18, + SDL_SCANCODE_P = 19, + SDL_SCANCODE_Q = 20, + SDL_SCANCODE_R = 21, + SDL_SCANCODE_S = 22, + SDL_SCANCODE_T = 23, + SDL_SCANCODE_U = 24, + SDL_SCANCODE_V = 25, + SDL_SCANCODE_W = 26, + SDL_SCANCODE_X = 27, + SDL_SCANCODE_Y = 28, + SDL_SCANCODE_Z = 29, + + SDL_SCANCODE_1 = 30, + SDL_SCANCODE_2 = 31, + SDL_SCANCODE_3 = 32, + SDL_SCANCODE_4 = 33, + SDL_SCANCODE_5 = 34, + SDL_SCANCODE_6 = 35, + SDL_SCANCODE_7 = 36, + SDL_SCANCODE_8 = 37, + SDL_SCANCODE_9 = 38, + SDL_SCANCODE_0 = 39, + + SDL_SCANCODE_RETURN = 40, + SDL_SCANCODE_ESCAPE = 41, + SDL_SCANCODE_BACKSPACE = 42, + SDL_SCANCODE_TAB = 43, + SDL_SCANCODE_SPACE = 44, + + SDL_SCANCODE_MINUS = 45, + SDL_SCANCODE_EQUALS = 46, + SDL_SCANCODE_LEFTBRACKET = 47, + SDL_SCANCODE_RIGHTBRACKET = 48, + SDL_SCANCODE_BACKSLASH = 49, + SDL_SCANCODE_NONUSHASH = 50, + SDL_SCANCODE_SEMICOLON = 51, + SDL_SCANCODE_APOSTROPHE = 52, + SDL_SCANCODE_GRAVE = 53, + SDL_SCANCODE_COMMA = 54, + SDL_SCANCODE_PERIOD = 55, + SDL_SCANCODE_SLASH = 56, + + SDL_SCANCODE_CAPSLOCK = 57, + + SDL_SCANCODE_F1 = 58, + SDL_SCANCODE_F2 = 59, + SDL_SCANCODE_F3 = 60, + SDL_SCANCODE_F4 = 61, + SDL_SCANCODE_F5 = 62, + SDL_SCANCODE_F6 = 63, + SDL_SCANCODE_F7 = 64, + SDL_SCANCODE_F8 = 65, + SDL_SCANCODE_F9 = 66, + SDL_SCANCODE_F10 = 67, + SDL_SCANCODE_F11 = 68, + SDL_SCANCODE_F12 = 69, + + SDL_SCANCODE_PRINTSCREEN = 70, + SDL_SCANCODE_SCROLLLOCK = 71, + SDL_SCANCODE_PAUSE = 72, + SDL_SCANCODE_INSERT = 73, + SDL_SCANCODE_HOME = 74, + SDL_SCANCODE_PAGEUP = 75, + SDL_SCANCODE_DELETE = 76, + SDL_SCANCODE_END = 77, + SDL_SCANCODE_PAGEDOWN = 78, + SDL_SCANCODE_RIGHT = 79, + SDL_SCANCODE_LEFT = 80, + SDL_SCANCODE_DOWN = 81, + SDL_SCANCODE_UP = 82, + + SDL_SCANCODE_NUMLOCKCLEAR = 83, + SDL_SCANCODE_KP_DIVIDE = 84, + SDL_SCANCODE_KP_MULTIPLY = 85, + SDL_SCANCODE_KP_MINUS = 86, + SDL_SCANCODE_KP_PLUS = 87, + SDL_SCANCODE_KP_ENTER = 88, + SDL_SCANCODE_KP_1 = 89, + SDL_SCANCODE_KP_2 = 90, + SDL_SCANCODE_KP_3 = 91, + SDL_SCANCODE_KP_4 = 92, + SDL_SCANCODE_KP_5 = 93, + SDL_SCANCODE_KP_6 = 94, + SDL_SCANCODE_KP_7 = 95, + SDL_SCANCODE_KP_8 = 96, + SDL_SCANCODE_KP_9 = 97, + SDL_SCANCODE_KP_0 = 98, + SDL_SCANCODE_KP_PERIOD = 99, + + SDL_SCANCODE_NONUSBACKSLASH = 100, + SDL_SCANCODE_APPLICATION = 101, + SDL_SCANCODE_POWER = 102, + SDL_SCANCODE_KP_EQUALS = 103, + SDL_SCANCODE_F13 = 104, + SDL_SCANCODE_F14 = 105, + SDL_SCANCODE_F15 = 106, + SDL_SCANCODE_F16 = 107, + SDL_SCANCODE_F17 = 108, + SDL_SCANCODE_F18 = 109, + SDL_SCANCODE_F19 = 110, + SDL_SCANCODE_F20 = 111, + SDL_SCANCODE_F21 = 112, + SDL_SCANCODE_F22 = 113, + SDL_SCANCODE_F23 = 114, + SDL_SCANCODE_F24 = 115, + SDL_SCANCODE_EXECUTE = 116, + SDL_SCANCODE_HELP = 117, + SDL_SCANCODE_MENU = 118, + SDL_SCANCODE_SELECT = 119, + SDL_SCANCODE_STOP = 120, + SDL_SCANCODE_AGAIN = 121, + SDL_SCANCODE_UNDO = 122, + SDL_SCANCODE_CUT = 123, + SDL_SCANCODE_COPY = 124, + SDL_SCANCODE_PASTE = 125, + SDL_SCANCODE_FIND = 126, + SDL_SCANCODE_MUTE = 127, + SDL_SCANCODE_VOLUMEUP = 128, + SDL_SCANCODE_VOLUMEDOWN = 129, + /* not sure whether there's a reason to enable these */ + /* SDL_SCANCODE_LOCKINGCAPSLOCK = 130, */ + /* SDL_SCANCODE_LOCKINGNUMLOCK = 131, */ + /* SDL_SCANCODE_LOCKINGSCROLLLOCK = 132, */ + SDL_SCANCODE_KP_COMMA = 133, + SDL_SCANCODE_KP_EQUALSAS400 = 134, + + SDL_SCANCODE_INTERNATIONAL1 = 135, + SDL_SCANCODE_INTERNATIONAL2 = 136, + SDL_SCANCODE_INTERNATIONAL3 = 137, + SDL_SCANCODE_INTERNATIONAL4 = 138, + SDL_SCANCODE_INTERNATIONAL5 = 139, + SDL_SCANCODE_INTERNATIONAL6 = 140, + SDL_SCANCODE_INTERNATIONAL7 = 141, + SDL_SCANCODE_INTERNATIONAL8 = 142, + SDL_SCANCODE_INTERNATIONAL9 = 143, + SDL_SCANCODE_LANG1 = 144, + SDL_SCANCODE_LANG2 = 145, + SDL_SCANCODE_LANG3 = 146, + SDL_SCANCODE_LANG4 = 147, + SDL_SCANCODE_LANG5 = 148, + SDL_SCANCODE_LANG6 = 149, + SDL_SCANCODE_LANG7 = 150, + SDL_SCANCODE_LANG8 = 151, + SDL_SCANCODE_LANG9 = 152, + + SDL_SCANCODE_ALTERASE = 153, + SDL_SCANCODE_SYSREQ = 154, + SDL_SCANCODE_CANCEL = 155, + SDL_SCANCODE_CLEAR = 156, + SDL_SCANCODE_PRIOR = 157, + SDL_SCANCODE_RETURN2 = 158, + SDL_SCANCODE_SEPARATOR = 159, + SDL_SCANCODE_OUT = 160, + SDL_SCANCODE_OPER = 161, + SDL_SCANCODE_CLEARAGAIN = 162, + SDL_SCANCODE_CRSEL = 163, + SDL_SCANCODE_EXSEL = 164, + + SDL_SCANCODE_KP_00 = 176, + SDL_SCANCODE_KP_000 = 177, + SDL_SCANCODE_THOUSANDSSEPARATOR = 178, + SDL_SCANCODE_DECIMALSEPARATOR = 179, + SDL_SCANCODE_CURRENCYUNIT = 180, + SDL_SCANCODE_CURRENCYSUBUNIT = 181, + SDL_SCANCODE_KP_LEFTPAREN = 182, + SDL_SCANCODE_KP_RIGHTPAREN = 183, + SDL_SCANCODE_KP_LEFTBRACE = 184, + SDL_SCANCODE_KP_RIGHTBRACE = 185, + SDL_SCANCODE_KP_TAB = 186, + SDL_SCANCODE_KP_BACKSPACE = 187, + SDL_SCANCODE_KP_A = 188, + SDL_SCANCODE_KP_B = 189, + SDL_SCANCODE_KP_C = 190, + SDL_SCANCODE_KP_D = 191, + SDL_SCANCODE_KP_E = 192, + SDL_SCANCODE_KP_F = 193, + SDL_SCANCODE_KP_XOR = 194, + SDL_SCANCODE_KP_POWER = 195, + SDL_SCANCODE_KP_PERCENT = 196, + SDL_SCANCODE_KP_LESS = 197, + SDL_SCANCODE_KP_GREATER = 198, + SDL_SCANCODE_KP_AMPERSAND = 199, + SDL_SCANCODE_KP_DBLAMPERSAND = 200, + SDL_SCANCODE_KP_VERTICALBAR = 201, + SDL_SCANCODE_KP_DBLVERTICALBAR = 202, + SDL_SCANCODE_KP_COLON = 203, + SDL_SCANCODE_KP_HASH = 204, + SDL_SCANCODE_KP_SPACE = 205, + SDL_SCANCODE_KP_AT = 206, + SDL_SCANCODE_KP_EXCLAM = 207, + SDL_SCANCODE_KP_MEMSTORE = 208, + SDL_SCANCODE_KP_MEMRECALL = 209, + SDL_SCANCODE_KP_MEMCLEAR = 210, + SDL_SCANCODE_KP_MEMADD = 211, + SDL_SCANCODE_KP_MEMSUBTRACT = 212, + SDL_SCANCODE_KP_MEMMULTIPLY = 213, + SDL_SCANCODE_KP_MEMDIVIDE = 214, + SDL_SCANCODE_KP_PLUSMINUS = 215, + SDL_SCANCODE_KP_CLEAR = 216, + SDL_SCANCODE_KP_CLEARENTRY = 217, + SDL_SCANCODE_KP_BINARY = 218, + SDL_SCANCODE_KP_OCTAL = 219, + SDL_SCANCODE_KP_DECIMAL = 220, + SDL_SCANCODE_KP_HEXADECIMAL = 221, + + SDL_SCANCODE_LCTRL = 224, + SDL_SCANCODE_LSHIFT = 225, + SDL_SCANCODE_LALT = 226, + SDL_SCANCODE_LGUI = 227, + SDL_SCANCODE_RCTRL = 228, + SDL_SCANCODE_RSHIFT = 229, + SDL_SCANCODE_RALT = 230, + SDL_SCANCODE_RGUI = 231, + + SDL_SCANCODE_MODE = 257, + + /* These come from the USB consumer page (0x0C) */ + SDL_SCANCODE_AUDIONEXT = 258, + SDL_SCANCODE_AUDIOPREV = 259, + SDL_SCANCODE_AUDIOSTOP = 260, + SDL_SCANCODE_AUDIOPLAY = 261, + SDL_SCANCODE_AUDIOMUTE = 262, + SDL_SCANCODE_MEDIASELECT = 263, + SDL_SCANCODE_WWW = 264, + SDL_SCANCODE_MAIL = 265, + SDL_SCANCODE_CALCULATOR = 266, + SDL_SCANCODE_COMPUTER = 267, + SDL_SCANCODE_AC_SEARCH = 268, + SDL_SCANCODE_AC_HOME = 269, + SDL_SCANCODE_AC_BACK = 270, + SDL_SCANCODE_AC_FORWARD = 271, + SDL_SCANCODE_AC_STOP = 272, + SDL_SCANCODE_AC_REFRESH = 273, + SDL_SCANCODE_AC_BOOKMARKS = 274, + + /* These come from other sources, and are mostly mac related */ + SDL_SCANCODE_BRIGHTNESSDOWN = 275, + SDL_SCANCODE_BRIGHTNESSUP = 276, + SDL_SCANCODE_DISPLAYSWITCH = 277, + SDL_SCANCODE_KBDILLUMTOGGLE = 278, + SDL_SCANCODE_KBDILLUMDOWN = 279, + SDL_SCANCODE_KBDILLUMUP = 280, + SDL_SCANCODE_EJECT = 281, + SDL_SCANCODE_SLEEP = 282, + + SDL_SCANCODE_APP1 = 283, + SDL_SCANCODE_APP2 = 284, + + /* This is not a key, simply marks the number of scancodes + * so that you know how big to make your arrays. */ + SDL_NUM_SCANCODES = 512 + } + + #endregion + + #region SDL_keycode.h + + public const int SDLK_SCANCODE_MASK = (1 << 30); + public static SDL_Keycode SDL_SCANCODE_TO_KEYCODE(SDL_Scancode X) + { + return (SDL_Keycode)((int)X | SDLK_SCANCODE_MASK); + } + + /* So, in the C headers, SDL_Keycode is a typedef of Sint32 + * and all of the names are in an anonymous enum. Yeah... + * that's not going to cut it for C#. We'll just put them in an + * enum for now? */ + public enum SDL_Keycode + { + SDLK_UNKNOWN = 0, + + SDLK_RETURN = '\r', + SDLK_ESCAPE = 27, // '\033' + SDLK_BACKSPACE = '\b', + SDLK_TAB = '\t', + SDLK_SPACE = ' ', + SDLK_EXCLAIM = '!', + SDLK_QUOTEDBL = '"', + SDLK_HASH = '#', + SDLK_PERCENT = '%', + SDLK_DOLLAR = '$', + SDLK_AMPERSAND = '&', + SDLK_QUOTE = '\'', + SDLK_LEFTPAREN = '(', + SDLK_RIGHTPAREN = ')', + SDLK_ASTERISK = '*', + SDLK_PLUS = '+', + SDLK_COMMA = ',', + SDLK_MINUS = '-', + SDLK_PERIOD = '.', + SDLK_SLASH = '/', + SDLK_0 = '0', + SDLK_1 = '1', + SDLK_2 = '2', + SDLK_3 = '3', + SDLK_4 = '4', + SDLK_5 = '5', + SDLK_6 = '6', + SDLK_7 = '7', + SDLK_8 = '8', + SDLK_9 = '9', + SDLK_COLON = ':', + SDLK_SEMICOLON = ';', + SDLK_LESS = '<', + SDLK_EQUALS = '=', + SDLK_GREATER = '>', + SDLK_QUESTION = '?', + SDLK_AT = '@', + /* + Skip uppercase letters + */ + SDLK_LEFTBRACKET = '[', + SDLK_BACKSLASH = '\\', + SDLK_RIGHTBRACKET = ']', + SDLK_CARET = '^', + SDLK_UNDERSCORE = '_', + SDLK_BACKQUOTE = '`', + SDLK_a = 'a', + SDLK_b = 'b', + SDLK_c = 'c', + SDLK_d = 'd', + SDLK_e = 'e', + SDLK_f = 'f', + SDLK_g = 'g', + SDLK_h = 'h', + SDLK_i = 'i', + SDLK_j = 'j', + SDLK_k = 'k', + SDLK_l = 'l', + SDLK_m = 'm', + SDLK_n = 'n', + SDLK_o = 'o', + SDLK_p = 'p', + SDLK_q = 'q', + SDLK_r = 'r', + SDLK_s = 's', + SDLK_t = 't', + SDLK_u = 'u', + SDLK_v = 'v', + SDLK_w = 'w', + SDLK_x = 'x', + SDLK_y = 'y', + SDLK_z = 'z', + + SDLK_CAPSLOCK = (int)SDL_Scancode.SDL_SCANCODE_CAPSLOCK | SDLK_SCANCODE_MASK, + + SDLK_F1 = (int)SDL_Scancode.SDL_SCANCODE_F1 | SDLK_SCANCODE_MASK, + SDLK_F2 = (int)SDL_Scancode.SDL_SCANCODE_F2 | SDLK_SCANCODE_MASK, + SDLK_F3 = (int)SDL_Scancode.SDL_SCANCODE_F3 | SDLK_SCANCODE_MASK, + SDLK_F4 = (int)SDL_Scancode.SDL_SCANCODE_F4 | SDLK_SCANCODE_MASK, + SDLK_F5 = (int)SDL_Scancode.SDL_SCANCODE_F5 | SDLK_SCANCODE_MASK, + SDLK_F6 = (int)SDL_Scancode.SDL_SCANCODE_F6 | SDLK_SCANCODE_MASK, + SDLK_F7 = (int)SDL_Scancode.SDL_SCANCODE_F7 | SDLK_SCANCODE_MASK, + SDLK_F8 = (int)SDL_Scancode.SDL_SCANCODE_F8 | SDLK_SCANCODE_MASK, + SDLK_F9 = (int)SDL_Scancode.SDL_SCANCODE_F9 | SDLK_SCANCODE_MASK, + SDLK_F10 = (int)SDL_Scancode.SDL_SCANCODE_F10 | SDLK_SCANCODE_MASK, + SDLK_F11 = (int)SDL_Scancode.SDL_SCANCODE_F11 | SDLK_SCANCODE_MASK, + SDLK_F12 = (int)SDL_Scancode.SDL_SCANCODE_F12 | SDLK_SCANCODE_MASK, + + SDLK_PRINTSCREEN = (int)SDL_Scancode.SDL_SCANCODE_PRINTSCREEN | SDLK_SCANCODE_MASK, + SDLK_SCROLLLOCK = (int)SDL_Scancode.SDL_SCANCODE_SCROLLLOCK | SDLK_SCANCODE_MASK, + SDLK_PAUSE = (int)SDL_Scancode.SDL_SCANCODE_PAUSE | SDLK_SCANCODE_MASK, + SDLK_INSERT = (int)SDL_Scancode.SDL_SCANCODE_INSERT | SDLK_SCANCODE_MASK, + SDLK_HOME = (int)SDL_Scancode.SDL_SCANCODE_HOME | SDLK_SCANCODE_MASK, + SDLK_PAGEUP = (int)SDL_Scancode.SDL_SCANCODE_PAGEUP | SDLK_SCANCODE_MASK, + SDLK_DELETE = 127, + SDLK_END = (int)SDL_Scancode.SDL_SCANCODE_END | SDLK_SCANCODE_MASK, + SDLK_PAGEDOWN = (int)SDL_Scancode.SDL_SCANCODE_PAGEDOWN | SDLK_SCANCODE_MASK, + SDLK_RIGHT = (int)SDL_Scancode.SDL_SCANCODE_RIGHT | SDLK_SCANCODE_MASK, + SDLK_LEFT = (int)SDL_Scancode.SDL_SCANCODE_LEFT | SDLK_SCANCODE_MASK, + SDLK_DOWN = (int)SDL_Scancode.SDL_SCANCODE_DOWN | SDLK_SCANCODE_MASK, + SDLK_UP = (int)SDL_Scancode.SDL_SCANCODE_UP | SDLK_SCANCODE_MASK, + + SDLK_NUMLOCKCLEAR = (int)SDL_Scancode.SDL_SCANCODE_NUMLOCKCLEAR | SDLK_SCANCODE_MASK, + SDLK_KP_DIVIDE = (int)SDL_Scancode.SDL_SCANCODE_KP_DIVIDE | SDLK_SCANCODE_MASK, + SDLK_KP_MULTIPLY = (int)SDL_Scancode.SDL_SCANCODE_KP_MULTIPLY | SDLK_SCANCODE_MASK, + SDLK_KP_MINUS = (int)SDL_Scancode.SDL_SCANCODE_KP_MINUS | SDLK_SCANCODE_MASK, + SDLK_KP_PLUS = (int)SDL_Scancode.SDL_SCANCODE_KP_PLUS | SDLK_SCANCODE_MASK, + SDLK_KP_ENTER = (int)SDL_Scancode.SDL_SCANCODE_KP_ENTER | SDLK_SCANCODE_MASK, + SDLK_KP_1 = (int)SDL_Scancode.SDL_SCANCODE_KP_1 | SDLK_SCANCODE_MASK, + SDLK_KP_2 = (int)SDL_Scancode.SDL_SCANCODE_KP_2 | SDLK_SCANCODE_MASK, + SDLK_KP_3 = (int)SDL_Scancode.SDL_SCANCODE_KP_3 | SDLK_SCANCODE_MASK, + SDLK_KP_4 = (int)SDL_Scancode.SDL_SCANCODE_KP_4 | SDLK_SCANCODE_MASK, + SDLK_KP_5 = (int)SDL_Scancode.SDL_SCANCODE_KP_5 | SDLK_SCANCODE_MASK, + SDLK_KP_6 = (int)SDL_Scancode.SDL_SCANCODE_KP_6 | SDLK_SCANCODE_MASK, + SDLK_KP_7 = (int)SDL_Scancode.SDL_SCANCODE_KP_7 | SDLK_SCANCODE_MASK, + SDLK_KP_8 = (int)SDL_Scancode.SDL_SCANCODE_KP_8 | SDLK_SCANCODE_MASK, + SDLK_KP_9 = (int)SDL_Scancode.SDL_SCANCODE_KP_9 | SDLK_SCANCODE_MASK, + SDLK_KP_0 = (int)SDL_Scancode.SDL_SCANCODE_KP_0 | SDLK_SCANCODE_MASK, + SDLK_KP_PERIOD = (int)SDL_Scancode.SDL_SCANCODE_KP_PERIOD | SDLK_SCANCODE_MASK, + + SDLK_APPLICATION = (int)SDL_Scancode.SDL_SCANCODE_APPLICATION | SDLK_SCANCODE_MASK, + SDLK_POWER = (int)SDL_Scancode.SDL_SCANCODE_POWER | SDLK_SCANCODE_MASK, + SDLK_KP_EQUALS = (int)SDL_Scancode.SDL_SCANCODE_KP_EQUALS | SDLK_SCANCODE_MASK, + SDLK_F13 = (int)SDL_Scancode.SDL_SCANCODE_F13 | SDLK_SCANCODE_MASK, + SDLK_F14 = (int)SDL_Scancode.SDL_SCANCODE_F14 | SDLK_SCANCODE_MASK, + SDLK_F15 = (int)SDL_Scancode.SDL_SCANCODE_F15 | SDLK_SCANCODE_MASK, + SDLK_F16 = (int)SDL_Scancode.SDL_SCANCODE_F16 | SDLK_SCANCODE_MASK, + SDLK_F17 = (int)SDL_Scancode.SDL_SCANCODE_F17 | SDLK_SCANCODE_MASK, + SDLK_F18 = (int)SDL_Scancode.SDL_SCANCODE_F18 | SDLK_SCANCODE_MASK, + SDLK_F19 = (int)SDL_Scancode.SDL_SCANCODE_F19 | SDLK_SCANCODE_MASK, + SDLK_F20 = (int)SDL_Scancode.SDL_SCANCODE_F20 | SDLK_SCANCODE_MASK, + SDLK_F21 = (int)SDL_Scancode.SDL_SCANCODE_F21 | SDLK_SCANCODE_MASK, + SDLK_F22 = (int)SDL_Scancode.SDL_SCANCODE_F22 | SDLK_SCANCODE_MASK, + SDLK_F23 = (int)SDL_Scancode.SDL_SCANCODE_F23 | SDLK_SCANCODE_MASK, + SDLK_F24 = (int)SDL_Scancode.SDL_SCANCODE_F24 | SDLK_SCANCODE_MASK, + SDLK_EXECUTE = (int)SDL_Scancode.SDL_SCANCODE_EXECUTE | SDLK_SCANCODE_MASK, + SDLK_HELP = (int)SDL_Scancode.SDL_SCANCODE_HELP | SDLK_SCANCODE_MASK, + SDLK_MENU = (int)SDL_Scancode.SDL_SCANCODE_MENU | SDLK_SCANCODE_MASK, + SDLK_SELECT = (int)SDL_Scancode.SDL_SCANCODE_SELECT | SDLK_SCANCODE_MASK, + SDLK_STOP = (int)SDL_Scancode.SDL_SCANCODE_STOP | SDLK_SCANCODE_MASK, + SDLK_AGAIN = (int)SDL_Scancode.SDL_SCANCODE_AGAIN | SDLK_SCANCODE_MASK, + SDLK_UNDO = (int)SDL_Scancode.SDL_SCANCODE_UNDO | SDLK_SCANCODE_MASK, + SDLK_CUT = (int)SDL_Scancode.SDL_SCANCODE_CUT | SDLK_SCANCODE_MASK, + SDLK_COPY = (int)SDL_Scancode.SDL_SCANCODE_COPY | SDLK_SCANCODE_MASK, + SDLK_PASTE = (int)SDL_Scancode.SDL_SCANCODE_PASTE | SDLK_SCANCODE_MASK, + SDLK_FIND = (int)SDL_Scancode.SDL_SCANCODE_FIND | SDLK_SCANCODE_MASK, + SDLK_MUTE = (int)SDL_Scancode.SDL_SCANCODE_MUTE | SDLK_SCANCODE_MASK, + SDLK_VOLUMEUP = (int)SDL_Scancode.SDL_SCANCODE_VOLUMEUP | SDLK_SCANCODE_MASK, + SDLK_VOLUMEDOWN = (int)SDL_Scancode.SDL_SCANCODE_VOLUMEDOWN | SDLK_SCANCODE_MASK, + SDLK_KP_COMMA = (int)SDL_Scancode.SDL_SCANCODE_KP_COMMA | SDLK_SCANCODE_MASK, + SDLK_KP_EQUALSAS400 = + (int)SDL_Scancode.SDL_SCANCODE_KP_EQUALSAS400 | SDLK_SCANCODE_MASK, + + SDLK_ALTERASE = (int)SDL_Scancode.SDL_SCANCODE_ALTERASE | SDLK_SCANCODE_MASK, + SDLK_SYSREQ = (int)SDL_Scancode.SDL_SCANCODE_SYSREQ | SDLK_SCANCODE_MASK, + SDLK_CANCEL = (int)SDL_Scancode.SDL_SCANCODE_CANCEL | SDLK_SCANCODE_MASK, + SDLK_CLEAR = (int)SDL_Scancode.SDL_SCANCODE_CLEAR | SDLK_SCANCODE_MASK, + SDLK_PRIOR = (int)SDL_Scancode.SDL_SCANCODE_PRIOR | SDLK_SCANCODE_MASK, + SDLK_RETURN2 = (int)SDL_Scancode.SDL_SCANCODE_RETURN2 | SDLK_SCANCODE_MASK, + SDLK_SEPARATOR = (int)SDL_Scancode.SDL_SCANCODE_SEPARATOR | SDLK_SCANCODE_MASK, + SDLK_OUT = (int)SDL_Scancode.SDL_SCANCODE_OUT | SDLK_SCANCODE_MASK, + SDLK_OPER = (int)SDL_Scancode.SDL_SCANCODE_OPER | SDLK_SCANCODE_MASK, + SDLK_CLEARAGAIN = (int)SDL_Scancode.SDL_SCANCODE_CLEARAGAIN | SDLK_SCANCODE_MASK, + SDLK_CRSEL = (int)SDL_Scancode.SDL_SCANCODE_CRSEL | SDLK_SCANCODE_MASK, + SDLK_EXSEL = (int)SDL_Scancode.SDL_SCANCODE_EXSEL | SDLK_SCANCODE_MASK, + + SDLK_KP_00 = (int)SDL_Scancode.SDL_SCANCODE_KP_00 | SDLK_SCANCODE_MASK, + SDLK_KP_000 = (int)SDL_Scancode.SDL_SCANCODE_KP_000 | SDLK_SCANCODE_MASK, + SDLK_THOUSANDSSEPARATOR = + (int)SDL_Scancode.SDL_SCANCODE_THOUSANDSSEPARATOR | SDLK_SCANCODE_MASK, + SDLK_DECIMALSEPARATOR = + (int)SDL_Scancode.SDL_SCANCODE_DECIMALSEPARATOR | SDLK_SCANCODE_MASK, + SDLK_CURRENCYUNIT = (int)SDL_Scancode.SDL_SCANCODE_CURRENCYUNIT | SDLK_SCANCODE_MASK, + SDLK_CURRENCYSUBUNIT = + (int)SDL_Scancode.SDL_SCANCODE_CURRENCYSUBUNIT | SDLK_SCANCODE_MASK, + SDLK_KP_LEFTPAREN = (int)SDL_Scancode.SDL_SCANCODE_KP_LEFTPAREN | SDLK_SCANCODE_MASK, + SDLK_KP_RIGHTPAREN = (int)SDL_Scancode.SDL_SCANCODE_KP_RIGHTPAREN | SDLK_SCANCODE_MASK, + SDLK_KP_LEFTBRACE = (int)SDL_Scancode.SDL_SCANCODE_KP_LEFTBRACE | SDLK_SCANCODE_MASK, + SDLK_KP_RIGHTBRACE = (int)SDL_Scancode.SDL_SCANCODE_KP_RIGHTBRACE | SDLK_SCANCODE_MASK, + SDLK_KP_TAB = (int)SDL_Scancode.SDL_SCANCODE_KP_TAB | SDLK_SCANCODE_MASK, + SDLK_KP_BACKSPACE = (int)SDL_Scancode.SDL_SCANCODE_KP_BACKSPACE | SDLK_SCANCODE_MASK, + SDLK_KP_A = (int)SDL_Scancode.SDL_SCANCODE_KP_A | SDLK_SCANCODE_MASK, + SDLK_KP_B = (int)SDL_Scancode.SDL_SCANCODE_KP_B | SDLK_SCANCODE_MASK, + SDLK_KP_C = (int)SDL_Scancode.SDL_SCANCODE_KP_C | SDLK_SCANCODE_MASK, + SDLK_KP_D = (int)SDL_Scancode.SDL_SCANCODE_KP_D | SDLK_SCANCODE_MASK, + SDLK_KP_E = (int)SDL_Scancode.SDL_SCANCODE_KP_E | SDLK_SCANCODE_MASK, + SDLK_KP_F = (int)SDL_Scancode.SDL_SCANCODE_KP_F | SDLK_SCANCODE_MASK, + SDLK_KP_XOR = (int)SDL_Scancode.SDL_SCANCODE_KP_XOR | SDLK_SCANCODE_MASK, + SDLK_KP_POWER = (int)SDL_Scancode.SDL_SCANCODE_KP_POWER | SDLK_SCANCODE_MASK, + SDLK_KP_PERCENT = (int)SDL_Scancode.SDL_SCANCODE_KP_PERCENT | SDLK_SCANCODE_MASK, + SDLK_KP_LESS = (int)SDL_Scancode.SDL_SCANCODE_KP_LESS | SDLK_SCANCODE_MASK, + SDLK_KP_GREATER = (int)SDL_Scancode.SDL_SCANCODE_KP_GREATER | SDLK_SCANCODE_MASK, + SDLK_KP_AMPERSAND = (int)SDL_Scancode.SDL_SCANCODE_KP_AMPERSAND | SDLK_SCANCODE_MASK, + SDLK_KP_DBLAMPERSAND = + (int)SDL_Scancode.SDL_SCANCODE_KP_DBLAMPERSAND | SDLK_SCANCODE_MASK, + SDLK_KP_VERTICALBAR = + (int)SDL_Scancode.SDL_SCANCODE_KP_VERTICALBAR | SDLK_SCANCODE_MASK, + SDLK_KP_DBLVERTICALBAR = + (int)SDL_Scancode.SDL_SCANCODE_KP_DBLVERTICALBAR | SDLK_SCANCODE_MASK, + SDLK_KP_COLON = (int)SDL_Scancode.SDL_SCANCODE_KP_COLON | SDLK_SCANCODE_MASK, + SDLK_KP_HASH = (int)SDL_Scancode.SDL_SCANCODE_KP_HASH | SDLK_SCANCODE_MASK, + SDLK_KP_SPACE = (int)SDL_Scancode.SDL_SCANCODE_KP_SPACE | SDLK_SCANCODE_MASK, + SDLK_KP_AT = (int)SDL_Scancode.SDL_SCANCODE_KP_AT | SDLK_SCANCODE_MASK, + SDLK_KP_EXCLAM = (int)SDL_Scancode.SDL_SCANCODE_KP_EXCLAM | SDLK_SCANCODE_MASK, + SDLK_KP_MEMSTORE = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMSTORE | SDLK_SCANCODE_MASK, + SDLK_KP_MEMRECALL = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMRECALL | SDLK_SCANCODE_MASK, + SDLK_KP_MEMCLEAR = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMCLEAR | SDLK_SCANCODE_MASK, + SDLK_KP_MEMADD = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMADD | SDLK_SCANCODE_MASK, + SDLK_KP_MEMSUBTRACT = + (int)SDL_Scancode.SDL_SCANCODE_KP_MEMSUBTRACT | SDLK_SCANCODE_MASK, + SDLK_KP_MEMMULTIPLY = + (int)SDL_Scancode.SDL_SCANCODE_KP_MEMMULTIPLY | SDLK_SCANCODE_MASK, + SDLK_KP_MEMDIVIDE = (int)SDL_Scancode.SDL_SCANCODE_KP_MEMDIVIDE | SDLK_SCANCODE_MASK, + SDLK_KP_PLUSMINUS = (int)SDL_Scancode.SDL_SCANCODE_KP_PLUSMINUS | SDLK_SCANCODE_MASK, + SDLK_KP_CLEAR = (int)SDL_Scancode.SDL_SCANCODE_KP_CLEAR | SDLK_SCANCODE_MASK, + SDLK_KP_CLEARENTRY = (int)SDL_Scancode.SDL_SCANCODE_KP_CLEARENTRY | SDLK_SCANCODE_MASK, + SDLK_KP_BINARY = (int)SDL_Scancode.SDL_SCANCODE_KP_BINARY | SDLK_SCANCODE_MASK, + SDLK_KP_OCTAL = (int)SDL_Scancode.SDL_SCANCODE_KP_OCTAL | SDLK_SCANCODE_MASK, + SDLK_KP_DECIMAL = (int)SDL_Scancode.SDL_SCANCODE_KP_DECIMAL | SDLK_SCANCODE_MASK, + SDLK_KP_HEXADECIMAL = + (int)SDL_Scancode.SDL_SCANCODE_KP_HEXADECIMAL | SDLK_SCANCODE_MASK, + + SDLK_LCTRL = (int)SDL_Scancode.SDL_SCANCODE_LCTRL | SDLK_SCANCODE_MASK, + SDLK_LSHIFT = (int)SDL_Scancode.SDL_SCANCODE_LSHIFT | SDLK_SCANCODE_MASK, + SDLK_LALT = (int)SDL_Scancode.SDL_SCANCODE_LALT | SDLK_SCANCODE_MASK, + SDLK_LGUI = (int)SDL_Scancode.SDL_SCANCODE_LGUI | SDLK_SCANCODE_MASK, + SDLK_RCTRL = (int)SDL_Scancode.SDL_SCANCODE_RCTRL | SDLK_SCANCODE_MASK, + SDLK_RSHIFT = (int)SDL_Scancode.SDL_SCANCODE_RSHIFT | SDLK_SCANCODE_MASK, + SDLK_RALT = (int)SDL_Scancode.SDL_SCANCODE_RALT | SDLK_SCANCODE_MASK, + SDLK_RGUI = (int)SDL_Scancode.SDL_SCANCODE_RGUI | SDLK_SCANCODE_MASK, + + SDLK_MODE = (int)SDL_Scancode.SDL_SCANCODE_MODE | SDLK_SCANCODE_MASK, + + SDLK_AUDIONEXT = (int)SDL_Scancode.SDL_SCANCODE_AUDIONEXT | SDLK_SCANCODE_MASK, + SDLK_AUDIOPREV = (int)SDL_Scancode.SDL_SCANCODE_AUDIOPREV | SDLK_SCANCODE_MASK, + SDLK_AUDIOSTOP = (int)SDL_Scancode.SDL_SCANCODE_AUDIOSTOP | SDLK_SCANCODE_MASK, + SDLK_AUDIOPLAY = (int)SDL_Scancode.SDL_SCANCODE_AUDIOPLAY | SDLK_SCANCODE_MASK, + SDLK_AUDIOMUTE = (int)SDL_Scancode.SDL_SCANCODE_AUDIOMUTE | SDLK_SCANCODE_MASK, + SDLK_MEDIASELECT = (int)SDL_Scancode.SDL_SCANCODE_MEDIASELECT | SDLK_SCANCODE_MASK, + SDLK_WWW = (int)SDL_Scancode.SDL_SCANCODE_WWW | SDLK_SCANCODE_MASK, + SDLK_MAIL = (int)SDL_Scancode.SDL_SCANCODE_MAIL | SDLK_SCANCODE_MASK, + SDLK_CALCULATOR = (int)SDL_Scancode.SDL_SCANCODE_CALCULATOR | SDLK_SCANCODE_MASK, + SDLK_COMPUTER = (int)SDL_Scancode.SDL_SCANCODE_COMPUTER | SDLK_SCANCODE_MASK, + SDLK_AC_SEARCH = (int)SDL_Scancode.SDL_SCANCODE_AC_SEARCH | SDLK_SCANCODE_MASK, + SDLK_AC_HOME = (int)SDL_Scancode.SDL_SCANCODE_AC_HOME | SDLK_SCANCODE_MASK, + SDLK_AC_BACK = (int)SDL_Scancode.SDL_SCANCODE_AC_BACK | SDLK_SCANCODE_MASK, + SDLK_AC_FORWARD = (int)SDL_Scancode.SDL_SCANCODE_AC_FORWARD | SDLK_SCANCODE_MASK, + SDLK_AC_STOP = (int)SDL_Scancode.SDL_SCANCODE_AC_STOP | SDLK_SCANCODE_MASK, + SDLK_AC_REFRESH = (int)SDL_Scancode.SDL_SCANCODE_AC_REFRESH | SDLK_SCANCODE_MASK, + SDLK_AC_BOOKMARKS = (int)SDL_Scancode.SDL_SCANCODE_AC_BOOKMARKS | SDLK_SCANCODE_MASK, + + SDLK_BRIGHTNESSDOWN = + (int)SDL_Scancode.SDL_SCANCODE_BRIGHTNESSDOWN | SDLK_SCANCODE_MASK, + SDLK_BRIGHTNESSUP = (int)SDL_Scancode.SDL_SCANCODE_BRIGHTNESSUP | SDLK_SCANCODE_MASK, + SDLK_DISPLAYSWITCH = (int)SDL_Scancode.SDL_SCANCODE_DISPLAYSWITCH | SDLK_SCANCODE_MASK, + SDLK_KBDILLUMTOGGLE = + (int)SDL_Scancode.SDL_SCANCODE_KBDILLUMTOGGLE | SDLK_SCANCODE_MASK, + SDLK_KBDILLUMDOWN = (int)SDL_Scancode.SDL_SCANCODE_KBDILLUMDOWN | SDLK_SCANCODE_MASK, + SDLK_KBDILLUMUP = (int)SDL_Scancode.SDL_SCANCODE_KBDILLUMUP | SDLK_SCANCODE_MASK, + SDLK_EJECT = (int)SDL_Scancode.SDL_SCANCODE_EJECT | SDLK_SCANCODE_MASK, + SDLK_SLEEP = (int)SDL_Scancode.SDL_SCANCODE_SLEEP | SDLK_SCANCODE_MASK + } + + /* Key modifiers (bitfield) */ + [Flags] + public enum SDL_Keymod : ushort + { + KMOD_NONE = 0x0000, + KMOD_LSHIFT = 0x0001, + KMOD_RSHIFT = 0x0002, + KMOD_LCTRL = 0x0040, + KMOD_RCTRL = 0x0080, + KMOD_LALT = 0x0100, + KMOD_RALT = 0x0200, + KMOD_LGUI = 0x0400, + KMOD_RGUI = 0x0800, + KMOD_NUM = 0x1000, + KMOD_CAPS = 0x2000, + KMOD_MODE = 0x4000, + KMOD_RESERVED = 0x8000, + + /* These are defines in the SDL headers */ + KMOD_CTRL = (KMOD_LCTRL | KMOD_RCTRL), + KMOD_SHIFT = (KMOD_LSHIFT | KMOD_RSHIFT), + KMOD_ALT = (KMOD_LALT | KMOD_RALT), + KMOD_GUI = (KMOD_LGUI | KMOD_RGUI) + } + + #endregion + + #region SDL_keyboard.h + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_Keysym + { + public SDL_Scancode scancode; + public SDL_Keycode sym; + public SDL_Keymod mod; /* UInt16 */ + public UInt32 unicode; /* Deprecated */ + } + + /* Get the window which has kbd focus */ + /* Return type is an SDL_Window pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetKeyboardFocus(); + + /* Get a snapshot of the keyboard state. */ + /* Return value is a pointer to a UInt8 array */ + /* Numkeys returns the size of the array if non-null */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetKeyboardState(out int numkeys); + + /* Get the current key modifier state for the keyboard. */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_Keymod SDL_GetModState(); + + /* Set the current key modifier state */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetModState(SDL_Keymod modstate); + + /* Get the key code corresponding to the given scancode + * with the current keyboard layout. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_Keycode SDL_GetKeyFromScancode(SDL_Scancode scancode); + + /* Get the scancode for the given keycode */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_Scancode SDL_GetScancodeFromKey(SDL_Keycode key); + + /* Wrapper for SDL_GetScancodeName */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetScancodeName(SDL_Scancode scancode); + + /* Get a scancode from a human-readable name */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_Scancode SDL_GetScancodeFromName( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] string name + ); + + /* Wrapper for SDL_GetKeyName */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetKeyName(SDL_Keycode key); + + /* Get a key code from a human-readable name */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_Keycode SDL_GetKeyFromName( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] string name + ); + + /* Start accepting Unicode text input events, show keyboard */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_StartTextInput(); + + /* Check if unicode input events are enabled */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_IsTextInputActive(); + + /* Stop receiving any text input events, hide onscreen kbd */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_StopTextInput(); + + /* Set the rectangle used for text input, hint for IME */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetTextInputRect(ref SDL_Rect rect); + + /* Does the platform support an on-screen keyboard? */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_HasScreenKeyboardSupport(); + + /* Is the on-screen keyboard shown for a given window? */ + /* window is an SDL_Window pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_IsScreenKeyboardShown(IntPtr window); + + #endregion + + #region SDL_mouse.c + + /* Note: SDL_Cursor is a typedef normally. We'll treat it as + * an IntPtr, because C# doesn't do typedefs. Yay! + */ + + /* System cursor types */ + public enum SDL_SystemCursor + { + SDL_SYSTEM_CURSOR_ARROW, // Arrow + SDL_SYSTEM_CURSOR_IBEAM, // I-beam + SDL_SYSTEM_CURSOR_WAIT, // Wait + SDL_SYSTEM_CURSOR_CROSSHAIR, // Crosshair + SDL_SYSTEM_CURSOR_WAITARROW, // Small wait cursor (or Wait if not available) + SDL_SYSTEM_CURSOR_SIZENWSE, // Double arrow pointing northwest and southeast + SDL_SYSTEM_CURSOR_SIZENESW, // Double arrow pointing northeast and southwest + SDL_SYSTEM_CURSOR_SIZEWE, // Double arrow pointing west and east + SDL_SYSTEM_CURSOR_SIZENS, // Double arrow pointing north and south + SDL_SYSTEM_CURSOR_SIZEALL, // Four pointed arrow pointing north, south, east, and west + SDL_SYSTEM_CURSOR_NO, // Slashed circle or crossbones + SDL_SYSTEM_CURSOR_HAND, // Hand + SDL_NUM_SYSTEM_CURSORS + } + + /* Get the window which currently has mouse focus */ + /* Return value is an SDL_Window pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetMouseFocus(); + + /* Get the current state of the mouse */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 SDL_GetMouseState(out int x, out int y); + + /* Get the current state of the mouse */ + /* This overload allows for passing NULL to x */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 SDL_GetMouseState(IntPtr x, out int y); + + /* Get the current state of the mouse */ + /* This overload allows for passing NULL to y */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 SDL_GetMouseState(out int x, IntPtr y); + + /* Get the current state of the mouse */ + /* This overload allows for passing NULL to both x and y */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 SDL_GetMouseState(IntPtr x, IntPtr y); + + /* Get the mouse state with relative coords*/ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 SDL_GetRelativeMouseState(out int x, out int y); + + /* Set the mouse cursor's position (within a window) */ + /* window is an SDL_Window pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_WarpMouseInWindow(IntPtr window, int x, int y); + + /* Enable/Disable relative mouse mode (grabs mouse, rel coords) */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_SetRelativeMouseMode(SDL_bool enabled); + + /* Query if the relative mouse mode is enabled */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_GetRelativeMouseMode(); + + /* Create a cursor from bitmap data (amd mask) in MSB format */ + /* data and mask are byte arrays, and w must be a multiple of 8 */ + /* return value is an SDL_Cursor pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateCursor( + IntPtr data, + IntPtr mask, + int w, + int h, + int hot_x, + int hot_y + ); + + /* Create a cursor from an SDL_Surface */ + /* IntPtr refers to an SDL_Cursor*, surface to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateColorCursor( + IntPtr surface, + int hot_x, + int hot_y + ); + + /* Create a cursor from a system cursor id */ + /* return value is an SDL_Cursor pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_CreateSystemCursor(SDL_SystemCursor id); + + /* Set the active cursor */ + /* cursor is an SDL_Cursor pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_SetCursor(IntPtr cursor); + + /* Return the active cursor */ + /* return value is an SDL_Cursor pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetCursor(); + + /* Frees a cursor created with one of the CreateCursor functions */ + /* cursor in an SDL_Cursor pointer */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_FreeCursor(IntPtr cursor); + + /* Toggle whether or not the cursor is shown */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_ShowCursor(int toggle); + + public static uint SDL_BUTTON(uint X) + { + // If only there were a better way of doing this in C# + return (uint) (1 << ((int) X - 1)); + } + + public const uint SDL_BUTTON_LEFT = 1; + public const uint SDL_BUTTON_MIDDLE = 2; + public const uint SDL_BUTTON_RIGHT = 3; + public const uint SDL_BUTTON_X1 = 4; + public const uint SDL_BUTTON_X2 = 5; + public static readonly UInt32 SDL_BUTTON_LMASK = SDL_BUTTON(SDL_BUTTON_LEFT); + public static readonly UInt32 SDL_BUTTON_MMASK = SDL_BUTTON(SDL_BUTTON_MIDDLE); + public static readonly UInt32 SDL_BUTTON_RMASK = SDL_BUTTON(SDL_BUTTON_RIGHT); + public static readonly UInt32 SDL_BUTTON_X1MASK = SDL_BUTTON(SDL_BUTTON_X1); + public static readonly UInt32 SDL_BUTTON_X2MASK = SDL_BUTTON(SDL_BUTTON_X2); + + #endregion + + #region SDL_touch.h + + public const uint SDL_TOUCH_MOUSEID = uint.MaxValue; + + public struct SDL_Finger + { + public long id; // SDL_FingerID + public float x; + public float y; + public float pressure; + } + + /** + * \brief Get the number of registered touch devices. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetNumTouchDevices(); + + /** + * \brief Get the touch ID with the given index, or 0 if the index is invalid. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern long SDL_GetTouchDevice(int index); + + /** + * \brief Get the number of active fingers for a given touch device. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetNumTouchFingers(long touchID); + + /** + * \brief Get the finger object of the given touch, with the given index. + * Returns pointer to SDL_Finger. + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GetTouchFinger(long touchID, int index); + + #endregion + + #region SDL_joystick.h + + public const byte SDL_HAT_CENTERED = 0x00; + public const byte SDL_HAT_UP = 0x01; + public const byte SDL_HAT_RIGHT = 0x02; + public const byte SDL_HAT_DOWN = 0x04; + public const byte SDL_HAT_LEFT = 0x08; + public const byte SDL_HAT_RIGHTUP = SDL_HAT_RIGHT | SDL_HAT_UP; + public const byte SDL_HAT_RIGHTDOWN = SDL_HAT_RIGHT | SDL_HAT_DOWN; + public const byte SDL_HAT_LEFTUP = SDL_HAT_LEFT | SDL_HAT_UP; + public const byte SDL_HAT_LEFTDOWN = SDL_HAT_LEFT | SDL_HAT_DOWN; + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_JoystickClose(IntPtr joystick); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickEventState(int state); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern short SDL_JoystickGetAxis( + IntPtr joystick, + int axis + ); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickGetBall( + IntPtr joystick, + int ball, + out int dx, + out int dy + ); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern byte SDL_JoystickGetButton( + IntPtr joystick, + int button + ); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern byte SDL_JoystickGetHat( + IntPtr joystick, + int hat + ); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_JoystickName( + IntPtr joystick + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_JoystickNameForIndex( + int device_index + ); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickNumAxes(IntPtr joystick); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickNumBalls(IntPtr joystick); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickNumButtons(IntPtr joystick); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickNumHats(IntPtr joystick); + + /* IntPtr refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_JoystickOpen(int device_index); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickOpened(int device_index); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_JoystickUpdate(); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_NumJoysticks(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern Guid SDL_JoystickGetDeviceGUID( + int device_index + ); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern Guid SDL_JoystickGetGUID( + IntPtr joystick + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_JoystickGetGUIDString( + Guid guid, + byte[] pszGUID, + int cbGUID + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern Guid SDL_JoystickGetGUIDFromString( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string pchGUID + ); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_JoystickGetAttached(IntPtr joystick); + + /* int refers to an SDL_JoystickID, joystick to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickInstanceID(IntPtr joystick); + + #endregion + + #region SDL_gamecontroller.h + + public enum SDL_GameControllerBindType + { + SDL_CONTROLLER_BINDTYPE_NONE, + SDL_CONTROLLER_BINDTYPE_BUTTON, + SDL_CONTROLLER_BINDTYPE_AXIS, + SDL_CONTROLLER_BINDTYPE_HAT + } + + public enum SDL_GameControllerAxis + { + SDL_CONTROLLER_AXIS_INVALID = -1, + SDL_CONTROLLER_AXIS_LEFTX, + SDL_CONTROLLER_AXIS_LEFTY, + SDL_CONTROLLER_AXIS_RIGHTX, + SDL_CONTROLLER_AXIS_RIGHTY, + SDL_CONTROLLER_AXIS_TRIGGERLEFT, + SDL_CONTROLLER_AXIS_TRIGGERRIGHT, + SDL_CONTROLLER_AXIS_MAX + } + + public enum SDL_GameControllerButton + { + SDL_CONTROLLER_BUTTON_INVALID = -1, + SDL_CONTROLLER_BUTTON_A, + SDL_CONTROLLER_BUTTON_B, + SDL_CONTROLLER_BUTTON_X, + SDL_CONTROLLER_BUTTON_Y, + SDL_CONTROLLER_BUTTON_BACK, + SDL_CONTROLLER_BUTTON_GUIDE, + SDL_CONTROLLER_BUTTON_START, + SDL_CONTROLLER_BUTTON_LEFTSTICK, + SDL_CONTROLLER_BUTTON_RIGHTSTICK, + SDL_CONTROLLER_BUTTON_LEFTSHOULDER, + SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, + SDL_CONTROLLER_BUTTON_DPAD_UP, + SDL_CONTROLLER_BUTTON_DPAD_DOWN, + SDL_CONTROLLER_BUTTON_DPAD_LEFT, + SDL_CONTROLLER_BUTTON_DPAD_RIGHT, + SDL_CONTROLLER_BUTTON_MAX, + } + + // FIXME: I'd rather this somehow be private... + [StructLayout(LayoutKind.Sequential)] + public struct INTERNAL_GameControllerButtonBind_hat + { + public int hat; + public int hat_mask; + } + + /* This struct has a union in it, hence the Explicit layout. */ + [StructLayout(LayoutKind.Explicit)] + public struct SDL_GameControllerButtonBind + { + /* Note: enum size is 4 bytes. */ + [FieldOffset(0)] + public SDL_GameControllerBindType bindType; + [FieldOffset(4)] + public int button; + [FieldOffset(4)] + public int axis; + [FieldOffset(4)] + public INTERNAL_GameControllerButtonBind_hat hat; + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GameControllerAddMapping( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string mappingString + ); + + /* THIS IS AN RWops FUNCTION! */ + [DllImport(nativeLibName, EntryPoint = "SDL_GameControllerAddMappingsFromRW", CallingConvention = CallingConvention.Cdecl)] + private static extern int INTERNAL_SDL_GameControllerAddMappingsFromRW( + IntPtr rw, + int freerw + ); + public static int SDL_GameControllerAddMappingsFromFile(string file) + { + IntPtr rwops = INTERNAL_SDL_RWFromFile(file, "rb"); + return INTERNAL_SDL_GameControllerAddMappingsFromRW(rwops, 1); + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GameControllerMappingForGUID( + Guid guid + ); + + /* gamecontroller refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GameControllerMapping( + IntPtr gamecontroller + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_IsGameController(int joystick_index); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GameControllerNameForIndex( + int joystick_index + ); + + /* IntPtr refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GameControllerOpen(int joystick_index); + + /* gamecontroller refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GameControllerName( + IntPtr gamecontroller + ); + + /* gamecontroller refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_GameControllerGetAttached( + IntPtr gamecontroller + ); + + /* IntPtr refers to an SDL_Joystick* + * gamecontroller refers to an SDL_GameController* + */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_GameControllerGetJoystick( + IntPtr gamecontroller + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GameControllerEventState(int state); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GameControllerUpdate(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_GameControllerAxis SDL_GameControllerGetAxisFromString( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string pchString + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GameControllerGetStringForAxis( + SDL_GameControllerAxis axis + ); + + /* gamecontroller refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis( + IntPtr gamecontroller, + SDL_GameControllerAxis axis + ); + + /* gamecontroller refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern short SDL_GameControllerGetAxis( + IntPtr gamecontroller, + SDL_GameControllerAxis axis + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_GameControllerButton SDL_GameControllerGetButtonFromString( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string pchString + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GameControllerGetStringForButton( + SDL_GameControllerButton button + ); + + /* gamecontroller refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton( + IntPtr gamecontroller, + SDL_GameControllerButton button + ); + + /* gamecontroller refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern byte SDL_GameControllerGetButton( + IntPtr gamecontroller, + SDL_GameControllerButton button + ); + + /* gamecontroller refers to an SDL_GameController* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_GameControllerClose( + IntPtr gamecontroller + ); + + #endregion + + #region SDL_haptic.h + + /* SDL_HapticEffect type */ + public const ushort SDL_HAPTIC_CONSTANT = (1 << 0); + public const ushort SDL_HAPTIC_SINE = (1 << 1); + public const ushort SDL_HAPTIC_LEFTRIGHT = (1 << 2); + public const ushort SDL_HAPTIC_TRIANGLE = (1 << 3); + public const ushort SDL_HAPTIC_SAWTOOTHUP = (1 << 4); + public const ushort SDL_HAPTIC_SAWTOOTHDOWN = (1 << 5); + public const ushort SDL_HAPTIC_SPRING = (1 << 7); + public const ushort SDL_HAPTIC_DAMPER = (1 << 8); + public const ushort SDL_HAPTIC_INERTIA = (1 << 9); + public const ushort SDL_HAPTIC_FRICTION = (1 << 10); + public const ushort SDL_HAPTIC_CUSTOM = (1 << 11); + public const ushort SDL_HAPTIC_GAIN = (1 << 12); + public const ushort SDL_HAPTIC_AUTOCENTER = (1 << 13); + public const ushort SDL_HAPTIC_STATUS = (1 << 14); + public const ushort SDL_HAPTIC_PAUSE = (1 << 15); + + /* SDL_HapticDirection type */ + public const byte SDL_HAPTIC_POLAR = 0; + public const byte SDL_HAPTIC_CARTESIAN = 1; + public const byte SDL_HAPTIC_SPHERICAL = 2; + + /* SDL_HapticRunEffect */ + public const uint SDL_HAPTIC_INFINITY = 4292967295U; + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct SDL_HapticDirection + { + public byte type; + public fixed int dir[3]; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_HapticConstant + { + // Header + public ushort type; + public SDL_HapticDirection direction; + // Replay + public uint length; + public ushort delay; + // Trigger + public ushort button; + public ushort interval; + // Constant + public short level; + // Envelope + public ushort attack_length; + public ushort attack_level; + public ushort fade_length; + public ushort fade_level; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_HapticPeriodic + { + // Header + public ushort type; + public SDL_HapticDirection direction; + // Replay + public uint length; + public ushort delay; + // Trigger + public ushort button; + public ushort interval; + // Periodic + public ushort period; + public short magnitude; + public short offset; + public ushort phase; + // Envelope + public ushort attack_length; + public ushort attack_level; + public ushort fade_length; + public ushort fade_level; + } + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct SDL_HapticCondition + { + // Header + public ushort type; + public SDL_HapticDirection direction; + // Replay + public uint length; + public ushort delay; + // Trigger + public ushort button; + public ushort interval; + // Condition + public fixed ushort right_sat[3]; + public fixed ushort left_sat[3]; + public fixed short right_coeff[3]; + public fixed short left_coeff[3]; + public fixed ushort deadband[3]; + public fixed short center[3]; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_HapticRamp + { + // Header + public ushort type; + public SDL_HapticDirection direction; + // Replay + public uint length; + public ushort delay; + // Trigger + public ushort button; + public ushort interval; + // Ramp + public short start; + public short end; + // Envelope + public ushort attack_length; + public ushort attack_level; + public ushort fade_length; + public ushort fade_level; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_HapticLeftRight + { + // Header + public ushort type; + // Replay + public uint length; + // Rumble + public ushort large_magnitude; + public ushort small_magnitude; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_HapticCustom + { + // Header + public ushort type; + public SDL_HapticDirection direction; + // Replay + public uint length; + public ushort delay; + // Trigger + public ushort button; + public ushort interval; + // Custom + public byte channels; + public ushort period; + public ushort samples; + public IntPtr data; // Uint16* + // Envelope + public ushort attack_length; + public ushort attack_level; + public ushort fade_length; + public ushort fade_level; + } + + [StructLayout(LayoutKind.Explicit)] + public struct SDL_HapticEffect + { + [FieldOffset(0)] + public ushort type; + [FieldOffset(0)] + public SDL_HapticConstant constant; + [FieldOffset(0)] + public SDL_HapticPeriodic periodic; + [FieldOffset(0)] + public SDL_HapticCondition condition; + [FieldOffset(0)] + public SDL_HapticRamp ramp; + [FieldOffset(0)] + public SDL_HapticLeftRight leftright; + [FieldOffset(0)] + public SDL_HapticCustom custom; + } + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_HapticClose(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_HapticDestroyEffect( + IntPtr haptic, + int effect + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticEffectSupported( + IntPtr haptic, + ref SDL_HapticEffect effect + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticGetEffectStatus( + IntPtr haptic, + int effect + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticIndex(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_HapticName(int device_index); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticNewEffect( + IntPtr haptic, + ref SDL_HapticEffect effect + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticNumAxes(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticNumEffects(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticNumEffectsPlaying(IntPtr haptic); + + /* IntPtr refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_HapticOpen(int device_index); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticOpened(int device_index); + + /* IntPtr refers to an SDL_Haptic*, joystick to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_HapticOpenFromJoystick( + IntPtr joystick + ); + + /* IntPtr refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr SDL_HapticOpenFromMouse(); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticPause(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_HapticQuery(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticRumbleInit(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticRumblePlay( + IntPtr haptic, + float strength, + uint length + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticRumbleStop(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticRumbleSupported(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticRunEffect( + IntPtr haptic, + int effect, + uint iterations + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticSetAutocenter( + IntPtr haptic, + int autocenter + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticSetGain( + IntPtr haptic, + int gain + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticStopAll(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticStopEffect( + IntPtr haptic, + int effect + ); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticUnpause(IntPtr haptic); + + /* haptic refers to an SDL_Haptic* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_HapticUpdateEffect( + IntPtr haptic, + int effect, + ref SDL_HapticEffect data + ); + + /* joystick refers to an SDL_Joystick* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_JoystickIsHaptic(IntPtr joystick); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_MouseIsHaptic(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_NumHaptics(); + + #endregion + + #region SDL_audio.h + + public const ushort SDL_AUDIO_MASK_BITSIZE = 0xFF; + public const ushort SDL_AUDIO_MASK_DATATYPE = (1 << 8); + public const ushort SDL_AUDIO_MASK_ENDIAN = (1 << 12); + public const ushort SDL_AUDIO_MASK_SIGNED = (1 << 15); + + public static ushort SDL_AUDIO_BITSIZE(ushort x) + { + return (ushort) (x & SDL_AUDIO_MASK_BITSIZE); + } + + public static bool SDL_AUDIO_ISFLOAT(ushort x) + { + return (x & SDL_AUDIO_MASK_DATATYPE) != 0; + } + + public static bool SDL_AUDIO_ISBIGENDIAN(ushort x) + { + return (x & SDL_AUDIO_MASK_ENDIAN) != 0; + } + + public static bool SDL_AUDIO_ISSIGNED(ushort x) + { + return (x & SDL_AUDIO_MASK_SIGNED) != 0; + } + + public static bool SDL_AUDIO_ISINT(ushort x) + { + return (x & SDL_AUDIO_MASK_DATATYPE) == 0; + } + + public static bool SDL_AUDIO_ISLITTLEENDIAN(ushort x) + { + return (x & SDL_AUDIO_MASK_ENDIAN) == 0; + } + + public static bool SDL_AUDIO_ISUNSIGNED(ushort x) + { + return (x & SDL_AUDIO_MASK_SIGNED) == 0; + } + + public const ushort AUDIO_U8 = 0x0008; + public const ushort AUDIO_S8 = 0x8008; + public const ushort AUDIO_U16LSB = 0x0010; + public const ushort AUDIO_S16LSB = 0x8010; + public const ushort AUDIO_U16MSB = 0x1010; + public const ushort AUDIO_S16MSB = 0x9010; + public const ushort AUDIO_U16 = AUDIO_U16LSB; + public const ushort AUDIO_S16 = AUDIO_S16LSB; + public const ushort AUDIO_S32LSB = 0x8020; + public const ushort AUDIO_S32MSB = 0x9020; + public const ushort AUDIO_S32 = AUDIO_S32LSB; + public const ushort AUDIO_F32LSB = 0x8120; + public const ushort AUDIO_F32MSB = 0x9120; + public const ushort AUDIO_F32 = AUDIO_F32LSB; + + public static readonly ushort AUDIO_U16SYS = + BitConverter.IsLittleEndian ? AUDIO_U16LSB : AUDIO_U16MSB; + public static readonly ushort AUDIO_S16SYS = + BitConverter.IsLittleEndian ? AUDIO_S16LSB : AUDIO_S16MSB; + public static readonly ushort AUDIO_S32SYS = + BitConverter.IsLittleEndian ? AUDIO_S32LSB : AUDIO_S32MSB; + public static readonly ushort AUDIO_F32SYS = + BitConverter.IsLittleEndian ? AUDIO_F32LSB : AUDIO_F32MSB; + + public const uint SDL_AUDIO_ALLOW_FREQUENCY_CHANGE = 0x00000001; + public const uint SDL_AUDIO_ALLOW_FORMAT_CHANGE = 0x00000001; + public const uint SDL_AUDIO_ALLOW_CHANNELS_CHANGE = 0x00000001; + public const uint SDL_AUDIO_ALLOW_ANY_CHANGE = ( + SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | + SDL_AUDIO_ALLOW_FORMAT_CHANGE | + SDL_AUDIO_ALLOW_CHANNELS_CHANGE + ); + + public const int SDL_MIX_MAXVOLUME = 128; + + public enum SDL_AudioStatus + { + SDL_AUDIO_STOPPED, + SDL_AUDIO_PLAYING, + SDL_AUDIO_PAUSED + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_AudioSpec + { + public int freq; + public ushort format; // SDL_AudioFormat + public byte channels; + public byte silence; + public ushort samples; + public uint size; + public SDL_AudioCallback callback; + public IntPtr userdata; // void* + } + + /* userdata refers to a void*, stream to a Uint8 */ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void SDL_AudioCallback( + IntPtr userdata, + IntPtr stream, + int len + ); + + /* dev refers to an SDL_AudioDeviceID */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_AudioDeviceConnected(uint dev); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_AudioInit( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string driver_name + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_AudioQuit(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_CloseAudio(); + + /* dev refers to an SDL_AudioDeviceID */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_CloseAudioDevice(uint dev); + + /* audio_buf refers to a malloc()'d buffer from SDL_LoadWAV */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_FreeWAV(IntPtr audio_buf); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetAudioDeviceName( + int index, + int iscapture + ); + + /* dev refers to an SDL_AudioDeviceID */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_AudioStatus SDL_GetAudioDeviceStatus( + uint dev + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetAudioDriver(int index); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_AudioStatus SDL_GetAudioStatus(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string SDL_GetCurrentAudioDriver(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetNumAudioDevices(int iscapture); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetNumAudioDrivers(); + + /* audio_buf will refer to a malloc()'d byte buffer */ + /* THIS IS AN RWops FUNCTION! */ + [DllImport(nativeLibName, EntryPoint = "SDL_LoadWAV_RW", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr INTERNAL_SDL_LoadWAV_RW( + IntPtr src, + int freesrc, + ref SDL_AudioSpec spec, + out IntPtr audio_buf, + out uint audio_len + ); + public static SDL_AudioSpec SDL_LoadWAV( + string file, + ref SDL_AudioSpec spec, + out IntPtr audio_buf, + out uint audio_len + ) { + SDL_AudioSpec result; + IntPtr rwops = INTERNAL_SDL_RWFromFile(file, "rb"); + IntPtr result_ptr = INTERNAL_SDL_LoadWAV_RW( + rwops, + 1, + ref spec, + out audio_buf, + out audio_len + ); + result = (SDL_AudioSpec) Marshal.PtrToStructure( + result_ptr, + typeof(SDL_AudioSpec) + ); + return result; + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LockAudio(); + + /* dev refers to an SDL_AudioDeviceID */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_LockAudioDevice(uint dev); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_MixAudio( + [Out()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 2)] + byte[] dst, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 2)] + byte[] src, + uint len, + int volume + ); + + /* format refers to an SDL_AudioFormat */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_MixAudioFormat( + [Out()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 3)] + byte[] dst, + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 3)] + byte[] src, + ushort format, + uint len, + int volume + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_OpenAudio( + ref SDL_AudioSpec desired, + out SDL_AudioSpec obtained + ); + + /* uint refers to an SDL_AudioDeviceID */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint SDL_OpenAudioDevice( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string device, + int iscapture, + ref SDL_AudioSpec desired, + out SDL_AudioSpec obtained, + int allowed_changes + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_PauseAudio(int pause_on); + + /* dev refers to an SDL_AudioDeviceID */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_PauseAudioDevice( + uint dev, + int pause_on + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_UnlockAudio(); + + /* dev refers to an SDL_AudioDeviceID */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_UnlockAudioDevice(uint dev); + + #endregion + + #region SDL_timer.h + + /* System timers rely on different OS mechanisms depending on + * which operating system SDL2 is compiled against. + */ + + /* Compare tick values, return true if A has passed B. Introduced in SDL 2.0.1, + * but does not require it (it was a macro). + */ + public static bool SDL_TICKS_PASSED(UInt32 A, UInt32 B) + { + return ((Int32)(B - A) <= 0); + } + + /* Delays the thread's processing based on the milliseconds parameter */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SDL_Delay(UInt32 ms); + + /* Returns the milliseconds that have passed since SDL was initialized */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 SDL_GetTicks(); + + /* Get the current value of the high resolution counter */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt64 SDL_GetPerformanceCounter(); + + /* Get the count per second of the high resolution counter */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt64 SDL_GetPerformanceFrequency(); + + /* param refers to a void* */ + public delegate UInt32 SDL_TimerCallback(UInt32 interval, IntPtr param); + + /* int refers to an SDL_TimerID, param to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_AddTimer( + UInt32 interval, + SDL_TimerCallback callback, + IntPtr param + ); + + /* id refers to an SDL_TimerID */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_RemoveTimer(int id); + + #endregion + + #region SDL_syswm.h + + public enum SDL_SYSWM_TYPE + { + SDL_SYSWM_UNKNOWN, + SDL_SYSWM_WINDOWS, + SDL_SYSWM_X11, + SDL_SYSWM_DIRECTFB, + SDL_SYSWM_COCOA, + SDL_SYSWM_UIKIT + } + + // FIXME: I wish these weren't public... + [StructLayout(LayoutKind.Sequential)] + public struct INTERNAL_windows_wminfo + { + public IntPtr window; // Refers to an HWND + } + + [StructLayout(LayoutKind.Sequential)] + public struct INTERNAL_x11_wminfo + { + public IntPtr display; // Refers to a Display* + public IntPtr window; // Refers to a Window (XID, use ToInt64!) + } + + [StructLayout(LayoutKind.Sequential)] + public struct INTERNAL_directfb_wminfo + { + public IntPtr dfb; // Refers to an IDirectFB* + public IntPtr window; // Refers to an IDirectFBWindow* + public IntPtr surface; // Refers to an IDirectFBSurface* + } + + [StructLayout(LayoutKind.Sequential)] + public struct INTERNAL_cocoa_wminfo + { + public IntPtr window; // Refers to an NSWindow* + } + + [StructLayout(LayoutKind.Sequential)] + public struct INTERNAL_uikit_wminfo + { + public IntPtr window; // Refers to a UIWindow* + } + + [StructLayout(LayoutKind.Explicit)] + public struct INTERNAL_SysWMDriverUnion + { + [FieldOffset(0)] + public INTERNAL_windows_wminfo win; + [FieldOffset(0)] + public INTERNAL_x11_wminfo x11; + [FieldOffset(0)] + public INTERNAL_directfb_wminfo dfb; + [FieldOffset(0)] + public INTERNAL_cocoa_wminfo cocoa; + [FieldOffset(0)] + public INTERNAL_uikit_wminfo uikit; + // private int dummy; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SDL_SysWMinfo + { + public SDL_version version; + public SDL_SYSWM_TYPE subsystem; + public INTERNAL_SysWMDriverUnion info; + } + + /* window refers to an SDL_Window* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern SDL_bool SDL_GetWindowWMInfo( + IntPtr window, + ref SDL_SysWMinfo info + ); + + #endregion + + #region SDL_filesystem.h + + /// + /// Get the path where the application resides. + /// + /// Get the "base path". This is the directory where the application was run + /// from, which is probably the installation directory, and may or may not + /// be the process's current working directory. + /// + /// This returns an absolute path in UTF-8 encoding, and is garunteed to + /// end with a path separator ('\\' on Windows, '/' most other places). + /// + /// string of base dir in UTF-8 encoding + /// The underlying C string is owned by the application, + /// and can be NULL on some platforms. + /// + /// This function is not necessarily fast, so you should only + /// call it once and save the string if you need it. + /// + /// This function is only available in SDL 2.0.1 and later. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + public static extern string SDL_GetBasePath(); + + /// + /// Get the user-and-app-specific path where files can be written. + /// + /// Get the "pref dir". This is meant to be where users can write personal + /// files (preferences and save games, etc) that are specific to your + /// application. This directory is unique per user, per application. + /// + /// This function will decide the appropriate location in the native filesystem¸ + /// create the directory if necessary, and return a string of the absolute + /// path to the directory in UTF-8 encoding. + /// + /// The name of your organization. + /// The name of your application. + /// UTF-8 string of user dir in platform-dependent notation. NULL + /// if there's a problem (creating directory failed, etc). + /// The underlying C string is owned by the application, + /// and can be NULL on some platforms. .NET provides some similar functions. + /// + /// This function is not necessarily fast, so you should only + /// call it once and save the string if you need it. + /// + /// This function is only available in SDL 2.0.1 and later. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + public static extern string SDL_GetPrefPath( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string org, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string app + ); + + #endregion + + #region SDL_cpuinfo.h + + /// + /// This function returns the number of CPU cores available. + /// + /// The number of CPU cores available. + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetCPUCount(); + + /// + /// This function returns the amount of RAM configured in the system, in MB. + /// + /// The amount of RAM configured in the system, in MB. + /// + /// This function is only available in SDL 2.0.1 and later. + /// + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetSystemRAM(); + + #endregion + } +} diff --git a/OpenDiablo2.SDL2/SDL2-CS/SDL2_image.cs b/OpenDiablo2.SDL2/SDL2-CS/SDL2_image.cs new file mode 100644 index 00000000..e57c1b79 --- /dev/null +++ b/OpenDiablo2.SDL2/SDL2-CS/SDL2_image.cs @@ -0,0 +1,178 @@ +#region License +/* SDL2# - C# Wrapper for SDL2 + * + * Copyright (c) 2013-2015 Ethan Lee. + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * Ethan "flibitijibibo" Lee + * + */ +#endregion + +#region Using Statements +using System; +using System.Runtime.InteropServices; +#endregion + +namespace SDL2 +{ + public static class SDL_image + { + #region SDL2# Variables + + /* Used by DllImport to load the native library. */ + private const string nativeLibName = "SDL2_image.dll"; + + #endregion + + #region SDL_image.h + + /* Similar to the headers, this is the version we're expecting to be + * running with. You will likely want to check this somewhere in your + * program! + */ + public const int SDL_IMAGE_MAJOR_VERSION = 2; + public const int SDL_IMAGE_MINOR_VERSION = 0; + public const int SDL_IMAGE_PATCHLEVEL = 0; + + [Flags] + public enum IMG_InitFlags + { + IMG_INIT_JPG = 0x00000001, + IMG_INIT_PNG = 0x00000002, + IMG_INIT_TIF = 0x00000004, + IMG_INIT_WEBP = 0x00000008 + } + + public static void SDL_IMAGE_VERSION(out SDL.SDL_version X) + { + X.major = SDL_IMAGE_MAJOR_VERSION; + X.minor = SDL_IMAGE_MINOR_VERSION; + X.patch = SDL_IMAGE_PATCHLEVEL; + } + + [DllImport(nativeLibName, EntryPoint = "IMG_LinkedVersion", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr INTERNAL_IMG_LinkedVersion(); + public static SDL.SDL_version IMG_LinkedVersion() + { + SDL.SDL_version result; + IntPtr result_ptr = INTERNAL_IMG_LinkedVersion(); + result = (SDL.SDL_version) Marshal.PtrToStructure( + result_ptr, + typeof(SDL.SDL_version) + ); + return result; + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int IMG_Init(IMG_InitFlags flags); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void IMG_Quit(); + + /* IntPtr refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr IMG_Load( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string file + ); + + /* src refers to an SDL_RWops*, IntPtr to an SDL_Surface* */ + /* THIS IS A PUBLIC RWops FUNCTION! */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr IMG_Load_RW( + IntPtr src, + int freesrc + ); + + /* src refers to an SDL_RWops*, IntPtr to an SDL_Surface* */ + /* THIS IS A PUBLIC RWops FUNCTION! */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr IMG_LoadTyped_RW( + IntPtr src, + int freesrc, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string type + ); + + /* IntPtr refers to an SDL_Texture*, renderer to an SDL_Renderer* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr IMG_LoadTexture( + IntPtr renderer, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string file + ); + + /* renderer refers to an SDL_Renderer*. + * src refers to an SDL_RWops*. + * IntPtr to an SDL_Texture*. + */ + /* THIS IS A PUBLIC RWops FUNCTION! */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr IMG_LoadTexture_RW( + IntPtr renderer, + IntPtr src, + int freesrc + ); + + /* renderer refers to an SDL_Renderer*. + * src refers to an SDL_RWops*. + * IntPtr to an SDL_Texture*. + */ + /* THIS IS A PUBLIC RWops FUNCTION! */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr IMG_LoadTextureTyped_RW( + IntPtr renderer, + IntPtr src, + int freesrc, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string type + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int IMG_InvertAlpha(int on); + + /* IntPtr refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr IMG_ReadXPMFromArray( + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] + string[] xpm + ); + + /* surface refers to an SDL_Surface* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int IMG_SavePNG( + IntPtr surface, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string file + ); + + /* surface refers to an SDL_Surface*, dst to an SDL_RWops* */ + /* THIS IS A PUBLIC RWops FUNCTION! */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int IMG_SavePNG_RW( + IntPtr surface, + IntPtr dst, + int freedst + ); + + #endregion + } +} diff --git a/OpenDiablo2.SDL2/SDL2-CS/SDL2_mixer.cs b/OpenDiablo2.SDL2/SDL2-CS/SDL2_mixer.cs new file mode 100644 index 00000000..193c6df4 --- /dev/null +++ b/OpenDiablo2.SDL2/SDL2-CS/SDL2_mixer.cs @@ -0,0 +1,489 @@ +#region License +/* SDL2# - C# Wrapper for SDL2 + * + * Copyright (c) 2013-2015 Ethan Lee. + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * Ethan "flibitijibibo" Lee + * + */ +#endregion + +#region Using Statements +using System; +using System.Runtime.InteropServices; +#endregion + +namespace SDL2 +{ + public static class SDL_mixer + { + #region SDL2# Variables + + /* Used by DllImport to load the native library. */ + private const string nativeLibName = "SDL2_mixer.dll"; + + #endregion + + #region SDL_mixer.h + + /* Similar to the headers, this is the version we're expecting to be + * running with. You will likely want to check this somewhere in your + * program! + */ + public const int SDL_MIXER_MAJOR_VERSION = 2; + public const int SDL_MIXER_MINOR_VERSION = 0; + public const int SDL_MIXER_PATCHLEVEL = 0; + + /* In C, you can redefine this value before including SDL_mixer.h. + * We're not going to allow this in SDL2#, since the value of this + * variable is persistent and not dependent on preprocessor ordering. + */ + public const int MIX_CHANNELS = 8; + + public static readonly int MIX_DEFAULT_FREQUENCY = 22050; + public static readonly ushort MIX_DEFAULT_FORMAT = + BitConverter.IsLittleEndian ? SDL.AUDIO_S16LSB : SDL.AUDIO_S16MSB; + public static readonly int MIX_DEFAULT_CHANNELS = 2; + public static readonly byte MIX_MAX_VOLUME = 128; + + [Flags] + public enum MIX_InitFlags + { + MIX_INIT_FLAC = 0x00000001, + MIX_INIT_MOD = 0x00000002, + MIX_INIT_MP3 = 0x00000004, + MIX_INIT_OGG = 0x00000008, + MIX_INIT_FLUIDSYNTH = 0x00000010, + } + + public enum Mix_Fading + { + MIX_NO_FADING, + MIX_FADING_OUT, + MIX_FADING_IN + } + + public enum Mix_MusicType + { + MUS_NONE, + MUS_CMD, + MUS_WAV, + MUS_MOD, + MUS_MID, + MUS_OGG, + MUS_MP3, + MUS_MP3_MAD, + MUS_FLAC, + MUS_MODPLUG + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void MixFuncDelegate( + IntPtr udata, // void* + IntPtr stream, // Uint8* + int len + ); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void Mix_EffectFunc_t( + int chan, + IntPtr stream, // void* + int len, + IntPtr udata // void* + ); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void Mix_EffectDone_t( + int chan, + IntPtr udata // void* + ); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void MusicFinishedDelegate(); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ChannelFinishedDelegate(int channel); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int SoundFontDelegate( + IntPtr a, // const char* + IntPtr b // void* + ); + + public static void SDL_MIXER_VERSION(out SDL.SDL_version X) + { + X.major = SDL_MIXER_MAJOR_VERSION; + X.minor = SDL_MIXER_MINOR_VERSION; + X.patch = SDL_MIXER_PATCHLEVEL; + } + + [DllImport(nativeLibName, EntryPoint = "MIX_Linked_Version", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr INTERNAL_MIX_Linked_Version(); + public static SDL.SDL_version MIX_Linked_Version() + { + SDL.SDL_version result; + IntPtr result_ptr = INTERNAL_MIX_Linked_Version(); + result = (SDL.SDL_version) Marshal.PtrToStructure( + result_ptr, + typeof(SDL.SDL_version) + ); + return result; + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_Init(MIX_InitFlags flags); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_Quit(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_OpenAudio( + int frequency, + ushort format, + int channels, + int chunksize + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_AllocateChannels(int numchans); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_QuerySpec( + out int frequency, + out ushort format, + out int channels + ); + + /* src refers to an SDL_RWops*, IntPtr to a Mix_Chunk* */ + /* THIS IS A PUBLIC RWops FUNCTION! */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr Mix_LoadWAV_RW( + IntPtr src, + int freesrc + ); + + /* IntPtr refers to a Mix_Chunk* */ + /* This is an RWops macro in the C header. */ + public static IntPtr Mix_LoadWAV(string file) + { + IntPtr rwops = SDL.INTERNAL_SDL_RWFromFile(file, "rb"); + return Mix_LoadWAV_RW(rwops, 1); + } + + /* IntPtr refers to a Mix_Music* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr Mix_LoadMUS( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string file + ); + + /* IntPtr refers to a Mix_Chunk* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr Mix_QuickLoad_WAV( + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] + byte[] mem + ); + + /* IntPtr refers to a Mix_Chunk* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr Mix_QuickLoad_RAW( + [In()] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 1)] + byte[] mem, + uint len + ); + + /* chunk refers to a Mix_Chunk* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_FreeChunk(IntPtr chunk); + + /* music refers to a Mix_Music* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_FreeMusic(IntPtr music); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GetNumChunkDecoders(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string Mix_GetChunkDecoder(int index); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GetNumMusicDecoders(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string Mix_GetMusicDecoder(int index); + + /* music refers to a Mix_Music* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern Mix_MusicType Mix_GetMusicType(IntPtr music); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_SetPostMix( + MixFuncDelegate mix_func, + IntPtr arg // void* + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_HookMusic( + MixFuncDelegate mix_func, + IntPtr arg // void* + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_HookMusicFinished( + MusicFinishedDelegate music_finished + ); + + /* IntPtr refers to a void* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr Mix_GetMusicHookData(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_ChannelFinished( + ChannelFinishedDelegate channel_finished + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_RegisterEffect( + int chan, + Mix_EffectFunc_t f, + Mix_EffectDone_t d, + IntPtr arg // void* + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_UnregisterEffect( + int channel, + Mix_EffectFunc_t f + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_UnregisterAllEffects(int channel); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_SetPanning( + int channel, + byte left, + byte right + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_SetPosition( + int channel, + short angle, + byte distance + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_SetDistance(int channel, byte distance); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_SetReverseStereo(int channel, int flip); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_ReserveChannels(int num); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GroupChannel(int which, int tag); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GroupChannels(int from, int to, int tag); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GroupAvailable(int tag); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GroupCount(int tag); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GroupOldest(int tag); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GroupNewer(int tag); + + /* chunk refers to a Mix_Chunk* */ + public static int Mix_PlayChannel( + int channel, + IntPtr chunk, + int loops + ) { + return Mix_PlayChannelTimed(channel, chunk, loops, -1); + } + + /* chunk refers to a Mix_Chunk* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_PlayChannelTimed( + int channel, + IntPtr chunk, + int loops, + int ticks + ); + + /* music refers to a Mix_Music* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_PlayMusic(IntPtr music, int loops); + + /* music refers to a Mix_Music* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_FadeInMusic( + IntPtr music, + int loops, + int ms + ); + + /* music refers to a Mix_Music* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_FadeInMusicPos( + IntPtr music, + int loops, + int ms, + double position + ); + + /* chunk refers to a Mix_Chunk* */ + public static int Mix_FadeInChannel( + int channel, + IntPtr chunk, + int loops, + int ms + ) { + return Mix_FadeInChannelTimed(channel, chunk, loops, ms, -1); + } + + /* chunk refers to a Mix_Chunk* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_FadeInChannelTimed( + int channel, + IntPtr chunk, + int loops, + int ms, + int ticks + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_Volume(int channel, int volume); + + /* chunk refers to a Mix_Chunk* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_VolumeChunk( + IntPtr chunk, + int volume + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_VolumeMusic(int volume); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_HaltChannel(int channel); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_HaltGroup(int tag); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_HaltMusic(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_ExpireChannel(int channel, int ticks); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_FadeOutChannel(int which, int ms); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_FadeOutGroup(int tag, int ms); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_FadeOutMusic(int ms); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern Mix_Fading Mix_FadingMusic(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern Mix_Fading Mix_FadingChannel(int which); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_Pause(int channel); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_Resume(int channel); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_Paused(int channel); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_PauseMusic(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_ResumeMusic(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_RewindMusic(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_PausedMusic(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_SetMusicPosition(double position); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_Playing(int channel); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_PlayingMusic(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_SetMusicCMD( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string command + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_SetSynchroValue(int value); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_GetSynchroValue(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_SetSoundFonts( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string paths + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string Mix_GetSoundFonts(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int Mix_EachSoundFont( + SoundFontDelegate function, + IntPtr data // void* + ); + + /* IntPtr refers to a Mix_Chunk* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr Mix_GetChunk(int channel); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void Mix_CloseAudio(); + + #endregion + } +} diff --git a/OpenDiablo2.SDL2/SDL2-CS/SDL2_ttf.cs b/OpenDiablo2.SDL2/SDL2-CS/SDL2_ttf.cs new file mode 100644 index 00000000..ef1cfe33 --- /dev/null +++ b/OpenDiablo2.SDL2/SDL2-CS/SDL2_ttf.cs @@ -0,0 +1,406 @@ +#region License +/* SDL2# - C# Wrapper for SDL2 + * + * Copyright (c) 2013-2015 Ethan Lee. + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * Ethan "flibitijibibo" Lee + * + */ +#endregion + +#region Using Statements +using System; +using System.Runtime.InteropServices; +#endregion + +namespace SDL2 +{ + public static class SDL_ttf + { + #region SDL2# Variables + + /* Used by DllImport to load the native library. */ + private const string nativeLibName = "SDL2_ttf.dll"; + + #endregion + + #region SDL_ttf.h + + /* Similar to the headers, this is the version we're expecting to be + * running with. You will likely want to check this somewhere in your + * program! + */ + public const int SDL_TTF_MAJOR_VERSION = 2; + public const int SDL_TTF_MINOR_VERSION = 0; + public const int SDL_TTF_PATCHLEVEL = 12; + + public const int UNICODE_BOM_NATIVE = 0xFEFF; + public const int UNICODE_BOM_SWAPPED = 0xFFFE; + + public const int TTF_STYLE_NORMAL = 0x00; + public const int TTF_STYLE_BOLD = 0x01; + public const int TTF_STYLE_ITALIC = 0x02; + public const int TTF_STYLE_UNDERLINE = 0x04; + public const int TTF_STYLE_STRIKETHROUGH = 0x08; + + public const int TTF_HINTING_NORMAL = 0; + public const int TTF_HINTING_LIGHT = 1; + public const int TTF_HINTING_MONO = 2; + public const int TTF_HINTING_NONE = 3; + + public static void SDL_TTF_VERSION(out SDL.SDL_version X) + { + X.major = SDL_TTF_MAJOR_VERSION; + X.minor = SDL_TTF_MINOR_VERSION; + X.patch = SDL_TTF_PATCHLEVEL; + } + + [DllImport(nativeLibName, EntryPoint = "TTF_LinkedVersion", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr INTERNAL_TTF_LinkedVersion(); + public static SDL.SDL_version TTF_LinkedVersion() + { + SDL.SDL_version result; + IntPtr result_ptr = INTERNAL_TTF_LinkedVersion(); + result = (SDL.SDL_version) Marshal.PtrToStructure( + result_ptr, + typeof(SDL.SDL_version) + ); + return result; + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void TTF_ByteSwappedUNICODE(int swapped); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_Init(); + + /* IntPtr refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_OpenFont( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string file, + int ptsize + ); + + /* src refers to an SDL_RWops*, IntPtr to a TTF_Font* */ + /* THIS IS A PUBLIC RWops FUNCTION! */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_OpenFontRW( + IntPtr src, + int freesrc, + int ptsize + ); + + /* IntPtr refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_OpenFontIndex( + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string file, + int ptsize, + long index + ); + + /* src refers to an SDL_RWops*, IntPtr to a TTF_Font* */ + /* THIS IS A PUBLIC RWops FUNCTION! */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_OpenFontIndexRW( + IntPtr src, + int freesrc, + int ptsize, + long index + ); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_GetFontStyle(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void TTF_SetFontStyle(IntPtr font, int style); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_GetFontOutline(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void TTF_SetFontOutline(IntPtr font, int outline); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_GetFontHinting(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void TTF_SetFontHinting(IntPtr font, int hinting); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_FontHeight(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_FontAscent(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_FontDescent(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_FontLineSkip(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_GetFontKerning(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void TTF_SetFontKerning(IntPtr font, int allowed); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern long TTF_FontFaces(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_FontFaceIsFixedWidth(IntPtr font); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string TTF_FontFaceFamilyName( + IntPtr font + ); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler), MarshalCookie = LPUtf8StrMarshaler.LeaveAllocated)] + public static extern string TTF_FontFaceStyleName( + IntPtr font + ); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_GlyphIsProvided(IntPtr font, ushort ch); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_GlyphMetrics( + IntPtr font, + ushort ch, + out int minx, + out int maxx, + out int miny, + out int maxy, + out int advance + ); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_SizeText( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string text, + out int w, + out int h + ); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_SizeUTF8( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string text, + out int w, + out int h + ); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_SizeUNICODE( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPWStr)] + string text, + out int w, + out int h + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderText_Solid( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPStr)] + string text, + SDL.SDL_Color fg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderUTF8_Solid( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string text, + SDL.SDL_Color fg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderUNICODE_Solid( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPWStr)] + string text, + SDL.SDL_Color fg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderGlyph_Solid( + IntPtr font, + ushort ch, + SDL.SDL_Color fg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderText_Shaded( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPStr)] + string text, + SDL.SDL_Color fg, + SDL.SDL_Color bg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderUTF8_Shaded( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string text, + SDL.SDL_Color fg, + SDL.SDL_Color bg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderUNICODE_Shaded( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPWStr)] + string text, + SDL.SDL_Color fg, + SDL.SDL_Color bg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderGlyph_Shaded( + IntPtr font, + ushort ch, + SDL.SDL_Color fg, + SDL.SDL_Color bg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderText_Blended( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPStr)] + string text, + SDL.SDL_Color fg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderUTF8_Blended( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string text, + SDL.SDL_Color fg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderUNICODE_Blended( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPWStr)] + string text, + SDL.SDL_Color fg + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderText_Blended_Wrapped( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPStr)] + string text, + SDL.SDL_Color fg, + uint wrapped + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderUTF8_Blended_Wrapped( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LPUtf8StrMarshaler))] + string text, + SDL.SDL_Color fg, + uint wrapped + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderUNICODE_Blended_Wrapped( + IntPtr font, + [In()] [MarshalAs(UnmanagedType.LPWStr)] + string text, + SDL.SDL_Color fg, + uint wrapped + ); + + /* IntPtr refers to an SDL_Surface*, font to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr TTF_RenderGlyph_Blended( + IntPtr font, + ushort ch, + SDL.SDL_Color fg + ); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void TTF_CloseFont(IntPtr font); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern void TTF_Quit(); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int TTF_WasInit(); + + /* font refers to a TTF_Font* */ + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int SDL_GetFontKerningSize( + IntPtr font, + int prev_index, + int index + ); + + #endregion + } +} diff --git a/OpenDiablo2.SDL2/SDL2.dll b/OpenDiablo2.SDL2/SDL2.dll new file mode 100644 index 00000000..934f8091 Binary files /dev/null and b/OpenDiablo2.SDL2/SDL2.dll differ diff --git a/OpenDiablo2.SDL2/SDL2RenderWindow.cs b/OpenDiablo2.SDL2/SDL2RenderWindow.cs new file mode 100644 index 00000000..a1502134 --- /dev/null +++ b/OpenDiablo2.SDL2/SDL2RenderWindow.cs @@ -0,0 +1,91 @@ +using OpenDiablo2.Common.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SDL2; +using System.IO; +using System.Drawing; +using OpenDiablo2.Common.Models; +using Autofac; + +namespace OpenDiablo2.SDL2_ +{ + public sealed class SDL2RenderWindow : IRenderWindow, IRenderTarget + { + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private IntPtr window, renderer; + private bool running; + public bool IsRunning => running; + private readonly ILifetimeScope lifetimeScope; + + public SDL2RenderWindow(ILifetimeScope lifetimeScope) + { + this.lifetimeScope = lifetimeScope; + + SDL.SDL_Init(SDL.SDL_INIT_EVERYTHING); + if (SDL.SDL_SetHint(SDL.SDL_HINT_RENDER_SCALE_QUALITY, "0") == SDL.SDL_bool.SDL_FALSE) + throw new ApplicationException($"Unable to Init hinting: {SDL.SDL_GetError()}"); + + window = SDL.SDL_CreateWindow("OpenDiablo2", SDL.SDL_WINDOWPOS_UNDEFINED, SDL.SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL.SDL_WindowFlags.SDL_WINDOW_SHOWN); + if (window == IntPtr.Zero) + throw new ApplicationException($"Unable to create SDL Window: {SDL.SDL_GetError()}"); + + renderer = SDL.SDL_CreateRenderer(window, -1, SDL.SDL_RendererFlags.SDL_RENDERER_ACCELERATED); + if (renderer == IntPtr.Zero) + throw new ApplicationException($"Unable to create SDL Window: {SDL.SDL_GetError()}"); + + SDL.SDL_SetRenderDrawBlendMode(renderer, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + + running = true; + + } + public void Dispose() + { + SDL.SDL_DestroyRenderer(renderer); + SDL.SDL_DestroyWindow(window); + SDL.SDL_Quit(); + } + + public void Clear() + { + SDL.SDL_RenderClear(renderer); + + } + + public void Sync() + { + SDL.SDL_RenderPresent(renderer); + } + + public void Update() + { + while (SDL.SDL_PollEvent(out SDL.SDL_Event evt) != 0) + { + if (evt.type == SDL.SDL_EventType.SDL_QUIT) + running = false; + } + } + + + public void Draw(ISprite sprite) + { + var spr = sprite as SDL2Sprite; + var loc = spr.GetRenderPoint(); + + var destRect = new SDL.SDL_Rect + { + x = loc.X, + y = loc.Y, + w = spr.FrameSize.Width, + h = spr.FrameSize.Height + }; + SDL.SDL_RenderCopy(renderer, spr.textures[spr.Frame], IntPtr.Zero, ref destRect); + + } + + public ISprite LoadSprite(ImageSet source) + => new SDL2Sprite(source, renderer); + } +} diff --git a/OpenDiablo2.SDL2/SDL2Sprite.cs b/OpenDiablo2.SDL2/SDL2Sprite.cs new file mode 100644 index 00000000..e5a7605f --- /dev/null +++ b/OpenDiablo2.SDL2/SDL2Sprite.cs @@ -0,0 +1,123 @@ +using OpenDiablo2.Common.Interfaces; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SDL2; +using System.Runtime.InteropServices; +using OpenDiablo2.Common.Models; + +namespace OpenDiablo2.SDL2_ +{ + public sealed class SDL2Sprite : ISprite + { + public Point Location { get; set; } = new Point(); + public Size FrameSize { get; set; } = new Size(); + public int Frame { get; set; } + public int TotalFrames { get; internal set; } + + private Palette palette; + public Palette CurrentPalette + { + get => palette; + set + { + palette = value; + UpdateTextureData(); + } + } + private readonly ImageSet source; + private readonly IntPtr renderer; + internal IntPtr[] textures = new IntPtr[0]; + + public SDL2Sprite(ImageSet source, IntPtr renderer) + { + this.source = source; + this.renderer = renderer; + + + TotalFrames = source.Frames.Count(); + FrameSize = new Size(Pow2((int)source.Frames.Max(x => x.Width)), Pow2((int)source.Frames.Max(x => x.Height))); + + } + + internal Point GetRenderPoint() + => new Point( + Location.X + source.Frames[Frame].OffsetX, + (Location.Y - FrameSize.Height) + source.Frames[Frame].OffsetY + ); + + private void UpdateTextureData() + { + foreach (var texture in textures) + { + SDL.SDL_DestroyTexture(texture); + } + + textures = new IntPtr[TotalFrames]; + + for (var i = 0; i < source.Frames.Count(); i++) + textures[i] = LoadFrame(source.Frames[i], renderer); + + + } + + // TODO: Less dumb color correction + private Color AdjustColor(Color source) + => Color.FromArgb( + source.A, + (byte)Math.Min((float)source.R * 1.2, 255), + (byte)Math.Min((float)source.G * 1.2, 255), + (byte)Math.Min((float)source.B * 1.2, 255) + ); + + private IntPtr LoadFrame(ImageFrame frame, IntPtr renderer) + { + var texture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_TARGET, Pow2(FrameSize.Width), Pow2(FrameSize.Height)); + + if (texture == IntPtr.Zero) + throw new ApplicationException("Unaple to initialize texture."); + + SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + SDL.SDL_SetRenderTarget(renderer, texture); + SDL.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); + SDL.SDL_RenderFillRect(renderer, IntPtr.Zero); + SDL.SDL_SetRenderTarget(renderer, IntPtr.Zero); + + var binaryData = new UInt32[frame.Width * frame.Height]; + for (int y = 0; y < frame.Height; y++) + for (int x = 0; x < frame.Width; x++) + { + var col = AdjustColor(frame.GetColor(x, y, CurrentPalette)); + binaryData[x + y * frame.Width] = (uint)col.ToArgb(); + } + var rect = new SDL.SDL_Rect { x = 0, y = FrameSize.Height - (int)frame.Height, w = (int)frame.Width, h = (int)frame.Height }; + GCHandle pinnedArray = GCHandle.Alloc(binaryData, GCHandleType.Pinned); + SDL.SDL_UpdateTexture(texture, ref rect, pinnedArray.AddrOfPinnedObject(), (int)frame.Width * 4); + pinnedArray.Free(); + + return texture; + + } + + private int Pow2(int val) + { + int result = 1; + while (result < val) + result *= 2; + return result; + } + + public void Dispose() + { + foreach (var texture in textures) + { + SDL.SDL_DestroyTexture(texture); + + } + } + } +} diff --git a/OpenDiablo2.SDL2/packages.config b/OpenDiablo2.SDL2/packages.config new file mode 100644 index 00000000..f7b5915c --- /dev/null +++ b/OpenDiablo2.SDL2/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/OpenDiablo2.Scenes/AutofacModule.cs b/OpenDiablo2.Scenes/AutofacModule.cs new file mode 100644 index 00000000..d3232738 --- /dev/null +++ b/OpenDiablo2.Scenes/AutofacModule.cs @@ -0,0 +1,31 @@ +using Autofac; +using OpenDiablo2.Common.Attributes; +using OpenDiablo2.Common.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Scenes +{ + public sealed class AutofacModule : Module + { + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected override void Load(ContainerBuilder builder) + { + log.Info("Configuring OpenDiablo2.Scenes service implementations."); + + var types = ThisAssembly.GetTypes().Where(x => typeof(IScene).IsAssignableFrom(x) && x.IsClass); + foreach (var type in types) + { + var att = type.GetCustomAttributes(true).First(x => typeof(SceneAttribute).IsAssignableFrom(x.GetType())) as SceneAttribute; + builder + .RegisterType(type) + .Keyed(att.SceneName) + .InstancePerDependency(); + } + } + } +} diff --git a/OpenDiablo2.Scenes/MainMenu.cs b/OpenDiablo2.Scenes/MainMenu.cs new file mode 100644 index 00000000..adb072d1 --- /dev/null +++ b/OpenDiablo2.Scenes/MainMenu.cs @@ -0,0 +1,96 @@ +using OpenDiablo2.Common.Attributes; +using OpenDiablo2.Common.Interfaces; +using OpenDiablo2.Common.Models; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Scenes +{ + [Scene("Main Menu")] + public class MainMenu : IScene + { + static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private readonly IRenderWindow renderWindow; + private readonly IPaletteProvider paletteProvider; + private readonly IMPQProvider mpqProvider; + + private float logoFrame; + private ISprite backgroundSprite, diabloLogoLeft, diabloLogoRight, diabloLogoLeftBlack, diabloLogoRightBlack; + + public MainMenu( + IRenderWindow renderWindow, + IPaletteProvider paletteProvider, + IMPQProvider mpqProvider + ) + { + this.renderWindow = renderWindow; + this.paletteProvider = paletteProvider; + this.mpqProvider = mpqProvider; + + //var texture = renderWindow.LoadSprite(ImageSet.LoadFromStream(mpqProvider.GetStream("data\\global\\ui\\Logo\\logo.DC6"))); + backgroundSprite = renderWindow.LoadSprite(ImageSet.LoadFromStream(mpqProvider.GetStream("data\\global\\ui\\FrontEnd\\trademarkscreenEXP.DC6"))); + backgroundSprite.CurrentPalette = paletteProvider.PaletteTable["Sky"]; + + diabloLogoLeft = renderWindow.LoadSprite(ImageSet.LoadFromStream(mpqProvider.GetStream("data\\global\\ui\\FrontEnd\\D2logoFireLeft.DC6"))); + diabloLogoLeft.CurrentPalette = paletteProvider.PaletteTable["Units"]; + diabloLogoRight = renderWindow.LoadSprite(ImageSet.LoadFromStream(mpqProvider.GetStream("data\\global\\ui\\FrontEnd\\D2logoFireRight.DC6"))); + diabloLogoRight.CurrentPalette = paletteProvider.PaletteTable["Units"]; + diabloLogoLeftBlack = renderWindow.LoadSprite(ImageSet.LoadFromStream(mpqProvider.GetStream("data\\global\\ui\\FrontEnd\\D2logoBlackLeft.DC6"))); + diabloLogoLeftBlack.CurrentPalette = paletteProvider.PaletteTable["Units"]; + diabloLogoRightBlack = renderWindow.LoadSprite(ImageSet.LoadFromStream(mpqProvider.GetStream("data\\global\\ui\\FrontEnd\\D2logoBlackRight.DC6"))); + diabloLogoRightBlack.CurrentPalette = paletteProvider.PaletteTable["Units"]; + + logoFrame = 0f; + + diabloLogoLeft.Location = new Point(400, 120); + diabloLogoRight.Location = new Point(400, 120); + diabloLogoLeftBlack.Location = new Point(400, 120); + diabloLogoRightBlack.Location = new Point(400, 120); + + } + + public void Render() + { + renderWindow.Clear(); + + for (int y = 0; y < 3; y++) + for (int x = 0; x < 4; x++) + { + backgroundSprite.Frame = x + (y * 4); + backgroundSprite.Location = new Point(x * backgroundSprite.FrameSize.Width, (y + 1) * backgroundSprite.FrameSize.Height); + renderWindow.Draw(backgroundSprite); + } + + diabloLogoLeftBlack.Frame = (int)((float)diabloLogoLeftBlack.TotalFrames * logoFrame); + renderWindow.Draw(diabloLogoLeftBlack); + diabloLogoRightBlack.Frame = (int)((float)diabloLogoRightBlack.TotalFrames * logoFrame); + renderWindow.Draw(diabloLogoRightBlack); + + diabloLogoLeft.Frame = (int)((float)diabloLogoLeft.TotalFrames * logoFrame); + renderWindow.Draw(diabloLogoLeft); + diabloLogoRight.Frame = (int)((float)diabloLogoRight.TotalFrames * logoFrame); + renderWindow.Draw(diabloLogoRight); + + renderWindow.Sync(); + } + + public void Update(long ms) + { + float seconds = ((float)ms / 1000f); + logoFrame += seconds; + while (logoFrame >= 1f) + logoFrame -= 1f; + + } + + public void Dispose() + { + + } + } +} diff --git a/OpenDiablo2.Scenes/OpenDiablo2.Scenes.csproj b/OpenDiablo2.Scenes/OpenDiablo2.Scenes.csproj new file mode 100644 index 00000000..4f49394d --- /dev/null +++ b/OpenDiablo2.Scenes/OpenDiablo2.Scenes.csproj @@ -0,0 +1,65 @@ + + + + + Debug + AnyCPU + {05224FE7-293F-4184-B1D6-89F5171B60E0} + Library + Properties + OpenDiablo2.Scenes + OpenDiablo2.Scenes + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Autofac.4.8.1\lib\net45\Autofac.dll + + + ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll + + + + + + + + + + + + + + + + + + + {b743160e-a0bb-45dc-9998-967a85e50562} + OpenDiablo2.Common + + + + + + + \ No newline at end of file diff --git a/OpenDiablo2.Scenes/Properties/AssemblyInfo.cs b/OpenDiablo2.Scenes/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..c20597b6 --- /dev/null +++ b/OpenDiablo2.Scenes/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenDiablo2.Scenes")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenDiablo2.Scenes")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("05224fe7-293f-4184-b1d6-89f5171b60e0")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenDiablo2.Scenes/packages.config b/OpenDiablo2.Scenes/packages.config new file mode 100644 index 00000000..6764f843 --- /dev/null +++ b/OpenDiablo2.Scenes/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OpenDiablo2.sln b/OpenDiablo2.sln new file mode 100644 index 00000000..0d7993ba --- /dev/null +++ b/OpenDiablo2.sln @@ -0,0 +1,71 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28306.52 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2", "OpenDiablo2\OpenDiablo2.csproj", "{2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.Common", "OpenDiablo2.Common\OpenDiablo2.Common.csproj", "{B743160E-A0BB-45DC-9998-967A85E50562}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.Core", "OpenDiablo2.Core\OpenDiablo2.Core.csproj", "{8FC6BF7D-835A-47C1-A6B2-125495FA0900}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.SDL2", "OpenDiablo2.SDL2\OpenDiablo2.SDL2.csproj", "{1F8731D5-393B-4561-9CEA-887A2F466576}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.Scenes", "OpenDiablo2.Scenes\OpenDiablo2.Scenes.csproj", "{05224FE7-293F-4184-B1D6-89F5171B60E0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}.Debug|x64.ActiveCfg = Debug|x64 + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}.Debug|x64.Build.0 = Debug|x64 + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}.Release|Any CPU.Build.0 = Release|Any CPU + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}.Release|x64.ActiveCfg = Release|x64 + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}.Release|x64.Build.0 = Release|x64 + {B743160E-A0BB-45DC-9998-967A85E50562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B743160E-A0BB-45DC-9998-967A85E50562}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B743160E-A0BB-45DC-9998-967A85E50562}.Debug|x64.ActiveCfg = Debug|x64 + {B743160E-A0BB-45DC-9998-967A85E50562}.Debug|x64.Build.0 = Debug|x64 + {B743160E-A0BB-45DC-9998-967A85E50562}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B743160E-A0BB-45DC-9998-967A85E50562}.Release|Any CPU.Build.0 = Release|Any CPU + {B743160E-A0BB-45DC-9998-967A85E50562}.Release|x64.ActiveCfg = Release|x64 + {B743160E-A0BB-45DC-9998-967A85E50562}.Release|x64.Build.0 = Release|x64 + {8FC6BF7D-835A-47C1-A6B2-125495FA0900}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FC6BF7D-835A-47C1-A6B2-125495FA0900}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FC6BF7D-835A-47C1-A6B2-125495FA0900}.Debug|x64.ActiveCfg = Debug|x64 + {8FC6BF7D-835A-47C1-A6B2-125495FA0900}.Debug|x64.Build.0 = Debug|x64 + {8FC6BF7D-835A-47C1-A6B2-125495FA0900}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FC6BF7D-835A-47C1-A6B2-125495FA0900}.Release|Any CPU.Build.0 = Release|Any CPU + {8FC6BF7D-835A-47C1-A6B2-125495FA0900}.Release|x64.ActiveCfg = Release|x64 + {8FC6BF7D-835A-47C1-A6B2-125495FA0900}.Release|x64.Build.0 = Release|x64 + {1F8731D5-393B-4561-9CEA-887A2F466576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F8731D5-393B-4561-9CEA-887A2F466576}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F8731D5-393B-4561-9CEA-887A2F466576}.Debug|x64.ActiveCfg = Debug|x64 + {1F8731D5-393B-4561-9CEA-887A2F466576}.Debug|x64.Build.0 = Debug|x64 + {1F8731D5-393B-4561-9CEA-887A2F466576}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F8731D5-393B-4561-9CEA-887A2F466576}.Release|Any CPU.Build.0 = Release|Any CPU + {1F8731D5-393B-4561-9CEA-887A2F466576}.Release|x64.ActiveCfg = Release|x64 + {1F8731D5-393B-4561-9CEA-887A2F466576}.Release|x64.Build.0 = Release|x64 + {05224FE7-293F-4184-B1D6-89F5171B60E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05224FE7-293F-4184-B1D6-89F5171B60E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05224FE7-293F-4184-B1D6-89F5171B60E0}.Debug|x64.ActiveCfg = Debug|Any CPU + {05224FE7-293F-4184-B1D6-89F5171B60E0}.Debug|x64.Build.0 = Debug|Any CPU + {05224FE7-293F-4184-B1D6-89F5171B60E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05224FE7-293F-4184-B1D6-89F5171B60E0}.Release|Any CPU.Build.0 = Release|Any CPU + {05224FE7-293F-4184-B1D6-89F5171B60E0}.Release|x64.ActiveCfg = Release|Any CPU + {05224FE7-293F-4184-B1D6-89F5171B60E0}.Release|x64.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {782826E1-7E8E-4878-88FB-1B564D82C621} + EndGlobalSection +EndGlobal diff --git a/OpenDiablo2/App.config b/OpenDiablo2/App.config new file mode 100644 index 00000000..731f6de6 --- /dev/null +++ b/OpenDiablo2/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/OpenDiablo2/CommandLineOptions.cs b/OpenDiablo2/CommandLineOptions.cs new file mode 100644 index 00000000..2443be74 --- /dev/null +++ b/OpenDiablo2/CommandLineOptions.cs @@ -0,0 +1,10 @@ +using CommandLine; + +namespace OpenDiablo2 +{ + public sealed class CommandLineOptions + { + [Option('p', "datapath", Required = false, HelpText = "Specifies the root data path")] + public string DataPath { get; set; } + } +} diff --git a/OpenDiablo2/OpenDiablo2.csproj b/OpenDiablo2/OpenDiablo2.csproj new file mode 100644 index 00000000..6ee2e387 --- /dev/null +++ b/OpenDiablo2/OpenDiablo2.csproj @@ -0,0 +1,112 @@ + + + + + Debug + AnyCPU + {2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD} + Exe + OpenDiablo2 + OpenDiablo2 + v4.6.1 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + ..\packages\Autofac.4.8.1\lib\net45\Autofac.dll + + + ..\packages\CommandLineParser.2.3.0\lib\net45\CommandLine.dll + + + ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll + + + + + ..\packages\System.Console.4.3.1\lib\net46\System.Console.dll + + + + ..\packages\System.Reflection.TypeExtensions.4.5.1\lib\net461\System.Reflection.TypeExtensions.dll + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + {b743160e-a0bb-45dc-9998-967a85e50562} + OpenDiablo2.Common + + + {8fc6bf7d-835a-47c1-a6b2-125495fa0900} + OpenDiablo2.Core + + + {05224fe7-293f-4184-b1d6-89f5171b60e0} + OpenDiablo2.Scenes + + + {1f8731d5-393b-4561-9cea-887a2f466576} + OpenDiablo2.SDL2 + + + + \ No newline at end of file diff --git a/OpenDiablo2/Program.cs b/OpenDiablo2/Program.cs new file mode 100644 index 00000000..2d9d2a23 --- /dev/null +++ b/OpenDiablo2/Program.cs @@ -0,0 +1,88 @@ +using CommandLine; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Autofac; +using OpenDiablo2.Common.Models; +using System.Reflection; +using OpenDiablo2.Common.Interfaces; +using System.Diagnostics; + +namespace OpenDiablo2 +{ + static class Program + { + static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + static void Main(string[] args) + { + log.Info("OpenDiablo 2: The Free and Open Source Diablo 2 clone!"); + +#if !DEBUG + try + { +#endif + BuildContainer() + .ResolveCommandLineOptions(args) + .Resolve() + .Run(); +#if !DEBUG + } + catch (Exception ex) + { + log.Fatal("Uncaught exception detected, the game has been terminated!", ex); + } +#endif + } + + static IContainer BuildContainer() => new ContainerBuilder() + .RegisterLocalTypes() + .LoadAssemblyModules() + .Build(); + + + static IContainer ResolveCommandLineOptions(this IContainer container, IEnumerable args) + { + var globalConfiguration = container.Resolve(); + + Parser.Default.ParseArguments(args).WithParsed(o => + { + globalConfiguration.BaseDataPath = Path.GetFullPath(o.DataPath ?? Directory.GetCurrentDirectory()); + }); + + return container; + } + + static ContainerBuilder RegisterLocalTypes(this ContainerBuilder containerBuilder) + { + containerBuilder.RegisterType().AsSelf().SingleInstance(); + + containerBuilder.Register>(c => + { + var componentContext = c.Resolve(); + return (sceneName) => componentContext.ResolveKeyed(sceneName); + }); + + return containerBuilder; + } + + static ContainerBuilder LoadAssemblyModules(this ContainerBuilder containerBuilder) + { + var filesToLoad = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll"); + foreach (var file in filesToLoad) + { + try + { + var assembly = Assembly.LoadFrom(file); + containerBuilder.RegisterAssemblyModules(assembly); + + } + catch { /* Silently ignore assembly load errors as not all DLLs are our modules... */ } + } + return containerBuilder; + } + } +} diff --git a/OpenDiablo2/Properties/AssemblyInfo.cs b/OpenDiablo2/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..17845381 --- /dev/null +++ b/OpenDiablo2/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenDiablo 2")] +[assembly: AssemblyDescription("The free and open source Diablo 2 remake!")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenDiablo 2")] +[assembly: AssemblyCopyright("GLP v3")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2b0cf1ac-06dd-4322-ae8b-ff8a8c70a3cd")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")] diff --git a/OpenDiablo2/log4net.config b/OpenDiablo2/log4net.config new file mode 100644 index 00000000..4bf2bd96 --- /dev/null +++ b/OpenDiablo2/log4net.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenDiablo2/packages.config b/OpenDiablo2/packages.config new file mode 100644 index 00000000..30b8494a --- /dev/null +++ b/OpenDiablo2/packages.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file