mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-09 10:06:35 -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