mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-03 15:17:04 -05:00
Initial commit
This commit is contained in:
commit
4d124ad959
334
.gitignore
vendored
Normal file
334
.gitignore
vendored
Normal file
@ -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/
|
15
OpenDiablo2.Common/Attributes/SceneAttribute.cs
Normal file
15
OpenDiablo2.Common/Attributes/SceneAttribute.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
16
OpenDiablo2.Common/Enums/eMPQFormatVersion.cs
Normal file
16
OpenDiablo2.Common/Enums/eMPQFormatVersion.cs
Normal file
@ -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
|
||||
}
|
||||
}
|
13
OpenDiablo2.Common/Interfaces/IGameEngine.cs
Normal file
13
OpenDiablo2.Common/Interfaces/IGameEngine.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
14
OpenDiablo2.Common/Interfaces/IMPQProvider.cs
Normal file
14
OpenDiablo2.Common/Interfaces/IMPQProvider.cs
Normal file
@ -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<MPQ> GetMPQs();
|
||||
IEnumerable<IEnumerable<String>> GetTextFile(string fileName);
|
||||
Stream GetStream(string fileName);
|
||||
}
|
||||
}
|
10
OpenDiablo2.Common/Interfaces/IPaletteProvider.cs
Normal file
10
OpenDiablo2.Common/Interfaces/IPaletteProvider.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using OpenDiablo2.Common.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces
|
||||
{
|
||||
public interface IPaletteProvider
|
||||
{
|
||||
Dictionary<string, Palette> PaletteTable { get; }
|
||||
}
|
||||
}
|
13
OpenDiablo2.Common/Interfaces/IRenderTarget.cs
Normal file
13
OpenDiablo2.Common/Interfaces/IRenderTarget.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
20
OpenDiablo2.Common/Interfaces/IRenderWindow.cs
Normal file
20
OpenDiablo2.Common/Interfaces/IRenderWindow.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
14
OpenDiablo2.Common/Interfaces/IScene.cs
Normal file
14
OpenDiablo2.Common/Interfaces/IScene.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
15
OpenDiablo2.Common/Interfaces/ISprite.cs
Normal file
15
OpenDiablo2.Common/Interfaces/ISprite.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
54
OpenDiablo2.Common/Models/BitStream.cs
Normal file
54
OpenDiablo2.Common/Models/BitStream.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenDiablo2.Common.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A utility class for reading groups of bits from a stream
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
7
OpenDiablo2.Common/Models/GlobalConfiguration.cs
Normal file
7
OpenDiablo2.Common/Models/GlobalConfiguration.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace OpenDiablo2.Common.Models
|
||||
{
|
||||
public sealed class GlobalConfiguration
|
||||
{
|
||||
public string BaseDataPath { get; set; }
|
||||
}
|
||||
}
|
127
OpenDiablo2.Common/Models/ImageSet.cs
Normal file
127
OpenDiablo2.Common/Models/ImageSet.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
364
OpenDiablo2.Common/Models/MPQ.cs
Normal file
364
OpenDiablo2.Common/Models/MPQ.cs
Normal file
@ -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<BlockRecord> blockTable = new List<BlockRecord>();
|
||||
private List<HashRecord> hashTable = new List<HashRecord>();
|
||||
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<string> Files => GetFilePaths();
|
||||
|
||||
private List<string> GetFilePaths()
|
||||
{
|
||||
var stream = OpenFile("(listfile)");
|
||||
if (stream == null)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
404
OpenDiablo2.Common/Models/MPQHuffman.cs
Normal file
404
OpenDiablo2.Common/Models/MPQHuffman.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A decompressor for MPQ's huffman compression
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
374
OpenDiablo2.Common/Models/MPQStream.cs
Normal file
374
OpenDiablo2.Common/Models/MPQStream.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
125
OpenDiablo2.Common/Models/MPQWavCompression.cs
Normal file
125
OpenDiablo2.Common/Models/MPQWavCompression.cs
Normal file
@ -0,0 +1,125 @@
|
||||
using System.IO;
|
||||
|
||||
namespace OpenDiablo2.Common.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// An IMA ADPCM decompress for Mpq files
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
229
OpenDiablo2.Common/Models/PKLibDecompress.cs
Normal file
229
OpenDiablo2.Common/Models/PKLibDecompress.cs
Normal file
@ -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
|
||||
}
|
||||
/// <summary>
|
||||
/// A decompressor for PKLib implode/explode
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
41
OpenDiablo2.Common/Models/Palette.cs
Normal file
41
OpenDiablo2.Common/Models/Palette.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
73
OpenDiablo2.Common/Models/SoundEntry.cs
Normal file
73
OpenDiablo2.Common/Models/SoundEntry.cs
Normal file
@ -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]),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
94
OpenDiablo2.Common/OpenDiablo2.Common.csproj
Normal file
94
OpenDiablo2.Common/OpenDiablo2.Common.csproj
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{B743160E-A0BB-45DC-9998-967A85E50562}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OpenDiablo2.Common</RootNamespace>
|
||||
<AssemblyName>OpenDiablo2.Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="DotNetZip, Version=1.12.0.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DotNetZip.1.12.0\lib\net20\DotNetZip.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.84.0.0, Culture=neutral, PublicKeyToken=1b03e6acf1164f73">
|
||||
<HintPath>..\packages\NetSword.Common.ICSharpCode.SharpZipLib.0.84.0\lib\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Attributes\SceneAttribute.cs" />
|
||||
<Compile Include="Enums\eMPQFormatVersion.cs" />
|
||||
<Compile Include="Interfaces\IGameEngine.cs" />
|
||||
<Compile Include="Interfaces\IMPQProvider.cs" />
|
||||
<Compile Include="Interfaces\IPaletteProvider.cs" />
|
||||
<Compile Include="Interfaces\IRenderTarget.cs" />
|
||||
<Compile Include="Interfaces\IRenderWindow.cs" />
|
||||
<Compile Include="Interfaces\IScene.cs" />
|
||||
<Compile Include="Interfaces\ISprite.cs" />
|
||||
<Compile Include="Models\BitStream.cs" />
|
||||
<Compile Include="Models\GlobalConfiguration.cs" />
|
||||
<Compile Include="Models\ImageSet.cs" />
|
||||
<Compile Include="Models\MPQ.cs" />
|
||||
<Compile Include="Models\MPQHuffman.cs" />
|
||||
<Compile Include="Models\MPQStream.cs" />
|
||||
<Compile Include="Models\MPQWavCompression.cs" />
|
||||
<Compile Include="Models\Palette.cs" />
|
||||
<Compile Include="Models\PKLibDecompress.cs" />
|
||||
<Compile Include="Models\SoundEntry.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
36
OpenDiablo2.Common/Properties/AssemblyInfo.cs
Normal file
36
OpenDiablo2.Common/Properties/AssemblyInfo.cs
Normal file
@ -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")]
|
6
OpenDiablo2.Common/packages.config
Normal file
6
OpenDiablo2.Common/packages.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="DotNetZip" version="1.12.0" targetFramework="net461" />
|
||||
<package id="NetSword.Common.ICSharpCode.SharpZipLib" version="0.84.0" targetFramework="net461" developmentDependency="true" />
|
||||
<package id="SharpZipLib" version="1.0.0" targetFramework="net461" />
|
||||
</packages>
|
23
OpenDiablo2.Core/AutofacModule.cs
Normal file
23
OpenDiablo2.Core/AutofacModule.cs
Normal file
@ -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<GameEngine>().AsImplementedInterfaces().SingleInstance();
|
||||
builder.RegisterType<MPQProvider>().As<IMPQProvider>().SingleInstance();
|
||||
}
|
||||
}
|
||||
}
|
97
OpenDiablo2.Core/GameEngine.cs
Normal file
97
OpenDiablo2.Core/GameEngine.cs
Normal file
@ -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<string, IScene> getScene;
|
||||
private IScene currentScene;
|
||||
|
||||
private readonly MPQ[] MPQs;
|
||||
|
||||
private Dictionary<string, SoundEntry> soundTable = new Dictionary<string, SoundEntry>();
|
||||
public Dictionary<string, Palette> PaletteTable { get; private set; } = new Dictionary<string, Palette>();
|
||||
private Stopwatch sw = new Stopwatch();
|
||||
|
||||
|
||||
public GameEngine(IMPQProvider mpqProvider, IRenderWindow renderWindow, Func<string, IScene> 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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
40
OpenDiablo2.Core/MPQProvider.cs
Normal file
40
OpenDiablo2.Core/MPQProvider.cs
Normal file
@ -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<MPQ> GetMPQs() => mpqs;
|
||||
|
||||
public Stream GetStream(string fileName)
|
||||
=> mpqs.First(x => x.Files.Any(z =>z.ToLower() == fileName.ToLower())).OpenFile(fileName);
|
||||
|
||||
public IEnumerable<IEnumerable<string>> 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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
90
OpenDiablo2.Core/OpenDiablo2.Core.csproj
Normal file
90
OpenDiablo2.Core/OpenDiablo2.Core.csproj
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{8FC6BF7D-835A-47C1-A6B2-125495FA0900}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OpenDiablo2.Core</RootNamespace>
|
||||
<AssemblyName>OpenDiablo2.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=4.8.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Autofac.4.8.1\lib\net45\Autofac.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Xabe.FFmpeg, Version=3.1.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xabe.FFmpeg.3.1.4\lib\netstandard2.0\Xabe.FFmpeg.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AutofacModule.cs" />
|
||||
<Compile Include="GameEngine.cs" />
|
||||
<Compile Include="MPQProvider.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenDiablo2.Common\OpenDiablo2.Common.csproj">
|
||||
<Project>{b743160e-a0bb-45dc-9998-967a85e50562}</Project>
|
||||
<Name>OpenDiablo2.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
36
OpenDiablo2.Core/Properties/AssemblyInfo.cs
Normal file
36
OpenDiablo2.Core/Properties/AssemblyInfo.cs
Normal file
@ -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")]
|
7
OpenDiablo2.Core/packages.config
Normal file
7
OpenDiablo2.Core/packages.config
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Autofac" version="4.8.1" targetFramework="net461" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||
<package id="Xabe.FFmpeg" version="3.1.4" targetFramework="net461" />
|
||||
</packages>
|
18
OpenDiablo2.SDL2/AutofacModule.cs
Normal file
18
OpenDiablo2.SDL2/AutofacModule.cs
Normal file
@ -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<SDL2RenderWindow>().AsImplementedInterfaces().SingleInstance();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
96
OpenDiablo2.SDL2/OpenDiablo2.SDL2.csproj
Normal file
96
OpenDiablo2.SDL2/OpenDiablo2.SDL2.csproj
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{1F8731D5-393B-4561-9CEA-887A2F466576}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OpenDiablo2.SDL2</RootNamespace>
|
||||
<AssemblyName>OpenDiablo2.SDL2</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=4.8.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Autofac.4.8.1\lib\net45\Autofac.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AutofacModule.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SDL2-CS\LPUtf8StrMarshaler.cs" />
|
||||
<Compile Include="SDL2-CS\SDL2.cs" />
|
||||
<Compile Include="SDL2-CS\SDL2_image.cs" />
|
||||
<Compile Include="SDL2-CS\SDL2_mixer.cs" />
|
||||
<Compile Include="SDL2-CS\SDL2_ttf.cs" />
|
||||
<Compile Include="SDL2RenderWindow.cs" />
|
||||
<Compile Include="SDL2Sprite.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenDiablo2.Common\OpenDiablo2.Common.csproj">
|
||||
<Project>{b743160e-a0bb-45dc-9998-967a85e50562}</Project>
|
||||
<Name>OpenDiablo2.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="SDL2.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
36
OpenDiablo2.SDL2/Properties/AssemblyInfo.cs
Normal file
36
OpenDiablo2.SDL2/Properties/AssemblyInfo.cs
Normal file
@ -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")]
|
106
OpenDiablo2.SDL2/SDL2-CS/LPUtf8StrMarshaler.cs
Normal file
106
OpenDiablo2.SDL2/SDL2-CS/LPUtf8StrMarshaler.cs
Normal file
@ -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 <flibitijibibo@flibitijibibo.com>
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
5683
OpenDiablo2.SDL2/SDL2-CS/SDL2.cs
Normal file
5683
OpenDiablo2.SDL2/SDL2-CS/SDL2.cs
Normal file
File diff suppressed because it is too large
Load Diff
178
OpenDiablo2.SDL2/SDL2-CS/SDL2_image.cs
Normal file
178
OpenDiablo2.SDL2/SDL2-CS/SDL2_image.cs
Normal file
@ -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 <flibitijibibo@flibitijibibo.com>
|
||||
*
|
||||
*/
|
||||
#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
|
||||
}
|
||||
}
|
489
OpenDiablo2.SDL2/SDL2-CS/SDL2_mixer.cs
Normal file
489
OpenDiablo2.SDL2/SDL2-CS/SDL2_mixer.cs
Normal file
@ -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 <flibitijibibo@flibitijibibo.com>
|
||||
*
|
||||
*/
|
||||
#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
|
||||
}
|
||||
}
|
406
OpenDiablo2.SDL2/SDL2-CS/SDL2_ttf.cs
Normal file
406
OpenDiablo2.SDL2/SDL2-CS/SDL2_ttf.cs
Normal file
@ -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 <flibitijibibo@flibitijibibo.com>
|
||||
*
|
||||
*/
|
||||
#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
|
||||
}
|
||||
}
|
BIN
OpenDiablo2.SDL2/SDL2.dll
Normal file
BIN
OpenDiablo2.SDL2/SDL2.dll
Normal file
Binary file not shown.
91
OpenDiablo2.SDL2/SDL2RenderWindow.cs
Normal file
91
OpenDiablo2.SDL2/SDL2RenderWindow.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
123
OpenDiablo2.SDL2/SDL2Sprite.cs
Normal file
123
OpenDiablo2.SDL2/SDL2Sprite.cs
Normal file
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
OpenDiablo2.SDL2/packages.config
Normal file
6
OpenDiablo2.SDL2/packages.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Autofac" version="4.8.1" targetFramework="net461" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net461" />
|
||||
<package id="SDL2-CS" version="2.0.0.0" targetFramework="net461" />
|
||||
</packages>
|
31
OpenDiablo2.Scenes/AutofacModule.cs
Normal file
31
OpenDiablo2.Scenes/AutofacModule.cs
Normal file
@ -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<IScene>(att.SceneName)
|
||||
.InstancePerDependency();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
96
OpenDiablo2.Scenes/MainMenu.cs
Normal file
96
OpenDiablo2.Scenes/MainMenu.cs
Normal file
@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
65
OpenDiablo2.Scenes/OpenDiablo2.Scenes.csproj
Normal file
65
OpenDiablo2.Scenes/OpenDiablo2.Scenes.csproj
Normal file
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{05224FE7-293F-4184-B1D6-89F5171B60E0}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OpenDiablo2.Scenes</RootNamespace>
|
||||
<AssemblyName>OpenDiablo2.Scenes</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=4.8.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Autofac.4.8.1\lib\net45\Autofac.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AutofacModule.cs" />
|
||||
<Compile Include="MainMenu.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenDiablo2.Common\OpenDiablo2.Common.csproj">
|
||||
<Project>{b743160e-a0bb-45dc-9998-967a85e50562}</Project>
|
||||
<Name>OpenDiablo2.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
36
OpenDiablo2.Scenes/Properties/AssemblyInfo.cs
Normal file
36
OpenDiablo2.Scenes/Properties/AssemblyInfo.cs
Normal file
@ -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")]
|
5
OpenDiablo2.Scenes/packages.config
Normal file
5
OpenDiablo2.Scenes/packages.config
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Autofac" version="4.8.1" targetFramework="net461" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net461" />
|
||||
</packages>
|
71
OpenDiablo2.sln
Normal file
71
OpenDiablo2.sln
Normal file
@ -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
|
6
OpenDiablo2/App.config
Normal file
6
OpenDiablo2/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
</configuration>
|
10
OpenDiablo2/CommandLineOptions.cs
Normal file
10
OpenDiablo2/CommandLineOptions.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
112
OpenDiablo2/OpenDiablo2.csproj
Normal file
112
OpenDiablo2/OpenDiablo2.csproj
Normal file
@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>OpenDiablo2</RootNamespace>
|
||||
<AssemblyName>OpenDiablo2</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=4.8.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Autofac.4.8.1\lib\net45\Autofac.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CommandLine, Version=2.3.0.0, Culture=neutral, PublicKeyToken=de6f01bd326f8c32, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CommandLineParser.2.3.0\lib\net45\CommandLine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Console, Version=4.0.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Console.4.3.1\lib\net46\System.Console.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Reflection.TypeExtensions, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Reflection.TypeExtensions.4.5.1\lib\net461\System.Reflection.TypeExtensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CommandLineOptions.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="log4net.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenDiablo2.Common\OpenDiablo2.Common.csproj">
|
||||
<Project>{b743160e-a0bb-45dc-9998-967a85e50562}</Project>
|
||||
<Name>OpenDiablo2.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\OpenDiablo2.Core\OpenDiablo2.Core.csproj">
|
||||
<Project>{8fc6bf7d-835a-47c1-a6b2-125495fa0900}</Project>
|
||||
<Name>OpenDiablo2.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\OpenDiablo2.Scenes\OpenDiablo2.Scenes.csproj">
|
||||
<Project>{05224fe7-293f-4184-b1d6-89f5171b60e0}</Project>
|
||||
<Name>OpenDiablo2.Scenes</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\OpenDiablo2.SDL2\OpenDiablo2.SDL2.csproj">
|
||||
<Project>{1f8731d5-393b-4561-9cea-887a2f466576}</Project>
|
||||
<Name>OpenDiablo2.SDL2</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
88
OpenDiablo2/Program.cs
Normal file
88
OpenDiablo2/Program.cs
Normal file
@ -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<IGameEngine>()
|
||||
.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<string> args)
|
||||
{
|
||||
var globalConfiguration = container.Resolve<GlobalConfiguration>();
|
||||
|
||||
Parser.Default.ParseArguments<CommandLineOptions>(args).WithParsed<CommandLineOptions>(o =>
|
||||
{
|
||||
globalConfiguration.BaseDataPath = Path.GetFullPath(o.DataPath ?? Directory.GetCurrentDirectory());
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
static ContainerBuilder RegisterLocalTypes(this ContainerBuilder containerBuilder)
|
||||
{
|
||||
containerBuilder.RegisterType<GlobalConfiguration>().AsSelf().SingleInstance();
|
||||
|
||||
containerBuilder.Register<Func<string, IScene>>(c =>
|
||||
{
|
||||
var componentContext = c.Resolve<IComponentContext>();
|
||||
return (sceneName) => componentContext.ResolveKeyed<IScene>(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;
|
||||
}
|
||||
}
|
||||
}
|
37
OpenDiablo2/Properties/AssemblyInfo.cs
Normal file
37
OpenDiablo2/Properties/AssemblyInfo.cs
Normal file
@ -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")]
|
23
OpenDiablo2/log4net.config
Normal file
23
OpenDiablo2/log4net.config
Normal file
@ -0,0 +1,23 @@
|
||||
<log4net>
|
||||
<root>
|
||||
<level value="ALL" />
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="file" />
|
||||
</root>
|
||||
<appender name="console" type="log4net.Appender.ConsoleAppender">
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date %level %logger - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="file" type="log4net.Appender.RollingFileAppender">
|
||||
<file value="OpenDiablo2.log" />
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Size" />
|
||||
<maxSizeRollBackups value="5" />
|
||||
<maximumFileSize value="10MB" />
|
||||
<staticLogFileName value="true" />
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
</log4net>
|
19
OpenDiablo2/packages.config
Normal file
19
OpenDiablo2/packages.config
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Autofac" version="4.8.1" targetFramework="net461" />
|
||||
<package id="CommandLineParser" version="2.3.0" targetFramework="net461" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net461" />
|
||||
<package id="System.Collections" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Console" version="4.3.1" targetFramework="net461" />
|
||||
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Globalization" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.IO" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Linq" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Reflection" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Reflection.TypeExtensions" version="4.5.1" targetFramework="net461" />
|
||||
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Runtime" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net461" />
|
||||
</packages>
|
Loading…
Reference in New Issue
Block a user