Browse Source

Rebirth and Nuke

pull/18/head
aperturesecurity 8 years ago
commit
42ce77ce05
  1. 358
      .gitignore
  2. 34
      .travis.yml
  3. 522
      3rdParty/PKWare/explode.cpp
  4. 775
      3rdParty/PKWare/implode.cpp
  5. 142
      3rdParty/PKWare/pkware.h
  6. 93
      3rdParty/Storm/Source/Storm.dsp
  7. 146
      3rdParty/Storm/Source/Storm.vcxproj
  8. 238
      3rdParty/Storm/Source/storm.cpp
  9. 441
      3rdParty/Storm/Source/storm.def
  10. 1311
      3rdParty/Storm/Source/storm.h
  11. 495
      3rdParty/Storm/Source/storm_gcc.def
  12. 21
      3rdParty/StormLib/LICENSE
  13. 2830
      3rdParty/StormLib/src/FileStream.cpp
  14. 217
      3rdParty/StormLib/src/FileStream.h
  15. 1856
      3rdParty/StormLib/src/SBaseCommon.cpp
  16. 2962
      3rdParty/StormLib/src/SBaseFileTable.cpp
  17. 618
      3rdParty/StormLib/src/SBaseSubTypes.cpp
  18. 1166
      3rdParty/StormLib/src/SCompression.cpp
  19. 64
      3rdParty/StormLib/src/SFileExtractFile.cpp
  20. 481
      3rdParty/StormLib/src/SFileFindFile.cpp
  21. 1010
      3rdParty/StormLib/src/SFileGetFileInfo.cpp
  22. 618
      3rdParty/StormLib/src/SFileOpenArchive.cpp
  23. 398
      3rdParty/StormLib/src/SFileOpenFileEx.cpp
  24. 907
      3rdParty/StormLib/src/SFileReadFile.cpp
  25. 387
      3rdParty/StormLib/src/StormCommon.h
  26. 1134
      3rdParty/StormLib/src/StormLib.h
  27. 304
      3rdParty/StormLib/src/StormPort.h
  28. 16
      CMake/32bit.cmake
  29. 9
      CMake/SDL2_fixed.cmake
  30. 3
      CMake/out_of_tree.cmake
  31. 8
      CMake/sanitize.cmake
  32. 147
      CMakeLists.txt
  33. 431
      Diablo.dsp
  34. 59
      Diablo.dsw
  35. BIN
      Diablo.ico
  36. 291
      Diablo.rc
  37. 37
      Diablo.sln
  38. 293
      Diablo.vcxproj
  39. 467
      Diablo.vcxproj.filters
  40. 93
      DiabloUI/DiabloUI.dsp
  41. 146
      DiabloUI/DiabloUI.vcxproj
  42. 61
      DiabloUI/diabloui.cpp
  43. 29
      DiabloUI/diabloui.def
  44. 40
      DiabloUI/diabloui.h
  45. 48
      DiabloUI/diabloui_gcc.def
  46. 24
      LICENSE
  47. 55
      Makefile
  48. 83
      MakefileVC
  49. 152
      README.md
  50. 437
      Source/appfat.cpp
  51. 30
      Source/appfat.h
  52. 943
      Source/automap.cpp
  53. 37
      Source/automap.h
  54. 173
      Source/capture.cpp
  55. 13
      Source/capture.h
  56. 191
      Source/codec.cpp
  57. 10
      Source/codec.h
  58. 3431
      Source/control.cpp
  59. 141
      Source/control.h
  60. 1300
      Source/cursor.cpp
  61. 36
      Source/cursor.h
  62. 151
      Source/dead.cpp
  63. 13
      Source/dead.h
  64. 247
      Source/debug.cpp
  65. 26
      Source/debug.h
  66. 2303
      Source/diablo.cpp
  67. 102
      Source/diablo.h
  68. 113
      Source/doom.cpp
  69. 23
      Source/doom.h
  70. 2910
      Source/drlg_l1.cpp
  71. 68
      Source/drlg_l1.h
  72. 3376
      Source/drlg_l2.cpp
  73. 173
      Source/drlg_l2.h
  74. 2946
      Source/drlg_l3.cpp
  75. 87
      Source/drlg_l3.h
  76. 3339
      Source/drlg_l4.cpp
  77. 69
      Source/drlg_l4.h
  78. 200
      Source/dthread.cpp
  79. 25
      Source/dthread.h
  80. 298
      Source/dx.cpp
  81. 38
      Source/dx.h
  82. 1426
      Source/effects.cpp
  83. 41
      Source/effects.h
  84. 210
      Source/encrypt.cpp
  85. 17
      Source/encrypt.h
  86. 2920
      Source/engine.cpp
  87. 80
      Source/engine.h
  88. 217
      Source/error.cpp
  89. 17
      Source/error.h
  90. 248
      Source/fault.cpp
  91. 26
      Source/fault.h
  92. 327
      Source/gamemenu.cpp
  93. 36
      Source/gamemenu.h
  94. 1441
      Source/gendung.cpp
  95. 95
      Source/gendung.h
  96. 511
      Source/gmenu.cpp
  97. 44
      Source/gmenu.h
  98. 272
      Source/help.cpp
  99. 21
      Source/help.h
  100. 530
      Source/init.cpp
  101. Some files were not shown because too many files have changed in this diff Show More

358
.gitignore vendored

@ -0,0 +1,358 @@
# ELF object file.
*.o
# PE shared library and associated files.
*.lib
*.exp
*.dll
# PE executable.
*.exe
# GCC dependency file.
*.d
# Resource file.
*.res
# Created by https://www.gitignore.io/api/visualstudio
### VisualStudio ###
## 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
*.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/
WinDebug/
WinRel/
# 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
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.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
.cr/
# 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/
### VisualStudio Patch ###
# By default, sensitive information, such as encrypted password
# should be stored in the .pubxml.user file.
*.pubxml.user
# End of https://www.gitignore.io/api/visualstudio

34
.travis.yml

@ -0,0 +1,34 @@
language: cpp
os:
- linux
- osx
notifications:
email:
on_failure: change # default: always
addons:
# Packages for Linux
apt:
packages:
- mingw-w64
env:
- MAKE_BUILD=make
- MAKE_BUILD=debug
before_install:
# Packages for OSX
- if [ $TRAVIS_OS_NAME = osx ]; then brew install mingw-w64; fi
before_script:
- touch storm.dll
- touch diabloui.dll
script:
- if [ $MAKE_BUILD = make ]; then make; fi
- if [ $MAKE_BUILD = debug ]; then make debug; fi
after_script:
- make clean

522
3rdParty/PKWare/explode.cpp vendored

@ -0,0 +1,522 @@
/*****************************************************************************/
/* explode.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Implode function of PKWARE Data Compression library */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
/* 08.04.03 1.01 Lad Renamed to explode.cpp to be compatible with pkware */
/* 02.05.03 1.01 Lad Stress test done */
/* 22.04.10 1.01 Lad Documented */
/*****************************************************************************/
#include <assert.h>
#include <string.h>
#include "pkware.h"
#define PKDCL_OK 0
#define PKDCL_STREAM_END 1 // All data from the input stream is read
#define PKDCL_NEED_DICT 2 // Need more data (dictionary)
#define PKDCL_CONTINUE 10 // Internal flag, not returned to user
#define PKDCL_GET_INPUT 11 // Internal flag, not returned to user
static char CopyrightPkware[] = "PKWARE Data Compression Library for Win32\r\n"
"Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
"Patent No. 5,051,745\r\n"
"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
"Version 1.11\r\n";
//-----------------------------------------------------------------------------
// Tables
static unsigned char DistBits[] =
{
0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
static unsigned char DistCode[] =
{
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 unsigned char ExLenBits[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
static unsigned short LenBase[] =
{
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
};
static unsigned char LenBits[] =
{
0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
};
static unsigned char LenCode[] =
{
0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
};
static unsigned char ChBitsAsc[] =
{
0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
};
static unsigned short ChCodeAsc[] =
{
0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
};
//-----------------------------------------------------------------------------
// Local functions
static void GenDecodeTabs(
unsigned char * positions, // [out] Table of positions
unsigned char * start_indexes, // [in] Table of start indexes
unsigned char * length_bits, // [in] Table of lengths. Each length is stored as number of bits
size_t elements) // [in] Number of elements in start_indexes and length_bits
{
unsigned int index;
unsigned int length;
size_t i;
for(i = 0; i < elements; i++)
{
length = 1 << length_bits[i]; // Get the length in bytes
for(index = start_indexes[i]; index < 0x100; index += length)
{
positions[index] = (unsigned char)i;
}
}
}
static void GenAscTabs(TDcmpStruct * pWork)
{
unsigned short * pChCodeAsc = &ChCodeAsc[0xFF];
unsigned int acc, add;
unsigned short count;
for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--)
{
unsigned char * pChBitsAsc = pWork->ChBitsAsc + count;
unsigned char bits_asc = *pChBitsAsc;
if(bits_asc <= 8)
{
add = (1 << bits_asc);
acc = *pChCodeAsc;
do
{
pWork->offs2C34[acc] = (unsigned char)count;
acc += add;
}
while(acc < 0x100);
}
else if((acc = (*pChCodeAsc & 0xFF)) != 0)
{
pWork->offs2C34[acc] = 0xFF;
if(*pChCodeAsc & 0x3F)
{
bits_asc -= 4;
*pChBitsAsc = bits_asc;
add = (1 << bits_asc);
acc = *pChCodeAsc >> 4;
do
{
pWork->offs2D34[acc] = (unsigned char)count;
acc += add;
}
while(acc < 0x100);
}
else
{
bits_asc -= 6;
*pChBitsAsc = bits_asc;
add = (1 << bits_asc);
acc = *pChCodeAsc >> 6;
do
{
pWork->offs2E34[acc] = (unsigned char)count;
acc += add;
}
while(acc < 0x80);
}
}
else
{
bits_asc -= 8;
*pChBitsAsc = bits_asc;
add = (1 << bits_asc);
acc = *pChCodeAsc >> 8;
do
{
pWork->offs2EB4[acc] = (unsigned char)count;
acc += add;
}
while(acc < 0x100);
}
}
}
//-----------------------------------------------------------------------------
// Removes given number of bits in the bit buffer. New bits are reloaded from
// the input buffer, if needed.
// Returns: PKDCL_OK: Operation was successful
// PKDCL_STREAM_END: There are no more bits in the input buffer
static int WasteBits(TDcmpStruct * pWork, unsigned int nBits)
{
// If number of bits required is less than number of (bits in the buffer) ?
if(nBits <= pWork->extra_bits)
{
pWork->extra_bits -= nBits;
pWork->bit_buff >>= nBits;
return PKDCL_OK;
}
// Load input buffer if necessary
pWork->bit_buff >>= pWork->extra_bits;
if(pWork->in_pos == pWork->in_bytes)
{
pWork->in_pos = sizeof(pWork->in_buff);
if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0)
return PKDCL_STREAM_END;
pWork->in_pos = 0;
}
// Update bit buffer
pWork->bit_buff |= (pWork->in_buff[pWork->in_pos++] << 8);
pWork->bit_buff >>= (nBits - pWork->extra_bits);
pWork->extra_bits = (pWork->extra_bits - nBits) + 8;
return PKDCL_OK;
}
//-----------------------------------------------------------------------------
// Decodes next literal from the input (compressed) data.
// Returns : 0x000: One byte 0x00
// 0x001: One byte 0x01
// ...
// 0x0FF: One byte 0xFF
// 0x100: Repetition, length of 0x02 bytes
// 0x101: Repetition, length of 0x03 bytes
// ...
// 0x304: Repetition, length of 0x206 bytes
// 0x305: End of stream
// 0x306: Error
static unsigned int DecodeLit(TDcmpStruct * pWork)
{
unsigned int extra_length_bits; // Number of bits of extra literal length
unsigned int length_code; // Length code
unsigned int value;
// Test the current bit in byte buffer. If is not set, simply return the next 8 bits.
if(pWork->bit_buff & 1)
{
// Remove one bit from the input data
if(WasteBits(pWork, 1))
return 0x306;
// The next 8 bits hold the index to the length code table
length_code = pWork->LengthCodes[pWork->bit_buff & 0xFF];
// Remove the apropriate number of bits
if(WasteBits(pWork, pWork->LenBits[length_code]))
return 0x306;
// Are there some extra bits for the obtained length code ?
if((extra_length_bits = pWork->ExLenBits[length_code]) != 0)
{
unsigned int extra_length = pWork->bit_buff & ((1 << extra_length_bits) - 1);
if(WasteBits(pWork, extra_length_bits))
{
if((length_code + extra_length) != 0x10E)
return 0x306;
}
length_code = pWork->LenBase[length_code] + extra_length;
}
// In order to distinguish uncompressed byte from repetition length,
// we have to add 0x100 to the length.
return length_code + 0x100;
}
// Remove one bit from the input data
if(WasteBits(pWork, 1))
return 0x306;
// If the binary compression type, read 8 bits and return them as one byte.
if(pWork->ctype == CMP_BINARY)
{
unsigned int uncompressed_byte = pWork->bit_buff & 0xFF;
if(WasteBits(pWork, 8))
return 0x306;
return uncompressed_byte;
}
// When ASCII compression ...
if(pWork->bit_buff & 0xFF)
{
value = pWork->offs2C34[pWork->bit_buff & 0xFF];
if(value == 0xFF)
{
if(pWork->bit_buff & 0x3F)
{
if(WasteBits(pWork, 4))
return 0x306;
value = pWork->offs2D34[pWork->bit_buff & 0xFF];
}
else
{
if(WasteBits(pWork, 6))
return 0x306;
value = pWork->offs2E34[pWork->bit_buff & 0x7F];
}
}
}
else
{
if(WasteBits(pWork, 8))
return 0x306;
value = pWork->offs2EB4[pWork->bit_buff & 0xFF];
}
return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value;
}
//-----------------------------------------------------------------------------
// Decodes the distance of the repetition, backwards relative to the
// current output buffer position
static unsigned int DecodeDist(TDcmpStruct * pWork, unsigned int rep_length)
{
unsigned int dist_pos_code; // Distance position code
unsigned int dist_pos_bits; // Number of bits of distance position
unsigned int distance; // Distance position
// Next 2-8 bits in the input buffer is the distance position code
dist_pos_code = pWork->DistPosCodes[pWork->bit_buff & 0xFF];
dist_pos_bits = pWork->DistBits[dist_pos_code];
if(WasteBits(pWork, dist_pos_bits))
return 0;
if(rep_length == 2)
{
// If the repetition is only 2 bytes length,
// then take 2 bits from the stream in order to get the distance
distance = (dist_pos_code << 2) | (pWork->bit_buff & 0x03);
if(WasteBits(pWork, 2))
return 0;
}
else
{
// If the repetition is more than 2 bytes length,
// then take "dsize_bits" bits in order to get the distance
distance = (dist_pos_code << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask);
if(WasteBits(pWork, pWork->dsize_bits))
return 0;
}
return distance + 1;
}
static unsigned int Expand(TDcmpStruct * pWork)
{
unsigned int next_literal; // Literal decoded from the compressed data
unsigned int result; // Value to be returned
unsigned int copyBytes; // Number of bytes to copy to the output buffer
pWork->outputPos = 0x1000; // Initialize output buffer position
// Decode the next literal from the input data.
// The returned literal can either be an uncompressed byte (next_literal < 0x100)
// or an encoded length of the repeating byte sequence that
// is to be copied to the current buffer position
while((result = next_literal = DecodeLit(pWork)) < 0x305)
{
// If the literal is greater than 0x100, it holds length
// of repeating byte sequence
// literal of 0x100 means repeating sequence of 0x2 bytes
// literal of 0x101 means repeating sequence of 0x3 bytes
// ...
// literal of 0x305 means repeating sequence of 0x207 bytes
if(next_literal >= 0x100)
{
unsigned char * source;
unsigned char * target;
unsigned int rep_length; // Length of the repetition, in bytes
unsigned int minus_dist; // Backward distance to the repetition, relative to the current buffer position
// Get the length of the repeating sequence.
// Note that the repeating block may overlap the current output position,
// for example if there was a sequence of equal bytes
rep_length = next_literal - 0xFE;
// Get backward distance to the repetition
if((minus_dist = DecodeDist(pWork, rep_length)) == 0)
{
result = 0x306;
break;
}
// Target and source pointer
target = &pWork->out_buff[pWork->outputPos];
source = target - minus_dist;
// Update buffer output position
pWork->outputPos += rep_length;
// Copy the repeating sequence
while(rep_length-- > 0)
*target++ = *source++;
}
else
{
pWork->out_buff[pWork->outputPos++] = (unsigned char)next_literal;
}
// Flush the output buffer, if number of extracted bytes has reached the end
if(pWork->outputPos >= 0x2000)
{
// Copy decompressed data into user buffer
copyBytes = 0x1000;
pWork->write_buf((char *)&pWork->out_buff[0x1000], &copyBytes, pWork->param);
// Now copy the decompressed data to the first half of the buffer.
// This is needed because the decompression might reuse them as repetitions.
// Note that if the output buffer overflowed previously, the extra decompressed bytes
// are stored in "out_buff_overflow", and they will now be
// within decompressed part of the output buffer.
memmove(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);
pWork->outputPos -= 0x1000;
}
}
// Flush any remaining decompressed bytes
copyBytes = pWork->outputPos - 0x1000;
pWork->write_buf((char *)&pWork->out_buff[0x1000], &copyBytes, pWork->param);
return result;
}
//-----------------------------------------------------------------------------
// Main exploding function.
unsigned int explode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param)
{
TDcmpStruct * pWork = (TDcmpStruct *)work_buf;
// Initialize work struct and load compressed data
// Note: The caller must zero the "work_buff" before passing it to explode
pWork->read_buf = read_buf;
pWork->write_buf = write_buf;
pWork->param = param;
pWork->in_pos = sizeof(pWork->in_buff);
pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param);
if(pWork->in_bytes <= 4)
return CMP_BAD_DATA;
pWork->ctype = pWork->in_buff[0]; // Get the compression type (CMP_BINARY or CMP_ASCII)
pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size
pWork->bit_buff = pWork->in_buff[2]; // Initialize 16-bit bit buffer
pWork->extra_bits = 0; // Extra (over 8) bits
pWork->in_pos = 3; // Position in input buffer
// Test for the valid dictionary size
if(4 > pWork->dsize_bits || pWork->dsize_bits > 6)
return CMP_INVALID_DICTSIZE;
pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction
if(pWork->ctype != CMP_BINARY)
{
if(pWork->ctype != CMP_ASCII)
return CMP_INVALID_MODE;
memcpy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc));
GenAscTabs(pWork);
}
memcpy(pWork->LenBits, LenBits, sizeof(pWork->LenBits));
GenDecodeTabs(pWork->LengthCodes, LenCode, pWork->LenBits, sizeof(pWork->LenBits));
memcpy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits));
memcpy(pWork->LenBase, LenBase, sizeof(pWork->LenBase));
memcpy(pWork->DistBits, DistBits, sizeof(pWork->DistBits));
GenDecodeTabs(pWork->DistPosCodes, DistCode, pWork->DistBits, sizeof(pWork->DistBits));
if(Expand(pWork) != 0x306)
return CMP_NO_ERROR;
return CMP_ABORT;
}

775
3rdParty/PKWare/implode.cpp vendored

@ -0,0 +1,775 @@
/*****************************************************************************/
/* implode.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Implode function of PKWARE Data Compression library */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 11.04.03 1.00 Lad First version of implode.cpp */
/* 02.05.03 1.00 Lad Stress test done */
/* 22.04.10 1.01 Lad Documented */
/*****************************************************************************/
#include <assert.h>
#include <string.h>
#include "pkware.h"
#if ((1200 < _MSC_VER) && (_MSC_VER < 1400))
#pragma optimize("", off)
#endif
//-----------------------------------------------------------------------------
// Defines
#define MAX_REP_LENGTH 0x204 // The longest allowed repetition
static char CopyrightPkware[] = "PKWARE Data Compression Library for Win32\r\n"
"Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
"Patent No. 5,051,745\r\n"
"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
"Version 1.11\r\n";
//-----------------------------------------------------------------------------
// Tables
static unsigned char DistBits[] =
{
0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
static unsigned char DistCode[] =
{
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 unsigned char ExLenBits[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
static unsigned char LenBits[] =
{
0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
};
static unsigned char LenCode[] =
{
0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
};
static unsigned char ChBitsAsc[] =
{
0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
};
static unsigned short ChCodeAsc[] =
{
0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
};
//-----------------------------------------------------------------------------
// Macros
// Macro for calculating hash of the current byte pair.
// Note that most exact byte pair hash would be buffer[0] + buffer[1] << 0x08,
// but even this way gives nice indication of equal byte pairs, with significantly
// smaller size of the array that holds numbers of those hashes
#define BYTE_PAIR_HASH(buffer) ((buffer[0] * 4) + (buffer[1] * 5))
//-----------------------------------------------------------------------------
// Local functions
// Builds the "hash_to_index" table and "pair_hash_offsets" table.
// Every element of "hash_to_index" will contain lowest index to the
// "pair_hash_offsets" table, effectively giving offset of the first
// occurence of the given PAIR_HASH in the input data.
static void SortBuffer(TCmpStruct * pWork, unsigned char * buffer_begin, unsigned char * buffer_end)
{
unsigned short * phash_to_index;
unsigned char * buffer_ptr;
unsigned short total_sum = 0;
unsigned long byte_pair_hash; // Hash value of the byte pair
unsigned short byte_pair_offs; // Offset of the byte pair, relative to "work_buff"
// Zero the entire "phash_to_index" table
memset(pWork->phash_to_index, 0, sizeof(pWork->phash_to_index));
// Step 1: Count amount of each PAIR_HASH in the input buffer
// The table will look like this:
// offs 0x000: Number of occurences of PAIR_HASH 0
// offs 0x001: Number of occurences of PAIR_HASH 1
// ...
// offs 0x8F7: Number of occurences of PAIR_HASH 0x8F7 (the highest hash value)
for(buffer_ptr = buffer_begin; buffer_ptr < buffer_end; buffer_ptr++)
pWork->phash_to_index[BYTE_PAIR_HASH(buffer_ptr)]++;
// Step 2: Convert the table to the array of PAIR_HASH amounts.
// Each element contains count of PAIR_HASHes that is less or equal
// to element index
// The table will look like this:
// offs 0x000: Number of occurences of PAIR_HASH 0 or lower
// offs 0x001: Number of occurences of PAIR_HASH 1 or lower
// ...
// offs 0x8F7: Number of occurences of PAIR_HASH 0x8F7 or lower
for(phash_to_index = pWork->phash_to_index; phash_to_index < &pWork->phash_to_index_end; phash_to_index++)
{
total_sum = total_sum + phash_to_index[0];
phash_to_index[0] = total_sum;
}
// Step 3: Convert the table to the array of indexes.
// Now, each element contains index to the first occurence of given PAIR_HASH
for(buffer_end--; buffer_end >= buffer_begin; buffer_end--)
{
byte_pair_hash = BYTE_PAIR_HASH(buffer_end);
byte_pair_offs = (unsigned short)(buffer_end - pWork->work_buff);
pWork->phash_to_index[byte_pair_hash]--;
pWork->phash_offs[pWork->phash_to_index[byte_pair_hash]] = byte_pair_offs;
}
}
static void FlushBuf(TCmpStruct * pWork)
{
unsigned char save_ch1;
unsigned char save_ch2;
unsigned int size = 0x800;
pWork->write_buf(pWork->out_buff, &size, pWork->param);
save_ch1 = pWork->out_buff[0x800];
save_ch2 = pWork->out_buff[pWork->out_bytes];
pWork->out_bytes -= 0x800;
memset(pWork->out_buff, 0, sizeof(pWork->out_buff));
if(pWork->out_bytes != 0)
pWork->out_buff[0] = save_ch1;
if(pWork->out_bits != 0)
pWork->out_buff[pWork->out_bytes] = save_ch2;
}
static void OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)
{
unsigned int out_bits;
// If more than 8 bits to output, do recursion
if(nbits > 8)
{
OutputBits(pWork, 8, bit_buff);
bit_buff >>= 8;
nbits -= 8;
}
// Add bits to the last out byte in out_buff;
out_bits = pWork->out_bits;
pWork->out_buff[pWork->out_bytes] |= (unsigned char)(bit_buff << out_bits);
pWork->out_bits += nbits;
// If 8 or more bits, increment number of bytes
if(pWork->out_bits > 8)
{
pWork->out_bytes++;
bit_buff >>= (8 - out_bits);
pWork->out_buff[pWork->out_bytes] = (unsigned char)bit_buff;
pWork->out_bits &= 7;
}
else
{
pWork->out_bits &= 7;
if(pWork->out_bits == 0)
pWork->out_bytes++;
}
// If there is enough compressed bytes, flush them
if(pWork->out_bytes >= 0x800)
FlushBuf(pWork);
}
// This function searches for a repetition
// (a previous occurence of the current byte sequence)
// Returns length of the repetition, and stores the backward distance
// to pWork structure.
static unsigned int FindRep(TCmpStruct * pWork, unsigned char * input_data)
{
unsigned short * phash_to_index; // Pointer into pWork->phash_to_index table
unsigned short * phash_offs; // Pointer to the table containing offsets of each PAIR_HASH
unsigned char * repetition_limit; // An eventual repetition must be at position below this pointer
unsigned char * prev_repetition; // Pointer to the previous occurence of the current PAIR_HASH
unsigned char * prev_rep_end; // End of the previous repetition
unsigned char * input_data_ptr;
unsigned short phash_offs_index; // Index to the table with PAIR_HASH positions
unsigned short min_phash_offs; // The lowest allowed hash offset
unsigned short offs_in_rep; // Offset within found repetition
unsigned int equal_byte_count; // Number of bytes that are equal to the previous occurence
unsigned int rep_length = 1; // Length of the found repetition
unsigned int rep_length2; // Secondary repetition
unsigned char pre_last_byte; // Last but one byte from a repetion
unsigned short di_val;
// Calculate the previous position of the PAIR_HASH
phash_to_index = pWork->phash_to_index + BYTE_PAIR_HASH(input_data);
min_phash_offs = (unsigned short)((input_data - pWork->work_buff) - pWork->dsize_bytes + 1);
phash_offs_index = phash_to_index[0];
// If the PAIR_HASH offset is below the limit, find a next one
phash_offs = pWork->phash_offs + phash_offs_index;
if(*phash_offs < min_phash_offs)
{
while(*phash_offs < min_phash_offs)
{
phash_offs_index++;
phash_offs++;
}
*phash_to_index = phash_offs_index;
}
// Get the first location of the PAIR_HASH,
// and thus the first eventual location of byte repetition
phash_offs = pWork->phash_offs + phash_offs_index;
prev_repetition = pWork->work_buff + phash_offs[0];
repetition_limit = input_data - 1;
// If the current PAIR_HASH was not encountered before,
// we haven't found a repetition.
if(prev_repetition >= repetition_limit)
return 0;
// We have found a match of a PAIR_HASH. Now we have to make sure
// that it is also a byte match, because PAIR_HASH is not unique.
// We compare the bytes and count the length of the repetition
input_data_ptr = input_data;
for(;;)
{
// If the first byte of the repetition and the so-far-last byte
// of the repetition are equal, we will compare the blocks.
if(*input_data_ptr == *prev_repetition && input_data_ptr[rep_length-1] == prev_repetition[rep_length-1])
{
// Skip the current byte
prev_repetition++;
input_data_ptr++;
equal_byte_count = 2;
// Now count how many more bytes are equal
while(equal_byte_count < MAX_REP_LENGTH)
{
prev_repetition++;
input_data_ptr++;
// Are the bytes different ?
if(*prev_repetition != *input_data_ptr)
break;
equal_byte_count++;
}
// If we found a repetition of at least the same length, take it.
// If there are multiple repetitions in the input buffer, this will
// make sure that we find the most recent one, which in turn allows
// us to store backward length in less amount of bits
input_data_ptr = input_data;
if(equal_byte_count >= rep_length)
{
// Calculate the backward distance of the repetition.
// Note that the distance is stored as decremented by 1
pWork->distance = (unsigned int)(input_data - prev_repetition + equal_byte_count - 1);
// Repetitions longer than 10 bytes will be stored in more bits,
// so they need a bit different handling
if((rep_length = equal_byte_count) > 10)
break;
}
}
// Move forward in the table of PAIR_HASH repetitions.
// There might be a more recent occurence of the same repetition.
phash_offs_index++;
phash_offs++;
prev_repetition = pWork->work_buff + phash_offs[0];
// If the next repetition is beyond the minimum allowed repetition, we are done.
if(prev_repetition >= repetition_limit)
{
// A repetition must have at least 2 bytes, otherwise it's not worth it
return (rep_length >= 2) ? rep_length : 0;
}
}
// If the repetition has max length of 0x204 bytes, we can't go any fuhrter
if(equal_byte_count == MAX_REP_LENGTH)
{
pWork->distance--;
return equal_byte_count;
}
// Check for possibility of a repetition that occurs at more recent position
phash_offs = pWork->phash_offs + phash_offs_index;
if(pWork->work_buff + phash_offs[1] >= repetition_limit)
return rep_length;
//
// The following part checks if there isn't a longer repetition at
// a latter offset, that would lead to better compression.
//
// Example of data that can trigger this optimization:
//
// "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEQQQQQQQQQQQQ"
// "XYZ"
// "EEEEEEEEEEEEEEEEQQQQQQQQQQQQ";
//
// Description of data in this buffer
// [0x00] Single byte "E"
// [0x01] Single byte "E"
// [0x02] Repeat 0x1E bytes from [0x00]
// [0x20] Single byte "X"
// [0x21] Single byte "Y"
// [0x22] Single byte "Z"
// [0x23] 17 possible previous repetitions of length at least 0x10 bytes:
// - Repetition of 0x10 bytes from [0x00] "EEEEEEEEEEEEEEEE"
// - Repetition of 0x10 bytes from [0x01] "EEEEEEEEEEEEEEEE"
// - Repetition of 0x10 bytes from [0x02] "EEEEEEEEEEEEEEEE"
// ...
// - Repetition of 0x10 bytes from [0x0F] "EEEEEEEEEEEEEEEE"
// - Repetition of 0x1C bytes from [0x10] "EEEEEEEEEEEEEEEEQQQQQQQQQQQQ"
// The last repetition is the best one.
//
pWork->offs09BC[0] = 0xFFFF;
pWork->offs09BC[1] = 0x0000;
di_val = 0;
// Note: I failed to figure out what does the table "offs09BC" mean.
// If anyone has an idea, let me know to zezula_at_volny_dot_cz
for(offs_in_rep = 1; offs_in_rep < rep_length; )
{
if(input_data[offs_in_rep] != input_data[di_val])
{
di_val = pWork->offs09BC[di_val];
if(di_val != 0xFFFF)
continue;
}
pWork->offs09BC[++offs_in_rep] = ++di_val;
}
//
// Now go through all the repetitions from the first found one
// to the current input data, and check if any of them migh be
// a start of a greater sequence match.
//
prev_repetition = pWork->work_buff + phash_offs[0];
prev_rep_end = prev_repetition + rep_length;
rep_length2 = rep_length;
for(;;)
{
rep_length2 = pWork->offs09BC[rep_length2];
if(rep_length2 == 0xFFFF)
rep_length2 = 0;
// Get the pointer to the previous repetition
phash_offs = pWork->phash_offs + phash_offs_index;
// Skip those repetitions that don't reach the end
// of the first found repetition
do
{
phash_offs++;
phash_offs_index++;
prev_repetition = pWork->work_buff + *phash_offs;
if(prev_repetition >= repetition_limit)
return rep_length;
}
while(prev_repetition + rep_length2 < prev_rep_end);
// Verify if the last but one byte from the repetition matches
// the last but one byte from the input data.
// If not, find a next repetition
pre_last_byte = input_data[rep_length - 2];
if(pre_last_byte == prev_repetition[rep_length - 2])
{
// If the new repetition reaches beyond the end
// of previously found repetition, reset the repetition length to zero.
if(prev_repetition + rep_length2 != prev_rep_end)
{
prev_rep_end = prev_repetition;
rep_length2 = 0;
}
}
else
{
phash_offs = pWork->phash_offs + phash_offs_index;
do
{
phash_offs++;
phash_offs_index++;
prev_repetition = pWork->work_buff + *phash_offs;
if(prev_repetition >= repetition_limit)
return rep_length;
}
while(prev_repetition[rep_length - 2] != pre_last_byte || prev_repetition[0] != input_data[0]);
// Reset the length of the repetition to 2 bytes only
prev_rep_end = prev_repetition + 2;
rep_length2 = 2;
}
// Find out how many more characters are equal to the first repetition.
while(*prev_rep_end == input_data[rep_length2])
{
if(++rep_length2 >= 0x204)
break;
prev_rep_end++;
}
// Is the newly found repetion at least as long as the previous one ?
if(rep_length2 >= rep_length)
{
// Calculate the distance of the new repetition
pWork->distance = (unsigned int)(input_data - prev_repetition - 1);
if((rep_length = rep_length2) == 0x204)
return rep_length;
// Update the additional elements in the "offs09BC" table
// to reflect new rep length
while(offs_in_rep < rep_length2)
{
if(input_data[offs_in_rep] != input_data[di_val])
{
di_val = pWork->offs09BC[di_val];
if(di_val != 0xFFFF)
continue;
}
pWork->offs09BC[++offs_in_rep] = ++di_val;
}
}
}
}
static void WriteCmpData(TCmpStruct * pWork)
{
unsigned char * input_data_end; // Pointer to the end of the input data
unsigned char * input_data = pWork->work_buff + pWork->dsize_bytes + 0x204;
unsigned int input_data_ended = 0; // If 1, then all data from the input stream have been already loaded
unsigned int save_rep_length; // Saved length of current repetition
unsigned int save_distance = 0; // Saved distance of current repetition
unsigned int rep_length; // Length of the found repetition
unsigned int phase = 0; //
// Store the compression type and dictionary size
pWork->out_buff[0] = (char)pWork->ctype;
pWork->out_buff[1] = (char)pWork->dsize_bits;
pWork->out_bytes = 2;
// Reset output buffer to zero
memset(&pWork->out_buff[2], 0, sizeof(pWork->out_buff) - 2);
pWork->out_bits = 0;
while(input_data_ended == 0)
{
unsigned int bytes_to_load = 0x1000;
int total_loaded = 0;
int bytes_loaded;
// Load the bytes from the input stream, up to 0x1000 bytes
while(bytes_to_load != 0)
{
bytes_loaded = pWork->read_buf((char *)pWork->work_buff + pWork->dsize_bytes + 0x204 + total_loaded,
&bytes_to_load,
pWork->param);
if(bytes_loaded == 0)
{
if(total_loaded == 0 && phase == 0)
goto __Exit;
input_data_ended = 1;
break;
}
else
{
bytes_to_load -= bytes_loaded;
total_loaded += bytes_loaded;
}
}
input_data_end = pWork->work_buff + pWork->dsize_bytes + total_loaded;
if(input_data_ended)
input_data_end += 0x204;
//
// Warning: The end of the buffer passed to "SortBuffer" is actually 2 bytes beyond
// valid data. It is questionable if this is actually a bug or not,
// but it might cause the compressed data output to be dependent on random bytes
// that are in the buffer.
// To prevent that, the calling application must always zero the compression
// buffer before passing it to "implode"
//
// Search the PAIR_HASHes of the loaded blocks. Also, include
// previously compressed data, if any.
switch(phase)
{
case 0:
SortBuffer(pWork, input_data, input_data_end + 1);
phase++;
if(pWork->dsize_bytes != 0x1000)
phase++;
break;
case 1:
SortBuffer(pWork, input_data - pWork->dsize_bytes + 0x204, input_data_end + 1);
phase++;
break;
default:
SortBuffer(pWork, input_data - pWork->dsize_bytes, input_data_end + 1);
break;
}
// Perform the compression of the current block
while(input_data < input_data_end)
{
// Find if the current byte sequence wasn't there before.
rep_length = FindRep(pWork, input_data);
while(rep_length != 0)
{
// If we found repetition of 2 bytes, that is 0x100 or fuhrter back,
// don't bother. Storing the distance of 0x100 bytes would actually
// take more space than storing the 2 bytes as-is.
if(rep_length == 2 && pWork->distance >= 0x100)
break;
// When we are at the end of the input data, we cannot allow
// the repetition to go past the end of the input data.
if(input_data_ended && input_data + rep_length > input_data_end)
{
// Shorten the repetition length so that it only covers valid data
rep_length = (unsigned long)(input_data_end - input_data);
if(rep_length < 2)
break;
// If we got repetition of 2 bytes, that is 0x100 or more backward, don't bother
if(rep_length == 2 && pWork->distance >= 0x100)
break;
goto __FlushRepetition;
}
if(rep_length >= 8 || input_data + 1 >= input_data_end)
goto __FlushRepetition;
// Try to find better repetition 1 byte later.
// Example: "ARROCKFORT" "AROCKFORT"
// When "input_data" points to the second string, FindRep
// returns the occurence of "AR". But there is longer repetition "ROCKFORT",
// beginning 1 byte after.
save_rep_length = rep_length;
save_distance = pWork->distance;
rep_length = FindRep(pWork, input_data + 1);
// Only use the new repetition if it's length is greater than the previous one
if(rep_length > save_rep_length)
{
// If the new repetition if only 1 byte better
// and the previous distance is less than 0x80 bytes, use the previous repetition
if(rep_length > save_rep_length + 1 || save_distance > 0x80)
{
// Flush one byte, so that input_data will point to the secondary repetition
OutputBits(pWork, pWork->nChBits[*input_data], pWork->nChCodes[*input_data]);
input_data++;
continue;
}
}
// Revert to the previous repetition
rep_length = save_rep_length;
pWork->distance = save_distance;
__FlushRepetition:
OutputBits(pWork, pWork->nChBits[rep_length + 0xFE], pWork->nChCodes[rep_length + 0xFE]);
if(rep_length == 2)
{
OutputBits(pWork, pWork->dist_bits[pWork->distance >> 2],
pWork->dist_codes[pWork->distance >> 2]);
OutputBits(pWork, 2, pWork->distance & 3);
}
else
{
OutputBits(pWork, pWork->dist_bits[pWork->distance >> pWork->dsize_bits],
pWork->dist_codes[pWork->distance >> pWork->dsize_bits]);
OutputBits(pWork, pWork->dsize_bits, pWork->dsize_mask & pWork->distance);
}
// Move the begin of the input data by the length of the repetition
input_data += rep_length;
goto _00402252;
}
// If there was no previous repetition for the current position in the input data,
// just output the 9-bit literal for the one character
OutputBits(pWork, pWork->nChBits[*input_data], pWork->nChCodes[*input_data]);
input_data++;
_00402252:;
}
if(input_data_ended == 0)
{
input_data -= 0x1000;
memmove(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + 0x204);
}
}
__Exit:
// Write the termination literal
OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
if(pWork->out_bits != 0)
pWork->out_bytes++;
pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
return;
}
//-----------------------------------------------------------------------------
// Main imploding function
unsigned int PKEXPORT implode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param,
unsigned int *type,
unsigned int *dsize)
{
TCmpStruct * pWork = (TCmpStruct *)work_buf;
unsigned int nChCode;
unsigned int nCount;
unsigned int i;
int nCount2;
// Fill the work buffer information
// Note: The caller must zero the "work_buff" before passing it to implode
pWork->read_buf = read_buf;
pWork->write_buf = write_buf;
pWork->dsize_bytes = *dsize;
pWork->ctype = *type;
pWork->param = param;
pWork->dsize_bits = 4;
pWork->dsize_mask = 0x0F;
// Test dictionary size
switch(*dsize)
{
case CMP_IMPLODE_DICT_SIZE3: // 0x1000 bytes
pWork->dsize_bits++;
pWork->dsize_mask |= 0x20;
// No break here !!!
case CMP_IMPLODE_DICT_SIZE2: // 0x800 bytes
pWork->dsize_bits++;
pWork->dsize_mask |= 0x10;
// No break here !!!
case CMP_IMPLODE_DICT_SIZE1: // 0x400
break;
default:
return CMP_INVALID_DICTSIZE;
}
// Test the compression type
switch(*type)
{
case CMP_BINARY: // We will compress data with binary compression type
for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++)
{
pWork->nChBits[nCount] = 9;
pWork->nChCodes[nCount] = (unsigned short)nChCode;
nChCode = (nChCode & 0x0000FFFF) + 2;
}
break;
case CMP_ASCII: // We will compress data with ASCII compression type
for(nCount = 0; nCount < 0x100; nCount++)
{
pWork->nChBits[nCount] = (unsigned char )(ChBitsAsc[nCount] + 1);
pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2);
}
break;
default:
return CMP_INVALID_MODE;
}
for(i = 0; i < 0x10; i++)
{
if(1 << ExLenBits[i])
{
for(nCount2 = 0; nCount2 < (1 << ExLenBits[i]); nCount2++)
{
pWork->nChBits[nCount] = (unsigned char)(ExLenBits[i] + LenBits[i] + 1);
pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1);
nCount++;
}
}
}
// Copy the distance codes and distance bits and perform the compression
memcpy(&pWork->dist_codes, DistCode, sizeof(DistCode));
memcpy(&pWork->dist_bits, DistBits, sizeof(DistBits));
WriteCmpData(pWork);
return CMP_NO_ERROR;
}

142
3rdParty/PKWare/pkware.h vendored

@ -0,0 +1,142 @@
/*****************************************************************************/
/* pkware.h Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Header file for PKWARE Data Compression Library */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 31.03.03 1.00 Lad The first version of pkware.h */
/*****************************************************************************/
#ifndef __PKWARE_H__
#define __PKWARE_H__
//-----------------------------------------------------------------------------
// Defines
#define CMP_BINARY 0 // Binary compression
#define CMP_ASCII 1 // Ascii compression
#define CMP_NO_ERROR 0
#define CMP_INVALID_DICTSIZE 1
#define CMP_INVALID_MODE 2
#define CMP_BAD_DATA 3
#define CMP_ABORT 4
#define CMP_IMPLODE_DICT_SIZE1 1024 // Dictionary size of 1024
#define CMP_IMPLODE_DICT_SIZE2 2048 // Dictionary size of 2048
#define CMP_IMPLODE_DICT_SIZE3 4096 // Dictionary size of 4096
//-----------------------------------------------------------------------------
// Define calling convention
#ifndef PKEXPORT
#ifdef WIN32
#define PKEXPORT __cdecl // Use for normal __cdecl calling
#else
#define PKEXPORT
#endif
#endif
//-----------------------------------------------------------------------------
// Internal structures
// Compression structure
typedef struct
{
unsigned int distance; // 0000: Backward distance of the currently found repetition, decreased by 1
unsigned int out_bytes; // 0004: # bytes available in out_buff
unsigned int out_bits; // 0008: # of bits available in the last out byte
unsigned int dsize_bits; // 000C: Number of bits needed for dictionary size. 4 = 0x400, 5 = 0x800, 6 = 0x1000
unsigned int dsize_mask; // 0010: Bit mask for dictionary. 0x0F = 0x400, 0x1F = 0x800, 0x3F = 0x1000
unsigned int ctype; // 0014: Compression type (CMP_ASCII or CMP_BINARY)
unsigned int dsize_bytes; // 0018: Dictionary size in bytes
unsigned char dist_bits[0x40]; // 001C: Distance bits
unsigned char dist_codes[0x40]; // 005C: Distance codes
unsigned char nChBits[0x306]; // 009C: Table of literal bit lengths to be put to the output stream
unsigned short nChCodes[0x306]; // 03A2: Table of literal codes to be put to the output stream
unsigned short offs09AE; // 09AE:
void * param; // 09B0: User parameter
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 9B4
void (*write_buf)(char *buf, unsigned int *size, void *param); // 9B8
unsigned short offs09BC[0x204]; // 09BC:
unsigned long offs0DC4; // 0DC4:
unsigned short phash_to_index[0x900]; // 0DC8: Array of indexes (one for each PAIR_HASH) to the "pair_hash_offsets" table
unsigned short phash_to_index_end; // 1FC8: End marker for "phash_to_index" table
char out_buff[0x802]; // 1FCA: Compressed data
unsigned char work_buff[0x2204]; // 27CC: Work buffer
// + DICT_OFFSET => Dictionary
// + UNCMP_OFFSET => Uncompressed data
unsigned short phash_offs[0x2204]; // 49D0: Table of offsets for each PAIR_HASH
} TCmpStruct;
#define CMP_BUFFER_SIZE sizeof(TCmpStruct) // Size of compression structure.
// Defined as 36312 in pkware header file
// Decompression structure
typedef struct
{
unsigned long offs0000; // 0000
unsigned long ctype; // 0004: Compression type (CMP_BINARY or CMP_ASCII)
unsigned long outputPos; // 0008: Position in output buffer
unsigned long dsize_bits; // 000C: Dict size (4, 5, 6 for 0x400, 0x800, 0x1000)
unsigned long dsize_mask; // 0010: Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000)
unsigned long bit_buff; // 0014: 16-bit buffer for processing input data
unsigned long extra_bits; // 0018: Number of extra (above 8) bits in bit buffer
unsigned int in_pos; // 001C: Position in in_buff
unsigned long in_bytes; // 0020: Number of bytes in input buffer
void * param; // 0024: Custom parameter
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // Pointer to function that reads data from the input stream
void (*write_buf)(char *buf, unsigned int *size, void *param);// Pointer to function that writes data to the output stream
unsigned char out_buff[0x2204]; // 0030: Output circle buffer.
// 0x0000 - 0x0FFF: Previous uncompressed data, kept for repetitions
// 0x1000 - 0x1FFF: Currently decompressed data
// 0x2000 - 0x2203: Reserve space for the longest possible repetition
unsigned char in_buff[0x800]; // 2234: Buffer for data to be decompressed
unsigned char DistPosCodes[0x100]; // 2A34: Table of distance position codes
unsigned char LengthCodes[0x100]; // 2B34: Table of length codes
unsigned char offs2C34[0x100]; // 2C34: Buffer for
unsigned char offs2D34[0x100]; // 2D34: Buffer for
unsigned char offs2E34[0x80]; // 2EB4: Buffer for
unsigned char offs2EB4[0x100]; // 2EB4: Buffer for
unsigned char ChBitsAsc[0x100]; // 2FB4: Buffer for
unsigned char DistBits[0x40]; // 30B4: Numbers of bytes to skip copied block length
unsigned char LenBits[0x10]; // 30F4: Numbers of bits for skip copied block length
unsigned char ExLenBits[0x10]; // 3104: Number of valid bits for copied block
unsigned short LenBase[0x10]; // 3114: Buffer for
} TDcmpStruct;
#define EXP_BUFFER_SIZE sizeof(TDcmpStruct) // Size of decompression structure
// Defined as 12596 in pkware headers
//-----------------------------------------------------------------------------
// Public functions
#ifdef __cplusplus
extern "C" {
#endif
unsigned int PKEXPORT implode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param,
unsigned int *type,
unsigned int *dsize);
unsigned int PKEXPORT explode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param);
#ifdef __cplusplus
} // End of 'extern "C"' declaration
#endif
#endif // __PKWARE_H__

93
3rdParty/Storm/Source/Storm.dsp vendored

@ -0,0 +1,93 @@
# Microsoft Developer Studio Project File - Name="Storm" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=Storm - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Storm.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Storm.mak" CFG="Storm - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Storm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "Storm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "Storm - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "WinRel"
# PROP BASE Intermediate_Dir "WinRel"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "WinRel"
# PROP Intermediate_Dir "WinRel"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"storm.def"
!ELSEIF "$(CFG)" == "Storm - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "WinDebug"
# PROP BASE Intermediate_Dir "WinDebug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "WinDebug"
# PROP Intermediate_Dir "WinDebug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /O1 /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /def:"storm.def" /pdbtype:sept
!ENDIF
# Begin Target
# Name "Storm - Win32 Release"
# Name "Storm - Win32 Debug"
# Begin Source File
SOURCE=.\storm.cpp
# End Source File
# End Target
# End Project

146
3rdParty/Storm/Source/Storm.vcxproj vendored

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<SccProjectName />
<SccLocalPath />
<ProjectGuid>{B28F69CE-15A1-424D-BBB5-2727258D675B}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>.\WinRel\</OutDir>
<IntDir>.\WinRel\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>.\WinDebug\</OutDir>
<IntDir>.\WinDebug\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<StringPooling>true</StringPooling>
<FunctionLevelLinking>true</FunctionLevelLinking>
<Optimization>MaxSpeed</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>.\WinRel\</AssemblerListingLocation>
<PrecompiledHeaderOutputFile>.\WinRel\Storm.pch</PrecompiledHeaderOutputFile>
<ObjectFileName>.\WinRel\</ObjectFileName>
<ProgramDataBaseFileName>.\WinRel\</ProgramDataBaseFileName>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\WinRel\Storm.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<RedirectOutputAndErrors>NUL</RedirectOutputAndErrors>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\WinRel\Storm.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>storm.def</ModuleDefinitionFile>
<OutputFile>.\WinRel\Storm.dll</OutputFile>
<ImportLibrary>.\WinRel\Storm.lib</ImportLibrary>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<Optimization>Disabled</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<MinimalRebuild>true</MinimalRebuild>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>.\WinDebug\</AssemblerListingLocation>
<PrecompiledHeaderOutputFile>.\WinDebug\Storm.pch</PrecompiledHeaderOutputFile>
<ObjectFileName>.\WinDebug\</ObjectFileName>
<ProgramDataBaseFileName>.\WinDebug\</ProgramDataBaseFileName>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\WinDebug\Storm.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<RedirectOutputAndErrors>NUL</RedirectOutputAndErrors>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\WinDebug\Storm.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>storm.def</ModuleDefinitionFile>
<OutputFile>.\WinDebug\Storm.dll</OutputFile>
<ImportLibrary>.\WinDebug\Storm.lib</ImportLibrary>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="storm.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="storm.def" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="storm.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

238
3rdParty/Storm/Source/storm.cpp vendored

@ -0,0 +1,238 @@
#include "storm.h"
#define rBool { return TRUE; }
#define rPVoid { return NULL; }
#define rVoid { return; }
#define rInt { return 0; }
BOOL STORMAPI SNetCreateGame(const char *pszGameName, const char *pszGamePassword, const char *pszGameStatString, DWORD dwGameType, char *GameTemplateData, int GameTemplateSize, int playerCount, char *creatorName, char *a11, int *playerID) rBool;
BOOL STORMAPI SNetDestroy() rBool;
BOOL STORMAPI SNetEnumProviders(int (STORMAPI *callback)(DWORD, DWORD, DWORD, DWORD), int mincaps) rBool;
BOOL STORMAPI SNetEnumGames(int (STORMAPI *callback)(DWORD, DWORD, DWORD), int *hintnextcall) rBool;
BOOL STORMAPI SNetDropPlayer(int playerid, DWORD flags) rBool;
BOOL STORMAPI SNetGetGameInfo(int type, void *dst, size_t length, size_t *byteswritten) rBool;
BOOL STORMAPI SNetGetNumPlayers(int *firstplayerid, int *lastplayerid, int *activeplayers) rBool;
BOOL STORMAPI SNetGetPlayerCaps(char playerid, PCAPS playerCaps) rBool;
BOOL STORMAPI SNetGetPlayerName(int playerid, char *buffer, size_t buffersize) rBool;
//BOOL STORMAPI SNetGetProviderCaps(PCAPS providerCaps) rBool;
BOOL STORMAPI SNetGetTurnsInTransit(int *turns) rBool;
BOOL STORMAPI SNetInitializeDevice(int a1, int a2, int a3, int a4, int *a5) rBool;
//BOOL STORMAPI SNetInitializeProvider(DWORD providerName, client_info *gameClientInfo, user_info *userData, battle_info *bnCallbacks, module_info *moduleData) rBool;
BOOL STORMAPI SNetJoinGame(int id, char *gameName, char *gamePassword, char *playerName, char *userStats, int *playerid) rBool;
BOOL STORMAPI SNetLeaveGame(int type) rBool;
BOOL STORMAPI SNetPerformUpgrade(DWORD *upgradestatus) rBool;
BOOL STORMAPI SNetReceiveMessage(int *senderplayerid, char **data, int *databytes) rBool;
BOOL STORMAPI SNetReceiveTurns(int a1, int arraysize, char **arraydata, unsigned int *arraydatabytes, DWORD *arrayplayerstatus) rBool;
//HANDLE STORMAPI SNetRegisterEventHandler(int type, void (STORMAPI *sEvent)(PS_EVT)) rPVoid;
int STORMAPI SNetSelectGame(int a1, int a2, int a3, int a4, int a5, int *playerid) rInt;
BOOL STORMAPI SNetSendMessage(int playerID, void *data, size_t databytes) rBool;
BOOL STORMAPI SNetSendTurn(char *data, size_t databytes) rBool;
BOOL STORMAPI SNetSetGameMode(DWORD modeFlags, bool makePublic) rBool;
BOOL STORMAPI SNetEnumGamesEx(int a1, int a2, int (__fastcall *callback)(DWORD, DWORD, DWORD), int *hintnextcall) rBool;
BOOL STORMAPI SNetSendServerChatCommand(const char *command) rBool;
BOOL STORMAPI SNetDisconnectAll(DWORD flags) rBool;
BOOL STORMAPI SNetCreateLadderGame(const char *pszGameName, const char *pszGamePassword, const char *pszGameStatString, DWORD dwGameType, DWORD dwGameLadderType, DWORD dwGameModeFlags, char *GameTemplateData, int GameTemplateSize, int playerCount, char *creatorName, char *a11, int *playerID) rBool;
BOOL STORMAPI SNetReportGameResult(unsigned a1, int size, int *results, const char* headerInfo, const char* detailInfo) rBool;
int STORMAPI SNetSendLeagueCommand(char *cmd, char *callback) rInt;
int STORMAPI SNetSendReplayPath(int a1, int a2, char *replayPath) rInt;
int STORMAPI SNetGetLeagueName(int leagueID) rInt;
BOOL STORMAPI SNetGetPlayerNames(char **names) rBool;
int STORMAPI SNetLeagueLogout(char *bnetName) rInt;
int STORMAPI SNetGetLeaguePlayerName(char *curPlayerLeageName, size_t nameSize) rInt;
HGDIOBJ STORMAPI SDlgDefDialogProc(HWND hDlg, signed int DlgType, HDC textLabel, HWND hWnd) rPVoid;
HANDLE STORMAPI SDlgDialogBoxIndirectParam(HMODULE hModule, LPCSTR lpName, HWND hWndParent, LPVOID lpParam, LPARAM lParam) rPVoid;
BOOL STORMAPI SDlgEndDialog(HWND hDlg, HANDLE nResult) rBool;
BOOL STORMAPI SDlgSetControlBitmaps(HWND parentwindow, int *id, int a3, char *buffer2, char *buffer, int flags, int mask) rBool;
BOOL STORMAPI SDlgBltToWindowE(HWND hWnd, HRGN a2, char *a3, int a4, void *buffer, RECT *rct, SIZE *size, int a8, int a9, DWORD rop) rBool;
BOOL STORMAPI SDlgSetBitmapE(HWND hWnd, int a2, char *src, int mask1, int flags, int a6, int a7, int width, int a9, int mask2) rBool;
int STORMAPI Ordinal224(int a1) rInt;
BOOL STORMAPI SFileCloseArchive(HANDLE hArchive) rBool;
BOOL STORMAPI SFileCloseFile(HANDLE hFile) rBool;
BOOL STORMAPI SFileDdaBeginEx(HANDLE directsound, DWORD flags, DWORD mask, unsigned __int32 lDistanceToMove, signed __int32 volume, signed int a6, int a7) rBool;
BOOL STORMAPI SFileDdaDestroy() rBool;
BOOL STORMAPI SFileDdaEnd(HANDLE directsound) rBool;
BOOL STORMAPI SFileDdaGetPos(HANDLE directsound, int a2, int a3) rBool;
BOOL STORMAPI SFileDdaInitialize(HANDLE directsound) rBool;
BOOL STORMAPI SFileDdaSetVolume(HANDLE directsound, signed int bigvolume, signed int volume) rBool;
BOOL STORMAPI SFileDestroy() rBool;
BOOL STORMAPI SFileGetFileArchive(HANDLE hFile, HANDLE archive) rBool;
LONG STORMAPI SFileGetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) rInt;
BOOL STORMAPI SFileOpenArchive(const char *szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE *phMpq) rBool;
BOOL STORMAPI SFileOpenFile(const char *filename, HANDLE *phFile) rBool;
BOOL STORMAPI SFileOpenFileEx(HANDLE hMpq, const char *szFileName, DWORD dwSearchScope, HANDLE *phFile) rBool;
BOOL STORMAPI SFileReadFile(HANDLE hFile, void *buffer, DWORD nNumberOfBytesToRead, DWORD *read, LONG lpDistanceToMoveHigh) rBool;
void STORMAPI SFileSetLocale(LCID lcLocale) rVoid;
BOOL STORMAPI SFileSetIoErrorMode(int mode, BOOL (STORMAPI *callback)(char*,int,int) ) rBool;
BOOL STORMAPI SFileGetArchiveName(HANDLE hArchive, char *name, int length) rBool;
BOOL STORMAPI SFileGetFileName(HANDLE hFile, char *buffer, int length) rBool;
BOOL STORMAPI SFileLoadFile(char *filename, void *buffer, int buffersize, int a4, int a5) rBool;
BOOL STORMAPI SFileUnloadFile(HANDLE hFile) rBool;
BOOL STORMAPI SFileLoadFileEx(void *hArchive, char *filename, int a3, int a4, int a5, DWORD searchScope, struct _OVERLAPPED *lpOverlapped) rBool;
BOOL STORMAPI SBltROP3(void *lpDstBuffer, void *lpSrcBuffer, int width, int height, int a5, int a6, int a7, DWORD rop) rBool;
BOOL STORMAPI SBltROP3Clipped(void *lpDstBuffer, RECT *lpDstRect, POINT *lpDstPt, int a4, void *lpSrcBuffer, RECT *lpSrcRect, POINT *lpSrcPt, int a8, int a9, DWORD rop) rBool;
BOOL STORMAPI SBmpDecodeImage(DWORD dwImgType, void *pSrcBuffer, DWORD dwSrcBuffersize, PALETTEENTRY *pPalette, void *pDstBuffer, DWORD dwDstBuffersize, DWORD *pdwWidth, DWORD *pdwHeight, DWORD *pdwBpp) rBool;
BOOL STORMAPI SBmpLoadImage(const char *pszFileName, PALETTEENTRY *pPalette, void *pBuffer, DWORD dwBuffersize, DWORD *pdwWidth, DWORD *dwHeight, DWORD *pdwBpp) rBool;
BOOL STORMAPI SBmpSaveImage(const char*, PALETTEENTRY*, void*, DWORD, DWORD, DWORD) rBool;
HANDLE STORMAPI SBmpAllocLoadImage(const char *fileName, PALETTEENTRY *palette, void **buffer, int *width, int *height, int unused6, int unused7, void *(STORMAPI *allocFunction)(DWORD)) rPVoid;
BOOL STORMAPI SCodeCompile(char *directives1, char *directives2, char *loopstring, unsigned int maxiterations, unsigned int flags, HANDLE handle) rBool;
BOOL STORMAPI SCodeDelete(HANDLE handle) rBool;
int STORMAPI SCodeExecute(HANDLE handle, int a2) rInt;
BOOL STORMAPI SDrawAutoInitialize(HINSTANCE hInst, LPCSTR lpClassName, LPCSTR lpWindowName, WNDPROC pfnWndProc, int nMode, int nWidth, int nHeight, int nBits) rBool;
BOOL STORMAPI SDrawCaptureScreen(const char *source) rBool;
HWND STORMAPI SDrawGetFrameWindow(HWND *sdraw_framewindow) rPVoid;
BOOL STORMAPI SDrawGetObjects(LPDIRECTDRAW *ddInterface, LPDIRECTDRAWSURFACE *primarySurface, LPDIRECTDRAWSURFACE *surface2, LPDIRECTDRAWSURFACE *surface3, LPDIRECTDRAWSURFACE *backSurface, LPDIRECTDRAWPALETTE *ddPalette, HPALETTE *hPalette) rBool;
BOOL STORMAPI SDrawGetScreenSize(DWORD *pdwWidth, DWORD *pdwHeight, DWORD *pdwBpp) rBool;
BOOL STORMAPI SDrawLockSurface(int surfacenumber, RECT *lpDestRect, void **lplpSurface, int *lpPitch, int arg_unused) rBool;
BOOL STORMAPI SDrawManualInitialize(HWND hWnd, LPDIRECTDRAW ddInterface, LPDIRECTDRAWSURFACE primarySurface, LPDIRECTDRAWSURFACE surface2, LPDIRECTDRAWSURFACE surface3, LPDIRECTDRAWSURFACE backSurface, LPDIRECTDRAWPALETTE ddPalette, HPALETTE hPalette) rBool;
BOOL STORMAPI SDrawPostClose() rBool;
//BOOL STORMAPI SDrawRealizePalette() rBool;
BOOL STORMAPI SDrawUnlockSurface(int surfacenumber, void *lpSurface, int a3, RECT *lpRect) rBool;
BOOL STORMAPI SDrawUpdatePalette(unsigned int firstentry, unsigned int numentries, PALETTEENTRY *pPalEntries, int a4) rBool;
BOOL STORMAPI SEvtDispatch(DWORD dwMessageID, DWORD dwFlags, int type, PS_EVT pEvent) rBool;
BOOL STORMAPI SGdiDeleteObject(HANDLE handle) rBool;
BOOL STORMAPI SGdiExtTextOut(int a1, int a2, int a3, int a4, unsigned int a8, signed int a6, signed int a7, const char *string, unsigned int arg20) rBool;
BOOL STORMAPI SGdiImportFont(HGDIOBJ handle, int windowsfont) rBool;
BOOL STORMAPI SGdiSelectObject(int handle) rBool;
BOOL STORMAPI SGdiSetPitch(int pitch) rBool;
BOOL STORMAPI Ordinal393(char *string, int, int) rBool;
void* STORMAPI SMemAlloc(size_t amount, char *logfilename, int logline, char defaultValue) rPVoid;
BOOL STORMAPI SMemFree(void *location, char *logfilename, int logline, char defaultValue) rBool;
void* STORMAPI SMemReAlloc(void *location, size_t amount, char *logfilename, int logline, char defaultValue) rPVoid;
BOOL STORMAPI SRegLoadData(const char *keyname, const char *valuename, int size, LPBYTE lpData, BYTE flags, LPDWORD lpcbData) rBool;
BOOL STORMAPI SRegLoadString(const char *keyname, const char *valuename, BYTE flags, char *buffer, size_t buffersize) rBool;
BOOL STORMAPI SRegLoadValue(const char *keyname, const char *valuename, BYTE flags, int *value) rBool;
BOOL STORMAPI SRegSaveData(const char *keyname, const char *valuename, int size, BYTE *lpData, DWORD cbData) rBool;
BOOL STORMAPI SRegSaveString(const char *keyname, const char *valuename, BYTE flags, char *string) rBool;
BOOL STORMAPI SRegSaveValue(const char *keyname, const char *valuename, BYTE flags, DWORD result) rBool;
BOOL STORMAPI SRegDeleteValue(const char *keyname, const char *valuename, BYTE flags) rBool;
BOOL STORMAPI STransBlt(void *lpSurface, int x, int y, int width, HANDLE hTrans) rBool;
BOOL STORMAPI STransBltUsingMask(void *lpSurface, void *lpSource, int pitch, int width, HANDLE hTrans) rBool;
BOOL STORMAPI STransDelete(HANDLE hTrans) rBool;
BOOL STORMAPI STransDuplicate(HANDLE hTransSource, HANDLE hTransDest) rBool;
BOOL STORMAPI STransIntersectDirtyArray(HANDLE hTrans, char * dirtyarraymask, unsigned flags, HANDLE * phTransResult) rBool;
BOOL STORMAPI STransInvertMask(HANDLE hTrans, HANDLE * phTransResult) rBool;
BOOL STORMAPI STransSetDirtyArrayInfo(int width, int height, int depth, int bits) rBool;
BOOL STORMAPI STransPointInMask(HANDLE hTrans, int x, int y) rBool;
BOOL STORMAPI STransCombineMasks(HANDLE hTransA, HANDLE hTransB, int left, int top, int flags, HANDLE * phTransResult) rBool;
BOOL STORMAPI STransCreateE(void *pBuffer, int width, int height, int bpp, int a5, int bufferSize, HANDLE *phTransOut) rBool;
BOOL STORMAPI SVidDestroy() rBool;
BOOL STORMAPI SVidGetSize(HANDLE video, int width, int height, int zero) rBool;
BOOL STORMAPI SVidInitialize(HANDLE video) rBool;
BOOL STORMAPI SVidPlayBegin(char *filename, int arg4, int a3, int a4, int a5, int a6, HANDLE* video) rBool;
BOOL STORMAPI SVidPlayContinueSingle(HANDLE video, int a2, int a3) rBool;
BOOL STORMAPI SVidPlayEnd(HANDLE video) rBool;
BOOL STORMAPI SErrDisplayError(DWORD dwErrMsg, const char *logfilename, int logline, const char *message, BOOL allowOption, int exitCode) rBool;
BOOL STORMAPI SErrGetErrorStr(DWORD dwErrCode, char *buffer, size_t bufferchars) rBool;
DWORD STORMAPI SErrGetLastError() rInt;
void STORMAPI SErrSetLastError(DWORD dwErrCode) rVoid;
void STORMAPI SErrSuppressErrors(BOOL suppressErrors) rVoid;
void STORMAPI SMemCopy(void *dest, const void *source, size_t size) rVoid;
void STORMAPI SMemFill(void *location, size_t length, char fillWith) rVoid;
void STORMAPI SMemZero(void *location, DWORD length) rVoid;
int STORMAPI SMemCmp(void *location1, void *location2, DWORD size) rInt;
int STORMAPI SStrCopy(char *dest, const char *src, int max_length) rInt;
DWORD STORMAPI SStrHash(const char *string, DWORD flags, DWORD Seed) rInt;
int STORMAPI SStrNCat(char *dest, const char *src, DWORD max_length) rInt;
int STORMAPI SStrLen(const char* string) rInt;
int STORMAPI SStrCmp(const char *string1, const char *string2, size_t size) rInt;
int STORMAPI SStrCmpI(const char *string1, const char *string2, size_t size) rInt;
char* STORMAPI SStrUpper(char* string) rPVoid;
void STORMAPI SRgn523(HANDLE hRgn, RECT *pRect, int a3, int a4) rVoid;
void STORMAPI SRgnCreateRegion(HANDLE *hRgn, int a2) rVoid;
void STORMAPI SRgnDeleteRegion(HANDLE hRgn) rVoid;
void STORMAPI SRgn529i(int handle, int a2, int a3) rVoid;
BOOL SErrDisplayErrorFmt(DWORD dwErrMsg, const char *logfilename, int logline, BOOL allowOption, int exitCode, const char *format, ...) rBool;
void STORMAPI SErrCatchUnhandledExceptions() rVoid;
char* STORMAPI SStrChr(const char *string, char c) rPVoid;
char* STORMAPI SStrChrR(const char *string, char c) rPVoid;
size_t SStrVPrintf(char *dest, size_t size, const char *format, ...) rInt;
int STORMAPI SBigDel(void *buffer) rInt;
int STORMAPI SBigFromBinary(void *buffer, const void *str, size_t size) rInt;
int STORMAPI SBigNew(void **buffer) rInt;
int STORMAPI SBigPowMod(void *buffer1, void *buffer2, int a3, int a4) rInt;
int STORMAPI SBigToBinaryBuffer(void *buffer, int length, int a3, int a4) rInt;
//
void __stdcall SDrawMessageBox(char *,char *,int) rVoid;
void __cdecl SDrawDestroy(void) rVoid;
bool __cdecl StormDestroy(void) rBool;
bool __stdcall SFileSetBasePath(char *) rBool;
void __cdecl SDrawRealizePalette(void) rVoid;
bool __cdecl SVidPlayContinue(void) rBool;
bool __stdcall SNetGetOwnerTurnsWaiting(int *) rBool;
void * __stdcall SNetUnregisterEventHandler(int,void (__stdcall*)(struct _SNETEVENT *)) rPVoid;
void * __stdcall SNetRegisterEventHandler(int,void (__stdcall*)(struct _SNETEVENT *)) rPVoid;
bool __stdcall SNetSetBasePlayer(int) rBool;
int __stdcall SNetInitializeProvider(unsigned long,struct _SNETPROGRAMDATA *,struct _SNETPLAYERDATA *,struct _SNETUIDATA *,struct _SNETVERSIONDATA *) rInt;
int __stdcall SNetGetProviderCaps(struct _SNETCAPS *) rInt;
int __stdcall SFileSetFilePointer(HANDLE,int,HANDLE,int) rInt;

441
3rdParty/Storm/Source/storm.def vendored

@ -0,0 +1,441 @@
LIBRARY "Storm"
EXPORTS
SNetCreateGame @101 NONAME
SNetDestroy @102 NONAME
SNetEnumProviders @103 NONAME
;SNetEnumDevices @104 NONAME
SNetEnumGames @105 NONAME
SNetDropPlayer @106 NONAME
SNetGetGameInfo @107 NONAME
;SNetGetNetworkLatency @108 NONAME
SNetGetNumPlayers @109 NONAME
SNetGetOwnerTurnsWaiting @110 NONAME
;SNetGetPerformanceData @111 NONAME
SNetGetPlayerCaps @112 NONAME
SNetGetPlayerName @113 NONAME
SNetGetProviderCaps @114 NONAME
SNetGetTurnsInTransit @115 NONAME
SNetInitializeDevice @116 NONAME
SNetInitializeProvider @117 NONAME
SNetJoinGame @118 NONAME
SNetLeaveGame @119 NONAME
SNetPerformUpgrade @120 NONAME
SNetReceiveMessage @121 NONAME
SNetReceiveTurns @122 NONAME
SNetRegisterEventHandler @123 NONAME
;SNetResetLatencyMeasurements @124 NONAME
SNetSelectGame @125 NONAME
;SNetSelectProvider @126 NONAME
SNetSendMessage @127 NONAME
SNetSendTurn @128 NONAME
SNetSetBasePlayer @129 NONAME
SNetSetGameMode @130 NONAME
SNetUnregisterEventHandler @131 NONAME
SNetEnumGamesEx @133 NONAME
SNetSendServerChatCommand @134 NONAME
;SNetSendDatagram @135 NONAME
;SNetReceiveDatagram @136 NONAME
SNetDisconnectAll @137 NONAME
SNetCreateLadderGame @138 NONAME
SNetReportGameResult @139 NONAME
;SNetCheckDataFile @140 NONAME
SNetSendLeagueCommand @141 NONAME
SNetSendReplayPath @142 NONAME
SNetGetLeagueName @143 NONAME
SNetGetPlayerNames @144 NONAME
SNetLeagueLogout @145 NONAME
SNetGetLeaguePlayerName @146 NONAME
;Ordinal150 @150 NONAME
;Ordinal151 @151 NONAME
;SDlgBeginPaint @201 NONAME
;SDlgBltToWindowI @202 NONAME
;SDlgCheckTimers @203 NONAME
;SDlgCreateDialogIndirectParam @204 NONAME
;SDlgCreateDialogParam @205 NONAME
SDlgDefDialogProc @206 NONAME
SDlgDialogBoxIndirectParam @208 NONAME
;SDlgDialogBoxParam @209 NONAME
;SDlgDrawBitmap @210 NONAME
SDlgEndDialog @211 NONAME
;SDlgEndPaint @212 NONAME
;SDlgKillTimer @213 NONAME
;SDlgSetBaseFont @214 NONAME
;SDlgSetBitmapI @215 NONAME
SDlgSetControlBitmaps @216 NONAME
;SDlgSetCursor @217 NONAME
;SDlgSetSystemCursor @218 NONAME
;SDlgSetTimer @219 NONAME
;SDlgUpdateCursor @220 NONAME
SDlgBltToWindowE @221 NONAME
SDlgSetBitmapE @222 NONAME
;SDlgSetLocale @223 NONAME
Ordinal224 @224 NONAME
;SFileAuthenticateArchive @251 NONAME
SFileCloseArchive @252 NONAME
SFileCloseFile @253 NONAME
;SFileDdaBegin @254 NONAME
SFileDdaBeginEx @255 NONAME
SFileDdaDestroy @256 NONAME
SFileDdaEnd @257 NONAME
SFileDdaGetPos @258 NONAME
;SFileDdaGetVolume @259 NONAME
SFileDdaInitialize @260 NONAME
SFileDdaSetVolume @261 NONAME
SFileDestroy @262 NONAME
;SFileEnableDirectAccess @263 NONAME
SFileGetFileArchive @264 NONAME
SFileGetFileSize @265 NONAME
SFileOpenArchive @266 NONAME
SFileOpenFile @267 NONAME
SFileOpenFileEx @268 NONAME
SFileReadFile @269 NONAME
SFileSetBasePath @270 NONAME
SFileSetFilePointer @271 NONAME
SFileSetLocale @272 NONAME
;SFileGetBasePath @273 NONAME
SFileSetIoErrorMode @274 NONAME
SFileGetArchiveName @275 NONAME
SFileGetFileName @276 NONAME
;SFileGetArchiveInfo @277 NONAME
;SFileSetPlatform @278 NONAME
SFileLoadFile @279 NONAME
SFileUnloadFile @280 NONAME
SFileLoadFileEx @281 NONAME
;SFilePrioritizeRequest @282 NONAME
;SFileCancelRequest @283 NONAME
;SFileSetAsyncBudget @284 NONAME
;SFileSetDataChunkSize @285 NONAME
;SFileEnableSeekOptimization @286 NONAME
;SFileReadFileEx @287 NONAME
;SFileFileExists @288 NONAME
;SFileFileExistsEx @289 NONAME
;SFileReadFileEx2 @290 NONAME
;SFileReadFile2 @291 NONAME
;SFileLoadFile2 @292 NONAME
;SFileOpenFileAsArchive @293 NONAME
;SFileGetLocale @294 NONAME
;SFileRegisterLoadNotifyProc @295 NONAME
;SFileGetFileCompressedSize @296 NONAME
;Ordinal297 @297 NONAME
;Ordinal298 @298 NONAME
;SFileAuthenticateArchiveEx @299 NONAME
;SFileOpenPathAsArchive @300 NONAME
StormDestroy @301 NONAME
;StormGetInstance @302 NONAME
;StormGetOption @303 NONAME
;StormSetOption @304 NONAME
;SBltGetSCode @312 NONAME
SBltROP3 @313 NONAME
SBltROP3Clipped @314 NONAME
;SBltROP3Tiled @315 NONAME
SBmpDecodeImage @321 NONAME
SBmpLoadImage @323 NONAME
SBmpSaveImage @324 NONAME
SBmpAllocLoadImage @325 NONAME
;SBmpSaveImageEx @326 NONAME
SCodeCompile @331 NONAME
SCodeDelete @332 NONAME
SCodeExecute @334 NONAME
;SCodeGetPseudocode @335 NONAME
SDrawAutoInitialize @341 NONAME
SDrawCaptureScreen @342 NONAME
;SDrawClearSurface @343 NONAME
SDrawDestroy @344 NONAME
;SDrawFlipPage @345 NONAME
SDrawGetFrameWindow @346 NONAME
SDrawGetObjects @347 NONAME
SDrawGetScreenSize @348 NONAME
;SDrawGetServiceLevel @349 NONAME
SDrawLockSurface @350 NONAME
SDrawManualInitialize @351 NONAME
SDrawMessageBox @352 NONAME
SDrawPostClose @353 NONAME
SDrawRealizePalette @354 NONAME
;SDrawSelectGdiSurface @355 NONAME
SDrawUnlockSurface @356 NONAME
SDrawUpdatePalette @357 NONAME
;SDrawUpdateScreen @358 NONAME
;SDrawWaitForVerticalBlank @359 NONAME
SEvtDispatch @372 NONAME
;SEvtRegisterHandler @373 NONAME
;SEvtUnregisterHandler @374 NONAME
;SEvtUnregisterType @375 NONAME
;SEvtPopState @376 NONAME
;SEvtPushState @377 NONAME
;SEvtBreakHandlerChain @378 NONAME
;SGdiBitBlt @381 NONAME
;SGdiCreateFont @382 NONAME
SGdiDeleteObject @383 NONAME
;SGdiDestroy @384 NONAME
SGdiExtTextOut @385 NONAME
SGdiImportFont @386 NONAME
;SGdiLoadFont @387 NONAME
;SGdiRectangle @388 NONAME
SGdiSelectObject @389 NONAME
SGdiSetPitch @390 NONAME
;SGdiTextOut @391 NONAME
;SGdi392 @392 NONAME
Ordinal393 @393 NONAME
;SMem399 @399 NONAME
SMemAlloc @401 NONAME
;SMemDestroy @402 NONAME
SMemFree @403 NONAME
;SMemGetSize @404 NONAME
SMemReAlloc @405 NONAME
;Storm406 @406 NONAME
;SMsgDispatchMessage @412 NONAME
;SMsgDoMessageLoop @413 NONAME
;SMsgRegisterCommand @414 NONAME
;SMsgRegisterKeyDown @415 NONAME
;SMsgRegisterKeyUp @416 NONAME
;SMsgRegisterMessage @417 NONAME
;SMsgPopRegisterState @418 NONAME
;SMsgPushRegisterState @419 NONAME
;SMsg420 @420 NONAME
SRegLoadData @421 NONAME
SRegLoadString @422 NONAME
SRegLoadValue @423 NONAME
SRegSaveData @424 NONAME
SRegSaveString @425 NONAME
SRegSaveValue @426 NONAME
;SRegGetBaseKey @427 NONAME
SRegDeleteValue @428 NONAME
;SReg429 @429 NONAME
;SReg430 @430 NONAME
STransBlt @431 NONAME
STransBltUsingMask @432 NONAME
;STransCreateI @433 NONAME
STransDelete @434 NONAME
STransDuplicate @436 NONAME
STransIntersectDirtyArray @437 NONAME
STransInvertMask @438 NONAME
;STransLoadI @439 NONAME
STransSetDirtyArrayInfo @440 NONAME
;STransUpdateDirtyArray @441 NONAME
STransPointInMask @442 NONAME
STransCombineMasks @443 NONAME
;STransCreateI @444 NONAME
STransCreateE @445 NONAME
;STrans446 @446 NONAME
;STransLoadE @447 NONAME
SVidDestroy @451 NONAME
SVidGetSize @452 NONAME
SVidInitialize @453 NONAME
SVidPlayBegin @454 NONAME
;SVidPlayBeginFromMemory @455 NONAME
SVidPlayContinue @456 NONAME
SVidPlayContinueSingle @457 NONAME
SVidPlayEnd @458 NONAME
;SVidSetVolume @459 NONAME
;Storm460 @460 NONAME
SErrDisplayError @461 NONAME
SErrGetErrorStr @462 NONAME
SErrGetLastError @463 NONAME
;SErrRegisterMessageSource @464 NONAME
SErrSetLastError @465 NONAME
;SErrReportNamedResourceLeak @466 NONAME
;SErrReportResourceLeak @467 NONAME
SErrSuppressErrors @468 NONAME
;SErrRegisterHandler @469 NONAME
;SErrUnregisterHandler @470 NONAME
;Storm471 @471 NONAME
;SCmdGetBool @472 NONAME
;SCmdGetNum @473 NONAME
;SCmdGetString @474 NONAME
;SCmdProcess @475 NONAME
;SCmdRegisterArgList @476 NONAME
;SCmdRegisterArgument @477 NONAME
;SCmdStringExists @478 NONAME
;SCmdProcessCommandLine @479 NONAME
;Ordinal480 @480 NONAME
;SMemFindNextBlock @481 NONAME
;SMemFindNextHeap @482 NONAME
;SMemGetHeapByCaller @483 NONAME
;SMemGetHeapByPtr @484 NONAME
;SMemHeapAlloc @485 NONAME
;SMemHeapCreate @486 NONAME
;SMemHeapDestroy @487 NONAME
;SMemHeapFree @488 NONAME
;SMemHeapRealloc @489 NONAME
;SMemHeapSize @490 NONAME
SMemCopy @491 NONAME
SMemFill @492 NONAME
;SMemMove @493 NONAME
SMemZero @494 NONAME
SMemCmp @495 NONAME
;SMem496 @496 NONAME
;SMemDumpState @497 NONAME
;Ordinal498 @498 NONAME
SStrCopy @501 NONAME
SStrHash @502 NONAME
SStrNCat @503 NONAME
;SStrTokenize @504 NONAME
;SStrPack @505 NONAME
SStrLen @506 NONAME
;SStrDup @507 NONAME
SStrCmp @508 NONAME
SStrCmpI @509 NONAME
SStrUpper @510 NONAME
;SMsgBreakHandlerChain @511 NONAME
;SMsgUnregisterCommand @512 NONAME
;SMsgUnregisterKeyDown @513 NONAME
;SMsgUnregisterKeyUp @514 NONAME
;SMsgUnregisterMessage @515 NONAME
;SMsgGetDispatcher @516 NONAME
;SMsgSetDefaultWindow @517 NONAME
;SMsgGetDefaultWindow @518 NONAME
;SMsg519 @519 NONAME
;SRgn521 @521 NONAME
SRgn523 @523 NONAME
SRgnCreateRegion @524 NONAME
SRgnDeleteRegion @525 NONAME
;SRgn527 @527 NONAME
;SRgn528i @528 NONAME
SRgn529i @529 NONAME
;SRgn530i @530 NONAME
;SRgn531i @531 NONAME
;SRgn532i @532 NONAME
;SRgn533i @533 NONAME
;SRgn534 @534 NONAME
;SRgn535f @535 NONAME
;SRgn536f @536 NONAME
;SRgn537f @537 NONAME
;SRgn538f @538 NONAME
;SRgn539f @539 NONAME
;SRgn540f @540 NONAME
;SLogClose @541 NONAME
;SLogCreate @542 NONAME
;SLog543 @543 NONAME
;SLogDump @544 NONAME
;SLogFlush @545 NONAME
;SLogFlushAll @546 NONAME
;SLogPend @547 NONAME
;SLogWrite @548 NONAME
;SLog549 @549 NONAME
;SLogCriticalLog @550 NONAME
;SCompCompress @551 NONAME
;SCompDecompress @552 NONAME
;SLogVWrite @553 NONAME
;Ordinal554 @554 NONAME
;Ordinal555 @555 NONAME
;Ordinal556 @556 NONAME
;Ordinal557 @557 NONAME
;Ordinal558 @558 NONAME
;Ordinal559 @559 NONAME
;Ordinal560 @560 NONAME
;SErrCheckDebugSymbolLibrary @561 NONAME
SErrDisplayErrorFmt @562 NONAME
;SErrIsDisplayingError @563 NONAME
;SErrPrepareAppFatal @564 NONAME
;SErrSetLogTitleString @565 NONAME
;SErrDisplayAppFatal @566 NONAME
SErrCatchUnhandledExceptions @567 NONAME
;Storm568 @568 NONAME
;SStrChr @569 NONAME
;SStrChrR @570 NONAME
SStrChr @571 NONAME
SStrChrR @572 NONAME
;SStrToDouble @573 NONAME
;SStrToFloat @574 NONAME
;SStrToInt @575 NONAME
;SStrToUnsigned @576 NONAME
;SStrToInt64 @577 NONAME
SStrVPrintf @578 NONAME
;SStrLower @579 NONAME
;SStrHash64 @580 NONAME
;SStrPrintf @581 NONAME
;SDrawSetClientRect @582 NONAME
;SDrawGetClientRect @583 NONAME
;SStrStrI @584 NONAME
;SStrStrI @585 NONAME
;SStrStr @586 NONAME
;SStrStr @587 NONAME
;SNet588 @588 NONAME
;SBigAdd @601 NONAME
;SBigAnd @602 NONAME
;SBigCompare @603 NONAME
;SBigCopy @604 NONAME
;SBigDec @605 NONAME
SBigDel @606 NONAME
;SBigDiv @607 NONAME
;SBigFindPrime @608 NONAME
SBigFromBinary @609 NONAME
;SBigFromStr @610 NONAME
;SBigFromStream @611 NONAME
;SBigFromUnsigned @612 NONAME
;SBigGcd @613 NONAME
;SBigInc @614 NONAME
;SBigInvMod @615 NONAME
;SBigIsEven @616 NONAME
;SBigIsOdd @617 NONAME
;SBigIsOne @618 NONAME
;SBigIsPrime @619 NONAME
;SBigIsZero @620 NONAME
;SBigMod @621 NONAME
;SBigMul @622 NONAME
;SBigMulMod @623 NONAME
SBigNew @624 NONAME
;SBigNot @625 NONAME
;SBigOr @626 NONAME
;SBigPow @627 NONAME
SBigPowMod @628 NONAME
;SBigRand @629 NONAME
;SBigSet2Exp @630 NONAME
;SBigSetOne @631 NONAME
;SBigSetZero @632 NONAME
;SBigShl @633 NONAME
;SBigShr @634 NONAME
;SBigSquare @635 NONAME
;SBigSub @636 NONAME
;SBigToBinaryArray @637 NONAME
SBigToBinaryBuffer @638 NONAME
;SBigToBinaryPtr @639 NONAME
;SBigToStrArray @640 NONAME
;SBigToStrBuffer @641 NONAME
;SBigToStrPtr @642 NONAME
;SBigToStreamArray @643 NONAME
;SBigToStreamBuffer @644 NONAME
;SBigToStreamPtr @645 NONAME
;SBigToUnsigned @646 NONAME
;SBigXor @647 NONAME
;SUniConvertUTF16to8Len @901 NONAME
;SUniConvertUTF16to8 @902 NONAME
;SUniConvertUTF8to16Len @903 NONAME
;SUniConvertUTF8to16 @904 NONAME
;SUniS905 @905 NONAME
;SUniS906 @906 NONAME
;SUniFindAfterUTF8Chr @907 NONAME
;SUniFindUTF8ChrStart @908 NONAME
;SUniConvertUTF16To909 @909 NONAME
;SUniConvertUTF16To910 @910 NONAME
;SUniConvertUTF16To911 @911 NONAME
;SUniConvert912 @912 NONAME
;SUniConvert913 @913 NONAME
;SUniConvert914 @914 NONAME
;SUniConvertUTF8ToWin @915 NONAME
; END

1311
3rdParty/Storm/Source/storm.h vendored

File diff suppressed because it is too large Load Diff

495
3rdParty/Storm/Source/storm_gcc.def vendored

@ -0,0 +1,495 @@
LIBRARY "Storm"
EXPORTS
SNetCreateGame @101 NONAME
SNetCreateGame@40 @101 NONAME
SNetDestroy @102 NONAME
SNetDestroy@0 @102 NONAME
SNetEnumProviders @103 NONAME
;SNetEnumDevices @104 NONAME
SNetEnumGames @105 NONAME
SNetDropPlayer @106 NONAME
SNetDropPlayer@8 @106 NONAME
SNetGetGameInfo @107 NONAME
SNetGetGameInfo@16 @107 NONAME
;SNetGetNetworkLatency @108 NONAME
SNetGetNumPlayers @109 NONAME
SNetGetOwnerTurnsWaiting @110 NONAME
SNetGetOwnerTurnsWaiting@4 @110 NONAME
;SNetGetPerformanceData @111 NONAME
SNetGetPlayerCaps @112 NONAME
SNetGetPlayerName @113 NONAME
SNetGetProviderCaps @114 NONAME
SNetGetProviderCaps@4 @114 NONAME
SNetGetTurnsInTransit @115 NONAME
SNetGetTurnsInTransit@4 @115 NONAME
SNetInitializeDevice @116 NONAME
SNetInitializeProvider @117 NONAME
SNetInitializeProvider@20 @117 NONAME
SNetJoinGame @118 NONAME
SNetLeaveGame @119 NONAME
SNetLeaveGame@4 @119 NONAME
SNetPerformUpgrade @120 NONAME
SNetPerformUpgrade@4 @120 NONAME
SNetReceiveMessage @121 NONAME
SNetReceiveMessage@12 @121 NONAME
SNetReceiveTurns @122 NONAME
SNetReceiveTurns@20 @122 NONAME
SNetRegisterEventHandler @123 NONAME
SNetRegisterEventHandler@8 @123 NONAME
;SNetResetLatencyMeasurements @124 NONAME
SNetSelectGame @125 NONAME
;SNetSelectProvider @126 NONAME
SNetSendMessage @127 NONAME
SNetSendMessage@12 @127 NONAME
SNetSendTurn @128 NONAME
SNetSendTurn@8 @128 NONAME
SNetSetBasePlayer @129 NONAME
SNetSetBasePlayer@4 @129 NONAME
SNetSetGameMode @130 NONAME
SNetUnregisterEventHandler @131 NONAME
SNetUnregisterEventHandler@8 @131 NONAME
SNetEnumGamesEx @133 NONAME
SNetSendServerChatCommand @134 NONAME
SNetSendServerChatCommand@4 @134 NONAME
;SNetSendDatagram @135 NONAME
;SNetReceiveDatagram @136 NONAME
SNetDisconnectAll @137 NONAME
SNetCreateLadderGame @138 NONAME
SNetReportGameResult @139 NONAME
;SNetCheckDataFile @140 NONAME
SNetSendLeagueCommand @141 NONAME
SNetSendReplayPath @142 NONAME
SNetGetLeagueName @143 NONAME
SNetGetPlayerNames @144 NONAME
SNetLeagueLogout @145 NONAME
SNetGetLeaguePlayerName @146 NONAME
;Ordinal150 @150 NONAME
;Ordinal151 @151 NONAME
;SDlgBeginPaint @201 NONAME
;SDlgBltToWindowI @202 NONAME
;SDlgCheckTimers @203 NONAME
;SDlgCreateDialogIndirectParam @204 NONAME
;SDlgCreateDialogParam @205 NONAME
SDlgDefDialogProc @206 NONAME
SDlgDialogBoxIndirectParam @208 NONAME
;SDlgDialogBoxParam @209 NONAME
;SDlgDrawBitmap @210 NONAME
SDlgEndDialog @211 NONAME
;SDlgEndPaint @212 NONAME
;SDlgKillTimer @213 NONAME
;SDlgSetBaseFont @214 NONAME
;SDlgSetBitmapI @215 NONAME
SDlgSetControlBitmaps @216 NONAME
;SDlgSetCursor @217 NONAME
;SDlgSetSystemCursor @218 NONAME
;SDlgSetTimer @219 NONAME
;SDlgUpdateCursor @220 NONAME
SDlgBltToWindowE @221 NONAME
SDlgSetBitmapE @222 NONAME
;SDlgSetLocale @223 NONAME
Ordinal224 @224 NONAME
;SFileAuthenticateArchive @251 NONAME
SFileCloseArchive @252 NONAME
SFileCloseArchive@4 @252 NONAME
SFileCloseFile @253 NONAME
SFileCloseFile@4 @253 NONAME
;SFileDdaBegin @254 NONAME
SFileDdaBeginEx @255 NONAME
SFileDdaBeginEx@28 @255 NONAME
SFileDdaDestroy @256 NONAME
SFileDdaDestroy@0 @256 NONAME
SFileDdaEnd @257 NONAME
SFileDdaEnd@4 @257 NONAME
SFileDdaGetPos @258 NONAME
SFileDdaGetPos@12 @258 NONAME
;SFileDdaGetVolume @259 NONAME
SFileDdaInitialize @260 NONAME
SFileDdaInitialize@4 @260 NONAME
SFileDdaSetVolume @261 NONAME
SFileDdaSetVolume@12 @261 NONAME
SFileDestroy @262 NONAME
;SFileEnableDirectAccess @263 NONAME
SFileGetFileArchive @264 NONAME
SFileGetFileArchive@8 @264 NONAME
SFileGetFileSize @265 NONAME
SFileGetFileSize@8 @265 NONAME
SFileOpenArchive @266 NONAME
SFileOpenArchive@16 @266 NONAME
SFileOpenFile @267 NONAME
SFileOpenFile@8 @267 NONAME
SFileOpenFileEx @268 NONAME
SFileOpenFileEx@16 @268 NONAME
SFileReadFile @269 NONAME
SFileReadFile@20 @269 NONAME
SFileSetBasePath @270 NONAME
SFileSetBasePath@4 @270 NONAME
SFileSetFilePointer @271 NONAME
SFileSetFilePointer@16 @271 NONAME
SFileSetLocale @272 NONAME
;SFileGetBasePath @273 NONAME
SFileSetIoErrorMode @274 NONAME
SFileGetArchiveName @275 NONAME
SFileGetFileName @276 NONAME
;SFileGetArchiveInfo @277 NONAME
;SFileSetPlatform @278 NONAME
SFileLoadFile @279 NONAME
SFileUnloadFile @280 NONAME
SFileLoadFileEx @281 NONAME
;SFilePrioritizeRequest @282 NONAME
;SFileCancelRequest @283 NONAME
;SFileSetAsyncBudget @284 NONAME
;SFileSetDataChunkSize @285 NONAME
;SFileEnableSeekOptimization @286 NONAME
;SFileReadFileEx @287 NONAME
;SFileFileExists @288 NONAME
;SFileFileExistsEx @289 NONAME
;SFileReadFileEx2 @290 NONAME
;SFileReadFile2 @291 NONAME
;SFileLoadFile2 @292 NONAME
;SFileOpenFileAsArchive @293 NONAME
;SFileGetLocale @294 NONAME
;SFileRegisterLoadNotifyProc @295 NONAME
;SFileGetFileCompressedSize @296 NONAME
;Ordinal297 @297 NONAME
;Ordinal298 @298 NONAME
;SFileAuthenticateArchiveEx @299 NONAME
;SFileOpenPathAsArchive @300 NONAME
StormDestroy @301 NONAME
;StormGetInstance @302 NONAME
;StormGetOption @303 NONAME
;StormSetOption @304 NONAME
;SBltGetSCode @312 NONAME
SBltROP3 @313 NONAME
SBltROP3Clipped @314 NONAME
;SBltROP3Tiled @315 NONAME
SBmpDecodeImage @321 NONAME
SBmpLoadImage @323 NONAME
SBmpSaveImage @324 NONAME
SBmpAllocLoadImage @325 NONAME
;SBmpSaveImageEx @326 NONAME
SCodeCompile @331 NONAME
SCodeDelete @332 NONAME
SCodeExecute @334 NONAME
;SCodeGetPseudocode @335 NONAME
SDrawAutoInitialize @341 NONAME
SDrawCaptureScreen @342 NONAME
;SDrawClearSurface @343 NONAME
SDrawDestroy @344 NONAME
;SDrawFlipPage @345 NONAME
SDrawGetFrameWindow @346 NONAME
SDrawGetFrameWindow@4 @346 NONAME
SDrawGetObjects @347 NONAME
SDrawGetScreenSize @348 NONAME
;SDrawGetServiceLevel @349 NONAME
SDrawLockSurface @350 NONAME
SDrawManualInitialize @351 NONAME
SDrawManualInitialize@32 @351 NONAME
SDrawMessageBox @352 NONAME
SDrawMessageBox@12 @352 NONAME
SDrawPostClose @353 NONAME
SDrawRealizePalette @354 NONAME
;SDrawSelectGdiSurface @355 NONAME
SDrawUnlockSurface @356 NONAME
SDrawUpdatePalette @357 NONAME
SDrawUpdatePalette@16 @357 NONAME
;SDrawUpdateScreen @358 NONAME
;SDrawWaitForVerticalBlank @359 NONAME
SEvtDispatch @372 NONAME
;SEvtRegisterHandler @373 NONAME
;SEvtUnregisterHandler @374 NONAME
;SEvtUnregisterType @375 NONAME
;SEvtPopState @376 NONAME
;SEvtPushState @377 NONAME
;SEvtBreakHandlerChain @378 NONAME
;SGdiBitBlt @381 NONAME
;SGdiCreateFont @382 NONAME
SGdiDeleteObject @383 NONAME
;SGdiDestroy @384 NONAME
SGdiExtTextOut @385 NONAME
SGdiImportFont @386 NONAME
;SGdiLoadFont @387 NONAME
;SGdiRectangle @388 NONAME
SGdiSelectObject @389 NONAME
SGdiSetPitch @390 NONAME
;SGdiTextOut @391 NONAME
;SGdi392 @392 NONAME
Ordinal393 @393 NONAME
;SMem399 @399 NONAME
SMemAlloc @401 NONAME
SMemAlloc@16 @401 NONAME
;SMemDestroy @402 NONAME
SMemFree @403 NONAME
SMemFree@16 @403 NONAME
;SMemGetSize @404 NONAME
SMemReAlloc @405 NONAME
;Storm406 @406 NONAME
;SMsgDispatchMessage @412 NONAME
;SMsgDoMessageLoop @413 NONAME
;SMsgRegisterCommand @414 NONAME
;SMsgRegisterKeyDown @415 NONAME
;SMsgRegisterKeyUp @416 NONAME
;SMsgRegisterMessage @417 NONAME
;SMsgPopRegisterState @418 NONAME
;SMsgPushRegisterState @419 NONAME
;SMsg420 @420 NONAME
SRegLoadData @421 NONAME
SRegLoadData@24 @421 NONAME
SRegLoadString @422 NONAME
SRegLoadString@20 @422 NONAME
SRegLoadValue @423 NONAME
SRegLoadValue@16 @423 NONAME
SRegSaveData @424 NONAME
SRegSaveData@20 @424 NONAME
SRegSaveString @425 NONAME
SRegSaveString@16 @425 NONAME
SRegSaveValue @426 NONAME
SRegSaveValue@16 @426 NONAME
;SRegGetBaseKey @427 NONAME
SRegDeleteValue @428 NONAME
;SReg429 @429 NONAME
;SReg430 @430 NONAME
STransBlt @431 NONAME
STransBltUsingMask @432 NONAME
;STransCreateI @433 NONAME
STransDelete @434 NONAME
STransDuplicate @436 NONAME
STransIntersectDirtyArray @437 NONAME
STransInvertMask @438 NONAME
;STransLoadI @439 NONAME
STransSetDirtyArrayInfo @440 NONAME
;STransUpdateDirtyArray @441 NONAME
STransPointInMask @442 NONAME
STransCombineMasks @443 NONAME
;STransCreateI @444 NONAME
STransCreateE @445 NONAME
;STrans446 @446 NONAME
;STransLoadE @447 NONAME
SVidDestroy @451 NONAME
SVidDestroy@0 @451 NONAME
SVidGetSize @452 NONAME
SVidInitialize @453 NONAME
SVidInitialize@4 @453 NONAME
SVidPlayBegin @454 NONAME
SVidPlayBegin@28 @454 NONAME
;SVidPlayBeginFromMemory @455 NONAME
SVidPlayContinue @456 NONAME
SVidPlayContinueSingle @457 NONAME
SVidPlayEnd @458 NONAME
SVidPlayEnd@4 @458 NONAME
;SVidSetVolume @459 NONAME
;Storm460 @460 NONAME
SErrDisplayError @461 NONAME
SErrGetErrorStr @462 NONAME
SErrGetErrorStr@12 @462 NONAME
SErrGetLastError @463 NONAME
SErrGetLastError@0 @463 NONAME
;SErrRegisterMessageSource @464 NONAME
SErrSetLastError @465 NONAME
SErrSetLastError@4 @465 NONAME
;SErrReportNamedResourceLeak @466 NONAME
;SErrReportResourceLeak @467 NONAME
SErrSuppressErrors @468 NONAME
;SErrRegisterHandler @469 NONAME
;SErrUnregisterHandler @470 NONAME
;Storm471 @471 NONAME
;SCmdGetBool @472 NONAME
;SCmdGetNum @473 NONAME
;SCmdGetString @474 NONAME
;SCmdProcess @475 NONAME
;SCmdRegisterArgList @476 NONAME
;SCmdRegisterArgument @477 NONAME
;SCmdStringExists @478 NONAME
;SCmdProcessCommandLine @479 NONAME
;Ordinal480 @480 NONAME
;SMemFindNextBlock @481 NONAME
;SMemFindNextHeap @482 NONAME
;SMemGetHeapByCaller @483 NONAME
;SMemGetHeapByPtr @484 NONAME
;SMemHeapAlloc @485 NONAME
;SMemHeapCreate @486 NONAME
;SMemHeapDestroy @487 NONAME
;SMemHeapFree @488 NONAME
;SMemHeapRealloc @489 NONAME
;SMemHeapSize @490 NONAME
SMemCopy @491 NONAME
SMemFill @492 NONAME
;SMemMove @493 NONAME
SMemZero @494 NONAME
SMemCmp @495 NONAME
;SMem496 @496 NONAME
;SMemDumpState @497 NONAME
;Ordinal498 @498 NONAME
SStrCopy @501 NONAME
SStrCopy@12 @501 NONAME
SStrHash @502 NONAME
SStrNCat @503 NONAME
;SStrTokenize @504 NONAME
;SStrPack @505 NONAME
SStrLen @506 NONAME
;SStrDup @507 NONAME
SStrCmp @508 NONAME
SStrCmpI @509 NONAME
SStrUpper @510 NONAME
;SMsgBreakHandlerChain @511 NONAME
;SMsgUnregisterCommand @512 NONAME
;SMsgUnregisterKeyDown @513 NONAME
;SMsgUnregisterKeyUp @514 NONAME
;SMsgUnregisterMessage @515 NONAME
;SMsgGetDispatcher @516 NONAME
;SMsgSetDefaultWindow @517 NONAME
;SMsgGetDefaultWindow @518 NONAME
;SMsg519 @519 NONAME
;SRgn521 @521 NONAME
SRgn523 @523 NONAME
SRgnCreateRegion @524 NONAME
SRgnDeleteRegion @525 NONAME
;SRgn527 @527 NONAME
;SRgn528i @528 NONAME
SRgn529i @529 NONAME
;SRgn530i @530 NONAME
;SRgn531i @531 NONAME
;SRgn532i @532 NONAME
;SRgn533i @533 NONAME
;SRgn534 @534 NONAME
;SRgn535f @535 NONAME
;SRgn536f @536 NONAME
;SRgn537f @537 NONAME
;SRgn538f @538 NONAME
;SRgn539f @539 NONAME
;SRgn540f @540 NONAME
;SLogClose @541 NONAME
;SLogCreate @542 NONAME
;SLog543 @543 NONAME
;SLogDump @544 NONAME
;SLogFlush @545 NONAME
;SLogFlushAll @546 NONAME
;SLogPend @547 NONAME
;SLogWrite @548 NONAME
;SLog549 @549 NONAME
;SLogCriticalLog @550 NONAME
;SCompCompress @551 NONAME
;SCompDecompress @552 NONAME
;SLogVWrite @553 NONAME
;Ordinal554 @554 NONAME
;Ordinal555 @555 NONAME
;Ordinal556 @556 NONAME
;Ordinal557 @557 NONAME
;Ordinal558 @558 NONAME
;Ordinal559 @559 NONAME
;Ordinal560 @560 NONAME
;SErrCheckDebugSymbolLibrary @561 NONAME
SErrDisplayErrorFmt @562 NONAME
;SErrIsDisplayingError @563 NONAME
;SErrPrepareAppFatal @564 NONAME
;SErrSetLogTitleString @565 NONAME
;SErrDisplayAppFatal @566 NONAME
SErrCatchUnhandledExceptions @567 NONAME
;Storm568 @568 NONAME
;SStrChr @569 NONAME
;SStrChrR @570 NONAME
SStrChr @571 NONAME
SStrChrR @572 NONAME
;SStrToDouble @573 NONAME
;SStrToFloat @574 NONAME
;SStrToInt @575 NONAME
;SStrToUnsigned @576 NONAME
;SStrToInt64 @577 NONAME
SStrVPrintf @578 NONAME
;SStrLower @579 NONAME
;SStrHash64 @580 NONAME
;SStrPrintf @581 NONAME
;SDrawSetClientRect @582 NONAME
;SDrawGetClientRect @583 NONAME
;SStrStrI @584 NONAME
;SStrStrI @585 NONAME
;SStrStr @586 NONAME
;SStrStr @587 NONAME
;SNet588 @588 NONAME
;SBigAdd @601 NONAME
;SBigAnd @602 NONAME
;SBigCompare @603 NONAME
;SBigCopy @604 NONAME
;SBigDec @605 NONAME
SBigDel @606 NONAME
;SBigDiv @607 NONAME
;SBigFindPrime @608 NONAME
SBigFromBinary @609 NONAME
;SBigFromStr @610 NONAME
;SBigFromStream @611 NONAME
;SBigFromUnsigned @612 NONAME
;SBigGcd @613 NONAME
;SBigInc @614 NONAME
;SBigInvMod @615 NONAME
;SBigIsEven @616 NONAME
;SBigIsOdd @617 NONAME
;SBigIsOne @618 NONAME
;SBigIsPrime @619 NONAME
;SBigIsZero @620 NONAME
;SBigMod @621 NONAME
;SBigMul @622 NONAME
;SBigMulMod @623 NONAME
SBigNew @624 NONAME
;SBigNot @625 NONAME
;SBigOr @626 NONAME
;SBigPow @627 NONAME
SBigPowMod @628 NONAME
;SBigRand @629 NONAME
;SBigSet2Exp @630 NONAME
;SBigSetOne @631 NONAME
;SBigSetZero @632 NONAME
;SBigShl @633 NONAME
;SBigShr @634 NONAME
;SBigSquare @635 NONAME
;SBigSub @636 NONAME
;SBigToBinaryArray @637 NONAME
SBigToBinaryBuffer @638 NONAME
;SBigToBinaryPtr @639 NONAME
;SBigToStrArray @640 NONAME
;SBigToStrBuffer @641 NONAME
;SBigToStrPtr @642 NONAME
;SBigToStreamArray @643 NONAME
;SBigToStreamBuffer @644 NONAME
;SBigToStreamPtr @645 NONAME
;SBigToUnsigned @646 NONAME
;SBigXor @647 NONAME
;SUniConvertUTF16to8Len @901 NONAME
;SUniConvertUTF16to8 @902 NONAME
;SUniConvertUTF8to16Len @903 NONAME
;SUniConvertUTF8to16 @904 NONAME
;SUniS905 @905 NONAME
;SUniS906 @906 NONAME
;SUniFindAfterUTF8Chr @907 NONAME
;SUniFindUTF8ChrStart @908 NONAME
;SUniConvertUTF16To909 @909 NONAME
;SUniConvertUTF16To910 @910 NONAME
;SUniConvertUTF16To911 @911 NONAME
;SUniConvert912 @912 NONAME
;SUniConvert913 @913 NONAME
;SUniConvert914 @914 NONAME
;SUniConvertUTF8ToWin @915 NONAME
; END

21
3rdParty/StormLib/LICENSE vendored

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 1999-2013 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.

2830
3rdParty/StormLib/src/FileStream.cpp vendored

File diff suppressed because it is too large Load Diff

217
3rdParty/StormLib/src/FileStream.h vendored

@ -0,0 +1,217 @@
/*****************************************************************************/
/* FileStream.h Copyright (c) Ladislav Zezula 2012 */
/*---------------------------------------------------------------------------*/
/* Description: Definitions for FileStream object */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 14.04.12 1.00 Lad The first version of FileStream.h */
/*****************************************************************************/
#ifndef __FILESTREAM_H__
#define __FILESTREAM_H__
//-----------------------------------------------------------------------------
// Function prototypes
typedef void (*STREAM_INIT)(
struct TFileStream * pStream // Pointer to an unopened stream
);
typedef bool (*STREAM_CREATE)(
struct TFileStream * pStream // Pointer to an unopened stream
);
typedef bool (*STREAM_OPEN)(
struct TFileStream * pStream, // Pointer to an unopened stream
const TCHAR * szFileName, // Pointer to file name to be open
DWORD dwStreamFlags // Stream flags
);
typedef bool (*STREAM_READ)(
struct TFileStream * pStream, // Pointer to an open stream
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
void * pvBuffer, // Pointer to data to be read
DWORD dwBytesToRead // Number of bytes to read from the file
);
typedef bool (*STREAM_WRITE)(
struct TFileStream * pStream, // Pointer to an open stream
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it writes to the current position
const void * pvBuffer, // Pointer to data to be written
DWORD dwBytesToWrite // Number of bytes to read from the file
);
typedef bool (*STREAM_RESIZE)(
struct TFileStream * pStream, // Pointer to an open stream
ULONGLONG FileSize // New size for the file, in bytes
);
typedef bool (*STREAM_GETSIZE)(
struct TFileStream * pStream, // Pointer to an open stream
ULONGLONG * pFileSize // Receives the file size, in bytes
);
typedef bool (*STREAM_GETPOS)(
struct TFileStream * pStream, // Pointer to an open stream
ULONGLONG * pByteOffset // Pointer to store current file position
);
typedef void (*STREAM_CLOSE)(
struct TFileStream * pStream // Pointer to an open stream
);
typedef bool (*BLOCK_READ)(
struct TFileStream * pStream, // Pointer to a block-oriented stream
ULONGLONG StartOffset, // Byte offset of start of the block array
ULONGLONG EndOffset, // End offset (either end of the block or end of the file)
LPBYTE BlockBuffer, // Pointer to block-aligned buffer
DWORD BytesNeeded, // Number of bytes that are really needed
bool bAvailable // true if the block is available
);
typedef bool (*BLOCK_CHECK)(
struct TFileStream * pStream, // Pointer to a block-oriented stream
ULONGLONG BlockOffset // Offset of the file to check
);
typedef void (*BLOCK_SAVEMAP)(
struct TFileStream * pStream // Pointer to a block-oriented stream
);
//-----------------------------------------------------------------------------
// Local structures - partial file structure and bitmap footer
#define ID_FILE_BITMAP_FOOTER 0x33767470 // Signature of the file bitmap footer ('ptv3')
#define DEFAULT_BLOCK_SIZE 0x00004000 // Default size of the stream block
#define DEFAULT_BUILD_NUMBER 10958 // Build number for newly created partial MPQs
typedef struct _PART_FILE_HEADER
{
DWORD PartialVersion; // Always set to 2
char GameBuildNumber[0x20]; // Minimum build number of the game that can use this MPQ
DWORD Flags; // Flags (details unknown)
DWORD FileSizeLo; // Low 32 bits of the contained file size
DWORD FileSizeHi; // High 32 bits of the contained file size
DWORD BlockSize; // Size of one file block, in bytes
} PART_FILE_HEADER, *PPART_FILE_HEADER;
// Structure describing the block-to-file map entry
typedef struct _PART_FILE_MAP_ENTRY
{
DWORD Flags; // 3 = the block is present in the file
DWORD BlockOffsLo; // Low 32 bits of the block position in the file
DWORD BlockOffsHi; // High 32 bits of the block position in the file
DWORD LargeValueLo; // 64-bit value, meaning is unknown
DWORD LargeValueHi;
} PART_FILE_MAP_ENTRY, *PPART_FILE_MAP_ENTRY;
typedef struct _FILE_BITMAP_FOOTER
{
DWORD Signature; // 'ptv3' (ID_FILE_BITMAP_FOOTER)
DWORD Version; // Unknown, seems to always have value of 3 (version?)
DWORD BuildNumber; // Game build number for that MPQ
DWORD MapOffsetLo; // Low 32-bits of the offset of the bit map
DWORD MapOffsetHi; // High 32-bits of the offset of the bit map
DWORD BlockSize; // Size of one block (usually 0x4000 bytes)
} FILE_BITMAP_FOOTER, *PFILE_BITMAP_FOOTER;
//-----------------------------------------------------------------------------
// Structure for file stream
union TBaseProviderData
{
struct
{
ULONGLONG FileSize; // Size of the file
ULONGLONG FilePos; // Current file position
ULONGLONG FileTime; // Last write time
HANDLE hFile; // File handle
} File;
struct
{
ULONGLONG FileSize; // Size of the file
ULONGLONG FilePos; // Current file position
ULONGLONG FileTime; // Last write time
LPBYTE pbFile; // Pointer to mapped view
} Map;
struct
{
ULONGLONG FileSize; // Size of the file
ULONGLONG FilePos; // Current file position
ULONGLONG FileTime; // Last write time
HANDLE hInternet; // Internet handle
HANDLE hConnect; // Connection to the internet server
} Http;
};
struct TFileStream
{
// Stream provider functions
STREAM_READ StreamRead; // Pointer to stream read function for this archive. Do not use directly.
STREAM_WRITE StreamWrite; // Pointer to stream write function for this archive. Do not use directly.
STREAM_RESIZE StreamResize; // Pointer to function changing file size
STREAM_GETSIZE StreamGetSize; // Pointer to function returning file size
STREAM_GETPOS StreamGetPos; // Pointer to function that returns current file position
STREAM_CLOSE StreamClose; // Pointer to function closing the stream
// Block-oriented functions
BLOCK_READ BlockRead; // Pointer to function reading one or more blocks
BLOCK_CHECK BlockCheck; // Pointer to function checking whether the block is present
// Base provider functions
STREAM_CREATE BaseCreate; // Pointer to base create function
STREAM_OPEN BaseOpen; // Pointer to base open function
STREAM_READ BaseRead; // Read from the stream
STREAM_WRITE BaseWrite; // Write to the stream
STREAM_RESIZE BaseResize; // Pointer to function changing file size
STREAM_GETSIZE BaseGetSize; // Pointer to function returning file size
STREAM_GETPOS BaseGetPos; // Pointer to function that returns current file position
STREAM_CLOSE BaseClose; // Pointer to function closing the stream
// Base provider data (file size, file position)
TBaseProviderData Base;
// Stream provider data
TFileStream * pMaster; // Master stream (e.g. MPQ on a web server)
TCHAR * szFileName; // File name (self-relative pointer)
ULONGLONG StreamSize; // Stream size (can be less than file size)
ULONGLONG StreamPos; // Stream position
DWORD BuildNumber; // Game build number
DWORD dwFlags; // Stream flags
// Followed by stream provider data, with variable length
};
//-----------------------------------------------------------------------------
// Structures for block-oriented stream
struct TBlockStream : public TFileStream
{
SFILE_DOWNLOAD_CALLBACK pfnCallback; // Callback for downloading
void * FileBitmap; // Array of bits for file blocks
void * UserData; // User data to be passed to the download callback
DWORD BitmapSize; // Size of the file bitmap (in bytes)
DWORD BlockSize; // Size of one block, in bytes
DWORD BlockCount; // Number of data blocks in the file
DWORD IsComplete; // If nonzero, no blocks are missing
DWORD IsModified; // nonzero if the bitmap has been modified
};
//-----------------------------------------------------------------------------
// Structure for encrypted stream
#define MPQE_CHUNK_SIZE 0x40 // Size of one chunk to be decrypted
struct TEncryptedStream : public TBlockStream
{
BYTE Key[MPQE_CHUNK_SIZE]; // File key
};
#endif // __FILESTREAM_H__

1856
3rdParty/StormLib/src/SBaseCommon.cpp vendored

File diff suppressed because it is too large Load Diff

2962
3rdParty/StormLib/src/SBaseFileTable.cpp vendored

File diff suppressed because it is too large Load Diff

618
3rdParty/StormLib/src/SBaseSubTypes.cpp vendored

@ -0,0 +1,618 @@
/*****************************************************************************/
/* SBaseSubTypes.cpp Copyright (c) Ladislav Zezula 2013 */
/*---------------------------------------------------------------------------*/
/* Conversion routines for archive formats that are similar to MPQ format */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 02.11.11 1.00 Lad The first version of SBaseSubTypes.cpp */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "StormCommon.h"
/*****************************************************************************/
/* */
/* Support for SQP file format (War of the Immortals) */
/* */
/*****************************************************************************/
typedef struct _TSQPHeader
{
// The ID_MPQ ('MPQ\x1A') signature
DWORD dwID;
// Size of the archive header
DWORD dwHeaderSize;
// 32-bit size of MPQ archive
DWORD dwArchiveSize;
// Offset to the beginning of the hash table, relative to the beginning of the archive.
DWORD dwHashTablePos;
// Offset to the beginning of the block table, relative to the beginning of the archive.
DWORD dwBlockTablePos;
// Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for
// the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
DWORD dwHashTableSize;
// Number of entries in the block table
DWORD dwBlockTableSize;
// Must be zero for SQP files
USHORT wFormatVersion;
// Power of two exponent specifying the number of 512-byte disk sectors in each file sector
// in the archive. The size of each file sector in the archive is 512 * 2 ^ wSectorSize.
USHORT wSectorSize;
} TSQPHeader;
typedef struct _TSQPHash
{
// Most likely the lcLocale+wPlatform.
DWORD dwAlwaysZero;
// If the hash table entry is valid, this is the index into the block table of the file.
// Otherwise, one of the following two values:
// - FFFFFFFFh: Hash table entry is empty, and has always been empty.
// Terminates searches for a given file.
// - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file).
// Does not terminate searches for a given file.
DWORD dwBlockIndex;
// The hash of the file path, using method A.
DWORD dwName1;
// The hash of the file path, using method B.
DWORD dwName2;
} TSQPHash;
typedef struct _TSQPBlock
{
// Offset of the beginning of the file, relative to the beginning of the archive.
DWORD dwFilePos;
// Flags for the file. See MPQ_FILE_XXXX constants
DWORD dwFlags;
// Compressed file size
DWORD dwCSize;
// Uncompressed file size
DWORD dwFSize;
} TSQPBlock;
//-----------------------------------------------------------------------------
// Functions - SQP file format
// This function converts SQP file header into MPQ file header
int ConvertSqpHeaderToFormat4(
TMPQArchive * ha,
ULONGLONG FileSize,
DWORD dwFlags)
{
TSQPHeader * pSqpHeader = (TSQPHeader *)ha->HeaderData;
TMPQHeader Header;
// SQP files from War of the Immortal use MPQ file format with slightly
// modified structure. These fields have different position:
//
// Offset TMPQHeader TSQPHeader
// ------ ---------- -----------
// 000C wFormatVersion dwHashTablePos (lo)
// 000E wSectorSize dwHashTablePos (hi)
// 001C dwBlockTableSize (lo) wBlockSize
// 001E dwHashTableSize (hi) wFormatVersion
// Can't open the archive with certain flags
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
return ERROR_FILE_CORRUPT;
// The file must not be greater than 4 GB
if((FileSize >> 0x20) != 0)
return ERROR_FILE_CORRUPT;
// Translate the SQP header into a MPQ header
memset(&Header, 0, sizeof(TMPQHeader));
Header.dwID = BSWAP_INT32_UNSIGNED(pSqpHeader->dwID);
Header.dwHeaderSize = BSWAP_INT32_UNSIGNED(pSqpHeader->dwHeaderSize);
Header.dwArchiveSize = BSWAP_INT32_UNSIGNED(pSqpHeader->dwArchiveSize);
Header.dwHashTablePos = BSWAP_INT32_UNSIGNED(pSqpHeader->dwHashTablePos);
Header.dwBlockTablePos = BSWAP_INT32_UNSIGNED(pSqpHeader->dwBlockTablePos);
Header.dwHashTableSize = BSWAP_INT32_UNSIGNED(pSqpHeader->dwHashTableSize);
Header.dwBlockTableSize = BSWAP_INT32_UNSIGNED(pSqpHeader->dwBlockTableSize);
Header.wFormatVersion = BSWAP_INT16_UNSIGNED(pSqpHeader->wFormatVersion);
Header.wSectorSize = BSWAP_INT16_UNSIGNED(pSqpHeader->wSectorSize);
// Verify the SQP header
if(Header.dwID == ID_MPQ && Header.dwHeaderSize == sizeof(TSQPHeader) && Header.dwArchiveSize == FileSize)
{
// Check for fixed values of version and sector size
if(Header.wFormatVersion == MPQ_FORMAT_VERSION_1 && Header.wSectorSize == 3)
{
// Initialize the fields of 3.0 header
Header.ArchiveSize64 = Header.dwArchiveSize;
Header.HashTableSize64 = Header.dwHashTableSize * sizeof(TMPQHash);
Header.BlockTableSize64 = Header.dwBlockTableSize * sizeof(TMPQBlock);
// Copy the converted MPQ header back
memcpy(ha->HeaderData, &Header, sizeof(TMPQHeader));
// Mark this file as SQP file
ha->pfnHashString = HashStringSlash;
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
ha->dwSubType = MPQ_SUBTYPE_SQP;
return ERROR_SUCCESS;
}
}
return ERROR_FILE_CORRUPT;
}
void * LoadSqpTable(TMPQArchive * ha, DWORD dwByteOffset, DWORD cbTableSize, DWORD dwKey)
{
ULONGLONG ByteOffset;
LPBYTE pbSqpTable;
// Allocate buffer for the table
pbSqpTable = STORM_ALLOC(BYTE, cbTableSize);
if(pbSqpTable != NULL)
{
// Load the table
ByteOffset = ha->MpqPos + dwByteOffset;
if(FileStream_Read(ha->pStream, &ByteOffset, pbSqpTable, cbTableSize))
{
// Decrypt the SQP table
DecryptMpqBlock(pbSqpTable, cbTableSize, dwKey);
return pbSqpTable;
}
// Free the table
STORM_FREE(pbSqpTable);
}
return NULL;
}
TMPQHash * LoadSqpHashTable(TMPQArchive * ha)
{
TMPQHeader * pHeader = ha->pHeader;
TSQPHash * pSqpHashTable;
TSQPHash * pSqpHashEnd;
TSQPHash * pSqpHash;
TMPQHash * pMpqHash;
int nError = ERROR_SUCCESS;
// Load the hash table
pSqpHashTable = (TSQPHash *)LoadSqpTable(ha, pHeader->dwHashTablePos, pHeader->dwHashTableSize * sizeof(TSQPHash), MPQ_KEY_HASH_TABLE);
if(pSqpHashTable != NULL)
{
// Parse the entire hash table and convert it to MPQ hash table
pSqpHashEnd = pSqpHashTable + pHeader->dwHashTableSize;
pMpqHash = (TMPQHash *)pSqpHashTable;
for(pSqpHash = pSqpHashTable; pSqpHash < pSqpHashEnd; pSqpHash++, pMpqHash++)
{
// Ignore free entries
if(pSqpHash->dwBlockIndex != HASH_ENTRY_FREE)
{
// Check block index against the size of the block table
if(pHeader->dwBlockTableSize <= MPQ_BLOCK_INDEX(pSqpHash) && pSqpHash->dwBlockIndex < HASH_ENTRY_DELETED)
nError = ERROR_FILE_CORRUPT;
// We do not support nonzero locale and platform ID
if(pSqpHash->dwAlwaysZero != 0 && pSqpHash->dwAlwaysZero != HASH_ENTRY_FREE)
nError = ERROR_FILE_CORRUPT;
// Store the file name hash
pMpqHash->dwName1 = pSqpHash->dwName1;
pMpqHash->dwName2 = pSqpHash->dwName2;
// Store the rest. Note that this must be done last,
// because block index corresponds to pMpqHash->dwName2
pMpqHash->dwBlockIndex = MPQ_BLOCK_INDEX(pSqpHash);
pMpqHash->Platform = 0;
pMpqHash->lcLocale = 0;
}
}
// If an error occured, we need to free the hash table
if(nError != ERROR_SUCCESS)
{
STORM_FREE(pSqpHashTable);
pSqpHashTable = NULL;
}
}
// Return the converted hash table (or NULL on failure)
return (TMPQHash *)pSqpHashTable;
}
// Loads the SQP Block table and converts it to a MPQ block table
TMPQBlock * LoadSqpBlockTable(TMPQArchive * ha)
{
TMPQHeader * pHeader = ha->pHeader;
TSQPBlock * pSqpBlockTable;
TSQPBlock * pSqpBlockEnd;
TSQPBlock * pSqpBlock;
TMPQBlock * pMpqBlock;
DWORD dwFlags;
int nError = ERROR_SUCCESS;
// Load the hash table
pSqpBlockTable = (TSQPBlock *)LoadSqpTable(ha, pHeader->dwBlockTablePos, pHeader->dwBlockTableSize * sizeof(TSQPBlock), MPQ_KEY_BLOCK_TABLE);
if(pSqpBlockTable != NULL)
{
// Parse the entire hash table and convert it to MPQ hash table
pSqpBlockEnd = pSqpBlockTable + pHeader->dwBlockTableSize;
pMpqBlock = (TMPQBlock *)pSqpBlockTable;
for(pSqpBlock = pSqpBlockTable; pSqpBlock < pSqpBlockEnd; pSqpBlock++, pMpqBlock++)
{
// Check for valid flags
if(pSqpBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS)
nError = ERROR_FILE_CORRUPT;
// Convert SQP block table entry to MPQ block table entry
dwFlags = pSqpBlock->dwFlags;
pMpqBlock->dwCSize = pSqpBlock->dwCSize;
pMpqBlock->dwFSize = pSqpBlock->dwFSize;
pMpqBlock->dwFlags = dwFlags;
}
// If an error occured, we need to free the hash table
if(nError != ERROR_SUCCESS)
{
STORM_FREE(pSqpBlockTable);
pSqpBlockTable = NULL;
}
}
// Return the converted hash table (or NULL on failure)
return (TMPQBlock *)pSqpBlockTable;
}
/*****************************************************************************/
/* */
/* Support for MPK file format (Longwu Online) */
/* */
/*****************************************************************************/
#define MPK_FILE_UNKNOWN_0001 0x00000001 // Seems to be always present
#define MPK_FILE_UNKNOWN_0010 0x00000010 // Seems to be always present
#define MPK_FILE_COMPRESSED 0x00000100 // Indicates a compressed file
#define MPK_FILE_UNKNOWN_2000 0x00002000 // Seems to be always present
#define MPK_FILE_EXISTS 0x01000000 // Seems to be always present
typedef struct _TMPKHeader
{
// The ID_MPK ('MPK\x1A') signature
DWORD dwID;
// Contains '2000'
DWORD dwVersion;
// 32-bit size of the archive
DWORD dwArchiveSize;
// Size of the archive header
DWORD dwHeaderSize;
DWORD dwHashTablePos;
DWORD dwHashTableSize;
DWORD dwBlockTablePos;
DWORD dwBlockTableSize;
DWORD dwUnknownPos;
DWORD dwUnknownSize;
} TMPKHeader;
typedef struct _TMPKHash
{
// The hash of the file path, using method A.
DWORD dwName1;
// The hash of the file path, using method B.
DWORD dwName2;
// The hash of the file path, using method C.
DWORD dwName3;
// If the hash table entry is valid, this is the index into the block table of the file.
// Otherwise, one of the following two values:
// - FFFFFFFFh: Hash table entry is empty, and has always been empty.
// Terminates searches for a given file.
// - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file).
// Does not terminate searches for a given file.
DWORD dwBlockIndex;
} TMPKHash;
typedef struct _TMPKBlock
{
DWORD dwFlags; // 0x1121 - Compressed , 0x1120 - Not compressed
DWORD dwFilePos; // Offset of the beginning of the file, relative to the beginning of the archive.
DWORD dwFSize; // Uncompressed file size
DWORD dwCSize; // Compressed file size
DWORD dwUnknown; // 0x86364E6D
} TMPKBlock;
//-----------------------------------------------------------------------------
// Local variables - MPK file format
static const unsigned char MpkDecryptionKey[512] =
{
0x60, 0x20, 0x29, 0xE1, 0x01, 0xCE, 0xAA, 0xFE, 0xA3, 0xAB, 0x8E, 0x30, 0xAF, 0x02, 0xD1, 0x7D,
0x41, 0x24, 0x06, 0xBD, 0xAE, 0xBE, 0x43, 0xC3, 0xBA, 0xB7, 0x08, 0x13, 0x51, 0xCF, 0xF8, 0xF7,
0x25, 0x42, 0xA5, 0x4A, 0xDA, 0x0F, 0x52, 0x1C, 0x90, 0x3B, 0x63, 0x49, 0x36, 0xF6, 0xDD, 0x1B,
0xEA, 0x58, 0xD4, 0x40, 0x70, 0x61, 0x55, 0x09, 0xCD, 0x0B, 0xA2, 0x4B, 0x68, 0x2C, 0x8A, 0xF1,
0x3C, 0x3A, 0x65, 0xBB, 0xA1, 0xA8, 0x23, 0x97, 0xFD, 0x15, 0x00, 0x94, 0x88, 0x33, 0x59, 0xE9,
0xFB, 0x69, 0x21, 0xEF, 0x85, 0x5B, 0x57, 0x6C, 0xFA, 0xB5, 0xEE, 0xB8, 0x71, 0xDC, 0xB1, 0x38,
0x0C, 0x0A, 0x5C, 0x56, 0xC9, 0xB4, 0x84, 0x17, 0x1E, 0xE5, 0xD3, 0x5A, 0xCC, 0xFC, 0x11, 0x86,
0x7F, 0x45, 0x4F, 0x54, 0xC8, 0x8D, 0x73, 0x89, 0x79, 0x5D, 0xB3, 0xBF, 0xB9, 0xE3, 0x93, 0xE4,
0x6F, 0x35, 0x2D, 0x46, 0xF2, 0x76, 0xC5, 0x7E, 0xE2, 0xA4, 0xE6, 0xD9, 0x6E, 0x48, 0x34, 0x2B,
0xC6, 0x5F, 0xBC, 0xA0, 0x6D, 0x0D, 0x47, 0x6B, 0x95, 0x96, 0x92, 0x91, 0xB2, 0x27, 0xEB, 0x9E,
0xEC, 0x8F, 0xDF, 0x9C, 0x74, 0x99, 0x64, 0xF5, 0xFF, 0x28, 0xB6, 0x37, 0xF3, 0x7C, 0x81, 0x03,
0x44, 0x62, 0x1F, 0xDB, 0x04, 0x7B, 0xB0, 0x9B, 0x31, 0xA7, 0xDE, 0x78, 0x9F, 0xAD, 0x0E, 0x3F,
0x3E, 0x4D, 0xC7, 0xD7, 0x39, 0x19, 0x5E, 0xC2, 0xD0, 0xAC, 0xE8, 0x1A, 0x87, 0x8B, 0x07, 0x05,
0x22, 0xED, 0x72, 0x2E, 0x1D, 0xC1, 0xA9, 0xD6, 0xE0, 0x83, 0xD5, 0xD8, 0xCB, 0x80, 0xF0, 0x66,
0x7A, 0x9D, 0x50, 0xF9, 0x10, 0x4E, 0x16, 0x14, 0x77, 0x75, 0x6A, 0x67, 0xD2, 0xC0, 0xA6, 0xC4,
0x53, 0x8C, 0x32, 0xCA, 0x82, 0x2A, 0x18, 0x9A, 0xF4, 0x4C, 0x3D, 0x26, 0x12, 0xE7, 0x98, 0x2F,
0x4A, 0x04, 0x0D, 0xAF, 0xB4, 0xCF, 0x12, 0xCE, 0x1A, 0x37, 0x61, 0x39, 0x60, 0x95, 0xBE, 0x25,
0xE4, 0x6E, 0xFC, 0x1B, 0xE7, 0x49, 0xE6, 0x67, 0xF6, 0xC5, 0xCB, 0x2F, 0x27, 0xD4, 0x68, 0xB2,
0x01, 0x52, 0xD0, 0x46, 0x11, 0x20, 0xFB, 0x9D, 0xA9, 0x02, 0xF5, 0x8F, 0x3D, 0x82, 0xD3, 0xFF,
0x0B, 0xB8, 0xF2, 0x4D, 0x8E, 0x81, 0x2C, 0xAB, 0x5F, 0xC4, 0x41, 0x29, 0x40, 0xFA, 0xC0, 0xBF,
0x33, 0x10, 0x21, 0x16, 0xB0, 0x71, 0x83, 0x96, 0x8D, 0x2B, 0x23, 0x3B, 0xF9, 0xC1, 0xE5, 0x72,
0xE2, 0x1C, 0x26, 0xF0, 0x73, 0x36, 0x63, 0x56, 0x31, 0x4E, 0x6B, 0x55, 0x62, 0x79, 0xC6, 0x91,
0x00, 0x35, 0xB1, 0x2A, 0xA6, 0x42, 0xDF, 0xEB, 0x3C, 0x51, 0xEA, 0x97, 0x57, 0x94, 0x8C, 0x80,
0x34, 0x5C, 0xD2, 0x76, 0xA4, 0xE9, 0x85, 0xE8, 0xBB, 0x78, 0xE0, 0xB5, 0xAD, 0x0F, 0x87, 0x70,
0xDD, 0xAE, 0xF4, 0xD9, 0x66, 0x54, 0x6F, 0xCC, 0x4C, 0x77, 0x3E, 0xCD, 0xF1, 0x75, 0x0A, 0xA1,
0x28, 0x9B, 0x9A, 0x7E, 0x4B, 0x98, 0x99, 0x47, 0xFE, 0xA5, 0xF7, 0xB7, 0xA3, 0xE1, 0x9F, 0xBC,
0x93, 0x44, 0x3A, 0x08, 0x89, 0x22, 0xEE, 0xB9, 0x45, 0xD6, 0x06, 0x09, 0xC9, 0xBD, 0x14, 0x0C,
0xB6, 0x5E, 0x9C, 0x7A, 0x65, 0x59, 0xAA, 0x19, 0x5B, 0x7C, 0x18, 0x43, 0x92, 0x13, 0x15, 0x7B,
0xED, 0xD5, 0xC7, 0x17, 0xEF, 0x86, 0x90, 0xC2, 0x74, 0x64, 0xF3, 0xDC, 0x6C, 0x38, 0x05, 0x1D,
0xC8, 0x0E, 0xEC, 0x6A, 0x32, 0xDA, 0xD7, 0xC3, 0xDB, 0x8B, 0x24, 0xB3, 0x5D, 0x2E, 0xBA, 0xA2,
0xD8, 0x03, 0x88, 0x7D, 0x7F, 0x69, 0x8A, 0xFD, 0xCA, 0x4F, 0x30, 0x9E, 0xA0, 0xD1, 0x5A, 0x53,
0xDE, 0x3F, 0x84, 0xAC, 0xF8, 0xA7, 0x2D, 0x1F, 0x1E, 0xE3, 0x58, 0x50, 0x6D, 0x48, 0x07, 0xA8
};
//-----------------------------------------------------------------------------
// Functions - MPK file format
// This function converts MPK file header into MPQ file header
int ConvertMpkHeaderToFormat4(
TMPQArchive * ha,
ULONGLONG FileSize,
DWORD dwFlags)
{
TMPKHeader * pMpkHeader = (TMPKHeader *)ha->HeaderData;
TMPQHeader Header;
// Can't open the archive with certain flags
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
return ERROR_FILE_CORRUPT;
// Translate the MPK header into a MPQ header
// Note: Hash table size and block table size are in bytes, not in entries
memset(&Header, 0, sizeof(TMPQHeader));
Header.dwID = BSWAP_INT32_UNSIGNED(pMpkHeader->dwID);
Header.dwArchiveSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwArchiveSize);
Header.dwHeaderSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwHeaderSize);
Header.dwHashTablePos = BSWAP_INT32_UNSIGNED(pMpkHeader->dwHashTablePos);
Header.dwHashTableSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwHashTableSize) / sizeof(TMPKHash);
Header.dwBlockTablePos = BSWAP_INT32_UNSIGNED(pMpkHeader->dwBlockTablePos);
Header.dwBlockTableSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwBlockTableSize) / sizeof(TMPKBlock);
// Header.dwUnknownPos = BSWAP_INT32_UNSIGNED(pMpkHeader->dwUnknownPos);
// Header.dwUnknownSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwUnknownSize);
assert(Header.dwHeaderSize == sizeof(TMPKHeader));
// Verify the MPK header
if(Header.dwID == ID_MPK && Header.dwHeaderSize == sizeof(TMPKHeader) && Header.dwArchiveSize == (DWORD)FileSize)
{
// The header ID must be ID_MPQ
Header.dwID = ID_MPQ;
Header.wFormatVersion = MPQ_FORMAT_VERSION_1;
Header.wSectorSize = 3;
// Initialize the fields of 3.0 header
Header.ArchiveSize64 = Header.dwArchiveSize;
Header.HashTableSize64 = Header.dwHashTableSize * sizeof(TMPQHash);
Header.BlockTableSize64 = Header.dwBlockTableSize * sizeof(TMPQBlock);
// Copy the converted MPQ header back
memcpy(ha->HeaderData, &Header, sizeof(TMPQHeader));
// Mark this file as MPK file
ha->pfnHashString = HashStringLower;
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
ha->dwSubType = MPQ_SUBTYPE_MPK;
return ERROR_SUCCESS;
}
return ERROR_FILE_CORRUPT;
}
// Attempts to search a free hash entry in the hash table being converted.
// The created hash table must always be of nonzero size,
// should have no duplicated items and no deleted entries
TMPQHash * FindFreeHashEntry(TMPQHash * pHashTable, DWORD dwHashTableSize, DWORD dwStartIndex)
{
TMPQHash * pHash;
DWORD dwIndex;
// Set the initial index
dwStartIndex = dwIndex = (dwStartIndex & (dwHashTableSize - 1));
assert(dwHashTableSize != 0);
// Search the hash table and return the found entries in the following priority:
for(;;)
{
// We are not expecting to find matching entry in the hash table being built
// We are not expecting to find deleted entry either
pHash = pHashTable + dwIndex;
// If we found a free entry, we need to stop searching
if(pHash->dwBlockIndex == HASH_ENTRY_FREE)
return pHash;
// Move to the next hash entry.
// If we reached the starting entry, it's failure.
dwIndex = (dwIndex + 1) & (dwHashTableSize - 1);
if(dwIndex == dwStartIndex)
break;
}
// We haven't found anything
assert(false);
return NULL;
}
void DecryptMpkTable(void * pvMpkTable, size_t cbSize)
{
LPBYTE pbMpkTable = (LPBYTE)pvMpkTable;
for(size_t i = 0; i < cbSize; i++)
pbMpkTable[i] = MpkDecryptionKey[pbMpkTable[i]];
}
void * LoadMpkTable(TMPQArchive * ha, DWORD dwByteOffset, DWORD cbTableSize)
{
ULONGLONG ByteOffset;
LPBYTE pbMpkTable = NULL;
// Allocate space for the table
pbMpkTable = STORM_ALLOC(BYTE, cbTableSize);
if(pbMpkTable != NULL)
{
// Load and the MPK hash table
ByteOffset = ha->MpqPos + dwByteOffset;
if(FileStream_Read(ha->pStream, &ByteOffset, pbMpkTable, cbTableSize))
{
// Decrypt the table
DecryptMpkTable(pbMpkTable, cbTableSize);
return pbMpkTable;
}
// Free the MPK table
STORM_FREE(pbMpkTable);
pbMpkTable = NULL;
}
// Return the table
return pbMpkTable;
}
TMPQHash * LoadMpkHashTable(TMPQArchive * ha)
{
TMPQHeader * pHeader = ha->pHeader;
TMPQHash * pHashTable = NULL;
TMPKHash * pMpkHash;
TMPQHash * pHash = NULL;
DWORD dwHashTableSize = pHeader->dwHashTableSize;
// MPKs use different hash table searching.
// Instead of using MPQ_HASH_TABLE_INDEX hash as index,
// they store the value directly in the hash table.
// Also for faster searching, the hash table is sorted ascending by the value
// Load and decrypt the MPK hash table.
pMpkHash = (TMPKHash *)LoadMpkTable(ha, pHeader->dwHashTablePos, pHeader->dwHashTableSize * sizeof(TMPKHash));
if(pMpkHash != NULL)
{
// Calculate the hash table size as if it was real MPQ hash table
pHeader->dwHashTableSize = GetNearestPowerOfTwo(pHeader->dwHashTableSize);
pHeader->HashTableSize64 = pHeader->dwHashTableSize * sizeof(TMPQHash);
// Now allocate table that will serve like a true MPQ hash table,
// so we translate the MPK hash table to MPQ hash table
pHashTable = STORM_ALLOC(TMPQHash, pHeader->dwHashTableSize);
if(pHashTable != NULL)
{
// Set the entire hash table to free
memset(pHashTable, 0xFF, (size_t)pHeader->HashTableSize64);
// Copy the MPK hash table into MPQ hash table
for(DWORD i = 0; i < dwHashTableSize; i++)
{
// Finds the free hash entry in the hash table
// We don't expect any errors here, because we are putting files to empty hash table
pHash = FindFreeHashEntry(pHashTable, pHeader->dwHashTableSize, pMpkHash[i].dwName1);
assert(pHash->dwBlockIndex == HASH_ENTRY_FREE);
// Copy the MPK hash entry to the hash table
pHash->dwBlockIndex = pMpkHash[i].dwBlockIndex;
pHash->Platform = 0;
pHash->lcLocale = 0;
pHash->dwName1 = pMpkHash[i].dwName2;
pHash->dwName2 = pMpkHash[i].dwName3;
}
}
// Free the temporary hash table
STORM_FREE(pMpkHash);
}
return pHashTable;
}
static DWORD ConvertMpkFlagsToMpqFlags(DWORD dwMpkFlags)
{
DWORD dwMpqFlags = MPQ_FILE_EXISTS;
// Check for flags that are always present
assert((dwMpkFlags & MPK_FILE_UNKNOWN_0001) != 0);
assert((dwMpkFlags & MPK_FILE_UNKNOWN_0010) != 0);
assert((dwMpkFlags & MPK_FILE_UNKNOWN_2000) != 0);
assert((dwMpkFlags & MPK_FILE_EXISTS) != 0);
// Append the compressed flag
dwMpqFlags |= (dwMpkFlags & MPK_FILE_COMPRESSED) ? MPQ_FILE_COMPRESS : 0;
// All files in the MPQ seem to be single unit files
dwMpqFlags |= MPQ_FILE_ENCRYPTED | MPQ_FILE_SINGLE_UNIT;
return dwMpqFlags;
}
TMPQBlock * LoadMpkBlockTable(TMPQArchive * ha)
{
TMPQHeader * pHeader = ha->pHeader;
TMPKBlock * pMpkBlockTable;
TMPKBlock * pMpkBlockEnd;
TMPQBlock * pBlockTable = NULL;
TMPKBlock * pMpkBlock;
TMPQBlock * pMpqBlock;
// Load and decrypt the MPK block table
pMpkBlockTable = pMpkBlock = (TMPKBlock *)LoadMpkTable(ha, pHeader->dwBlockTablePos, pHeader->dwBlockTableSize * sizeof(TMPKBlock));
if(pMpkBlockTable != NULL)
{
// Allocate buffer for MPQ-like block table
pBlockTable = pMpqBlock = STORM_ALLOC(TMPQBlock, pHeader->dwBlockTableSize);
if(pBlockTable != NULL)
{
// Convert the MPK block table to MPQ block table
pMpkBlockEnd = pMpkBlockTable + pHeader->dwBlockTableSize;
while(pMpkBlock < pMpkBlockEnd)
{
// Translate the MPK block table entry to MPQ block table entry
pMpqBlock->dwFilePos = pMpkBlock->dwFilePos;
pMpqBlock->dwCSize = pMpkBlock->dwCSize;
pMpqBlock->dwFSize = pMpkBlock->dwFSize;
pMpqBlock->dwFlags = ConvertMpkFlagsToMpqFlags(pMpkBlock->dwFlags);
// Move both
pMpkBlock++;
pMpqBlock++;
}
}
// Free the MPK block table
STORM_FREE(pMpkBlockTable);
}
return pBlockTable;
}

1166
3rdParty/StormLib/src/SCompression.cpp vendored

File diff suppressed because it is too large Load Diff

64
3rdParty/StormLib/src/SFileExtractFile.cpp vendored

@ -0,0 +1,64 @@
/*****************************************************************************/
/* SFileExtractFile.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Simple extracting utility */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 20.06.03 1.00 Lad The first version of SFileExtractFile.cpp */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "StormCommon.h"
bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope)
{
TFileStream * pLocalFile = NULL;
HANDLE hMpqFile = NULL;
int nError = ERROR_SUCCESS;
// Open the MPQ file
if(nError == ERROR_SUCCESS)
{
if(!SFileOpenFileEx(hMpq, szToExtract, dwSearchScope, &hMpqFile))
nError = GetLastError();
}
// Create the local file
if(nError == ERROR_SUCCESS)
{
pLocalFile = FileStream_CreateFile(szExtracted, 0);
if(pLocalFile == NULL)
nError = GetLastError();
}
// Copy the file's content
while(nError == ERROR_SUCCESS)
{
char szBuffer[0x1000];
DWORD dwTransferred = 0;
// dwTransferred is only set to nonzero if something has been read.
// nError can be ERROR_SUCCESS or ERROR_HANDLE_EOF
if(!SFileReadFile(hMpqFile, szBuffer, sizeof(szBuffer), &dwTransferred, NULL))
nError = GetLastError();
if(nError == ERROR_HANDLE_EOF)
nError = ERROR_SUCCESS;
if(dwTransferred == 0)
break;
// If something has been actually read, write it
if(!FileStream_Write(pLocalFile, NULL, szBuffer, dwTransferred))
nError = GetLastError();
}
// Close the files
if(hMpqFile != NULL)
SFileCloseFile(hMpqFile);
if(pLocalFile != NULL)
FileStream_Close(pLocalFile);
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}

481
3rdParty/StormLib/src/SFileFindFile.cpp vendored

@ -0,0 +1,481 @@
/*****************************************************************************/
/* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* A module for file searching within MPQs */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "StormCommon.h"
//-----------------------------------------------------------------------------
// Private structure used for file search (search handle)
// Used by searching in MPQ archives
struct TMPQSearch
{
TMPQArchive * ha; // Handle to MPQ, where the search runs
TFileEntry ** pSearchTable; // Table for files that have been already found
DWORD dwSearchTableItems; // Number of items in the search table
DWORD dwNextIndex; // Next file index to be checked
DWORD dwFlagMask; // For checking flag mask
char szSearchMask[1]; // Search mask (variable length)
};
//-----------------------------------------------------------------------------
// Local functions
static TMPQSearch * IsValidSearchHandle(HANDLE hFind)
{
TMPQSearch * hs = (TMPQSearch *)hFind;
if(hs != NULL && IsValidMpqHandle(hs->ha))
return hs;
return NULL;
}
bool CheckWildCard(const char * szString, const char * szWildCard)
{
const char * szWildCardPtr;
for(;;)
{
// If there is '?' in the wildcard, we skip one char
while(szWildCard[0] == '?')
{
if(szString[0] == 0)
return false;
szWildCard++;
szString++;
}
// Handle '*'
szWildCardPtr = szWildCard;
if(szWildCardPtr[0] != 0)
{
if(szWildCardPtr[0] == '*')
{
szWildCardPtr++;
if(szWildCardPtr[0] == '*')
continue;
if(szWildCardPtr[0] == 0)
return true;
if(AsciiToUpperTable[szWildCardPtr[0]] == AsciiToUpperTable[szString[0]])
{
if(CheckWildCard(szString, szWildCardPtr))
return true;
}
}
else
{
if(AsciiToUpperTable[szWildCardPtr[0]] != AsciiToUpperTable[szString[0]])
return false;
szWildCard = szWildCardPtr + 1;
}
if(szString[0] == 0)
return false;
szString++;
}
else
{
return (szString[0] == 0) ? true : false;
}
}
}
static DWORD GetSearchTableItems(TMPQArchive * ha)
{
DWORD dwMergeItems = 0;
// Loop over all patches
while(ha != NULL)
{
// Append the number of files
dwMergeItems += (ha->pHetTable != NULL) ? ha->pHetTable->dwEntryCount
: ha->pHeader->dwBlockTableSize;
// Move to the patched archive
ha = ha->haPatch;
}
// Return the double size of number of items
return (dwMergeItems | 1);
}
static bool FileWasFoundBefore(
TMPQArchive * ha,
TMPQSearch * hs,
TFileEntry * pFileEntry)
{
TFileEntry * pEntry;
char * szRealFileName = pFileEntry->szFileName;
DWORD dwStartIndex;
DWORD dwNameHash;
DWORD dwIndex;
if(hs->pSearchTable != NULL && szRealFileName != NULL)
{
// If we are in patch MPQ, we check if patch prefix matches
// and then trim the patch prefix
if(ha->pPatchPrefix != NULL)
{
// If the patch prefix doesn't fit, we pretend that the file
// was there before and it will be skipped
if(_strnicmp(szRealFileName, ha->pPatchPrefix->szPatchPrefix, ha->pPatchPrefix->nLength))
return true;
szRealFileName += ha->pPatchPrefix->nLength;
}
// Calculate the hash to the table
dwNameHash = ha->pfnHashString(szRealFileName, MPQ_HASH_NAME_A);
dwStartIndex = dwIndex = (dwNameHash % hs->dwSearchTableItems);
// The file might have been found before
// only if this is not the first MPQ being searched
if(ha->haBase != NULL)
{
// Enumerate all entries in the search table
for(;;)
{
// Get the file entry at that position
pEntry = hs->pSearchTable[dwIndex];
if(pEntry == NULL)
break;
if(pEntry->szFileName != NULL)
{
// Does the name match?
if(!_stricmp(pEntry->szFileName, szRealFileName))
return true;
}
// Move to the next entry
dwIndex = (dwIndex + 1) % hs->dwSearchTableItems;
if(dwIndex == dwStartIndex)
break;
}
}
// Put the entry to the table for later use
hs->pSearchTable[dwIndex] = pFileEntry;
}
return false;
}
static TFileEntry * FindPatchEntry(TMPQArchive * ha, TFileEntry * pFileEntry)
{
TFileEntry * pPatchEntry = pFileEntry;
TFileEntry * pTempEntry;
char szFileName[MAX_PATH+1];
// Can't find patch entry for a file that doesn't have name
if(pFileEntry->szFileName != NULL && pFileEntry->szFileName[0] != 0)
{
// Go while there are patches
while(ha->haPatch != NULL)
{
// Move to the patch archive
ha = ha->haPatch;
szFileName[0] = 0;
// Prepare the prefix for the file name
if(ha->pPatchPrefix && ha->pPatchPrefix->nLength)
StringCopy(szFileName, _countof(szFileName), ha->pPatchPrefix->szPatchPrefix);
StringCat(szFileName, _countof(szFileName), pFileEntry->szFileName);
// Try to find the file there
pTempEntry = GetFileEntryExact(ha, szFileName, 0, NULL);
if(pTempEntry != NULL)
pPatchEntry = pTempEntry;
}
}
// Return the found patch entry
return pPatchEntry;
}
static bool DoMPQSearch_FileEntry(
TMPQSearch * hs,
SFILE_FIND_DATA * lpFindFileData,
TMPQArchive * ha,
TMPQHash * pHashEntry,
TFileEntry * pFileEntry)
{
TFileEntry * pPatchEntry;
HANDLE hFile = NULL;
const char * szFileName;
size_t nPrefixLength = (ha->pPatchPrefix != NULL) ? ha->pPatchPrefix->nLength : 0;
DWORD dwBlockIndex;
char szNameBuff[MAX_PATH];
// Is it a file but not a patch file?
if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
{
// Now we have to check if this file was not enumerated before
if(!FileWasFoundBefore(ha, hs, pFileEntry))
{
// if(pFileEntry != NULL && !_stricmp(pFileEntry->szFileName, "TriggerLibs\\NativeLib.galaxy"))
// DebugBreak();
// Find a patch to this file
// Note: This either succeeds or returns pFileEntry
pPatchEntry = FindPatchEntry(ha, pFileEntry);
// Prepare the block index
dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
// Get the file name. If it's not known, we will create pseudo-name
szFileName = pFileEntry->szFileName;
if(szFileName == NULL)
{
// Open the file by its pseudo-name.
sprintf(szNameBuff, "File%08u.xxx", (unsigned int)dwBlockIndex);
if(SFileOpenFileEx((HANDLE)hs->ha, szNameBuff, SFILE_OPEN_BASE_FILE, &hFile))
{
SFileGetFileName(hFile, szNameBuff);
szFileName = szNameBuff;
SFileCloseFile(hFile);
}
}
// If the file name is still NULL, we cannot include the file to search results
if(szFileName != NULL)
{
// Check the file name against the wildcard
if(CheckWildCard(szFileName + nPrefixLength, hs->szSearchMask))
{
// Fill the found entry. hash entry and block index are taken from the base MPQ
lpFindFileData->dwHashIndex = HASH_ENTRY_FREE;
lpFindFileData->dwBlockIndex = dwBlockIndex;
lpFindFileData->dwFileSize = pPatchEntry->dwFileSize;
lpFindFileData->dwFileFlags = pPatchEntry->dwFlags;
lpFindFileData->dwCompSize = pPatchEntry->dwCmpSize;
lpFindFileData->lcLocale = 0; // pPatchEntry->lcLocale;
// Fill the filetime
lpFindFileData->dwFileTimeHi = (DWORD)(pPatchEntry->FileTime >> 32);
lpFindFileData->dwFileTimeLo = (DWORD)(pPatchEntry->FileTime);
// Fill-in the entries from hash table entry, if given
if(pHashEntry != NULL)
{
lpFindFileData->dwHashIndex = (DWORD)(pHashEntry - ha->pHashTable);
lpFindFileData->lcLocale = pHashEntry->lcLocale;
}
// Fill the file name and plain file name
StringCopy(lpFindFileData->cFileName, _countof(lpFindFileData->cFileName), szFileName + nPrefixLength);
lpFindFileData->szPlainName = (char *)GetPlainFileName(lpFindFileData->cFileName);
return true;
}
}
}
}
// Either not a valid item or was found before
return false;
}
static int DoMPQSearch_HashTable(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData, TMPQArchive * ha)
{
TMPQHash * pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
TMPQHash * pHash;
// Parse the file table
for(pHash = ha->pHashTable + hs->dwNextIndex; pHash < pHashTableEnd; pHash++)
{
// Increment the next index for subsequent search
hs->dwNextIndex++;
// Does this hash table entry point to a proper block table entry?
if(IsValidHashEntry(ha, pHash))
{
// Check if this file entry should be included in the search result
if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, pHash, ha->pFileTable + MPQ_BLOCK_INDEX(pHash)))
return ERROR_SUCCESS;
}
}
// No more files
return ERROR_NO_MORE_FILES;
}
static int DoMPQSearch_FileTable(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData, TMPQArchive * ha)
{
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
TFileEntry * pFileEntry;
// Parse the file table
for(pFileEntry = ha->pFileTable + hs->dwNextIndex; pFileEntry < pFileTableEnd; pFileEntry++)
{
// Increment the next index for subsequent search
hs->dwNextIndex++;
// Check if this file entry should be included in the search result
if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, NULL, pFileEntry))
return ERROR_SUCCESS;
}
// No more files
return ERROR_NO_MORE_FILES;
}
// Performs one MPQ search
static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
{
TMPQArchive * ha = hs->ha;
int nError;
// Start searching with base MPQ
while(ha != NULL)
{
// If the archive has hash table, we need to use hash table
// in order to catch hash table index and file locale.
// Note: If multiple hash table entries, point to the same block entry,
// we need, to report them all
nError = (ha->pHashTable != NULL) ? DoMPQSearch_HashTable(hs, lpFindFileData, ha)
: DoMPQSearch_FileTable(hs, lpFindFileData, ha);
if(nError == ERROR_SUCCESS)
return nError;
// If there is no more patches in the chain, stop it.
// This also keeps hs->ha non-NULL, which is required
// for freeing the handle later
if(ha->haPatch == NULL)
break;
// Move to the next patch in the patch chain
hs->ha = ha = ha->haPatch;
hs->dwNextIndex = 0;
}
// No more files found, return error
return ERROR_NO_MORE_FILES;
}
static void FreeMPQSearch(TMPQSearch *& hs)
{
if(hs != NULL)
{
if(hs->pSearchTable != NULL)
STORM_FREE(hs->pSearchTable);
STORM_FREE(hs);
hs = NULL;
}
}
//-----------------------------------------------------------------------------
// Public functions
HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const TCHAR * szListFile)
{
TMPQArchive * ha = (TMPQArchive *)hMpq;
TMPQSearch * hs = NULL;
size_t nSize = 0;
int nError = ERROR_SUCCESS;
// Check for the valid parameters
if(!IsValidMpqHandle(hMpq))
nError = ERROR_INVALID_HANDLE;
if(szMask == NULL || lpFindFileData == NULL)
nError = ERROR_INVALID_PARAMETER;
#ifdef FULL
// Include the listfile into the MPQ's internal listfile
// Note that if the listfile name is NULL, do nothing because the
// internal listfile is always included.
if(nError == ERROR_SUCCESS && szListFile != NULL && *szListFile != 0)
nError = SFileAddListFile((HANDLE)ha, szListFile);
#endif
// Allocate the structure for MPQ search
if(nError == ERROR_SUCCESS)
{
nSize = sizeof(TMPQSearch) + strlen(szMask) + 1;
if((hs = (TMPQSearch *)STORM_ALLOC(char, nSize)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Perform the first search
if(nError == ERROR_SUCCESS)
{
memset(hs, 0, sizeof(TMPQSearch));
strcpy(hs->szSearchMask, szMask);
hs->dwFlagMask = MPQ_FILE_EXISTS;
hs->ha = ha;
// If the archive is patched archive, we have to create a merge table
// to prevent files being repeated
if(ha->haPatch != NULL)
{
hs->dwSearchTableItems = GetSearchTableItems(ha);
hs->pSearchTable = STORM_ALLOC(TFileEntry *, hs->dwSearchTableItems);
hs->dwFlagMask = MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE;
if(hs->pSearchTable != NULL)
memset(hs->pSearchTable, 0, hs->dwSearchTableItems * sizeof(TFileEntry *));
else
nError = ERROR_NOT_ENOUGH_MEMORY;
}
}
// Perform first item searching
if(nError == ERROR_SUCCESS)
{
nError = DoMPQSearch(hs, lpFindFileData);
}
// Cleanup
if(nError != ERROR_SUCCESS)
{
FreeMPQSearch(hs);
SetLastError(nError);
}
// Return the result value
return (HANDLE)hs;
}
bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
{
TMPQSearch * hs = IsValidSearchHandle(hFind);
int nError = ERROR_SUCCESS;
// Check the parameters
if(hs == NULL)
nError = ERROR_INVALID_HANDLE;
if(lpFindFileData == NULL)
nError = ERROR_INVALID_PARAMETER;
if(nError == ERROR_SUCCESS)
nError = DoMPQSearch(hs, lpFindFileData);
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
bool WINAPI SFileFindClose(HANDLE hFind)
{
TMPQSearch * hs = IsValidSearchHandle(hFind);
// Check the parameters
if(hs == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
}
FreeMPQSearch(hs);
return true;
}

1010
3rdParty/StormLib/src/SFileGetFileInfo.cpp vendored

File diff suppressed because it is too large Load Diff

618
3rdParty/StormLib/src/SFileOpenArchive.cpp vendored

@ -0,0 +1,618 @@
/*****************************************************************************/
/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */
/* */
/* Author : Ladislav Zezula */
/* E-mail : ladik@zezula.net */
/* WWW : www.zezula.net */
/*---------------------------------------------------------------------------*/
/* Archive functions of Storm.dll */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */
/* 19.11.03 1.01 Dan Big endian handling */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "StormCommon.h"
#define HEADER_SEARCH_BUFFER_SIZE 0x1000
/*****************************************************************************/
/* Local functions */
/*****************************************************************************/
static bool IsAviFile(DWORD * HeaderData)
{
DWORD DwordValue0 = BSWAP_INT32_UNSIGNED(HeaderData[0]);
DWORD DwordValue2 = BSWAP_INT32_UNSIGNED(HeaderData[2]);
DWORD DwordValue3 = BSWAP_INT32_UNSIGNED(HeaderData[3]);
// Test for 'RIFF', 'AVI ' or 'LIST'
return (DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C);
}
static bool IsWarcraft3Map(DWORD * HeaderData)
{
DWORD DwordValue0 = BSWAP_INT32_UNSIGNED(HeaderData[0]);
DWORD DwordValue1 = BSWAP_INT32_UNSIGNED(HeaderData[1]);
return (DwordValue0 == 0x57334D48 && DwordValue1 == 0x00000000);
}
static TMPQUserData * IsValidMpqUserData(ULONGLONG ByteOffset, ULONGLONG FileSize, void * pvUserData)
{
TMPQUserData * pUserData;
// BSWAP the source data and copy them to our buffer
BSWAP_ARRAY32_UNSIGNED(&pvUserData, sizeof(TMPQUserData));
pUserData = (TMPQUserData *)pvUserData;
// Check the sizes
if(pUserData->cbUserDataHeader <= pUserData->cbUserDataSize && pUserData->cbUserDataSize <= pUserData->dwHeaderOffs)
{
// Move to the position given by the userdata
ByteOffset += pUserData->dwHeaderOffs;
// The MPQ header should be within range of the file size
if((ByteOffset + MPQ_HEADER_SIZE_V1) < FileSize)
{
// Note: We should verify if there is the MPQ header.
// However, the header could be at any position below that
// that is multiplier of 0x200
return (TMPQUserData *)pvUserData;
}
}
return NULL;
}
// This function gets the right positions of the hash table and the block table.
static int VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize)
{
TMPQHeader * pHeader = ha->pHeader;
ULONGLONG ByteOffset;
// Check the begin of HET table
if(pHeader->HetTablePos64)
{
ByteOffset = ha->MpqPos + pHeader->HetTablePos64;
if(ByteOffset > FileSize)
return ERROR_BAD_FORMAT;
}
// Check the begin of BET table
if(pHeader->BetTablePos64)
{
ByteOffset = ha->MpqPos + pHeader->BetTablePos64;
if(ByteOffset > FileSize)
return ERROR_BAD_FORMAT;
}
// Check the begin of hash table
if(pHeader->wHashTablePosHi || pHeader->dwHashTablePos)
{
ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos));
if(ByteOffset > FileSize)
return ERROR_BAD_FORMAT;
}
// Check the begin of block table
if(pHeader->wBlockTablePosHi || pHeader->dwBlockTablePos)
{
ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos));
if(ByteOffset > FileSize)
return ERROR_BAD_FORMAT;
}
// Check the begin of hi-block table
if(pHeader->HiBlockTablePos64 != 0)
{
ByteOffset = ha->MpqPos + pHeader->HiBlockTablePos64;
if(ByteOffset > FileSize)
return ERROR_BAD_FORMAT;
}
// All OK.
return ERROR_SUCCESS;
}
/*****************************************************************************/
/* Public functions */
/*****************************************************************************/
//-----------------------------------------------------------------------------
// SFileGetLocale and SFileSetLocale
// Set the locale for all newly opened files
LCID WINAPI SFileGetLocale()
{
return lcFileLocale;
}
LCID WINAPI SFileSetLocale(LCID lcNewLocale)
{
lcFileLocale = lcNewLocale;
return lcFileLocale;
}
//-----------------------------------------------------------------------------
// SFileOpenArchive
//
// szFileName - MPQ archive file name to open
// dwPriority - When SFileOpenFileEx called, this contains the search priority for searched archives
// dwFlags - See MPQ_OPEN_XXX in StormLib.h
// phMpq - Pointer to store open archive handle
bool WINAPI SFileOpenArchive(
const TCHAR * szMpqName,
DWORD dwPriority,
DWORD dwFlags,
HANDLE * phMpq)
{
TMPQUserData * pUserData;
TFileStream * pStream = NULL; // Open file stream
TMPQArchive * ha = NULL; // Archive handle
TFileEntry * pFileEntry;
ULONGLONG FileSize = 0; // Size of the file
LPBYTE pbHeaderBuffer = NULL; // Buffer for searching MPQ header
DWORD dwStreamFlags = (dwFlags & STREAM_FLAGS_MASK);
bool bIsWarcraft3Map = false;
int nError = ERROR_SUCCESS;
// Verify the parameters
if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// One time initialization of MPQ cryptography
InitializeMpqCryptography();
dwPriority = dwPriority;
// If not forcing MPQ v 1.0, also use file bitmap
dwStreamFlags |= (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) ? 0 : STREAM_FLAG_USE_BITMAP;
#ifndef FULL
char translatedName[260];
TranslateFileName(translatedName, sizeof(translatedName), szMpqName);
#endif
// Open the MPQ archive file
pStream = FileStream_OpenFile(translatedName, dwStreamFlags);
if(pStream == NULL)
return false;
// Check the file size. There must be at least 0x20 bytes
if(nError == ERROR_SUCCESS)
{
FileStream_GetSize(pStream, &FileSize);
if(FileSize < MPQ_HEADER_SIZE_V1)
nError = ERROR_BAD_FORMAT;
}
// Allocate the MPQhandle
if(nError == ERROR_SUCCESS)
{
if((ha = STORM_ALLOC(TMPQArchive, 1)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Allocate buffer for searching MPQ header
if(nError == ERROR_SUCCESS)
{
pbHeaderBuffer = STORM_ALLOC(BYTE, HEADER_SEARCH_BUFFER_SIZE);
if(pbHeaderBuffer == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Find the position of MPQ header
if(nError == ERROR_SUCCESS)
{
ULONGLONG SearchOffset = 0;
ULONGLONG EndOfSearch = FileSize;
DWORD dwStrmFlags = 0;
DWORD dwHeaderSize;
DWORD dwHeaderID;
bool bSearchComplete = false;
memset(ha, 0, sizeof(TMPQArchive));
ha->pfnHashString = HashStringSlash;
ha->pStream = pStream;
pStream = NULL;
// Set the archive read only if the stream is read-only
FileStream_GetFlags(ha->pStream, &dwStrmFlags);
ha->dwFlags |= (dwStrmFlags & STREAM_FLAG_READ_ONLY) ? MPQ_FLAG_READ_ONLY : 0;
// Also remember if we shall check sector CRCs when reading file
ha->dwFlags |= (dwFlags & MPQ_OPEN_CHECK_SECTOR_CRC) ? MPQ_FLAG_CHECK_SECTOR_CRC : 0;
// Also remember if this MPQ is a patch
ha->dwFlags |= (dwFlags & MPQ_OPEN_PATCH) ? MPQ_FLAG_PATCH : 0;
// Limit the header searching to about 130 MB of data
if(EndOfSearch > 0x08000000)
EndOfSearch = 0x08000000;
// Find the offset of MPQ header within the file
while(bSearchComplete == false && SearchOffset < EndOfSearch)
{
// Always read at least 0x1000 bytes for performance.
// This is what Storm.dll (2002) does.
DWORD dwBytesAvailable = HEADER_SEARCH_BUFFER_SIZE;
DWORD dwInBufferOffset = 0;
// Cut the bytes available, if needed
if((FileSize - SearchOffset) < HEADER_SEARCH_BUFFER_SIZE)
dwBytesAvailable = (DWORD)(FileSize - SearchOffset);
// Read the eventual MPQ header
if(!FileStream_Read(ha->pStream, &SearchOffset, pbHeaderBuffer, dwBytesAvailable))
{
nError = GetLastError();
break;
}
// There are AVI files from Warcraft III with 'MPQ' extension.
if(SearchOffset == 0)
{
if(IsAviFile((DWORD *)pbHeaderBuffer))
{
nError = ERROR_AVI_FILE;
break;
}
bIsWarcraft3Map = IsWarcraft3Map((DWORD *)pbHeaderBuffer);
}
// Search the header buffer
while(dwInBufferOffset < dwBytesAvailable)
{
// Copy the data from the potential header buffer to the MPQ header
memcpy(ha->HeaderData, pbHeaderBuffer + dwInBufferOffset, sizeof(ha->HeaderData));
// If there is the MPQ user data, process it
// Note that Warcraft III does not check for user data, which is abused by many map protectors
dwHeaderID = BSWAP_INT32_UNSIGNED(ha->HeaderData[0]);
if(bIsWarcraft3Map == false && (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0)
{
if(ha->pUserData == NULL && dwHeaderID == ID_MPQ_USERDATA)
{
// Verify if this looks like a valid user data
pUserData = IsValidMpqUserData(SearchOffset, FileSize, ha->HeaderData);
if(pUserData != NULL)
{
// Fill the user data header
ha->UserDataPos = SearchOffset;
ha->pUserData = &ha->UserData;
memcpy(ha->pUserData, pUserData, sizeof(TMPQUserData));
// Continue searching from that position
SearchOffset += ha->pUserData->dwHeaderOffs;
break;
}
}
}
// There must be MPQ header signature. Note that STORM.dll from Warcraft III actually
// tests the MPQ header size. It must be at least 0x20 bytes in order to load it
// Abused by Spazzler Map protector. Note that the size check is not present
// in Storm.dll v 1.00, so Diablo I code would load the MPQ anyway.
dwHeaderSize = BSWAP_INT32_UNSIGNED(ha->HeaderData[1]);
if(dwHeaderID == ID_MPQ && dwHeaderSize >= MPQ_HEADER_SIZE_V1)
{
// Now convert the header to version 4
nError = ConvertMpqHeaderToFormat4(ha, SearchOffset, FileSize, dwFlags, bIsWarcraft3Map);
bSearchComplete = true;
break;
}
// Check for MPK archives (Longwu Online - MPQ fork)
if(bIsWarcraft3Map == false && dwHeaderID == ID_MPK)
{
// Now convert the MPK header to MPQ Header version 4
nError = ConvertMpkHeaderToFormat4(ha, FileSize, dwFlags);
bSearchComplete = true;
break;
}
// If searching for the MPQ header is disabled, return an error
if(dwFlags & MPQ_OPEN_NO_HEADER_SEARCH)
{
nError = ERROR_NOT_SUPPORTED;
bSearchComplete = true;
break;
}
// Move the pointers
SearchOffset += 0x200;
dwInBufferOffset += 0x200;
}
}
// Did we identify one of the supported headers?
if(nError == ERROR_SUCCESS)
{
// Set the user data position to the MPQ header, if none
if(ha->pUserData == NULL)
ha->UserDataPos = SearchOffset;
// Set the position of the MPQ header
ha->pHeader = (TMPQHeader *)ha->HeaderData;
ha->MpqPos = SearchOffset;
ha->FileSize = FileSize;
// Sector size must be nonzero.
if(SearchOffset >= FileSize || ha->pHeader->wSectorSize == 0)
nError = ERROR_BAD_FORMAT;
}
}
// Fix table positions according to format
if(nError == ERROR_SUCCESS)
{
// Dump the header
// DumpMpqHeader(ha->pHeader);
// W3x Map Protectors use the fact that War3's Storm.dll ignores the MPQ user data,
// and ignores the MPQ format version as well. The trick is to
// fake MPQ format 2, with an improper hi-word position of hash table and block table
// We can overcome such protectors by forcing opening the archive as MPQ v 1.0
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
{
ha->pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
ha->pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
ha->pUserData = NULL;
}
// Anti-overflow. If the hash table size in the header is
// higher than 0x10000000, it would overflow in 32-bit version
// Observed in the malformed Warcraft III maps
// Example map: MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x
ha->pHeader->dwBlockTableSize = (ha->pHeader->dwBlockTableSize & BLOCK_INDEX_MASK);
ha->pHeader->dwHashTableSize = (ha->pHeader->dwHashTableSize & BLOCK_INDEX_MASK);
// Both MPQ_OPEN_NO_LISTFILE or MPQ_OPEN_NO_ATTRIBUTES trigger read only mode
if(dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES))
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
// Remember whether whis is a map for Warcraft III
if(bIsWarcraft3Map)
ha->dwFlags |= MPQ_FLAG_WAR3_MAP;
// Set the size of file sector
ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize);
// Verify if any of the tables doesn't start beyond the end of the file
nError = VerifyMpqTablePositions(ha, FileSize);
}
// Read the hash table. Ignore the result, as hash table is no longer required
// Read HET table. Ignore the result, as HET table is no longer required
if(nError == ERROR_SUCCESS)
{
nError = LoadAnyHashTable(ha);
}
// Now, build the file table. It will be built by combining
// the block table, BET table, hi-block table, (attributes) and (listfile).
if(nError == ERROR_SUCCESS)
{
nError = BuildFileTable(ha);
}
#ifdef FULL
// Load the internal listfile and include it to the file table
if(nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_LISTFILE) == 0)
{
// Quick check for (listfile)
pFileEntry = GetFileEntryLocale(ha, LISTFILE_NAME, LANG_NEUTRAL);
if(pFileEntry != NULL)
{
// Ignore result of the operation. (listfile) is optional.
SFileAddListFile((HANDLE)ha, NULL);
ha->dwFileFlags1 = pFileEntry->dwFlags;
}
}
// Load the "(attributes)" file and merge it to the file table
if(nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_ATTRIBUTES) == 0 && (ha->dwFlags & MPQ_FLAG_BLOCK_TABLE_CUT) == 0)
{
// Quick check for (attributes)
pFileEntry = GetFileEntryLocale(ha, ATTRIBUTES_NAME, LANG_NEUTRAL);
if(pFileEntry != NULL)
{
// Ignore result of the operation. (attributes) is optional.
SAttrLoadAttributes(ha);
ha->dwFileFlags2 = pFileEntry->dwFlags;
}
}
#endif
// Remember whether the archive has weak signature. Only for MPQs format 1.0.
if(nError == ERROR_SUCCESS)
{
// Quick check for (signature)
pFileEntry = GetFileEntryLocale(ha, SIGNATURE_NAME, LANG_NEUTRAL);
if(pFileEntry != NULL)
{
// Just remember that the archive is weak-signed
assert((pFileEntry->dwFlags & MPQ_FILE_EXISTS) != 0);
ha->dwFileFlags3 = pFileEntry->dwFlags;
}
// Finally, set the MPQ_FLAG_READ_ONLY if the MPQ was found malformed
ha->dwFlags |= (ha->dwFlags & MPQ_FLAG_MALFORMED) ? MPQ_FLAG_READ_ONLY : 0;
}
// Cleanup and exit
if(nError != ERROR_SUCCESS)
{
FileStream_Close(pStream);
FreeArchiveHandle(ha);
SetLastError(nError);
ha = NULL;
}
// Free the header buffer
if(pbHeaderBuffer != NULL)
STORM_FREE(pbHeaderBuffer);
if(phMpq != NULL)
*phMpq = ha;
return (nError == ERROR_SUCCESS);
}
#ifdef FULL
//-----------------------------------------------------------------------------
// bool WINAPI SFileSetDownloadCallback(HANDLE, SFILE_DOWNLOAD_CALLBACK, void *);
//
// Sets a callback that is called when content is downloaded from the master MPQ
//
bool WINAPI SFileSetDownloadCallback(HANDLE hMpq, SFILE_DOWNLOAD_CALLBACK DownloadCB, void * pvUserData)
{
TMPQArchive * ha = (TMPQArchive *)hMpq;
// Do nothing if 'hMpq' is bad parameter
if(!IsValidMpqHandle(hMpq))
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
}
return FileStream_SetCallback(ha->pStream, DownloadCB, pvUserData);
}
//-----------------------------------------------------------------------------
// bool SFileFlushArchive(HANDLE hMpq)
//
// Saves all dirty data into MPQ archive.
// Has similar effect like SFileCloseArchive, but the archive is not closed.
// Use on clients who keep MPQ archive open even for write operations,
// and terminating without calling SFileCloseArchive might corrupt the archive.
//
bool WINAPI SFileFlushArchive(HANDLE hMpq)
{
TMPQArchive * ha;
int nResultError = ERROR_SUCCESS;
int nError;
// Do nothing if 'hMpq' is bad parameter
if((ha = IsValidMpqHandle(hMpq)) == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
}
// Only if the MPQ was changed
if(ha->dwFlags & MPQ_FLAG_CHANGED)
{
// Indicate that we are saving MPQ internal structures
ha->dwFlags |= MPQ_FLAG_SAVING_TABLES;
// Defragment the file table. This will allow us to put the internal files to the end
DefragmentFileTable(ha);
//
// Create each internal file
// Note that the (signature) file is usually before (listfile) in the file table
//
if(ha->dwFlags & MPQ_FLAG_SIGNATURE_NEW)
{
#ifdef FULL
nError = SSignFileCreate(ha);
if(nError != ERROR_SUCCESS)
nResultError = nError;
#else
assert(0);
#endif
}
if(ha->dwFlags & MPQ_FLAG_LISTFILE_NEW)
{
nError = SListFileSaveToMpq(ha);
if(nError != ERROR_SUCCESS)
nResultError = nError;
}
if(ha->dwFlags & MPQ_FLAG_ATTRIBUTES_NEW)
{
nError = SAttrFileSaveToMpq(ha);
if(nError != ERROR_SUCCESS)
nResultError = nError;
}
// Save HET table, BET table, hash table, block table, hi-block table
if(ha->dwFlags & MPQ_FLAG_CHANGED)
{
// Rebuild the HET table
if(ha->pHetTable != NULL)
RebuildHetTable(ha);
// Save all MPQ tables first
nError = SaveMPQTables(ha);
if(nError != ERROR_SUCCESS)
nResultError = nError;
// If the archive has weak signature, we need to finish it
if(ha->dwFileFlags3 != 0)
{
#ifdef FULL
nError = SSignFileFinish(ha);
if(nError != ERROR_SUCCESS)
nResultError = nError;
#else
assert(0);
#endif
}
}
// We are no longer saving internal MPQ structures
ha->dwFlags &= ~MPQ_FLAG_SAVING_TABLES;
}
// Return the error
if(nResultError != ERROR_SUCCESS)
SetLastError(nResultError);
return (nResultError == ERROR_SUCCESS);
}
#endif
//-----------------------------------------------------------------------------
// bool SFileCloseArchive(HANDLE hMpq);
//
bool WINAPI SFileCloseArchive(HANDLE hMpq)
{
TMPQArchive * ha = IsValidMpqHandle(hMpq);
bool bResult = true;
// Only if the handle is valid
if(ha == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
}
// Invalidate the add file callback so it won't be called
// when saving (listfile) and (attributes)
ha->pfnAddFileCB = NULL;
ha->pvAddFileUserData = NULL;
#ifdef FULL
// Flush all unsaved data to the storage
bResult = SFileFlushArchive(hMpq);
#endif
// Free all memory used by MPQ archive
FreeArchiveHandle(ha);
return bResult;
}

398
3rdParty/StormLib/src/SFileOpenFileEx.cpp vendored

@ -0,0 +1,398 @@
/*****************************************************************************/
/* SFileOpenFileEx.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Description : */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* xx.xx.99 1.00 Lad The first version of SFileOpenFileEx.cpp */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "StormCommon.h"
/*****************************************************************************/
/* Local functions */
/*****************************************************************************/
static DWORD FindHashIndex(TMPQArchive * ha, DWORD dwFileIndex)
{
TMPQHash * pHashTableEnd;
TMPQHash * pHash;
DWORD dwFirstIndex = HASH_ENTRY_FREE;
// Should only be called if the archive has hash table
assert(ha->pHashTable != NULL);
// Multiple hash table entries can point to the file table entry.
// We need to search all of them
pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++)
{
if(MPQ_BLOCK_INDEX(pHash) == dwFileIndex)
{
// Duplicate hash entry found
if(dwFirstIndex != HASH_ENTRY_FREE)
return HASH_ENTRY_FREE;
dwFirstIndex = (DWORD)(pHash - ha->pHashTable);
}
}
// Return the hash table entry index
return dwFirstIndex;
}
static const char * GetPatchFileName(TMPQArchive * ha, const char * szFileName, char * szBuffer)
{
TMPQNamePrefix * pPrefix;
// Are there patches in the current MPQ?
if(ha->dwFlags & MPQ_FLAG_PATCH)
{
// The patch prefix must be already known here
assert(ha->pPatchPrefix != NULL);
pPrefix = ha->pPatchPrefix;
// The patch name for "OldWorld\\XXX\\YYY" is "Base\\XXX\YYY"
// We need to remove the "OldWorld\\" prefix
if(!_strnicmp(szFileName, "OldWorld\\", 9))
szFileName += 9;
// Create the file name from the known patch entry
memcpy(szBuffer, pPrefix->szPatchPrefix, pPrefix->nLength);
strcpy(szBuffer + pPrefix->nLength, szFileName);
szFileName = szBuffer;
}
return szFileName;
}
static bool OpenLocalFile(const char * szFileName, HANDLE * PtrFile)
{
TFileStream * pStream;
TMPQFile * hf = NULL;
TCHAR szFileNameT[MAX_PATH];
// Convert the file name to UNICODE (if needed)
StringCopy(szFileNameT, _countof(szFileNameT), szFileName);
// Open the file and create the TMPQFile structure
pStream = FileStream_OpenFile(szFileNameT, STREAM_FLAG_READ_ONLY);
if(pStream != NULL)
{
// Allocate and initialize file handle
hf = CreateFileHandle(NULL, NULL);
if(hf != NULL)
{
hf->pStream = pStream;
*PtrFile = hf;
return true;
}
else
{
FileStream_Close(pStream);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
}
*PtrFile = NULL;
return false;
}
bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, HANDLE * PtrFile)
{
TMPQArchive * haBase = NULL;
TMPQArchive * ha = (TMPQArchive *)hMpq;
TFileEntry * pFileEntry;
TMPQFile * hfPatch; // Pointer to patch file
TMPQFile * hfBase = NULL; // Pointer to base open file
TMPQFile * hf = NULL;
HANDLE hPatchFile;
char szNameBuffer[MAX_PATH];
// First of all, find the latest archive where the file is in base version
// (i.e. where the original, unpatched version of the file exists)
while(ha != NULL)
{
// If the file is there, then we remember the archive
pFileEntry = GetFileEntryExact(ha, GetPatchFileName(ha, szFileName, szNameBuffer), 0, NULL);
if(pFileEntry != NULL && (pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
haBase = ha;
// Move to the patch archive
ha = ha->haPatch;
}
// If we couldn't find the base file in any of the patches, it doesn't exist
if((ha = haBase) == NULL)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return false;
}
// Now open the base file
if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, (HANDLE *)&hfBase))
{
// The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE
assert((hfBase->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0);
hf = hfBase;
// Now open all patches and attach them on top of the base file
for(ha = ha->haPatch; ha != NULL; ha = ha->haPatch)
{
// Prepare the file name with a correct prefix
if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, &hPatchFile))
{
// Remember the new version
hfPatch = (TMPQFile *)hPatchFile;
// We should not find patch file
assert((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) != 0);
// Attach the patch to the base file
hf->hfPatch = hfPatch;
hf = hfPatch;
}
}
}
// Give the updated base MPQ
if(PtrFile != NULL)
*PtrFile = (HANDLE)hfBase;
return (hfBase != NULL);
}
/*****************************************************************************/
/* Public functions */
/*****************************************************************************/
//-----------------------------------------------------------------------------
// SFileEnumLocales enums all locale versions within MPQ.
// Functions fills all available language identifiers on a file into the buffer
// pointed by plcLocales. There must be enough entries to copy the localed,
// otherwise the function returns ERROR_INSUFFICIENT_BUFFER.
int WINAPI SFileEnumLocales(
HANDLE hMpq,
const char * szFileName,
LCID * PtrLocales,
LPDWORD PtrMaxLocales,
DWORD dwSearchScope)
{
TMPQArchive * ha = (TMPQArchive *)hMpq;
TMPQHash * pFirstHash;
TMPQHash * pHash;
DWORD dwFileIndex = 0;
DWORD dwMaxLocales;
DWORD dwLocales = 0;
// Test the parameters
if(!IsValidMpqHandle(hMpq))
return ERROR_INVALID_HANDLE;
if(szFileName == NULL || *szFileName == 0)
return ERROR_INVALID_PARAMETER;
if(ha->pHashTable == NULL)
return ERROR_NOT_SUPPORTED;
if(PtrMaxLocales == NULL)
return ERROR_INVALID_PARAMETER;
if(IsPseudoFileName(szFileName, &dwFileIndex))
return ERROR_INVALID_PARAMETER;
// Keep compiler happy
dwMaxLocales = PtrMaxLocales[0];
dwSearchScope = dwSearchScope;
// Parse all files with that name
pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
while(pHash != NULL)
{
// Put the locales to the buffer
if(PtrLocales != NULL && dwLocales < dwMaxLocales)
*PtrLocales++ = pHash->lcLocale;
dwLocales++;
// Get the next locale
pHash = GetNextHashEntry(ha, pFirstHash, pHash);
}
// Give the caller the number of locales and return
PtrMaxLocales[0] = dwLocales;
return (dwLocales <= dwMaxLocales) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
}
//-----------------------------------------------------------------------------
// SFileOpenFileEx
//
// hMpq - Handle of opened MPQ archive
// szFileName - Name of file to open
// dwSearchScope - Where to search
// PtrFile - Pointer to store opened file handle
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * PtrFile)
{
TMPQArchive * ha = IsValidMpqHandle(hMpq);
TFileEntry * pFileEntry = NULL;
TMPQFile * hf = NULL;
DWORD dwHashIndex = HASH_ENTRY_FREE;
DWORD dwFileIndex = 0;
bool bOpenByIndex = false;
int nError = ERROR_SUCCESS;
// Don't accept NULL pointer to file handle
if(szFileName == NULL || *szFileName == 0)
nError = ERROR_INVALID_PARAMETER;
// When opening a file from MPQ, the handle must be valid
if(dwSearchScope != SFILE_OPEN_LOCAL_FILE && ha == NULL)
nError = ERROR_INVALID_HANDLE;
// When not checking for existence, the pointer to file handle must be valid
if(dwSearchScope != SFILE_OPEN_CHECK_EXISTS && PtrFile == NULL)
nError = ERROR_INVALID_PARAMETER;
// Prepare the file opening
if(nError == ERROR_SUCCESS)
{
switch(dwSearchScope)
{
case SFILE_OPEN_FROM_MPQ:
case SFILE_OPEN_BASE_FILE:
case SFILE_OPEN_CHECK_EXISTS:
// If this MPQ has no patches, open the file from this MPQ directly
if(ha->haPatch == NULL || dwSearchScope == SFILE_OPEN_BASE_FILE)
{
pFileEntry = GetFileEntryLocale2(ha, szFileName, lcFileLocale, &dwHashIndex);
}
// If this MPQ is a patched archive, open the file as patched
else
{
return OpenPatchedFile(hMpq, szFileName, PtrFile);
}
break;
case SFILE_OPEN_ANY_LOCALE:
// This open option is reserved for opening MPQ internal listfile.
// No argument validation. Tries to open file with neutral locale first,
// then any other available.
pFileEntry = GetFileEntryLocale2(ha, szFileName, 0, &dwHashIndex);
break;
case SFILE_OPEN_LOCAL_FILE:
// Open a local file
return OpenLocalFile(szFileName, PtrFile);
default:
// Don't accept any other value
nError = ERROR_INVALID_PARAMETER;
break;
}
}
// Check whether the file really exists in the MPQ
if(nError == ERROR_SUCCESS)
{
if(pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
{
// Check the pseudo-file name
if((bOpenByIndex = IsPseudoFileName(szFileName, &dwFileIndex)) == true)
{
// Get the file entry for the file
if(dwFileIndex < ha->dwFileTableSize)
{
pFileEntry = ha->pFileTable + dwFileIndex;
}
}
nError = ERROR_FILE_NOT_FOUND;
}
// Ignore unknown loading flags (example: MPQ_2016_v1_WME4_4.w3x)
// if(pFileEntry != NULL && pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
// nError = ERROR_NOT_SUPPORTED;
}
// Did the caller just wanted to know if the file exists?
if(nError == ERROR_SUCCESS && dwSearchScope != SFILE_OPEN_CHECK_EXISTS)
{
// Allocate file handle
hf = CreateFileHandle(ha, pFileEntry);
if(hf != NULL)
{
// Get the hash index for the file
if(ha->pHashTable != NULL && dwHashIndex == HASH_ENTRY_FREE)
dwHashIndex = FindHashIndex(ha, dwFileIndex);
if(dwHashIndex != HASH_ENTRY_FREE)
hf->pHashEntry = ha->pHashTable + dwHashIndex;
hf->dwHashIndex = dwHashIndex;
// If the MPQ has sector CRC enabled, enable if for the file
if(ha->dwFlags & MPQ_FLAG_CHECK_SECTOR_CRC)
hf->bCheckSectorCRCs = true;
// If we know the real file name, copy it to the file entry
if(bOpenByIndex == false)
{
// If there is no file name yet, allocate it
AllocateFileName(ha, pFileEntry, szFileName);
// If the file is encrypted, we should detect the file key
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
{
hf->dwFileKey = DecryptFileKey(szFileName,
pFileEntry->ByteOffset,
pFileEntry->dwFileSize,
pFileEntry->dwFlags);
}
}
}
else
{
nError = ERROR_NOT_ENOUGH_MEMORY;
}
}
// Give the file entry
if(PtrFile != NULL)
PtrFile[0] = hf;
// Return error code
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
//-----------------------------------------------------------------------------
// SFileHasFile
//
// hMpq - Handle of opened MPQ archive
// szFileName - Name of file to look for
bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
{
return SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_CHECK_EXISTS, NULL);
}
//-----------------------------------------------------------------------------
// bool WINAPI SFileCloseFile(HANDLE hFile);
bool WINAPI SFileCloseFile(HANDLE hFile)
{
TMPQFile * hf = (TMPQFile *)hFile;
if(!IsValidFileHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
}
// Free the structure
FreeFileHandle(hf);
return true;
}

907
3rdParty/StormLib/src/SFileReadFile.cpp vendored

@ -0,0 +1,907 @@
/*****************************************************************************/
/* SFileReadFile.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Description : */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* xx.xx.99 1.00 Lad The first version of SFileReadFile.cpp */
/* 24.03.99 1.00 Lad Added the SFileGetFileInfo function */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "StormCommon.h"
//-----------------------------------------------------------------------------
// Local functions
// hf - MPQ File handle.
// pbBuffer - Pointer to target buffer to store sectors.
// dwByteOffset - Position of sector in the file (relative to file begin)
// dwBytesToRead - Number of bytes to read. Must be multiplier of sector size.
// pdwBytesRead - Stored number of bytes loaded
static int ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, DWORD dwBytesToRead, LPDWORD pdwBytesRead)
{
ULONGLONG RawFilePos;
TMPQArchive * ha = hf->ha;
TFileEntry * pFileEntry = hf->pFileEntry;
LPBYTE pbRawSector = NULL;
LPBYTE pbOutSector = pbBuffer;
LPBYTE pbInSector = pbBuffer;
DWORD dwRawBytesToRead;
DWORD dwRawSectorOffset = dwByteOffset;
DWORD dwSectorsToRead = dwBytesToRead / ha->dwSectorSize;
DWORD dwSectorIndex = dwByteOffset / ha->dwSectorSize;
DWORD dwSectorsDone = 0;
DWORD dwBytesRead = 0;
int nError = ERROR_SUCCESS;
// Note that dwByteOffset must be aligned to size of one sector
// Note that dwBytesToRead must be a multiplier of one sector size
// This is local function, so we won't check if that's true.
// Note that files stored in single units are processed by a separate function
// If there is not enough bytes remaining, cut dwBytesToRead
if((dwByteOffset + dwBytesToRead) > hf->dwDataSize)
dwBytesToRead = hf->dwDataSize - dwByteOffset;
dwRawBytesToRead = dwBytesToRead;
// Perform all necessary work to do with compressed files
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
{
// If the sector positions are not loaded yet, do it
if(hf->SectorOffsets == NULL)
{
nError = AllocateSectorOffsets(hf, true);
if(nError != ERROR_SUCCESS || hf->SectorOffsets == NULL)
return nError;
}
// If the sector checksums are not loaded yet, load them now.
if(hf->SectorChksums == NULL && (pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->bLoadedSectorCRCs == false)
{
//
// Sector CRCs is plain crap feature. It is almost never present,
// often it's empty, or the end offset of sector CRCs is zero.
// We only try to load sector CRCs once, and regardless if it fails
// or not, we won't try that again for the given file.
//
AllocateSectorChecksums(hf, true);
hf->bLoadedSectorCRCs = true;
}
// TODO: If the raw data MD5s are not loaded yet, load them now
// Only do it if the MPQ is of format 4.0
// if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_4 && ha->pHeader->dwRawChunkSize != 0)
// {
// nError = AllocateRawMD5s(hf, true);
// if(nError != ERROR_SUCCESS)
// return nError;
// }
// Assign the temporary buffer as target for read operation
dwRawSectorOffset = hf->SectorOffsets[dwSectorIndex];
dwRawBytesToRead = hf->SectorOffsets[dwSectorIndex + dwSectorsToRead] - dwRawSectorOffset;
// If the file is compressed, also allocate secondary buffer
pbInSector = pbRawSector = STORM_ALLOC(BYTE, dwRawBytesToRead);
if(pbRawSector == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
}
// Calculate raw file offset where the sector(s) are stored.
RawFilePos = CalculateRawSectorOffset(hf, dwRawSectorOffset);
// Set file pointer and read all required sectors
if(FileStream_Read(ha->pStream, &RawFilePos, pbInSector, dwRawBytesToRead))
{
// Now we have to decrypt and decompress all file sectors that have been loaded
for(DWORD i = 0; i < dwSectorsToRead; i++)
{
DWORD dwRawBytesInThisSector = ha->dwSectorSize;
DWORD dwBytesInThisSector = ha->dwSectorSize;
DWORD dwIndex = dwSectorIndex + i;
// If there is not enough bytes in the last sector,
// cut the number of bytes in this sector
if(dwRawBytesInThisSector > dwBytesToRead)
dwRawBytesInThisSector = dwBytesToRead;
if(dwBytesInThisSector > dwBytesToRead)
dwBytesInThisSector = dwBytesToRead;
// If the file is compressed, we have to adjust the raw sector size
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
dwRawBytesInThisSector = hf->SectorOffsets[dwIndex + 1] - hf->SectorOffsets[dwIndex];
// If the file is encrypted, we have to decrypt the sector
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
{
BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
// If we don't know the key, try to detect it by file content
if(hf->dwFileKey == 0)
{
hf->dwFileKey = DetectFileKeyByContent(pbInSector, dwBytesInThisSector, hf->dwDataSize);
if(hf->dwFileKey == 0)
{
nError = ERROR_UNKNOWN_FILE_KEY;
break;
}
}
DecryptMpqBlock(pbInSector, dwRawBytesInThisSector, hf->dwFileKey + dwIndex);
BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
}
#ifdef FULL
// If the file has sector CRC check turned on, perform it
if(hf->bCheckSectorCRCs && hf->SectorChksums != NULL)
{
DWORD dwAdlerExpected = hf->SectorChksums[dwIndex];
DWORD dwAdlerValue = 0;
// We can only check sector CRC when it's not zero
// Neither can we check it if it's 0xFFFFFFFF.
if(dwAdlerExpected != 0 && dwAdlerExpected != 0xFFFFFFFF)
{
dwAdlerValue = adler32(0, pbInSector, dwRawBytesInThisSector);
if(dwAdlerValue != dwAdlerExpected)
{
nError = ERROR_CHECKSUM_ERROR;
break;
}
}
}
#endif
// If the sector is really compressed, decompress it.
// WARNING : Some sectors may not be compressed, it can be determined only
// by comparing uncompressed and compressed size !!!
if(dwRawBytesInThisSector < dwBytesInThisSector)
{
int cbOutSector = dwBytesInThisSector;
int cbInSector = dwRawBytesInThisSector;
int nResult = 0;
// Is the file compressed by Blizzard's multiple compression ?
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
{
// Remember the last used compression
hf->dwCompression0 = pbInSector[0];
// Decompress the data
if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
nResult = SCompDecompress2(pbOutSector, &cbOutSector, pbInSector, cbInSector);
else
nResult = SCompDecompress(pbOutSector, &cbOutSector, pbInSector, cbInSector);
}
// Is the file compressed by PKWARE Data Compression Library ?
else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
{
nResult = SCompExplode(pbOutSector, &cbOutSector, pbInSector, cbInSector);
}
// Did the decompression fail ?
if(nResult == 0)
{
nError = ERROR_FILE_CORRUPT;
break;
}
}
else
{
if(pbOutSector != pbInSector)
memcpy(pbOutSector, pbInSector, dwBytesInThisSector);
}
// Move pointers
dwBytesToRead -= dwBytesInThisSector;
dwByteOffset += dwBytesInThisSector;
dwBytesRead += dwBytesInThisSector;
pbOutSector += dwBytesInThisSector;
pbInSector += dwRawBytesInThisSector;
dwSectorsDone++;
}
}
else
{
nError = GetLastError();
}
// Free all used buffers
if(pbRawSector != NULL)
STORM_FREE(pbRawSector);
// Give the caller thenumber of bytes read
*pdwBytesRead = dwBytesRead;
return nError;
}
static int ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
{
ULONGLONG RawFilePos = hf->RawFilePos;
TMPQArchive * ha = hf->ha;
TFileEntry * pFileEntry = hf->pFileEntry;
LPBYTE pbCompressed = NULL;
LPBYTE pbRawData;
int nError = ERROR_SUCCESS;
// If the file buffer is not allocated yet, do it.
if(hf->pbFileSector == NULL)
{
nError = AllocateSectorBuffer(hf);
if(nError != ERROR_SUCCESS || hf->pbFileSector == NULL)
return nError;
}
// If the file is a patch file, adjust raw data offset
if(hf->pPatchInfo != NULL)
RawFilePos += hf->pPatchInfo->dwLength;
pbRawData = hf->pbFileSector;
// If the file sector is not loaded yet, do it
if(hf->dwSectorOffs != 0)
{
// Is the file compressed?
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
{
// Allocate space for compressed data
pbCompressed = STORM_ALLOC(BYTE, pFileEntry->dwCmpSize);
if(pbCompressed == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
pbRawData = pbCompressed;
}
// Load the raw (compressed, encrypted) data
if(!FileStream_Read(ha->pStream, &RawFilePos, pbRawData, pFileEntry->dwCmpSize))
{
STORM_FREE(pbCompressed);
return GetLastError();
}
// If the file is encrypted, we have to decrypt the data first
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
{
BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize);
DecryptMpqBlock(pbRawData, pFileEntry->dwCmpSize, hf->dwFileKey);
BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize);
}
// If the file is compressed, we have to decompress it now
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
{
int cbOutBuffer = (int)hf->dwDataSize;
int cbInBuffer = (int)pFileEntry->dwCmpSize;
int nResult = 0;
//
// If the file is an incremental patch, the size of compressed data
// is determined as pFileEntry->dwCmpSize - sizeof(TPatchInfo)
//
// In "wow-update-12694.MPQ" from Wow-Cataclysm BETA:
//
// File CmprSize DcmpSize DataSize Compressed?
// -------------------------------------- ---------- -------- -------- ---------------
// esES\DBFilesClient\LightSkyBox.dbc 0xBE->0xA2 0xBC 0xBC Yes
// deDE\DBFilesClient\MountCapability.dbc 0x93->0x77 0x77 0x77 No
//
if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
cbInBuffer = cbInBuffer - sizeof(TPatchInfo);
// Is the file compressed by Blizzard's multiple compression ?
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
{
// Remember the last used compression
hf->dwCompression0 = pbRawData[0];
// Decompress the file
if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
nResult = SCompDecompress2(hf->pbFileSector, &cbOutBuffer, pbRawData, cbInBuffer);
else
nResult = SCompDecompress(hf->pbFileSector, &cbOutBuffer, pbRawData, cbInBuffer);
}
// Is the file compressed by PKWARE Data Compression Library ?
// Note: Single unit files compressed with IMPLODE are not supported by Blizzard
else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
nResult = SCompExplode(hf->pbFileSector, &cbOutBuffer, pbRawData, cbInBuffer);
nError = (nResult != 0) ? ERROR_SUCCESS : ERROR_FILE_CORRUPT;
}
else
{
if(hf->pbFileSector != NULL && pbRawData != hf->pbFileSector)
memcpy(hf->pbFileSector, pbRawData, hf->dwDataSize);
}
// Free the decompression buffer.
if(pbCompressed != NULL)
STORM_FREE(pbCompressed);
// The file sector is now properly loaded
hf->dwSectorOffs = 0;
}
// At this moment, we have the file loaded into the file buffer.
// Copy as much as the caller wants
if(nError == ERROR_SUCCESS && hf->dwSectorOffs == 0)
{
// File position is greater or equal to file size ?
if(dwFilePos >= hf->dwDataSize)
{
*pdwBytesRead = 0;
return ERROR_SUCCESS;
}
// If not enough bytes remaining in the file, cut them
if((hf->dwDataSize - dwFilePos) < dwToRead)
dwToRead = (hf->dwDataSize - dwFilePos);
// Copy the bytes
memcpy(pvBuffer, hf->pbFileSector + dwFilePos, dwToRead);
// Give the number of bytes read
*pdwBytesRead = dwToRead;
return ERROR_SUCCESS;
}
// An error, sorry
return ERROR_CAN_NOT_COMPLETE;
}
static int ReadMpkFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
{
ULONGLONG RawFilePos = hf->RawFilePos + 0x0C; // For some reason, MPK files start at position (hf->RawFilePos + 0x0C)
TMPQArchive * ha = hf->ha;
TFileEntry * pFileEntry = hf->pFileEntry;
LPBYTE pbCompressed = NULL;
LPBYTE pbRawData = hf->pbFileSector;
int nError = ERROR_SUCCESS;
// We do not support patch files in MPK archives
assert(hf->pPatchInfo == NULL);
// If the file buffer is not allocated yet, do it.
if(hf->pbFileSector == NULL)
{
nError = AllocateSectorBuffer(hf);
if(nError != ERROR_SUCCESS || hf->pbFileSector == NULL)
return nError;
pbRawData = hf->pbFileSector;
}
// If the file sector is not loaded yet, do it
if(hf->dwSectorOffs != 0)
{
// Is the file compressed?
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
{
// Allocate space for compressed data
pbCompressed = STORM_ALLOC(BYTE, pFileEntry->dwCmpSize);
if(pbCompressed == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
pbRawData = pbCompressed;
}
// Load the raw (compressed, encrypted) data
if(!FileStream_Read(ha->pStream, &RawFilePos, pbRawData, pFileEntry->dwCmpSize))
{
STORM_FREE(pbCompressed);
return GetLastError();
}
// If the file is encrypted, we have to decrypt the data first
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
{
DecryptMpkTable(pbRawData, pFileEntry->dwCmpSize);
}
// If the file is compressed, we have to decompress it now
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
{
#ifdef FULL
int cbOutBuffer = (int)hf->dwDataSize;
hf->dwCompression0 = pbRawData[0];
if(!SCompDecompressMpk(hf->pbFileSector, &cbOutBuffer, pbRawData, (int)pFileEntry->dwCmpSize))
nError = ERROR_FILE_CORRUPT;
#else
assert(0);
#endif
}
else
{
if(pbRawData != hf->pbFileSector)
memcpy(hf->pbFileSector, pbRawData, hf->dwDataSize);
}
// Free the decompression buffer.
if(pbCompressed != NULL)
STORM_FREE(pbCompressed);
// The file sector is now properly loaded
hf->dwSectorOffs = 0;
}
// At this moment, we have the file loaded into the file buffer.
// Copy as much as the caller wants
if(nError == ERROR_SUCCESS && hf->dwSectorOffs == 0)
{
// File position is greater or equal to file size ?
if(dwFilePos >= hf->dwDataSize)
{
*pdwBytesRead = 0;
return ERROR_SUCCESS;
}
// If not enough bytes remaining in the file, cut them
if((hf->dwDataSize - dwFilePos) < dwToRead)
dwToRead = (hf->dwDataSize - dwFilePos);
// Copy the bytes
memcpy(pvBuffer, hf->pbFileSector + dwFilePos, dwToRead);
// Give the number of bytes read
*pdwBytesRead = dwToRead;
return ERROR_SUCCESS;
}
// An error, sorry
return ERROR_CAN_NOT_COMPLETE;
}
static int ReadMpqFileSectorFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwBytesToRead, LPDWORD pdwBytesRead)
{
TMPQArchive * ha = hf->ha;
LPBYTE pbBuffer = (BYTE *)pvBuffer;
DWORD dwTotalBytesRead = 0; // Total bytes read in all three parts
DWORD dwSectorSizeMask = ha->dwSectorSize - 1; // Mask for block size, usually 0x0FFF
DWORD dwFileSectorPos; // File offset of the loaded sector
DWORD dwBytesRead; // Number of bytes read (temporary variable)
int nError;
// If the file position is at or beyond end of file, do nothing
if(dwFilePos >= hf->dwDataSize)
{
*pdwBytesRead = 0;
return ERROR_SUCCESS;
}
// If not enough bytes in the file remaining, cut them
if(dwBytesToRead > (hf->dwDataSize - dwFilePos))
dwBytesToRead = (hf->dwDataSize - dwFilePos);
// Compute sector position in the file
dwFileSectorPos = dwFilePos & ~dwSectorSizeMask; // Position in the block
// If the file sector buffer is not allocated yet, do it now
if(hf->pbFileSector == NULL)
{
nError = AllocateSectorBuffer(hf);
if(nError != ERROR_SUCCESS || hf->pbFileSector == NULL)
return nError;
}
// Load the first (incomplete) file sector
if(dwFilePos & dwSectorSizeMask)
{
DWORD dwBytesInSector = ha->dwSectorSize;
DWORD dwBufferOffs = dwFilePos & dwSectorSizeMask;
DWORD dwToCopy;
// Is the file sector already loaded ?
if(hf->dwSectorOffs != dwFileSectorPos)
{
// Load one MPQ sector into archive buffer
nError = ReadMpqSectors(hf, hf->pbFileSector, dwFileSectorPos, ha->dwSectorSize, &dwBytesInSector);
if(nError != ERROR_SUCCESS)
return nError;
// Remember that the data loaded to the sector have new file offset
hf->dwSectorOffs = dwFileSectorPos;
}
else
{
if((dwFileSectorPos + dwBytesInSector) > hf->dwDataSize)
dwBytesInSector = hf->dwDataSize - dwFileSectorPos;
}
// Copy the data from the offset in the loaded sector to the end of the sector
dwToCopy = dwBytesInSector - dwBufferOffs;
if(dwToCopy > dwBytesToRead)
dwToCopy = dwBytesToRead;
// Copy data from sector buffer into target buffer
memcpy(pbBuffer, hf->pbFileSector + dwBufferOffs, dwToCopy);
// Update pointers and byte counts
dwTotalBytesRead += dwToCopy;
dwFileSectorPos += dwBytesInSector;
pbBuffer += dwToCopy;
dwBytesToRead -= dwToCopy;
}
// Load the whole ("middle") sectors only if there is at least one full sector to be read
if(dwBytesToRead >= ha->dwSectorSize)
{
DWORD dwBlockBytes = dwBytesToRead & ~dwSectorSizeMask;
// Load all sectors to the output buffer
nError = ReadMpqSectors(hf, pbBuffer, dwFileSectorPos, dwBlockBytes, &dwBytesRead);
if(nError != ERROR_SUCCESS)
return nError;
// Update pointers
dwTotalBytesRead += dwBytesRead;
dwFileSectorPos += dwBytesRead;
pbBuffer += dwBytesRead;
dwBytesToRead -= dwBytesRead;
}
// Read the terminating sector
if(dwBytesToRead > 0)
{
DWORD dwToCopy = ha->dwSectorSize;
// Is the file sector already loaded ?
if(hf->dwSectorOffs != dwFileSectorPos)
{
// Load one MPQ sector into archive buffer
nError = ReadMpqSectors(hf, hf->pbFileSector, dwFileSectorPos, ha->dwSectorSize, &dwBytesRead);
if(nError != ERROR_SUCCESS)
return nError;
// Remember that the data loaded to the sector have new file offset
hf->dwSectorOffs = dwFileSectorPos;
}
// Check number of bytes read
if(dwToCopy > dwBytesToRead)
dwToCopy = dwBytesToRead;
// Copy the data from the cached last sector to the caller's buffer
memcpy(pbBuffer, hf->pbFileSector, dwToCopy);
// Update pointers
dwTotalBytesRead += dwToCopy;
}
// Store total number of bytes read to the caller
*pdwBytesRead = dwTotalBytesRead;
return ERROR_SUCCESS;
}
#ifdef FULL
static int ReadMpqFilePatchFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
{
TMPQPatcher Patcher;
DWORD dwBytesToRead = dwToRead;
DWORD dwBytesRead = 0;
int nError = ERROR_SUCCESS;
// Make sure that the patch file is loaded completely
if(nError == ERROR_SUCCESS && hf->pbFileData == NULL)
{
// Initialize patching process and allocate data
nError = Patch_InitPatcher(&Patcher, hf);
if(nError != ERROR_SUCCESS)
return nError;
// Set the current data size
Patcher.cbFileData = hf->pFileEntry->dwFileSize;
// Initialize the patcher object with initial file data
if(hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
nError = ReadMpqFileSingleUnit(hf, Patcher.pbFileData1, 0, Patcher.cbFileData, &dwBytesRead);
else
nError = ReadMpqFileSectorFile(hf, Patcher.pbFileData1, 0, Patcher.cbFileData, &dwBytesRead);
// Perform the patching process
if(nError == ERROR_SUCCESS)
nError = Patch_Process(&Patcher, hf);
// Finalize the patcher structure
Patch_Finalize(&Patcher);
dwBytesRead = 0;
}
// If there is something to read, do it
if(nError == ERROR_SUCCESS)
{
if(dwFilePos < hf->cbFileData)
{
// Make sure we don't copy more than file size
if((dwFilePos + dwToRead) > hf->cbFileData)
dwToRead = hf->cbFileData - dwFilePos;
// Copy the appropriate amount of the file data to the caller's buffer
memcpy(pvBuffer, hf->pbFileData + dwFilePos, dwToRead);
dwBytesRead = dwToRead;
}
// Set the proper error code
nError = (dwBytesRead == dwBytesToRead) ? ERROR_SUCCESS : ERROR_HANDLE_EOF;
}
// Give the result to the caller
if(pdwBytesRead != NULL)
*pdwBytesRead = dwBytesRead;
return nError;
}
#endif
static int ReadMpqFileLocalFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
{
ULONGLONG FilePosition1 = dwFilePos;
ULONGLONG FilePosition2;
DWORD dwBytesRead = 0;
int nError = ERROR_SUCCESS;
assert(hf->pStream != NULL);
// Because stream I/O functions are designed to read
// "all or nothing", we compare file position before and after,
// and if they differ, we assume that number of bytes read
// is the difference between them
if(!FileStream_Read(hf->pStream, &FilePosition1, pvBuffer, dwToRead))
{
// If not all bytes have been read, then return the number of bytes read
if((nError = GetLastError()) == ERROR_HANDLE_EOF)
{
FileStream_GetPos(hf->pStream, &FilePosition2);
dwBytesRead = (DWORD)(FilePosition2 - FilePosition1);
}
}
else
{
dwBytesRead = dwToRead;
}
*pdwBytesRead = dwBytesRead;
return nError;
}
//-----------------------------------------------------------------------------
// SFileReadFile
bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD pdwRead, LPOVERLAPPED lpOverlapped)
{
TMPQFile * hf = (TMPQFile *)hFile;
DWORD dwBytesRead = 0; // Number of bytes read
int nError = ERROR_SUCCESS;
// Always zero the result
if(pdwRead != NULL)
*pdwRead = 0;
lpOverlapped = lpOverlapped;
// Check valid parameters
if(!IsValidFileHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
}
if(pvBuffer == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// If we didn't load the patch info yet, do it now
if(hf->pFileEntry != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) && hf->pPatchInfo == NULL)
{
nError = AllocatePatchInfo(hf, true);
if(nError != ERROR_SUCCESS || hf->pPatchInfo == NULL)
{
SetLastError(nError);
return false;
}
}
// Clear the last used compression
hf->dwCompression0 = 0;
// If the file is local file, read the data directly from the stream
if(hf->pStream != NULL)
{
nError = ReadMpqFileLocalFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
#ifdef FULL
// If the file is a patch file, we have to read it special way
else if(hf->hfPatch != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
{
nError = ReadMpqFilePatchFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
#endif
// If the archive is a MPK archive, we need special way to read the file
else if(hf->ha->dwSubType == MPQ_SUBTYPE_MPK)
{
nError = ReadMpkFileSingleUnit(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
// If the file is single unit file, redirect it to read file
else if(hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
{
nError = ReadMpqFileSingleUnit(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
// Otherwise read it as sector based MPQ file
else
{
nError = ReadMpqFileSectorFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
// Increment the file position
hf->dwFilePos += dwBytesRead;
// Give the caller the number of bytes read
if(pdwRead != NULL)
*pdwRead = dwBytesRead;
// If the read operation succeeded, but not full number of bytes was read,
// set the last error to ERROR_HANDLE_EOF
if(nError == ERROR_SUCCESS && (dwBytesRead < dwToRead))
nError = ERROR_HANDLE_EOF;
// If something failed, set the last error value
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
//-----------------------------------------------------------------------------
// SFileGetFileSize
DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh)
{
ULONGLONG FileSize;
TMPQFile * hf = (TMPQFile *)hFile;
// Validate the file handle before we go on
if(IsValidFileHandle(hFile))
{
// Make sure that the variable is initialized
FileSize = 0;
// If the file is patched file, we have to get the size of the last version
if(hf->hfPatch != NULL)
{
// Walk through the entire patch chain, take the last version
while(hf != NULL)
{
// Get the size of the currently pointed version
FileSize = hf->pFileEntry->dwFileSize;
// Move to the next patch file in the hierarchy
hf = hf->hfPatch;
}
}
else
{
// Is it a local file ?
if(hf->pStream != NULL)
{
FileStream_GetSize(hf->pStream, &FileSize);
}
else
{
FileSize = hf->dwDataSize;
}
}
// If opened from archive, return file size
if(pdwFileSizeHigh != NULL)
*pdwFileSizeHigh = (DWORD)(FileSize >> 32);
return (DWORD)FileSize;
}
SetLastError(ERROR_INVALID_HANDLE);
return SFILE_INVALID_SIZE;
}
DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHigh, DWORD dwMoveMethod)
{
TMPQFile * hf = (TMPQFile *)hFile;
ULONGLONG OldPosition;
ULONGLONG NewPosition;
ULONGLONG FileSize;
ULONGLONG DeltaPos;
// If the hFile is not a valid file handle, return an error.
if(!IsValidFileHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return SFILE_INVALID_POS;
}
// Retrieve the file size for handling the limits
if(hf->pStream != NULL)
{
FileStream_GetSize(hf->pStream, &FileSize);
}
else
{
FileSize = SFileGetFileSize(hFile, NULL);
}
// Handle the NULL and non-NULL values of plFilePosHigh
// Non-NULL: The DeltaPos is combined from lFilePos and *lpFilePosHigh
// NULL: The DeltaPos is sign-extended value of lFilePos
DeltaPos = (plFilePosHigh != NULL) ? MAKE_OFFSET64(plFilePosHigh[0], lFilePos) : (ULONGLONG)(LONGLONG)lFilePos;
// Get the relative point where to move from
switch(dwMoveMethod)
{
case FILE_BEGIN:
// Move relative to the file begin.
OldPosition = 0;
break;
case FILE_CURRENT:
// Retrieve the current file position
if(hf->pStream != NULL)
{
FileStream_GetPos(hf->pStream, &OldPosition);
}
else
{
OldPosition = hf->dwFilePos;
}
break;
case FILE_END:
// Move relative to the end of the file
OldPosition = FileSize;
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return SFILE_INVALID_POS;
}
// Calculate the new position
NewPosition = OldPosition + DeltaPos;
// If moving backward, don't allow the new position go negative
if((LONGLONG)DeltaPos < 0)
{
if(NewPosition > FileSize) // Position is negative
{
SetLastError(ERROR_NEGATIVE_SEEK);
return SFILE_INVALID_POS;
}
}
// If moving forward, don't allow the new position go past the end of the file
else
{
if(NewPosition > FileSize)
NewPosition = FileSize;
}
// Now apply the file pointer to the file
if(hf->pStream != NULL)
{
if(!FileStream_Read(hf->pStream, &NewPosition, NULL, 0))
return SFILE_INVALID_POS;
}
else
{
hf->dwFilePos = (DWORD)NewPosition;
}
// Return the new file position
if(plFilePosHigh != NULL)
*plFilePosHigh = (LONG)(NewPosition >> 32);
return (DWORD)NewPosition;
}

387
3rdParty/StormLib/src/StormCommon.h vendored

@ -0,0 +1,387 @@
/*****************************************************************************/
/* SCommon.h Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Common functions for encryption/decryption from Storm.dll. Included by */
/* SFile*** functions, do not include and do not use this file directly */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 24.03.03 1.00 Lad The first version of SFileCommon.h */
/* 12.06.04 1.00 Lad Renamed to SCommon.h */
/* 06.09.10 1.00 Lad Renamed to StormCommon.h */
/*****************************************************************************/
#ifndef __STORMCOMMON_H__
#define __STORMCOMMON_H__
//-----------------------------------------------------------------------------
// Compression support
// Include functions from Pkware Data Compression Library
#include "3rdParty/PKWare/pkware.h"
#ifdef FULL
// Include functions from Huffmann compression
#include "huffman/huff.h"
// Include functions from IMA ADPCM compression
#include "adpcm/adpcm.h"
// Include functions from SPARSE compression
#include "sparse/sparse.h"
// Include functions from LZMA compression
#include "lzma/C/LzmaEnc.h"
#include "lzma/C/LzmaDec.h"
// Include functions from zlib
#ifndef __SYS_ZLIB
#include "zlib/zlib.h"
#else
#include <zlib.h>
#endif
// Include functions from bzlib
#ifndef __SYS_BZLIB
#include "bzip2/bzlib.h"
#else
#include <bzlib.h>
#endif
//-----------------------------------------------------------------------------
// Cryptography support
// Headers from LibTomCrypt
#include "libtomcrypt/src/headers/tomcrypt.h"
// For HashStringJenkins
#include "jenkins/lookup.h"
#endif
//-----------------------------------------------------------------------------
// StormLib private defines
#define ID_MPQ_FILE 0x46494c45 // Used internally for checking TMPQFile ('FILE')
// Prevent problems with CRT "min" and "max" functions,
// as they are not defined on all platforms
#define STORMLIB_MIN(a, b) ((a < b) ? a : b)
#define STORMLIB_MAX(a, b) ((a > b) ? a : b)
#define STORMLIB_UNUSED(p) ((void)(p))
// Macro for building 64-bit file offset from two 32-bit
#define MAKE_OFFSET64(hi, lo) (((ULONGLONG)hi << 32) | (ULONGLONG)lo)
//-----------------------------------------------------------------------------
// MPQ signature information
// Size of each signature type
#define MPQ_WEAK_SIGNATURE_SIZE 64
#define MPQ_STRONG_SIGNATURE_SIZE 256
#define MPQ_STRONG_SIGNATURE_ID 0x5349474E // ID of the strong signature ("NGIS")
#define MPQ_SIGNATURE_FILE_SIZE (MPQ_WEAK_SIGNATURE_SIZE + 8)
// MPQ signature info
typedef struct _MPQ_SIGNATURE_INFO
{
ULONGLONG BeginMpqData; // File offset where the hashing starts
ULONGLONG BeginExclude; // Begin of the excluded area (used for (signature) file)
ULONGLONG EndExclude; // End of the excluded area (used for (signature) file)
ULONGLONG EndMpqData; // File offset where the hashing ends
ULONGLONG EndOfFile; // Size of the entire file
BYTE Signature[MPQ_STRONG_SIGNATURE_SIZE + 0x10];
DWORD cbSignatureSize; // Length of the signature
DWORD SignatureTypes; // See SIGNATURE_TYPE_XXX
} MPQ_SIGNATURE_INFO, *PMPQ_SIGNATURE_INFO;
//-----------------------------------------------------------------------------
// Memory management
//
// We use our own macros for allocating/freeing memory. If you want
// to redefine them, please keep the following rules:
//
// - The memory allocation must return NULL if not enough memory
// (i.e not to throw exception)
// - The allocating function does not need to fill the allocated buffer with zeros
// - Memory freeing function doesn't have to test the pointer to NULL
//
//#if defined(_MSC_VER) && defined(_DEBUG)
//
//#define STORM_ALLOC(type, nitems) (type *)HeapAlloc(GetProcessHeap(), 0, ((nitems) * sizeof(type)))
//#define STORM_REALLOC(type, ptr, nitems) (type *)HeapReAlloc(GetProcessHeap(), 0, ptr, ((nitems) * sizeof(type)))
//#define STORM_FREE(ptr) HeapFree(GetProcessHeap(), 0, ptr)
//
//#else
#define STORM_ALLOC(type, nitems) (type *)malloc((nitems) * sizeof(type))
#define STORM_REALLOC(type, ptr, nitems) (type *)realloc(ptr, ((nitems) * sizeof(type)))
#define STORM_FREE(ptr) free(ptr)
//#endif
//-----------------------------------------------------------------------------
// StormLib internal global variables
extern LCID lcFileLocale; // Preferred file locale
//-----------------------------------------------------------------------------
// Conversion to uppercase/lowercase (and "/" to "\")
extern unsigned char AsciiToLowerTable[256];
extern unsigned char AsciiToUpperTable[256];
//-----------------------------------------------------------------------------
// Safe string functions
void StringCopy(char * szTarget, size_t cchTarget, const char * szSource);
void StringCat(char * szTarget, size_t cchTargetMax, const char * szSource);
#ifdef _UNICODE
void StringCopy(TCHAR * szTarget, size_t cchTarget, const char * szSource);
void StringCopy(char * szTarget, size_t cchTarget, const TCHAR * szSource);
void StringCopy(TCHAR * szTarget, size_t cchTarget, const TCHAR * szSource);
void StringCat(TCHAR * szTarget, size_t cchTargetMax, const TCHAR * szSource);
#endif
//-----------------------------------------------------------------------------
// Encryption and decryption functions
#define MPQ_HASH_TABLE_INDEX 0x000
#define MPQ_HASH_NAME_A 0x100
#define MPQ_HASH_NAME_B 0x200
#define MPQ_HASH_FILE_KEY 0x300
#define MPQ_HASH_KEY2_MIX 0x400
DWORD HashString(const char * szFileName, DWORD dwHashType);
DWORD HashStringSlash(const char * szFileName, DWORD dwHashType);
DWORD HashStringLower(const char * szFileName, DWORD dwHashType);
void InitializeMpqCryptography();
DWORD GetNearestPowerOfTwo(DWORD dwFileCount);
bool IsPseudoFileName(const char * szFileName, LPDWORD pdwFileIndex);
ULONGLONG HashStringJenkins(const char * szFileName);
DWORD GetDefaultSpecialFileFlags(DWORD dwFileSize, USHORT wFormatVersion);
void EncryptMpqBlock(void * pvDataBlock, DWORD dwLength, DWORD dwKey);
void DecryptMpqBlock(void * pvDataBlock, DWORD dwLength, DWORD dwKey);
DWORD DetectFileKeyBySectorSize(LPDWORD EncryptedData, DWORD dwSectorSize, DWORD dwSectorOffsLen);
DWORD DetectFileKeyByContent(void * pvEncryptedData, DWORD dwSectorSize, DWORD dwFileSize);
DWORD DecryptFileKey(const char * szFileName, ULONGLONG MpqPos, DWORD dwFileSize, DWORD dwFlags);
bool IsValidMD5(LPBYTE pbMd5);
bool IsValidSignature(LPBYTE pbSignature);
bool VerifyDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE expected_md5);
void CalculateDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE md5_hash);
//-----------------------------------------------------------------------------
// Handle validation functions
TMPQArchive * IsValidMpqHandle(HANDLE hMpq);
TMPQFile * IsValidFileHandle(HANDLE hFile);
//-----------------------------------------------------------------------------
// Support for MPQ file tables
ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset);
ULONGLONG CalculateRawSectorOffset(TMPQFile * hf, DWORD dwSectorOffset);
int ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG MpqOffset, ULONGLONG FileSize, DWORD dwFlags, bool bIsWarcraft3Map);
bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash);
TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1, DWORD dwName2, LCID lcLocale);
TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName);
TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * pPrevHash);
TMPQHash * AllocateHashEntry(TMPQArchive * ha, TFileEntry * pFileEntry, LCID lcLocale);
TMPQExtHeader * LoadExtTable(TMPQArchive * ha, ULONGLONG ByteOffset, size_t Size, DWORD dwSignature, DWORD dwKey);
TMPQHetTable * LoadHetTable(TMPQArchive * ha);
TMPQBetTable * LoadBetTable(TMPQArchive * ha);
TMPQBlock * LoadBlockTable(TMPQArchive * ha, bool bDontFixEntries = false);
TMPQBlock * TranslateBlockTable(TMPQArchive * ha, ULONGLONG * pcbTableSize, bool * pbNeedHiBlockTable);
ULONGLONG FindFreeMpqSpace(TMPQArchive * ha);
// Functions that load the HET and BET tables
int CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize);
int LoadAnyHashTable(TMPQArchive * ha);
int BuildFileTable(TMPQArchive * ha);
int DefragmentFileTable(TMPQArchive * ha);
int CreateFileTable(TMPQArchive * ha, DWORD dwFileTableSize);
int RebuildHetTable(TMPQArchive * ha);
int RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize);
int SaveMPQTables(TMPQArchive * ha);
TMPQHetTable * CreateHetTable(DWORD dwEntryCount, DWORD dwTotalCount, DWORD dwHashBitSize, LPBYTE pbSrcData);
void FreeHetTable(TMPQHetTable * pHetTable);
TMPQBetTable * CreateBetTable(DWORD dwMaxFileCount);
void FreeBetTable(TMPQBetTable * pBetTable);
// Functions for finding files in the file table
TFileEntry * GetFileEntryLocale2(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex);
TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex);
// Allocates file name in the file entry
void AllocateFileName(TMPQArchive * ha, TFileEntry * pFileEntry, const char * szFileName);
// Allocates new file entry in the MPQ tables. Reuses existing, if possible
TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex);
int RenameFileEntry(TMPQArchive * ha, TMPQFile * hf, const char * szNewFileName);
int DeleteFileEntry(TMPQArchive * ha, TMPQFile * hf);
// Invalidates entries for (listfile) and (attributes)
void InvalidateInternalFiles(TMPQArchive * ha);
// Retrieves information about the strong signature
bool QueryMpqSignatureInfo(TMPQArchive * ha, PMPQ_SIGNATURE_INFO pSignatureInfo);
//-----------------------------------------------------------------------------
// Support for alternate file formats (SBaseSubTypes.cpp)
int ConvertSqpHeaderToFormat4(TMPQArchive * ha, ULONGLONG FileSize, DWORD dwFlags);
TMPQHash * LoadSqpHashTable(TMPQArchive * ha);
TMPQBlock * LoadSqpBlockTable(TMPQArchive * ha);
int ConvertMpkHeaderToFormat4(TMPQArchive * ha, ULONGLONG FileSize, DWORD dwFlags);
void DecryptMpkTable(void * pvMpkTable, size_t cbSize);
TMPQHash * LoadMpkHashTable(TMPQArchive * ha);
TMPQBlock * LoadMpkBlockTable(TMPQArchive * ha);
int SCompDecompressMpk(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
//-----------------------------------------------------------------------------
// Common functions - MPQ File
TMPQFile * CreateFileHandle(TMPQArchive * ha, TFileEntry * pFileEntry);
TMPQFile * CreateWritableHandle(TMPQArchive * ha, DWORD dwFileSize);
void * LoadMpqTable(TMPQArchive * ha, ULONGLONG ByteOffset, DWORD dwCompressedSize, DWORD dwRealSize, DWORD dwKey, bool * pbTableIsCut);
int AllocateSectorBuffer(TMPQFile * hf);
int AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile);
int AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile);
int AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile);
int WritePatchInfo(TMPQFile * hf);
int WriteSectorOffsets(TMPQFile * hf);
int WriteSectorChecksums(TMPQFile * hf);
int WriteMemDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, void * pvRawData, DWORD dwRawDataSize, DWORD dwChunkSize, LPDWORD pcbTotalSize);
int WriteMpqDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, DWORD dwRawDataSize, DWORD dwChunkSize);
void FreeFileHandle(TMPQFile *& hf);
void FreeArchiveHandle(TMPQArchive *& ha);
//-----------------------------------------------------------------------------
// Patch functions
// Structure used for the patching process
typedef struct _TMPQPatcher
{
BYTE this_md5[MD5_DIGEST_SIZE]; // MD5 of the current file state
LPBYTE pbFileData1; // Primary working buffer
LPBYTE pbFileData2; // Secondary working buffer
DWORD cbMaxFileData; // Maximum allowed size of the patch data
DWORD cbFileData; // Current size of the result data
DWORD nCounter; // Counter of the patch process
} TMPQPatcher;
bool IsIncrementalPatchFile(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize);
int Patch_InitPatcher(TMPQPatcher * pPatcher, TMPQFile * hf);
int Patch_Process(TMPQPatcher * pPatcher, TMPQFile * hf);
void Patch_Finalize(TMPQPatcher * pPatcher);
//-----------------------------------------------------------------------------
// Utility functions
bool CheckWildCard(const char * szString, const char * szWildCard);
bool IsInternalMpqFileName(const char * szFileName);
template <typename XCHAR>
const XCHAR * GetPlainFileName(const XCHAR * szFileName)
{
const XCHAR * szPlainName = szFileName;
while(*szFileName != 0)
{
if(*szFileName == '\\' || *szFileName == '/')
szPlainName = szFileName + 1;
szFileName++;
}
return szPlainName;
}
//-----------------------------------------------------------------------------
// Internal support for MPQ modifications
int SFileAddFile_Init(
TMPQArchive * ha,
const char * szArchivedName,
ULONGLONG ft,
DWORD dwFileSize,
LCID lcLocale,
DWORD dwFlags,
TMPQFile ** phf
);
int SFileAddFile_Init(
TMPQArchive * ha,
TMPQFile * hfSrc,
TMPQFile ** phf
);
int SFileAddFile_Write(
TMPQFile * hf,
const void * pvData,
DWORD dwSize,
DWORD dwCompression
);
int SFileAddFile_Finish(
TMPQFile * hf
);
//-----------------------------------------------------------------------------
// Attributes support
int SAttrLoadAttributes(TMPQArchive * ha);
int SAttrFileSaveToMpq(TMPQArchive * ha);
//-----------------------------------------------------------------------------
// Listfile functions
int SListFileSaveToMpq(TMPQArchive * ha);
//-----------------------------------------------------------------------------
// Weak signature support
int SSignFileCreate(TMPQArchive * ha);
int SSignFileFinish(TMPQArchive * ha);
//-----------------------------------------------------------------------------
// Dump data support
#ifdef __STORMLIB_DUMP_DATA__
void DumpMpqHeader(TMPQHeader * pHeader);
void DumpHashTable(TMPQHash * pHashTable, DWORD dwHashTableSize);
void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable);
void DumpFileTable(TFileEntry * pFileTable, DWORD dwFileTableSize);
#else
#define DumpMpqHeader(h) /* */
#define DumpHashTable(t, s) /* */
#define DumpHetAndBetTable(t, s) /* */
#define DumpFileTable(t, s) /* */
#endif
#endif // __STORMCOMMON_H__

1134
3rdParty/StormLib/src/StormLib.h vendored

File diff suppressed because it is too large Load Diff

304
3rdParty/StormLib/src/StormPort.h vendored

@ -0,0 +1,304 @@
/*****************************************************************************/
/* StormPort.h Copyright (c) Marko Friedemann 2001 */
/*---------------------------------------------------------------------------*/
/* Portability module for the StormLib library. Contains a wrapper symbols */
/* to make the compilation under Linux work */
/* */
/* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de> */
/* Created at: Mon Jan 29 18:26:01 CEST 2001 */
/* Computer: whiplash.flachland-chemnitz.de */
/* System: Linux 2.4.0 on i686 */
/* */
/* Author: Sam Wilkins <swilkins1337@gmail.com> */
/* System: Mac OS X and port to big endian processor */
/* */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 29.01.01 1.00 Mar Created */
/* 24.03.03 1.01 Lad Some cosmetic changes */
/* 12.11.03 1.02 Dan Macintosh compatibility */
/* 24.07.04 1.03 Sam Mac OS X compatibility */
/* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */
/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */
/* 17.10.12 1.05 Lad Moved error codes so they don't overlap with errno.h */
/*****************************************************************************/
#ifndef __STORMPORT_H__
#define __STORMPORT_H__
#ifndef __cplusplus
#define bool char
#define true 1
#define false 0
#endif
//-----------------------------------------------------------------------------
// Defines for Windows
#if !defined(PLATFORM_DEFINED) && defined(_WIN32)
// In MSVC 8.0, there are some functions declared as deprecated.
#if _MSC_VER >= 1400
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NON_CONFORMING_SWPRINTFS
#endif
#include <tchar.h>
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <windows.h>
#include <wininet.h>
#define PLATFORM_LITTLE_ENDIAN
#ifdef _WIN64
#define PLATFORM_64BIT
#else
#define PLATFORM_32BIT
#endif
#define PLATFORM_WINDOWS
#define PLATFORM_DEFINED // The platform is known now
#endif
//-----------------------------------------------------------------------------
// Defines for Mac
#if !defined(PLATFORM_DEFINED) && defined(__APPLE__) // Mac BSD API
// Macintosh
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
// Support for PowerPC on Max OS X
#if (__ppc__ == 1) || (__POWERPC__ == 1) || (_ARCH_PPC == 1)
#include <stdint.h>
#include <CoreFoundation/CFByteOrder.h>
#endif
#define PKEXPORT
#define __SYS_ZLIB
#define __SYS_BZLIB
#ifndef __BIG_ENDIAN__
#define PLATFORM_LITTLE_ENDIAN
#endif
#define PLATFORM_MAC
#define PLATFORM_DEFINED // The platform is known now
#endif
//-----------------------------------------------------------------------------
// Assumption: we are not on Windows nor Macintosh, so this must be linux *grin*
#if !defined(PLATFORM_DEFINED)
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#define PLATFORM_LITTLE_ENDIAN
#define PLATFORM_LINUX
#define PLATFORM_DEFINED
#endif
//-----------------------------------------------------------------------------
// Definition of Windows-specific types for non-Windows platforms
#ifndef PLATFORM_WINDOWS
#if __LP64__
#define PLATFORM_64BIT
#else
#define PLATFORM_32BIT
#endif
// Typedefs for ANSI C
typedef unsigned char BYTE;
typedef unsigned short USHORT;
typedef int LONG;
typedef unsigned int DWORD;
typedef unsigned long DWORD_PTR;
typedef long LONG_PTR;
typedef long INT_PTR;
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;
typedef void * HANDLE;
typedef void * LPOVERLAPPED; // Unsupported on Linux and Mac
typedef char TCHAR;
typedef unsigned int LCID;
typedef LONG * PLONG;
typedef DWORD * LPDWORD;
typedef BYTE * LPBYTE;
typedef const char * LPCTSTR;
typedef const char * LPCSTR;
typedef char * LPTSTR;
typedef char * LPSTR;
#ifdef PLATFORM_32BIT
#define _LZMA_UINT32_IS_ULONG
#endif
// Some Windows-specific defines
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif
#ifndef _countof
#define _countof(x) (sizeof(x) / sizeof(x[0]))
#endif
#define WINAPI
#define FILE_BEGIN SEEK_SET
#define FILE_CURRENT SEEK_CUR
#define FILE_END SEEK_END
#define _T(x) x
#define _tcslen strlen
#define _tcscpy strcpy
#define _tcscat strcat
#define _tcschr strchr
#define _tcsrchr strrchr
#define _tcsstr strstr
#define _tcsnicmp strncasecmp
#define _tprintf printf
#define _stprintf sprintf
#define _tremove remove
#define _tmain main
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#define _tcsicmp strcasecmp
#define _tcsnicmp strncasecmp
#endif // !PLATFORM_WINDOWS
// 64-bit calls are supplied by "normal" calls on Mac
#if defined(PLATFORM_MAC)
#define stat64 stat
#define fstat64 fstat
#define lseek64 lseek
#define ftruncate64 ftruncate
#define off64_t off_t
#define O_LARGEFILE 0
#endif
// Platform-specific error codes for UNIX-based platforms
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
#define ERROR_SUCCESS 0
#define ERROR_FILE_NOT_FOUND ENOENT
#define ERROR_ACCESS_DENIED EPERM
#define ERROR_INVALID_HANDLE EBADF
#define ERROR_NOT_ENOUGH_MEMORY ENOMEM
#define ERROR_NOT_SUPPORTED ENOTSUP
#define ERROR_INVALID_PARAMETER EINVAL
#define ERROR_NEGATIVE_SEEK EINVAL
#define ERROR_DISK_FULL ENOSPC
#define ERROR_ALREADY_EXISTS EEXIST
#define ERROR_INSUFFICIENT_BUFFER ENOBUFS
#define ERROR_BAD_FORMAT 1000 // No such error code under Linux
#define ERROR_NO_MORE_FILES 1001 // No such error code under Linux
#define ERROR_HANDLE_EOF 1002 // No such error code under Linux
#define ERROR_CAN_NOT_COMPLETE 1003 // No such error code under Linux
#define ERROR_FILE_CORRUPT 1004 // No such error code under Linux
#endif
//-----------------------------------------------------------------------------
// Swapping functions
#ifdef PLATFORM_LITTLE_ENDIAN
#define BSWAP_INT16_UNSIGNED(a) (a)
#define BSWAP_INT16_SIGNED(a) (a)
#define BSWAP_INT32_UNSIGNED(a) (a)
#define BSWAP_INT32_SIGNED(a) (a)
#define BSWAP_INT64_SIGNED(a) (a)
#define BSWAP_INT64_UNSIGNED(a) (a)
#define BSWAP_ARRAY16_UNSIGNED(a,b) {}
#define BSWAP_ARRAY32_UNSIGNED(a,b) {}
#define BSWAP_ARRAY64_UNSIGNED(a,b) {}
#define BSWAP_PART_HEADER(a) {}
#define BSWAP_TMPQHEADER(a,b) {}
#define BSWAP_TMPKHEADER(a) {}
#else
#ifdef __cplusplus
extern "C" {
#endif
int16_t SwapInt16(uint16_t);
uint16_t SwapUInt16(uint16_t);
int32_t SwapInt32(uint32_t);
uint32_t SwapUInt32(uint32_t);
int64_t SwapInt64(uint64_t);
uint64_t SwapUInt64(uint64_t);
void ConvertUInt16Buffer(void * ptr, size_t length);
void ConvertUInt32Buffer(void * ptr, size_t length);
void ConvertUInt64Buffer(void * ptr, size_t length);
void ConvertTMPQUserData(void *userData);
void ConvertTMPQHeader(void *header, uint16_t wPart);
void ConvertTMPKHeader(void *header);
#ifdef __cplusplus
}
#endif
#define BSWAP_INT16_SIGNED(a) SwapInt16((a))
#define BSWAP_INT16_UNSIGNED(a) SwapUInt16((a))
#define BSWAP_INT32_SIGNED(a) SwapInt32((a))
#define BSWAP_INT32_UNSIGNED(a) SwapUInt32((a))
#define BSWAP_INT64_SIGNED(a) SwapInt64((a))
#define BSWAP_INT64_UNSIGNED(a) SwapUInt64((a))
#define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUInt16Buffer((a),(b))
#define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUInt32Buffer((a),(b))
#define BSWAP_ARRAY64_UNSIGNED(a,b) ConvertUInt64Buffer((a),(b))
#define BSWAP_TMPQHEADER(a,b) ConvertTMPQHeader((a),(b))
#define BSWAP_TMPKHEADER(a) ConvertTMPKHeader((a))
#endif
//-----------------------------------------------------------------------------
// Macro for deprecated symbols
/*
#ifdef _MSC_VER
#if _MSC_FULL_VER >= 140050320
#define STORMLIB_DEPRECATED(_Text) __declspec(deprecated(_Text))
#else
#define STORMLIB_DEPRECATED(_Text) __declspec(deprecated)
#endif
#else
#ifdef __GNUC__
#define STORMLIB_DEPRECATED(_Text) __attribute__((deprecated))
#else
#define STORMLIB_DEPRECATED(_Text) __attribute__((deprecated(_Text)))
#endif
#endif
// When a flag is deprecated, use this macro
#ifndef _STORMLIB_NO_DEPRECATE
#define STORMLIB_DEPRECATED_FLAG(type, oldflag, newflag) \
const STORMLIB_DEPRECATED(#oldflag " is deprecated. Use " #newflag ". To supress this warning, define _STORMLIB_NO_DEPRECATE") static type oldflag = (type)newflag;
#else
#define STORMLIB_DEPRECATED_FLAG(type, oldflag, newflag) static type oldflag = (type)newflag;
#endif
*/
#define bool int
void TranslateFileName(char* dst, int dstLen, const char* src);
#endif // __STORMPORT_H__

16
CMake/32bit.cmake

@ -0,0 +1,16 @@
message(STATUS "Using 32-bit toolchain")
set(CMAKE_CXX_FLAGS -m32 CACHE STRING "")
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE)
find_path(DIR NAMES cmake PATHS /usr/lib32 /usr/lib/i386-linux-gnu NO_DEFAULT_PATH)
if(DIR)
message(STATUS "Using 32-bit libraries from ${DIR}")
# Read CMake modules from 32-bit packages
set(CMAKE_FIND_ROOT_PATH ${DIR})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()

9
CMake/SDL2_fixed.cmake

@ -0,0 +1,9 @@
find_package(SDL2 REQUIRED)
# WORKAROUND: Arch Linux SDL2 cmake config not setting this variable
if(NOT SDL2_LIBRARIES)
# Note: you will probably need to install multilib/lib32-dbus on Arch
set(SDL2_LIBRARIES SDL2::SDL2)
endif()
# WORKAROUND: Issue with Ubuntu 16.04 having whitespace (CMP0004)
string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES)

3
CMake/out_of_tree.cmake

@ -0,0 +1,3 @@
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(WARNING [[In-source build detected, please eg. create a new directory and use `cmake ..`]])
endif()

8
CMake/sanitize.cmake

@ -0,0 +1,8 @@
include(CheckCXXCompilerFlag)
set(SANITIZE_OPTIONS -fsanitize=null -fsanitize=return)
check_cxx_compiler_flag(HAS_SANITIZE_ADDRESS -fsanitize-recover=address)
if(HAS_SANITIZE_ADDRESS)
list(APPEND SANITIZE_OPTIONS -fsanitize=address -fsanitize-recover=address)
endif()

147
CMakeLists.txt

@ -0,0 +1,147 @@
cmake_minimum_required(VERSION 3.5)
include(CMake/out_of_tree.cmake)
# This must be included before project()
include(CMake/32bit.cmake)
set(CMAKE_CXX_STANDARD 11)
project(devil-miniwin
VERSION 0.0.1
LANGUAGES CXX
)
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 4)
message(WARNING "sizeof(void*) == ${CMAKE_SIZEOF_VOID_P}.")
message(FATAL_ERROR [[This project can only be compiled in 32-bit mode.]])
endif()
set(SOURCES
Source/automap.cpp
Source/codec.cpp
Source/control.cpp
Source/cursor.cpp
Source/dead.cpp
Source/debug.cpp
Source/diablo.cpp
Source/doom.cpp
Source/drlg_l1.cpp
Source/drlg_l2.cpp
Source/drlg_l3.cpp
Source/drlg_l4.cpp
# Source/effects.cpp
Source/encrypt.cpp
Source/engine.cpp
Source/error.cpp
Source/gamemenu.cpp
Source/gendung.cpp
Source/gmenu.cpp
Source/help.cpp
Source/interfac.cpp
Source/inv.cpp
Source/items.cpp
Source/lighting.cpp
Source/loadsave.cpp
Source/mainmenu.cpp
Source/minitext.cpp
Source/missiles.cpp
Source/monster.cpp
Source/mpqapi.cpp
Source/msgcmd.cpp
Source/msg.cpp
Source/multi.cpp
Source/objects.cpp
Source/pack.cpp
Source/palette.cpp
Source/path.cpp
Source/pfile.cpp
Source/player.cpp
Source/plrmsg.cpp
Source/portal.cpp
Source/quests.cpp
Source/render.cpp
Source/scrollrt.cpp
Source/setmaps.cpp
Source/sha.cpp
Source/spells.cpp
Source/stores.cpp
Source/sync.cpp
Source/textdat.cpp
Source/themes.cpp
Source/tmsg.cpp
Source/town.cpp
Source/towners.cpp
Source/track.cpp
Source/trigs.cpp
Source/wave.cpp
3rdParty/PKWare/explode.cpp
3rdParty/PKWare/implode.cpp
)
# Completely stubbed out sources, for reference
set(REPLACED_SOURCES
Source/capture.cpp
Source/appfat.cpp
Source/dthread.cpp
Source/dx.cpp
Source/fault.cpp
Source/init.cpp
Source/logging.cpp
Source/movie.cpp
Source/nthread.cpp
Source/restrict.cpp
Source/sound.cpp
Source/effects.cpp # There is a function here that references Dx3d and lead to crash.
)
set(STUB_SOURCES
Stub/miniwin.cpp
Stub/miniwin_rand.cpp
Stub/appfat.cpp
Stub/capture.cpp
Stub/dthread.cpp
Stub/dx.cpp
Stub/effects.cpp
Stub/fault.cpp
Stub/init.cpp
Stub/movie.cpp
Stub/nthread.cpp
Stub/restrict.cpp
Stub/sound.cpp
Stub/storm.cpp
Stub/diabloui.cpp
Stub/miniwin_io.cpp
Stub/miniwin_sdl.cpp
Stub/storm_net.cpp
Stub/sdlrender.cpp
Stub/SDL_FontCache.cpp
3rdParty/StormLib/src/FileStream.cpp
3rdParty/StormLib/src/SBaseCommon.cpp
3rdParty/StormLib/src/SBaseFileTable.cpp
3rdParty/StormLib/src/SBaseSubTypes.cpp
3rdParty/StormLib/src/SCompression.cpp
3rdParty/StormLib/src/SFileExtractFile.cpp
3rdParty/StormLib/src/SFileFindFile.cpp
3rdParty/StormLib/src/SFileGetFileInfo.cpp
3rdParty/StormLib/src/SFileOpenArchive.cpp
3rdParty/StormLib/src/SFileOpenFileEx.cpp
3rdParty/StormLib/src/SFileReadFile.cpp
)
include(CMake/SDL2_fixed.cmake)
include(CMake/sanitize.cmake)
include_directories(${SDL2_INCLUDE_DIRS})
include_directories(. Stub)
# FUTURE: use add_compile_definitions()
add_definitions(-DMINIWIN -D_DEBUG -DFASTER)
add_compile_options(-g -fpermissive -Wno-write-strings -Wno-multichar)
add_executable(devil-test ${SOURCES} ${STUB_SOURCES} Stub/main_test.cpp)
target_compile_options(devil-test PRIVATE ${SANITIZE_OPTIONS})
target_link_libraries(devil-test PUBLIC m ${SDL2_LIBRARIES} ${SANITIZE_OPTIONS})

431
Diablo.dsp

@ -0,0 +1,431 @@
# Microsoft Developer Studio Project File - Name="Diablo" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=Diablo - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Diablo.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Diablo.mak" CFG="Diablo - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Diablo - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "Diablo - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE "Diablo - Win32 Release with PDB" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "Diablo - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Source/WinRel"
# PROP BASE Intermediate_Dir "Source/WinRel"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "bld/WinRel"
# PROP Intermediate_Dir "Source/WinRel"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# SUBTRACT CPP /WX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 DiabloUI/WinRel/DiabloUI.lib 3rdParty/Storm/Source/WinRel/Storm.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /machine:I386
!ELSEIF "$(CFG)" == "Diablo - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Diablo__"
# PROP BASE Intermediate_Dir "Diablo__"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "bld/WinDebug"
# PROP Intermediate_Dir "Source/WinDebug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /Gm /GX /Zi /O1 /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "NDEBUG" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /D "NDEBUG" /mktyplib203 /o "NUL" /win32 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "NDEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib user32.lib gdi32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /machine:I386
/nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "Diablo - Win32 Release with PDB"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Diablo___Win32_Release_with_PDB"
# PROP BASE Intermediate_Dir "Diablo___Win32_Release_with_PDB"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "bld/WinRel"
# PROP Intermediate_Dir "Source/WinRel"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# SUBTRACT BASE CPP /WX
# ADD CPP /nologo /MT /W3 /GX /Zi /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# SUBTRACT CPP /WX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 DiabloUI/WinRel/DiabloUI.lib 3rdParty/Storm/Source/WinRel/Storm.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 DiabloUI/WinRel/DiabloUI.lib 3rdParty/Storm/Source/WinRel/Storm.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /debug /machine:I386
!ENDIF
# Begin Target
# Name "Diablo - Win32 Release"
# Name "Diablo - Win32 Debug"
# Name "Diablo - Win32 Release with PDB"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\Source\appfat.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\automap.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\capture.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\codec.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\control.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\cursor.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\dead.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\debug.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\diablo.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\doom.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\drlg_l1.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\drlg_l2.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\drlg_l3.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\drlg_l4.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\dthread.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\dx.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\effects.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\encrypt.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\engine.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\error.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\fault.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\gamemenu.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\gendung.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\gmenu.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\help.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\init.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\interfac.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\inv.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\items.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\lighting.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\loadsave.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\logging.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\mainmenu.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\minitext.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\missiles.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\monster.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\movie.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\mpqapi.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\msg.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\msgcmd.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\multi.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\nthread.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\objects.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\pack.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\palette.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\path.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\pfile.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\player.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\plrmsg.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\portal.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\quests.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\restrict.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\scrollrt.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\setmaps.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\sha.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\sound.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\spells.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\stores.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\sync.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\textdat.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\themes.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\tmsg.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\town.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\towners.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\track.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\trigs.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\wave.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\render.cpp
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\Diablo.ico
# End Source File
# Begin Source File
SOURCE=.\Diablo.rc
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\resource.h
# End Source File
# End Group
# Begin Group "PKWare"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\3rdParty\PKWare\explode.cpp
# End Source File
# Begin Source File
SOURCE=.\3rdParty\PKWare\implode.cpp
# End Source File
# End Group
# End Target
# End Project

59
Diablo.dsw

@ -0,0 +1,59 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "Diablo"=".\Diablo.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name DiabloUI
End Project Dependency
Begin Project Dependency
Project_Dep_Name Storm
End Project Dependency
}}}
###############################################################################
Project: "DiabloUI"=".\DiabloUI\DiabloUI.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "Storm"=".\3rdParty\Storm\Source\Storm.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

BIN
Diablo.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

291
Diablo.rc

@ -0,0 +1,291 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "Diablo.ico"
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 250, 241
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Direct Draw Error"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,193,220,50,14
LTEXT "Diablo was unable to properly initialize your video card using DirectX. Please try the following solutions to correct the problem:",
-1,7,7,236,18
LTEXT "Use the Diablo setup program ""SETUP.EXE"" provided on the Diablo CD-ROM to install DirectX 3.0.",
-1,19,26,210,18
LTEXT "Install the most recent DirectX video drivers provided by the manufacturer of your video card. A list of video card manufactuers can be found at: http://www.blizzard.com/support/vendors.htm",
-1,19,48,210,27
LTEXT "The error encountered while trying to initialize the video card was:",
-1,7,175,236,9
LTEXT "unknown error",1000,19,186,210,27
LTEXT "If you continue to have problems, we have also included Microsoft DirectX 2.0 drivers on the Diablo CD-ROM. This older version of DirectX may work in cases where DirectX 3.0 does not.",
-1,7,79,236,27
LTEXT "USA telephone: 1-800-426-9400\nInternational telephone: 206-882-8080\nhttp://www.microsoft.com",
-1,19,137,210,27
LTEXT "If you continue to have problems with DirectX, please contact Microsoft's Technical Support at:",
-1,7,116,236,18
END
IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 250, 213
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Out of Memory Error"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,193,192,50,14
LTEXT "Diablo has exhausted all the memory on your system. This problem can likely be corrected by changing the virtual memory settings for Windows. Ensure that your system has at least 10 megabytes of free disk space, then check your virtual memory settings:",
-1,7,7,236,36
LTEXT "Select ""Settings - Control Panel"" from the ""Start"" menu\nRun the ""System"" control panel applet\nSelect the ""Performance"" tab, and press ""Virtual Memory""\nUse the ""Let Windows manage my virtual memory..."" option",
-1,23,54,197,36
LTEXT "The error encountered was:",-1,7,146,236,11
LTEXT "unknown location",1000,20,157,210,27
LTEXT "For Windows 95:",-1,7,45,236,9
LTEXT "Select ""Settings - Control Panel"" from the ""Start"" menu\nRun the ""System"" control panel applet\nSelect the ""Performance"" tab\nPress ""Change"" in ""Virtual Memory"" settings\nEnsure that the virtual memory file is at least 32 megabytes",
-1,17,98,197,45
LTEXT "For Windows NT:",-1,7,89,236,9
END
IDD_DIALOG3 DIALOG DISCARDABLE 0, 0, 265, 114
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Data File Error"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,208,93,50,14
LTEXT "Diablo was unable to open a required file. Please ensure that the Diablo disc is in the CDROM drive. If this problem persists, try uninstalling and reinstalling Diablo using the program ""SETUP.EXE"" on the Diablo CD-ROM.",
-1,7,7,251,36
LTEXT "The problem occurred while trying to load a file",-1,7,
48,232,9
LTEXT "unknown file",1000,20,59,210,27
END
IDD_DIALOG4 DIALOG DISCARDABLE 0, 0, 250, 161
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Direct Draw Error"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,193,140,50,14
LTEXT "Diablo was unable to find the file ""ddraw.dll"", which is a component of Microsoft DirectX. Please run the program ""SETUP.EXE"" on the Diablo CD-ROM and install Microsoft DirectX.",
-1,7,7,236,27
LTEXT "The error encountered while trying to initialize DirectX was:",
-1,7,95,236,9
LTEXT "unknown error",1000,19,106,210,29
LTEXT "USA telephone: 1-800-426-9400\nInternational telephone: 206-882-8080\nhttp://www.microsoft.com",
-1,19,60,210,27
LTEXT "If you continue to have problems with DirectX, please contact Microsoft's Technical Support at:",
-1,7,39,236,18
END
IDD_DIALOG5 DIALOG DISCARDABLE 0, 0, 250, 161
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Direct Sound Error"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,193,140,50,14
LTEXT "Diablo was unable to find the file ""dsound.dll"", which is a component of Microsoft DirectX. Please run the program ""SETUP.EXE"" on the Diablo CD-ROM and install Microsoft DirectX.",
-1,7,7,236,27
LTEXT "The error encountered while trying to initialize DirectX was:",
-1,7,95,236,9
LTEXT "unknown error",1000,19,106,210,27
LTEXT "USA telephone: 1-800-426-9400\nInternational telephone: 206-882-8080\nhttp://www.microsoft.com",
-1,19,60,210,27
LTEXT "If you continue to have problems with DirectX, please contact Microsoft's Technical Support at:",
-1,7,39,236,18
END
/* IDD_DIALOG6 DIALOG DISCARDABLE 0, 0, 250, 92
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "System warning"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&OK",1,130,71,50,14
LTEXT "Diablo requires an Intel Pentium-class processor to run properly. Your system does not appear to have a Pentium-class processor installed.",
-1,7,7,236,18
LTEXT "You may still be able to play Diablo if your processor has the performance characteristics of a Pentium.",
-1,7,30,236,18
LTEXT "Press ""OK"" to proceed, otherwise press ""Cancel"" to exit this program.",
-1,7,53,236,9
PUSHBUTTON "&Cancel",2,193,71,50,14
END */
IDD_DIALOG7 DIALOG DISCARDABLE 0, 0, 250, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Out of Disk Space"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,193,79,50,14
LTEXT "Diablo requires at least 10 megabytes of free disk space to run properly. The disk:",
-1,7,7,236,18
LTEXT "",-1,7,43,232,9
LTEXT "unknown drive",1000,7,33,210,9
LTEXT "has less than 10 megabytes of free space left. Please free some space on your drive and run Diablo again.",
-1,7,52,236,18
END
IDD_DIALOG8 DIALOG DISCARDABLE 0, 0, 250, 161
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Direct Draw Error"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,193,140,50,14
LTEXT "Diablo was unable to switch video modes. This is a common problem for computers with more than one video card. To correct this problem, please set your video resolution to 640 x 480 and try running Diablo again.",
-1,7,7,236,27
LTEXT "The error encountered while trying to switch video modes was:",
-1,7,95,236,9
LTEXT "unknown error",1000,19,106,210,27
LTEXT "Select ""Settings - Control Panel"" from the ""Start"" menu\nRun the ""Display"" control panel applet\nSelect the ""Settings"" tab\nSet the ""Desktop Area"" to ""640 x 480 pixels""",
-1,23,50,197,36
LTEXT "For Windows 95 and Windows NT",-1,7,41,236,9
END
IDD_DIALOG9 DIALOG DISCARDABLE 0, 0, 250, 92
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Data File Error"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,136,71,50,14
LTEXT "Diablo cannot read a required data file. Your Diablo CD may not be in the CDROM drive. Please ensure that the Diablo disc is in the CDROM drive and press OK. To leave the program, press Exit.",
-1,7,7,236,27
LTEXT "unknown file",1000,20,37,210,27
PUSHBUTTON "Exit",2,193,71,50,14
END
IDD_DIALOG10 DIALOG DISCARDABLE 0, 0, 223, 116
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Windows 2000 Restricted User Advisory"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,166,95,50,14
LTEXT "In order to install, play or patch Diablo using the Windows 2000 operating system, you will need to log in as either an Administrator or as a Power User.",
-1,7,7,209,28
LTEXT "Users, also known as Restricted Users, do not have sufficient access to install or play the game properly.",
-1,7,39,209,20
LTEXT "If you have further questions regarding User Rights in Windows 2000, please refer to your Windows 2000 documentation or contact your system administrator.",
-1,7,63,209,28
END
IDD_DIALOG11 DIALOG DISCARDABLE 0, 0, 220, 121
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Read-Only Directory Error"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",1,163,100,50,14
LTEXT "Diablo is being run from:",-1,7,7,206,10
LTEXT "unknown directory",1000,17,20,186,20
LTEXT "Diablo or the current user does not seem to have write privilages in this directory. Contact your system administrator.\n\nNote that Windows 2000 Restricted Users can not write to the Windows or Program Files directory hierarchies.",
-1,7,44,206,50
END
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2001,5,18,1
PRODUCTVERSION 1,0,9,2
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Blizzard Entertainment\0"
VALUE "FileDescription", "Diablo\0"
VALUE "FileVersion", "2001, 5, 18, 1\0"
VALUE "InternalName", "Diablo\0"
VALUE "LegalCopyright", "Copyright © 1996-2001\0"
VALUE "OriginalFilename", "Diablo.exe\0"
VALUE "ProductName", "Blizzard Entertainment Diablo\0"
VALUE "ProductVersion", "1, 0, 9, 2\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // !_MAC
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

37
Diablo.sln

@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2035
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Diablo", "Diablo.vcxproj", "{23114A83-7D81-4F17-A6B8-2FC51F3D72F2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DiabloUI", "DiabloUI\DiabloUI.vcxproj", "{8408E35E-3CF5-4D4E-B873-AF3952CDABD4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Storm", "3rdParty\Storm\Source\Storm.vcxproj", "{B28F69CE-15A1-424D-BBB5-2727258D675B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{23114A83-7D81-4F17-A6B8-2FC51F3D72F2}.Debug|x86.ActiveCfg = Debug|Win32
{23114A83-7D81-4F17-A6B8-2FC51F3D72F2}.Debug|x86.Build.0 = Debug|Win32
{23114A83-7D81-4F17-A6B8-2FC51F3D72F2}.Release|x86.ActiveCfg = Release|Win32
{23114A83-7D81-4F17-A6B8-2FC51F3D72F2}.Release|x86.Build.0 = Release|Win32
{8408E35E-3CF5-4D4E-B873-AF3952CDABD4}.Debug|x86.ActiveCfg = Debug|Win32
{8408E35E-3CF5-4D4E-B873-AF3952CDABD4}.Debug|x86.Build.0 = Debug|Win32
{8408E35E-3CF5-4D4E-B873-AF3952CDABD4}.Release|x86.ActiveCfg = Release|Win32
{8408E35E-3CF5-4D4E-B873-AF3952CDABD4}.Release|x86.Build.0 = Release|Win32
{B28F69CE-15A1-424D-BBB5-2727258D675B}.Debug|x86.ActiveCfg = Debug|Win32
{B28F69CE-15A1-424D-BBB5-2727258D675B}.Debug|x86.Build.0 = Debug|Win32
{B28F69CE-15A1-424D-BBB5-2727258D675B}.Release|x86.ActiveCfg = Release|Win32
{B28F69CE-15A1-424D-BBB5-2727258D675B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6252549D-BED6-405B-9D6D-42C9074D0684}
EndGlobalSection
EndGlobal

293
Diablo.vcxproj

@ -0,0 +1,293 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<SccProjectName />
<SccLocalPath />
<ProjectGuid>{23114A83-7D81-4F17-A6B8-2FC51F3D72F2}</ProjectGuid>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>.\Source/WinRel\</OutDir>
<IntDir>.\Source/WinRel\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>.\Source/WinDebug\</OutDir>
<IntDir>.\Source/WinDebug\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<StringPooling>true</StringPooling>
<Optimization>MaxSpeed</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>.\Source/WinRel\</AssemblerListingLocation>
<ObjectFileName>.\Source/WinRel\</ObjectFileName>
<ProgramDataBaseFileName>.\Source/WinRel\</ProgramDataBaseFileName>
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
<MinimalRebuild>true</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\Source/WinRel\Diablo.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<RedirectOutputAndErrors>NUL</RedirectOutputAndErrors>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<OutputFile>.\Source/WinRel\Diablo.bsc</OutputFile>
</Bscmake>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>.\Source/WinRel\Diablo.exe</OutputFile>
<AdditionalDependencies>DiabloUI/WinRel/DiabloUI.lib;3rdParty/Storm/Source/WinRel/Storm.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DataExecutionPrevention>false</DataExecutionPrevention>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<Optimization>Disabled</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>.\Source/WinDebug\</AssemblerListingLocation>
<ObjectFileName>.\Source/WinDebug\</ObjectFileName>
<ProgramDataBaseFileName>.\Source/WinDebug\</ProgramDataBaseFileName>
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\Source/WinDebug\Diablo.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<RedirectOutputAndErrors>NUL</RedirectOutputAndErrors>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<OutputFile>.\Source/WinDebug\Diablo.bsc</OutputFile>
</Bscmake>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OutputFile>.\Source/WinDebug\Diablo.exe</OutputFile>
<AdditionalDependencies>DiabloUI/WinDebug/DiabloUI.lib;3rdParty/Storm/Source/WinDebug/Storm.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DataExecutionPrevention>false</DataExecutionPrevention>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="3rdParty\PKWare\explode.cpp" />
<ClCompile Include="3rdParty\PKWare\implode.cpp" />
<ClCompile Include="Source\appfat.cpp" />
<ClCompile Include="Source\automap.cpp" />
<ClCompile Include="Source\capture.cpp" />
<ClCompile Include="Source\codec.cpp" />
<ClCompile Include="Source\control.cpp" />
<ClCompile Include="Source\cursor.cpp" />
<ClCompile Include="Source\dead.cpp" />
<ClCompile Include="Source\debug.cpp" />
<ClCompile Include="Source\diablo.cpp" />
<ClCompile Include="Source\doom.cpp" />
<ClCompile Include="Source\drlg_l1.cpp" />
<ClCompile Include="Source\drlg_l2.cpp" />
<ClCompile Include="Source\drlg_l3.cpp" />
<ClCompile Include="Source\drlg_l4.cpp" />
<ClCompile Include="Source\dthread.cpp" />
<ClCompile Include="Source\dx.cpp" />
<ClCompile Include="Source\effects.cpp" />
<ClCompile Include="Source\encrypt.cpp" />
<ClCompile Include="Source\engine.cpp" />
<ClCompile Include="Source\error.cpp" />
<ClCompile Include="Source\fault.cpp" />
<ClCompile Include="Source\gamemenu.cpp" />
<ClCompile Include="Source\gendung.cpp" />
<ClCompile Include="Source\gmenu.cpp" />
<ClCompile Include="Source\help.cpp" />
<ClCompile Include="Source\init.cpp" />
<ClCompile Include="Source\interfac.cpp" />
<ClCompile Include="Source\inv.cpp" />
<ClCompile Include="Source\items.cpp" />
<ClCompile Include="Source\lighting.cpp" />
<ClCompile Include="Source\loadsave.cpp" />
<ClCompile Include="Source\logging.cpp" />
<ClCompile Include="Source\mainmenu.cpp" />
<ClCompile Include="Source\minitext.cpp" />
<ClCompile Include="Source\missiles.cpp" />
<ClCompile Include="Source\monster.cpp" />
<ClCompile Include="Source\movie.cpp" />
<ClCompile Include="Source\mpqapi.cpp" />
<ClCompile Include="Source\msg.cpp" />
<ClCompile Include="Source\msgcmd.cpp" />
<ClCompile Include="Source\multi.cpp" />
<ClCompile Include="Source\nthread.cpp" />
<ClCompile Include="Source\objects.cpp" />
<ClCompile Include="Source\pack.cpp" />
<ClCompile Include="Source\palette.cpp" />
<ClCompile Include="Source\path.cpp" />
<ClCompile Include="Source\pfile.cpp" />
<ClCompile Include="Source\player.cpp" />
<ClCompile Include="Source\plrmsg.cpp" />
<ClCompile Include="Source\portal.cpp" />
<ClCompile Include="Source\quests.cpp" />
<ClCompile Include="Source\restrict.cpp" />
<ClCompile Include="Source\scrollrt.cpp" />
<ClCompile Include="Source\setmaps.cpp" />
<ClCompile Include="Source\sha.cpp" />
<ClCompile Include="Source\sound.cpp" />
<ClCompile Include="Source\spells.cpp" />
<ClCompile Include="Source\stores.cpp" />
<ClCompile Include="Source\sync.cpp" />
<ClCompile Include="Source\textdat.cpp" />
<ClCompile Include="Source\themes.cpp" />
<ClCompile Include="Source\tmsg.cpp" />
<ClCompile Include="Source\town.cpp" />
<ClCompile Include="Source\towners.cpp" />
<ClCompile Include="Source\track.cpp" />
<ClCompile Include="Source\trigs.cpp" />
<ClCompile Include="Source\wave.cpp" />
<ClCompile Include="Source\render.cpp" />
</ItemGroup>
<ItemGroup>
<Image Include="Diablo.ico" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Diablo.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="3rdParty\PKWare\pkware.h" />
<ClInclude Include="defs.h" />
<ClInclude Include="enums.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Source\appfat.h" />
<ClInclude Include="Source\automap.h" />
<ClInclude Include="Source\capture.h" />
<ClInclude Include="Source\codec.h" />
<ClInclude Include="Source\control.h" />
<ClInclude Include="Source\cursor.h" />
<ClInclude Include="Source\dead.h" />
<ClInclude Include="Source\debug.h" />
<ClInclude Include="Source\diablo.h" />
<ClInclude Include="Source\doom.h" />
<ClInclude Include="Source\drlg_l1.h" />
<ClInclude Include="Source\drlg_l2.h" />
<ClInclude Include="Source\drlg_l3.h" />
<ClInclude Include="Source\drlg_l4.h" />
<ClInclude Include="Source\dthread.h" />
<ClInclude Include="Source\dx.h" />
<ClInclude Include="Source\effects.h" />
<ClInclude Include="Source\encrypt.h" />
<ClInclude Include="Source\engine.h" />
<ClInclude Include="Source\error.h" />
<ClInclude Include="Source\fault.h" />
<ClInclude Include="Source\gamemenu.h" />
<ClInclude Include="Source\gendung.h" />
<ClInclude Include="Source\gmenu.h" />
<ClInclude Include="Source\help.h" />
<ClInclude Include="Source\init.h" />
<ClInclude Include="Source\interfac.h" />
<ClInclude Include="Source\inv.h" />
<ClInclude Include="Source\items.h" />
<ClInclude Include="Source\lighting.h" />
<ClInclude Include="Source\loadsave.h" />
<ClInclude Include="Source\logging.h" />
<ClInclude Include="Source\mainmenu.h" />
<ClInclude Include="Source\minitext.h" />
<ClInclude Include="Source\missiles.h" />
<ClInclude Include="Source\monster.h" />
<ClInclude Include="Source\movie.h" />
<ClInclude Include="Source\mpqapi.h" />
<ClInclude Include="Source\msg.h" />
<ClInclude Include="Source\msgcmd.h" />
<ClInclude Include="Source\multi.h" />
<ClInclude Include="Source\nthread.h" />
<ClInclude Include="Source\objects.h" />
<ClInclude Include="Source\pack.h" />
<ClInclude Include="Source\palette.h" />
<ClInclude Include="Source\path.h" />
<ClInclude Include="Source\pfile.h" />
<ClInclude Include="Source\player.h" />
<ClInclude Include="Source\plrmsg.h" />
<ClInclude Include="Source\portal.h" />
<ClInclude Include="Source\quests.h" />
<ClInclude Include="Source\restrict.h" />
<ClInclude Include="Source\scrollrt.h" />
<ClInclude Include="Source\setmaps.h" />
<ClInclude Include="Source\sha.h" />
<ClInclude Include="Source\sound.h" />
<ClInclude Include="Source\spells.h" />
<ClInclude Include="Source\stores.h" />
<ClInclude Include="Source\sync.h" />
<ClInclude Include="Source\textdat.h" />
<ClInclude Include="Source\themes.h" />
<ClInclude Include="Source\tmsg.h" />
<ClInclude Include="Source\town.h" />
<ClInclude Include="Source\towners.h" />
<ClInclude Include="Source\track.h" />
<ClInclude Include="Source\trigs.h" />
<ClInclude Include="Source\wave.h" />
<ClInclude Include="Source\render.h" />
<ClInclude Include="structs.h" />
<ClInclude Include="types.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="3rdParty\Storm\Source\Storm.vcxproj">
<Project>{b28f69ce-15a1-424d-bbb5-2727258d675b}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="DiabloUI\DiabloUI.vcxproj">
<Project>{8408e35e-3cf5-4d4e-b873-af3952cdabd4}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

467
Diablo.vcxproj.filters

@ -0,0 +1,467 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{0fb229f0-d459-4ec9-b897-317b016e0a57}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{52f34be1-947a-42ee-b303-4a46566a14a7}</UniqueIdentifier>
<Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{8003aed2-27a6-444b-8fb0-bb8a59530005}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl</Extensions>
</Filter>
<Filter Include="PKWare">
<UniqueIdentifier>{5dbacde9-4fc8-4776-ba59-92912e0c8ab5}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Source\appfat.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\automap.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\capture.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\codec.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\control.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\cursor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\dead.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\debug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\diablo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\doom.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\drlg_l1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\drlg_l2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\drlg_l3.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\drlg_l4.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\dthread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\dx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\effects.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\encrypt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\engine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\error.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\fault.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\gamemenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\gendung.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\gmenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\help.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\init.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\interfac.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\inv.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\items.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\lighting.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\loadsave.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\logging.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\mainmenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\minitext.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\missiles.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\monster.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\movie.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\mpqapi.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\msg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\msgcmd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\multi.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\nthread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\objects.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\pack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\palette.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\path.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\pfile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\player.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\plrmsg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\portal.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\quests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\restrict.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\scrollrt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\setmaps.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\sha.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\sound.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\spells.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\stores.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\sync.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\textdat.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\themes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\tmsg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\town.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\towners.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\track.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\trigs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\wave.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Source\render.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="3rdParty\PKWare\explode.cpp">
<Filter>PKWare</Filter>
</ClCompile>
<ClCompile Include="3rdParty\PKWare\implode.cpp">
<Filter>PKWare</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Image Include="Diablo.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Diablo.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\appfat.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\automap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\capture.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\codec.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\control.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\cursor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\dead.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\debug.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\diablo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\doom.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\drlg_l1.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\drlg_l2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\drlg_l3.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\drlg_l4.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\dthread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\dx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\effects.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\encrypt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\engine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\error.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\fault.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\gamemenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\gendung.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\gmenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\help.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\init.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\interfac.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\inv.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\items.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\lighting.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\loadsave.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\logging.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\mainmenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\minitext.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\missiles.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\monster.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\movie.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\mpqapi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\msg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\msgcmd.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\multi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\nthread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\objects.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\pack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\palette.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\path.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\pfile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\player.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\plrmsg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\portal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\quests.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\restrict.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\scrollrt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\setmaps.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\sha.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\sound.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\spells.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\stores.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\sync.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\textdat.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\themes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\tmsg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\town.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\towners.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\track.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\trigs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\wave.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Source\render.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="defs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="enums.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="structs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="3rdParty\PKWare\pkware.h">
<Filter>PKWare</Filter>
</ClInclude>
</ItemGroup>
</Project>

93
DiabloUI/DiabloUI.dsp

@ -0,0 +1,93 @@
# Microsoft Developer Studio Project File - Name="DiabloUI" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=DiabloUI - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "DiabloUI.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "DiabloUI.mak" CFG="DiabloUI - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "DiabloUI - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "DiabloUI - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "DiabloUI - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "WinRel"
# PROP BASE Intermediate_Dir "WinRel"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "WinRel"
# PROP Intermediate_Dir "WinRel"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"diabloui.def"
!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "WinDebug"
# PROP BASE Intermediate_Dir "WinDebug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "WinDebug"
# PROP Intermediate_Dir "WinDebug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /O1 /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /def:"diabloui.def" /pdbtype:sept
!ENDIF
# Begin Target
# Name "DiabloUI - Win32 Release"
# Name "DiabloUI - Win32 Debug"
# Begin Source File
SOURCE=.\diabloui.cpp
# End Source File
# End Target
# End Project

146
DiabloUI/DiabloUI.vcxproj

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<SccProjectName />
<SccLocalPath />
<ProjectGuid>{8408E35E-3CF5-4D4E-B873-AF3952CDABD4}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>.\WinRel\</OutDir>
<IntDir>.\WinRel\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>.\WinDebug\</OutDir>
<IntDir>.\WinDebug\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<StringPooling>true</StringPooling>
<FunctionLevelLinking>true</FunctionLevelLinking>
<Optimization>MaxSpeed</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>.\WinRel\</AssemblerListingLocation>
<PrecompiledHeaderOutputFile>.\WinRel\DiabloUI.pch</PrecompiledHeaderOutputFile>
<ObjectFileName>.\WinRel\</ObjectFileName>
<ProgramDataBaseFileName>.\WinRel\</ProgramDataBaseFileName>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\WinRel\DiabloUI.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<RedirectOutputAndErrors>NUL</RedirectOutputAndErrors>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\WinRel\DiabloUI.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>diabloui.def</ModuleDefinitionFile>
<OutputFile>.\WinRel\DiabloUI.dll</OutputFile>
<ImportLibrary>.\WinRel\DiabloUI.lib</ImportLibrary>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<Optimization>Disabled</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<MinimalRebuild>true</MinimalRebuild>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>.\WinDebug\</AssemblerListingLocation>
<PrecompiledHeaderOutputFile>.\WinDebug\DiabloUI.pch</PrecompiledHeaderOutputFile>
<ObjectFileName>.\WinDebug\</ObjectFileName>
<ProgramDataBaseFileName>.\WinDebug\</ProgramDataBaseFileName>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\WinDebug\DiabloUI.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<RedirectOutputAndErrors>NUL</RedirectOutputAndErrors>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\WinDebug\DiabloUI.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>diabloui.def</ModuleDefinitionFile>
<OutputFile>.\WinDebug\DiabloUI.dll</OutputFile>
<ImportLibrary>.\WinDebug\DiabloUI.lib</ImportLibrary>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="diabloui.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="diabloui.def" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="diabloui.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

61
DiabloUI/diabloui.cpp

@ -0,0 +1,61 @@
#include <windows.h>
#include <stdio.h>
#include <ddraw.h>
#include <dsound.h>
#include <io.h>
#include <math.h>
#include <time.h>
#include <process.h>
#include <shlobj.h>
#ifdef _MSC_VER
#pragma warning (disable : 4018) // signed/unsigned mismatch
#endif
#include "..\defs.h"
#include "..\enums.h"
#include "..\structs.h"
#include "diabloui.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void __cdecl UiDestroy() { return; }
void __stdcall UiTitleDialog(int a1) { return; }
void __cdecl UiInitialize() { return; }
void __stdcall UiCopyProtError(int a1) { return; }
void __stdcall UiAppActivate(int a1) { return; }
int __stdcall UiValidPlayerName(char *a1) { return 0; }
int __stdcall UiSelHeroMultDialog(void *fninfo, void *fncreate, void *fnremove, void *fnstats, int *a5, int *a6, char *name) { return 0; }
int __stdcall UiSelHeroSingDialog(void *fninfo, void *fncreate, void *fnremove, void *fnstats, int *a5, char *name, int *difficulty) { return 0; }
void __stdcall UiCreditsDialog(int a1) { return; }
int __stdcall UiMainMenuDialog(char *name, int *a2, void *fnSound, int a4) { return 0; }
int __stdcall UiProgressDialog(HWND window, char *msg, int a3, void *fnfunc, int a5) { return 0; }
int __cdecl UiProfileGetString() { return 0; }
void __cdecl UiProfileCallback() { return; }
void __cdecl UiProfileDraw() { return; }
void __cdecl UiCategoryCallback() { return; }
void __cdecl UiGetDataCallback() { return; }
void __cdecl UiAuthCallback() { return; }
void __cdecl UiSoundCallback() { return; }
void __cdecl UiMessageBoxCallback() { return; }
void __cdecl UiDrawDescCallback() { return; }
void __cdecl UiCreateGameCallback() { return; }
void __cdecl UiArtCallback() { return; }
int __stdcall UiSelectGame(int a1, _SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, _SNETVERSIONDATA *file_info, int *a6) { return 0; }
int __stdcall UiSelectProvider(int a1, _SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, _SNETVERSIONDATA *file_info, int *type) { return 0; }
int __stdcall UiCreatePlayerDescription(_uiheroinfo *info, int mode, char *desc) { return 0; }
int __stdcall UiSetupPlayerInfo(char *str, _uiheroinfo *info, int mode) { return 0; }

29
DiabloUI/diabloui.def

@ -0,0 +1,29 @@
LIBRARY "DiabloUI"
EXPORTS
UiDestroy
UiTitleDialog
UiInitialize
UiCopyProtError
UiAppActivate
UiValidPlayerName
UiSelHeroMultDialog
UiSelHeroSingDialog
UiCreditsDialog
UiMainMenuDialog
UiProgressDialog
UiProfileGetString
UiProfileCallback
UiProfileDraw
UiCategoryCallback
UiGetDataCallback
UiAuthCallback
UiSoundCallback
UiMessageBoxCallback
UiDrawDescCallback
UiCreateGameCallback
UiArtCallback
UiSelectGame
UiSelectProvider
UiCreatePlayerDescription
UiSetupPlayerInfo

40
DiabloUI/diabloui.h

@ -0,0 +1,40 @@
//HEADER_GOES_HERE
#ifndef __DIABLOUI_H__
#define __DIABLOUI_H__
#ifdef __GNUC__
extern "C" {
#endif
void __cdecl UiDestroy();
void __stdcall UiTitleDialog(int a1);
void __cdecl UiInitialize();
void __stdcall UiCopyProtError(int a1);
void __stdcall UiAppActivate(int a1);
int __stdcall UiValidPlayerName(char *a1);
int __stdcall UiSelHeroMultDialog(void *fninfo, void *fncreate, void *fnremove, void *fnstats, int *a5, int *a6, char *name);
int __stdcall UiSelHeroSingDialog(void (*fninfo)(void (__stdcall *ui_add_hero_info)(_uiheroinfo *)), void (*fncreate)(_uiheroinfo *heroinfo), void (*fnremove)(), void (*fnstats)(), int *a5, char *name, int *difficulty);
void __stdcall UiCreditsDialog(int a1);
int __stdcall UiMainMenuDialog(char *name, int *a2, void *fnSound, int a4);
int __stdcall UiProgressDialog(HWND window, char *msg, int a3, void *fnfunc, int a5);
int __cdecl UiProfileGetString();
void __cdecl UiProfileCallback();
void __cdecl UiProfileDraw();
void __cdecl UiCategoryCallback();
void __cdecl UiGetDataCallback();
void __cdecl UiAuthCallback();
void __cdecl UiSoundCallback();
void __cdecl UiMessageBoxCallback();
void __cdecl UiDrawDescCallback();
void __cdecl UiCreateGameCallback();
void __cdecl UiArtCallback();
int __stdcall UiSelectGame(int a1, _SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, _SNETVERSIONDATA *file_info, int *a6);
int __stdcall UiSelectProvider(int a1, _SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, _SNETVERSIONDATA *file_info, int *type);
int __stdcall UiCreatePlayerDescription(_uiheroinfo *info, int mode, char *desc);
int __stdcall UiSetupPlayerInfo(char *str, _uiheroinfo *info, int mode);
#ifdef __GNUC__
}
#endif
#endif /* __DIABLOUI_H__ */

48
DiabloUI/diabloui_gcc.def

@ -0,0 +1,48 @@
LIBRARY "DiabloUI"
EXPORTS
UiValidPlayerName @1 NONAME
UiValidPlayerName@4 @1 NONAME
UiAppActivate @2 NONAME
UiAppActivate@4 @2 NONAME
UiArtCallback @3 NONAME
UiAuthCallback @4 NONAME
UiBetaDisclaimer @5 NONAME
UiCategoryCallback @6 NONAME
UiCopyProtError @7 NONAME
UiCreateGameCallback @8 NONAME
UiCreateGameCriteria @9 NONAME
UiCreatePlayerDescription @10 NONAME
UiCreatePlayerDescription@12 @10 NONAME
UiCreditsDialog @11 NONAME
UiCreditsDialog@4 @11 NONAME
UiDestroy @12 NONAME
UiDrawDescCallback @13 NONAME
UiGetDataCallback @14 NONAME
UiGetDefaultStats @15 NONAME
UiInitialize @16 NONAME
UiMainMenuDialog @17 NONAME
UiMainMenuDialog@16 @17 NONAME
UiMessageBoxCallback @18 NONAME
UiOnPaint @19 NONAME
UiProfileCallback @20 NONAME
UiProfileDraw @21 NONAME
UiProfileGetString @22 NONAME
UiProgressDialog @23 NONAME
UiProgressDialog@20 @23 NONAME
UiSelHeroMultDialog @24 NONAME
UiSelHeroMultDialog@28 @24 NONAME
UiSelHeroSingDialog @25 NONAME
UiSelHeroSingDialog@28 @25 NONAME
UiSelectGame @26 NONAME
UiSelectGame@24 @26 NONAME
UiSelectProvider @27 NONAME
UiSelectProvider@24 @27 NONAME
UiSelectRegion @28 NONAME
UiSetBackgroundBitmap @29 NONAME
UiSetSpawned @30 NONAME
UiSetupPlayerInfo @31 NONAME
UiSetupPlayerInfo@12 @31 NONAME
UiSoundCallback @32 NONAME
UiTitleDialog @33 NONAME
UiTitleDialog@4 @33 NONAME

24
LICENSE

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <http://unlicense.org>

55
Makefile

@ -0,0 +1,55 @@
# mingw32 and mingw64 have different executables
ifdef MINGW32
CXX=mingw32-g++
DLLTOOL=dlltool
WINDRES=windres
else
CXX=i686-w64-mingw32-g++
DLLTOOL=i686-w64-mingw32-dlltool
WINDRES=i686-w64-mingw32-windres
endif
# Clang doesn't understand permissive compilation, we need to "fix" invalid
# casts from a pointer type there using
# static_cast<NEW_TYPE>(reinterpret_cast<uintptr_t>(ptr))
# instead of
# (NEW_TYPE)(ptr)
CXXFLAGS=-fpermissive -Wno-write-strings
CPPFLAGS=-MMD -MF $*.d
LDLIBS=-lgdi32 -lversion -ldiabloui -lstorm
LDFLAGS=-L./ -static-libgcc -mwindows
all: devilution.exe
debug: CXXFLAGS += -D_DEBUG
debug: CPPFLAGS += -D_DEBUG
debug: devilution.exe
DIABLO_SRC=$(wildcard Source/*.cpp)
OBJS=$(DIABLO_SRC:.cpp=.o)
PKWARE_SRC=$(wildcard 3rdParty/PKWare/*.cpp)
PKWARE_OBJS=$(PKWARE_SRC:.cpp=.o)
devilution.exe: $(OBJS) $(PKWARE_OBJS) diabres.o diabloui.lib storm.lib
$(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS)
diabres.o: Diablo.rc
$(WINDRES) $< $@
diabloui.lib: diabloui.dll DiabloUI/diabloui_gcc.def
$(DLLTOOL) -d DiabloUI/diabloui_gcc.def -D $< -l $@
diabloui.dll:
# $(error Please copy diabloui.dll (version 1.09[b]) here)
storm.lib: storm.dll 3rdParty/Storm/Source/storm_gcc.def
$(DLLTOOL) -d 3rdParty/Storm/Source/storm_gcc.def -D $< -l $@
storm.dll:
# $(error Please copy storm.dll (version 1.09[b]) here)
clean:
@$(RM) -v $(OBJS) $(OBJS:.o=.d) $(PKWARE_OBJS) $(PKWARE_OBJS:.o=d) diabres.o storm.lib diabloui.lib devilution.exe
.PHONY: clean all

83
MakefileVC

@ -0,0 +1,83 @@
VC5_DIR ?= $(HOME)/DevStudio_5.10/VC
# The $(VS6_DIR) directory is a copy of the "Microsoft Visual Studio" directory.
#
# To get a working setup on Linux or other "portable" copies of VS,
# the following DLLs have to be compied to the
# $(VS6_DIR)/VC98/Bin directory.
#
# - $(VS6_DIR)/Common/MSDev98/Bin/MSPDB60.DLL
VS6_DIR ?= $(HOME)/VS6
VC6_DIR = $(VS6_DIR)/VC98
VC6_BIN_DIR = $(VC6_DIR)/Bin
VC6_INC_DIR = $(VC6_DIR)/Include
VC6_LIB_DIR = $(VC6_DIR)/Lib
VC5_LIB_DIR = $(VC5_DIR)/lib
IDE_DIR ?= $(VS6_DIR)/Common/MSDev98
IDE_BIN_DIR = $(IDE_DIR)/bin
ifeq ($(OS),Windows_NT)
CL = $(VC6_BIN_DIR)/CL.EXE
RC = $(IDE_BIN_DIR)/RC.EXE
VC5_LINK = $(VC5_DIR)/bin/link.exe
VC6_LINK = $(VC6_BIN_DIR)/link.exe
else
CL = wine $(VC6_BIN_DIR)/CL.EXE
RC = wine $(IDE_BIN_DIR)/RC.EXE
VC5_LINK = wine $(VC5_DIR)/bin/link.exe
VC6_LINK = wine $(VC6_BIN_DIR)/link.exe
endif
CFLAGS=/nologo /c /GX /W3 /O1 /I $(VC6_INC_DIR) /FD /MT /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fp"Diablo.pch" /YX /Gm /Zi
LINKFLAGS=/nologo /subsystem:windows /machine:I386 /incremental:no
ifeq ($(MAKE_BUILD),pdb)
VC_LINK = $(VC6_LINK)
LINKFLAGS += /pdb:"Diablo.pdb" /LIBPATH:$(VC6_LIB_DIR) /debug
else
VC_LINK=$(VC5_LINK)
LINKFLAGS+= /LIBPATH:$(VC5_LIB_DIR)
endif
all: Diablo.exe
# fix compilation order to match the VC6 workspace files
DIABLO_SRC=$(sort $(filter-out Source/render.cpp, $(wildcard Source/*.cpp)))
DIABLO_SRC += Source/render.cpp
OBJS=$(DIABLO_SRC:.cpp=.obj)
PKWARE_SRC=$(sort $(wildcard 3rdParty/PKWare/*.cpp))
PKWARE_OBJS=$(PKWARE_SRC:.cpp=.obj)
STORM_SRC=$(sort $(wildcard 3rdParty/Storm/Source/*.cpp))
STORM_OBJS=$(STORM_SRC:.cpp=.obj)
DIABLOUI_SRC=$(sort $(wildcard DiabloUI/*.cpp))
DIABLOUI_OBJS=$(DIABLOUI_SRC:.cpp=.obj)
Diablo.exe: main_files $(PKWARE_OBJS) diablo.res DiabloUI/diabloui.lib 3rdParty/Storm/Source/storm.lib
$(VC_LINK) /OUT:$@ $(LINKFLAGS) $(OBJS) $(PKWARE_OBJS) diablo.res advapi32.lib gdi32.lib shell32.lib user32.lib version.lib DiabloUI/diabloui.lib 3rdParty/Storm/Source/storm.lib
DiabloUI/diabloui.lib: $(DIABLOUI_OBJS)
$(CL) $^ /link /LINK50COMPAT /nologo /dll /subsystem:windows /machine:I386 /LIBPATH:$(VC6_LIB_DIR) /def:"DiabloUI/diabloui.def" /out:DiabloUI/diabloui.dll
3rdParty/Storm/Source/storm.lib: $(STORM_OBJS)
$(CL) $^ /link /LINK50COMPAT /nologo /dll /subsystem:windows /machine:I386 /LIBPATH:$(VC6_LIB_DIR) /def:"3rdParty/Storm/Source/storm.def" /out:3rdParty/Storm/Source/storm.dll
# compiles all main source files with once compiler call
main_files:
$(CL) $(CFLAGS) /FoSource/ $(DIABLO_SRC)
%.obj: %.cpp
$(CL) $(CFLAGS) /Fo$@ $<
diablo.res: Diablo.rc
$(RC) /i $(VC6_INC_DIR) /i $(VC6_DIR)/MFC/Include /l 0x409 /fo $@ $<
clean:
@$(RM) -v $(OBJS) $(PKWARE_OBJS) $(STORM_OBJS) $(DIABLOUI_OBJS) DiabloUI/diabloui.{exp,lib,dll} 3rdParty/Storm/Source/storm.{exp,lib,dll}
.PHONY: clean all

152
README.md

@ -0,0 +1,152 @@
Devilution: [![Build Status](https://travis-ci.org/diasurgical/devilution.svg?branch=master)](https://travis-ci.org/diasurgical/devilution)
[![Build status](https://ci.appveyor.com/api/projects/status/ssk0xjhoka1uu940?svg=true)](https://ci.appveyor.com/project/galaxyhaxz/devilution)
Nightly: [![Build Status](https://travis-ci.com/diasurgical/devil-nightly.svg?branch=master)](https://travis-ci.com/diasurgical/devil-nightly)
[Discord](https://discord.gg/XEKDxHK)
# Devilution
Diablo devolved - magic behind the 1996 computer game
Reverse engineered by GalaXyHaXz in 2018
# Introduction
While most titles from Blizzard receive years of love and support, Diablo stayed in the shadows. Abandoned in favor of a sequel, it remained full of bugs and unfinished potential. The game was last patched in 2001 before being discontinued altogether, a problem I wanted to fix. I played Diablo extensively as a teenager, but as time passed it became difficult to run the game on newer hardware. The lack of many improvements found in the sequel also kept it from aging well. At first the game appeared to be a lost cause, but thankfully a little oversight in 1997 made it not so.
With Diablo's development team moving on the source code was given to **Synergistic Software** to handle the expansion. Less known however is that it was also given to **Climax Studios** to create a PlayStation port. Now Sony has long been known for letting things slide; _especially_ in Japan. Anything from leaking prototypes to full source code and Diablo was no exception. Symbolic information was accidentally left on the Japanese port. Normally used for debugging, a symbol file contains a map of everything generated during compile time. This includes file names, functions, structures, variables, and more! To top it all off a special build is hidden on the PC release in `DIABDAT.MPQ -> D1221A.MPQ -> DIABLO.EXE`! This build contains debug tools and assert strings further giving away code information.
After months of piecing these mistakes together, Devilution was born. I present to you a reconstructed form of Diablo's original source code! Once more shall the heroes of Sanctuary return to the depths below!
# Purpose
Having the source code makes Diablo much easier to update and maintain. For years mod-makers had to rely on tedious code editing and memory injection. A few even went further and reversed most or all of the game. The problem is that they rarely shared their work. Usually being a one-person job, they move on with their lives due to the amount of time required or lack of interest. This brings us back to square one having to do countless hours of work all over again. Devilution aims to fix this by finally making the source code open to the community.
In order to ensure that everything is preserved, Devilution keeps everything as it was originally designed. This goes as far as bugs and badly written code in the original game. With that it serves as a base for developers to work with making it much easier than before to update, fix, and port the game to other platforms.
As a side goal Devilution tries to document the unused and cut content from the final game. Development of Diablo was rushed near the end--many ideas were scrapped and multiplayer was quickly hacked in. By examining the source, we can see various quirks of planned development.
# Compiling
Diablo was developed on Windows 95 using Visual C++ 4.20 and later 5.10 and 6 for newer patches. Devilution is optimized for the same tools originally used but is also compatible with modern setups.
### Building with Visual C++ 6
- Open the project workspace `Diablo.dsw`, choose `Debug` or `Release`, and then `Build Diablo.exe`.
To build a binary with functions compiled as close as possible to the original, use [Visual C++ 6](https://winworldpc.com/product/visual-c/6x) with Service Pack 5 and the [Processor Pack](https://download.microsoft.com/download/vb60ent/update/6/w9x2kxp/en-us/vcpp5.exe) (**important for proper code genration!**)
If you aim to build a binary as close as possible to the original one you will also need [Visual C++ 5](https://winworldpc.com/product/visual-c/5x) with [Service Pack 3](http://www.mediafire.com/file/jw4j4sd5dnzze4p/VS97SP3.zip), since the original binary as linked with the older linker from that. Sadly, you cannot use the old linker right out of VC6, so you'll need to link manually or via the `MakefileVC` in the project root.
### Building with Visual Studio 2010-2017
- Open the project solution `Diablo.sln`, choose `Debug` or `Release`, and then `Build Solution`.
Make sure to disable Data Execution Prevention. `Storm.dll` uses dynamic compilation to improve rendering performance but fails to mark the resulting memory page as executable, leading to a protection fault when trying to draw.
- Configuration options -> Linker -> Advanced -> Data Execution Prevention (DEP).
- Set this value to: No (/NXCOMPAT: NO).
You will also need the following dependencies installed if you are using Visual Studio 2017.
Make sure to enable these when installing (or modify your installation):
- Requires "Windows 8.1 SDK" (Target Platform)
- Requires "Visual C++ MFC for x86 and x64" (For afxres.h)
- Requires "Windows Universal CRT SDK" (For ctype.h)
### Building XDiablo (For Linux)
Install the following libs on your machine.
- apt-get install g++-multilib libc6-dev-i386
- apt-get install libsdl2-dev:i386
- apt-get install libsdl2-ttf-dev:i386
- apt-get install libsdl2-image-dev:i386
- apt-get install libsdl2-mixer-dev:i386
- apt-get install cmake
Edit File that is linking all the LIBS for CMAKE.
For me it was located in...
/usr/lib/i386-linux-gnu/cmake/SDL2/sdl2-config.cmake
The last line will have something like...
set(SDL2_LIBRARIES "-L${SDL2_LIBDIR} -lSDL2
Change it to ...
set(SDL2_LIBRARIES "-L${SDL2_LIBDIR} -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf ")
Copy the "diablodat.mpq" from your Diablo CD to the Diablo Directory and make sure it is LOWERCASE.
Copy the Xresources and fonts file to your Diablo Directory.
Keep in mind please that this is still being worked on and is missing parts of UI and SoundEffects are not properly playing now.
### Building with MinGW
- Execute `make MINGW32=1` for **MinGW32** or `make` for **MinGW64**. Optionally add `debug` to build with debug features.
To compile with MinGW64 on different platforms, refer to the respective documentation: [Linux](Support/INSTALL_linux.md) | [Windows](Support/INSTALL_windows.md) | [Mac](Support/INSTALL_mac.md).
[Debug Build Features](Support/debug.md)
| [Compatibility Matrix](Support/compatibility_matrix.md)
| [Troubleshooting](Support/troubleshooting.md)
# Installing
Once compiled, the Devilution binary will serve as a replacement for `Diablo.exe`. The following files from the original game patched to 1.09(b) need to be present: `DIABDAT.MPQ`, `DiabloUI.dll`, `SmackW32.dll`, `Standard.snp`, and `Storm.dll`. If `COPYPROT` was defined when compiling, the Diablo CD will also be required.
Additionally, Strange Bytes' [DirectDraw patch](http://www.strangebytes.com/index.php/projects/1-diablo-1-windows-7-vista-patch) is recommended to help fix compatibility issues and run the game in windowed mode.
# Multiplayer
TODO
# Contributing
[Guidelines](Support/CONTRIBUTING.md)
# Modding
Here are some screenshots of a few things I tinkered around with, to demonstrate the relative ease of improving the game:
![Screenshot 1: Monster lifebar+items](https://s33.postimg.cc/6xnnhhlmn/diabuimon.png "Monster lifebar+items")
![Screenshot 2: New trade screen](https://s22.postimg.cc/5i5k91vht/diabstore.png "New trade screen, items that couldn't spawn")
# F.A.Q.
> Wow, does this mean I can download and play Diablo for free now?
No, you'll need access to the data from the original game. Blizzard has discontinued Diablo, but there's plenty of used copies floating around. (I'm still using an original 1996-disc in 2018 without problems)
> Cool, so I fired your mod up, but there's no 1080p or new features?
Devilution aims to keep the original code unaltered, for documentation purposes.
> So will you ever add cross-platform support or new features in the future?
Yes! However, this will be a **_side project_** based on Devilution. I have yet to announce the project.
> When and what can I expect from the upcoming project?
Honestly I have no idea. More than 1,200 hours went into creating Devilution, and I have other things going on right now. Maybe in 6-12 months? The goal is to create a native Linux port, convert to OpenGL, modernize the UI, etc. you get the drill. There has to be some surprises. ;)
> Ok, so I'm playing Devilution now and all the sudden it crashed. NOW WHAT??
Open an issue and provide as much information as possible (OS version, etc.) including any crash logs.
> I thought I'd fix the crash myself, but after looking at the code its a disaster. Do you speak v2-34-v8?
That is the result of decompiled code. Whenever a program is compiled, much of the source is optimized and stripped away, so it's nearly impossible to decompile it back. Have patience. Everything will be cleaned up eventually. :)
> Will you be reverse engineering Diablo II next? Ooooh please!
Absolutely not. Diablo II would require far more work and is still supported by Blizzard. Setting that aside, there are rumors that the game will be remastered which takes the point out of it.
> Are you interested in working for me? I have this game I want you to reverse...
Sorry, but no. This project is time consuming enough as it is, and it's just a hobby.
> I think that's about all, but is Devilution even legal?
That's a tricky question. Under the DMCA, reverse-engineering has exceptions for the purpose of documentation and interoperability. Devilution provides the necessary documentation needed to achieve the latter. However, it falls into an entirely gray area. The real question is whether or not Blizzard deems it necessary to take action.
# Credits
- [sanctuary](https://github.com/sanctuary) - extensively documenting Diablo's game engine
- [BWAPI Team](https://github.com/bwapi) - providing library API to work with Storm
- [Ladislav Zezula](https://github.com/ladislav-zezula) - reversing PKWARE library, further documenting Storm
- [fearedbliss](https://github.com/fearedbliss) - being awe-inspiring
- Climax Studios & Sony - secretly helping with their undercover QA :P
- Blizzard North - wait, this was a typo!
- Depression - reason to waste four months of my life doing this ;)
# Legal
This software is being released to the Public Domain. No assets of Diablo are being provided. You must own a copy of Diablo and have access to the assets beforehand in order to use this software.
Battle.net(R) - Copyright (C) 1996 Blizzard Entertainment, Inc. All rights reserved. Battle.net and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.
Diablo(R) - Copyright (C) 1996 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.
This software is in no way associated with or endorsed by Blizzard Entertainment(R).

437
Source/appfat.cpp

@ -0,0 +1,437 @@
//HEADER_GOES_HERE
#include "../types.h"
// +Infinity after initialization of appfat.cpp.
float appfat_cpp_init_value;
#ifndef NO_GLOBALS
char sz_error_buf[256];
int terminating; // weak
int cleanup_thread_id; // weak
#endif
char empty_string;
// appfat_cpp_init initializes the C++ runtime of appfat.cpp.
struct appfat_cpp_init {
appfat_cpp_init() {
appfat_cpp_init_value = INFINITY;
}
} appfat_cpp_init;
// delete overloads the delete operator.
void operator delete(void *ptr) {
if (ptr != NULL) {
SMemFree(ptr, "delete", -1, 0);
}
}
char *__fastcall GetErrorStr(int error_code)
{
int v1; // edi
unsigned int v2; // eax
signed int v4; // eax
char *i; // ecx
v1 = error_code;
v2 = ((unsigned int)error_code >> 16) & 0x1FFF;
if ( v2 == 0x0878 )
{
TraceErrorDS(error_code, sz_error_buf, 256);
}
else if ( v2 == 0x0876 )
{
TraceErrorDD(error_code, sz_error_buf, 256);
}
else
{
if ( !SErrGetErrorStr(error_code, sz_error_buf, 256) && !FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, v1, 0x400u, sz_error_buf, 0x100u, NULL) )
wsprintf(sz_error_buf, "unknown error 0x%08x", v1);
}
v4 = strlen(sz_error_buf);
for ( i = &sz_error_buf[v4-1]; v4 > 0; *i = 0 )
{
--v4;
--i;
if ( *i != '\r' && *i != '\n' )
break;
}
return sz_error_buf;
}
#define CASE_ERROR(v, errName) case errName: v = #errName; break;
void __fastcall TraceErrorDD(int error_code, char *error_buf, int error_buf_len)
{
const char *v3; // eax
char v4[20]; // [esp+0h] [ebp-14h]
switch (error_code) {
CASE_ERROR(v3, DDERR_CANTPAGEUNLOCK);
CASE_ERROR(v3, DDERR_NOTPAGELOCKED);
CASE_ERROR(v3, DD_OK);
CASE_ERROR(v3, DDERR_CANTPAGELOCK);
CASE_ERROR(v3, DDERR_BLTFASTCANTCLIP);
CASE_ERROR(v3, DDERR_NOBLTHW);
CASE_ERROR(v3, DDERR_NODDROPSHW);
CASE_ERROR(v3, DDERR_OVERLAYNOTVISIBLE);
CASE_ERROR(v3, DDERR_NOOVERLAYDEST);
CASE_ERROR(v3, DDERR_INVALIDPOSITION);
CASE_ERROR(v3, DDERR_NOTAOVERLAYSURFACE);
CASE_ERROR(v3, DDERR_EXCLUSIVEMODEALREADYSET);
CASE_ERROR(v3, DDERR_NOTFLIPPABLE);
CASE_ERROR(v3, DDERR_CANTDUPLICATE);
CASE_ERROR(v3, DDERR_NOTLOCKED);
CASE_ERROR(v3, DDERR_CANTCREATEDC);
CASE_ERROR(v3, DDERR_NODC);
CASE_ERROR(v3, DDERR_WRONGMODE);
CASE_ERROR(v3, DDERR_IMPLICITLYCREATED);
CASE_ERROR(v3, DDERR_NOTPALETTIZED);
CASE_ERROR(v3, DDERR_NOMIPMAPHW);
CASE_ERROR(v3, DDERR_INVALIDSURFACETYPE);
CASE_ERROR(v3, DDERR_DCALREADYCREATED);
CASE_ERROR(v3, DDERR_NOPALETTEHW);
CASE_ERROR(v3, DDERR_DIRECTDRAWALREADYCREATED);
CASE_ERROR(v3, DDERR_NODIRECTDRAWHW);
CASE_ERROR(v3, DDERR_PRIMARYSURFACEALREADYEXISTS);
CASE_ERROR(v3, DDERR_NOEMULATION);
CASE_ERROR(v3, DDERR_REGIONTOOSMALL);
CASE_ERROR(v3, DDERR_CLIPPERISUSINGHWND);
CASE_ERROR(v3, DDERR_NOCLIPPERATTACHED);
CASE_ERROR(v3, DDERR_NOHWND);
CASE_ERROR(v3, DDERR_HWNDSUBCLASSED);
CASE_ERROR(v3, DDERR_HWNDALREADYSET);
CASE_ERROR(v3, DDERR_NOPALETTEATTACHED);
CASE_ERROR(v3, DDERR_INVALIDDIRECTDRAWGUID);
CASE_ERROR(v3, DDERR_UNSUPPORTEDFORMAT);
CASE_ERROR(v3, DDERR_UNSUPPORTEDMASK);
CASE_ERROR(v3, DDERR_VERTICALBLANKINPROGRESS);
CASE_ERROR(v3, DDERR_WASSTILLDRAWING);
CASE_ERROR(v3, DDERR_XALIGN);
CASE_ERROR(v3, DDERR_TOOBIGWIDTH);
CASE_ERROR(v3, DDERR_CANTLOCKSURFACE);
CASE_ERROR(v3, DDERR_SURFACEISOBSCURED);
CASE_ERROR(v3, DDERR_SURFACELOST);
CASE_ERROR(v3, DDERR_SURFACENOTATTACHED);
CASE_ERROR(v3, DDERR_TOOBIGHEIGHT);
CASE_ERROR(v3, DDERR_TOOBIGSIZE);
CASE_ERROR(v3, DDERR_SURFACEBUSY);
CASE_ERROR(v3, DDERR_OVERLAYCOLORKEYONLYONEACTIVE);
CASE_ERROR(v3, DDERR_PALETTEBUSY);
CASE_ERROR(v3, DDERR_COLORKEYNOTSET);
CASE_ERROR(v3, DDERR_SURFACEALREADYATTACHED);
CASE_ERROR(v3, DDERR_SURFACEALREADYDEPENDENT);
CASE_ERROR(v3, DDERR_OVERLAYCANTCLIP);
CASE_ERROR(v3, DDERR_NOVSYNCHW);
CASE_ERROR(v3, DDERR_NOZBUFFERHW);
CASE_ERROR(v3, DDERR_NOZOVERLAYHW);
CASE_ERROR(v3, DDERR_OUTOFCAPS);
CASE_ERROR(v3, DDERR_OUTOFVIDEOMEMORY);
CASE_ERROR(v3, DDERR_NOTEXTUREHW);
CASE_ERROR(v3, DDERR_NOROTATIONHW);
CASE_ERROR(v3, DDERR_NOSTRETCHHW);
CASE_ERROR(v3, DDERR_NOT4BITCOLOR);
CASE_ERROR(v3, DDERR_NOT4BITCOLORINDEX);
CASE_ERROR(v3, DDERR_NOT8BITCOLOR);
CASE_ERROR(v3, DDERR_NORASTEROPHW);
CASE_ERROR(v3, DDERR_NOEXCLUSIVEMODE);
CASE_ERROR(v3, DDERR_NOFLIPHW);
CASE_ERROR(v3, DDERR_NOGDI);
CASE_ERROR(v3, DDERR_NOMIRRORHW);
CASE_ERROR(v3, DDERR_NOTFOUND);
CASE_ERROR(v3, DDERR_NOOVERLAYHW);
CASE_ERROR(v3, DDERR_NOCOLORKEYHW);
CASE_ERROR(v3, DDERR_NOALPHAHW);
CASE_ERROR(v3, DDERR_NOCLIPLIST);
CASE_ERROR(v3, DDERR_NOCOLORCONVHW);
CASE_ERROR(v3, DDERR_NOCOOPERATIVELEVELSET);
CASE_ERROR(v3, DDERR_NOCOLORKEY);
CASE_ERROR(v3, DDERR_NO3D);
CASE_ERROR(v3, DDERR_INVALIDMODE);
CASE_ERROR(v3, DDERR_INVALIDOBJECT);
CASE_ERROR(v3, DDERR_INVALIDPIXELFORMAT);
CASE_ERROR(v3, DDERR_INVALIDRECT);
CASE_ERROR(v3, DDERR_LOCKEDSURFACES);
CASE_ERROR(v3, DDERR_INVALIDCLIPLIST);
CASE_ERROR(v3, DDERR_CURRENTLYNOTAVAIL);
CASE_ERROR(v3, DDERR_EXCEPTION);
CASE_ERROR(v3, DDERR_HEIGHTALIGN);
CASE_ERROR(v3, DDERR_INCOMPATIBLEPRIMARY);
CASE_ERROR(v3, DDERR_INVALIDCAPS);
CASE_ERROR(v3, DDERR_CANNOTDETACHSURFACE);
CASE_ERROR(v3, DDERR_UNSUPPORTED);
CASE_ERROR(v3, DDERR_GENERIC);
CASE_ERROR(v3, DDERR_OUTOFMEMORY);
CASE_ERROR(v3, DDERR_INVALIDPARAMS);
CASE_ERROR(v3, DDERR_ALREADYINITIALIZED);
CASE_ERROR(v3, DDERR_CANNOTATTACHSURFACE);
default:
strcpy(v4, "DDERR unknown 0x%x");
sprintf(error_buf, v4, error_code);
return;
}
strncpy(error_buf, v3, error_buf_len);
}
void __fastcall TraceErrorDS(int error_code, char *error_buf, int error_buf_len)
{
const char *v3; // eax
char v4[20]; // [esp+0h] [ebp-14h]
switch (error_code) {
CASE_ERROR(v3, DSERR_PRIOLEVELNEEDED);
CASE_ERROR(v3, DSERR_BADFORMAT);
CASE_ERROR(v3, DSERR_NODRIVER);
CASE_ERROR(v3, DSERR_ALREADYINITIALIZED);
CASE_ERROR(v3, DSERR_BUFFERLOST);
CASE_ERROR(v3, DS_OK);
CASE_ERROR(v3, DSERR_INVALIDCALL);
CASE_ERROR(v3, E_NOINTERFACE);
CASE_ERROR(v3, DSERR_NOAGGREGATION);
CASE_ERROR(v3, DSERR_OUTOFMEMORY);
CASE_ERROR(v3, DSERR_INVALIDPARAM);
CASE_ERROR(v3, DSERR_ALLOCATED);
CASE_ERROR(v3, DSERR_CONTROLUNAVAIL);
default:
strcpy(v4, "DSERR unknown 0x%x");
sprintf(error_buf, v4, error_code);
return;
}
strncpy(error_buf, v3, error_buf_len);
}
char *__cdecl TraceLastError()
{
int v0; // eax
v0 = GetLastError();
return GetErrorStr(v0);
}
void TermMsg(char *pszFmt, ...)
{
va_list arglist; // [esp+8h] [ebp+8h]
va_start(arglist, pszFmt);
FreeDlg();
if ( pszFmt )
MsgBox(pszFmt, arglist);
init_cleanup(0);
exit(1);
}
void __fastcall MsgBox(char *pszFmt, va_list va)
{
char Text[256]; // [esp+0h] [ebp-100h]
wvsprintf(Text, pszFmt, va);
if ( ghMainWnd )
SetWindowPos(ghMainWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
MessageBox(ghMainWnd, Text, "ERROR", MB_TASKMODAL|MB_ICONHAND);
}
void __cdecl FreeDlg()
{
if ( terminating && cleanup_thread_id != GetCurrentThreadId() )
Sleep(20000u);
terminating = 1;
cleanup_thread_id = GetCurrentThreadId();
dx_cleanup();
if ( (unsigned char)gbMaxPlayers > 1u )
{
if ( SNetLeaveGame(3) )
Sleep(2000u);
}
SNetDestroy();
ShowCursor(1);
}
// 4B7A34: using guessed type int terminating;
// 4B7A38: using guessed type int cleanup_thread_id;
// 679660: using guessed type char gbMaxPlayers;
void DrawDlg(char *pszFmt, ...)
{
char text[256]; // [esp+0h] [ebp-100h]
va_list arglist; // [esp+10Ch] [ebp+Ch]
va_start(arglist, pszFmt);
wvsprintf(text, pszFmt, arglist);
SDrawMessageBox(text, "Diablo", MB_TASKMODAL|MB_ICONEXCLAMATION);
}
void __fastcall DDErrMsg(int error_code, int log_line_nr, char *log_file_path)
{
int v3; // esi
char *v4; // eax
v3 = log_line_nr;
if ( error_code )
{
v4 = GetErrorStr(error_code);
TermMsg("Direct draw error (%s:%d)\n%s", log_file_path, v3, v4);
}
}
void __fastcall DSErrMsg(int error_code, int log_line_nr, char *log_file_path)
{
int v3; // esi
char *v4; // eax
v3 = log_line_nr;
if ( error_code )
{
v4 = GetErrorStr(error_code);
TermMsg("Direct sound error (%s:%d)\n%s", log_file_path, v3, v4);
}
}
void __fastcall center_window(HWND hDlg)
{
LONG v1; // esi
LONG v2; // edi
int v3; // ebx
char *v4; // eax
struct tagRECT Rect; // [esp+Ch] [ebp-1Ch]
int v6; // [esp+1Ch] [ebp-Ch]
HDC hdc; // [esp+20h] [ebp-8h]
HWND hWnd; // [esp+24h] [ebp-4h]
hWnd = hDlg;
GetWindowRect(hDlg, &Rect);
v1 = Rect.right - Rect.left;
v2 = Rect.bottom - Rect.top;
hdc = GetDC(hWnd);
v6 = GetDeviceCaps(hdc, HORZRES);
v3 = GetDeviceCaps(hdc, VERTRES);
ReleaseDC(hWnd, hdc);
if ( !SetWindowPos(hWnd, HWND_TOP, (v6 - v1) / 2, (v3 - v2) / 2, 0, 0, SWP_NOZORDER|SWP_NOSIZE) )
{
v4 = TraceLastError();
TermMsg("center_window: %s", v4);
}
}
void __fastcall ErrDlg(int template_id, int error_code, char *log_file_path, int log_line_nr)
{
int v4; // ebx
int v5; // edi
char *v6; // esi
char *v7; // eax
char *v8; // eax
LPARAM dwInitParam[128]; // [esp+Ch] [ebp-200h]
v4 = error_code;
v5 = template_id;
FreeDlg();
v6 = log_file_path;
v7 = strrchr(log_file_path, '\\');
if ( v7 )
v6 = v7 + 1;
v8 = GetErrorStr(v4);
wsprintf((LPSTR)dwInitParam, "%s\nat: %s line %d", v8, v6, log_line_nr);
if ( DialogBoxParam(ghInst, MAKEINTRESOURCE(v5), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)dwInitParam) == -1 )
TermMsg("ErrDlg: %d", v5);
TermMsg(0);
}
BOOL __stdcall FuncDlg(HWND hDlg, UINT uMsg, WPARAM wParam, char *text)
{
if ( uMsg == WM_INITDIALOG )
{
TextDlg(hDlg, text);
}
else
{
if ( uMsg != WM_COMMAND )
return 0;
if ( (_WORD)wParam == 1 )
{
EndDialog(hDlg, 1);
}
else if ( (_WORD)wParam == 2 )
{
EndDialog(hDlg, 0);
}
}
return 1;
}
void __fastcall TextDlg(HWND hDlg, char *text)
{
char *v2; // esi
HWND v3; // edi
v2 = text;
v3 = hDlg;
center_window(hDlg);
if ( v2 )
SetDlgItemText(v3, 1000, v2);
}
void __fastcall ErrOkDlg(int template_id, int error_code, char *log_file_path, int log_line_nr)
{
char *v4; // esi
int v5; // edi
unsigned short v6; // bx
char *v7; // eax
char *v8; // eax
LPARAM dwInitParam[128]; // [esp+Ch] [ebp-200h]
v4 = log_file_path;
v5 = error_code;
v6 = template_id;
v7 = strrchr(log_file_path, '\\');
if ( v7 )
v4 = v7 + 1;
v8 = GetErrorStr(v5);
wsprintf((LPSTR)dwInitParam, "%s\nat: %s line %d", v8, v4, log_line_nr);
DialogBoxParam(ghInst, MAKEINTRESOURCE(v6), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)dwInitParam);
}
void __fastcall FileErrDlg(char *error)
{
char *v1; // esi
v1 = error;
FreeDlg();
if ( !v1 )
v1 = &empty_string;
if ( DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_DIALOG3), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)v1) == -1 )
TermMsg("FileErrDlg");
TermMsg(0);
}
void __fastcall DiskFreeDlg(char *error)
{
char *v1; // esi
v1 = error;
FreeDlg();
if ( DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_DIALOG7), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)v1) == -1 )
TermMsg("DiskFreeDlg");
TermMsg(0);
}
bool __cdecl InsertCDDlg()
{
int v0; // edi
ShowCursor(1);
v0 = DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_DIALOG9), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)&empty_string);
if ( v0 == -1 )
TermMsg("InsertCDDlg");
ShowCursor(0);
return v0 == 1;
}
void __fastcall DirErrorDlg(char *error)
{
char *v1; // esi
v1 = error;
FreeDlg();
if ( DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_DIALOG11), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)v1) == -1 )
TermMsg("DirErrorDlg");
TermMsg(0);
}

30
Source/appfat.h

@ -0,0 +1,30 @@
//HEADER_GOES_HERE
#ifndef __APPFAT_H__
#define __APPFAT_H__
extern char sz_error_buf[256];
extern int terminating; // weak
extern int cleanup_thread_id; // weak
extern char empty_string;
char *__fastcall GetErrorStr(int error_code);
void __fastcall TraceErrorDD(int error_code, char *error_buf, int error_buf_len);
void __fastcall TraceErrorDS(int error_code, char *error_buf, int error_buf_len);
char *__cdecl TraceLastError();
void TermMsg(char *pszFmt, ...);
void __fastcall MsgBox(char *pszFmt, va_list va);
void __cdecl FreeDlg();
void DrawDlg(char *pszFmt, ...);
void __fastcall DDErrMsg(int error_code, int log_line_nr, char *log_file_path);
void __fastcall DSErrMsg(int error_code, int log_line_nr, char *log_file_path);
void __fastcall center_window(HWND hDlg);
void __fastcall ErrDlg(int template_id, int error_code, char *log_file_path, int log_line_nr);
BOOL __stdcall FuncDlg(HWND hDlg, UINT uMsg, WPARAM wParam, char *text);
void __fastcall TextDlg(HWND hDlg, char *text);
void __fastcall ErrOkDlg(int template_id, int error_code, char *log_file_path, int log_line_nr);
void __fastcall FileErrDlg(char *error);
void __fastcall DiskFreeDlg(char *error);
bool __cdecl InsertCDDlg();
void __fastcall DirErrorDlg(char *error);
#endif /* __APPFAT_H__ */

943
Source/automap.cpp

@ -0,0 +1,943 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifndef NO_GLOBALS
short automaptype[512];
int AMdword_4B7E40; // weak
int AMdword_4B7E44; // weak
bool automapflag; // idb
char AMbyte_4B7E4C[32];
char automapview[DMAXX][DMAXY];
int AutoMapScale; // idb
int AutoMapXOfs; // weak
int AutoMapYOfs; // weak
int AutoMapPosBits; // weak
int AutoMapXPos; // weak
int AutoMapYPos; // weak
int AMPlayerX; // weak
int AMPlayerY; // weak
#endif
void __cdecl InitAutomapOnce()
{
automapflag = 0;
AutoMapScale = 50;
AutoMapPosBits = 32;
AutoMapXPos = 16;
AutoMapYPos = 8;
AMPlayerX = 4;
AMPlayerY = 2;
}
// 4B84B8: using guessed type int AutoMapPosBits;
// 4B84BC: using guessed type int AutoMapXPos;
// 4B84C0: using guessed type int AutoMapYPos;
// 4B84C4: using guessed type int AMPlayerX;
// 4B84C8: using guessed type int AMPlayerY;
void __cdecl InitAutomap()
{
signed int v0; // edi
signed int v1; // ecx
int v2; // esi
char v3; // al
int v4; // esi
char v5; // al
char *v6; // ecx
unsigned char *v7; // eax
int v8; // ecx
unsigned char *v9; // edx
unsigned int i; // esi
unsigned char v11; // bl
_BYTE *v12; // edx
signed int v13; // ecx
_BYTE *v14; // eax
signed int v15; // edx
int size; // [esp+Ch] [ebp-4h]
v0 = 50;
v1 = 0;
do
{
v2 = (v0 << 6) / 100;
v3 = 2 * (320 / v2);
v4 = 320 % v2;
v5 = v3 + 1;
AMbyte_4B7E4C[v1] = v5;
if ( v4 )
AMbyte_4B7E4C[v1] = v5 + 1;
if ( v4 >= 32 * v0 / 100 )
++AMbyte_4B7E4C[v1];
v0 += 5;
++v1;
}
while ( v1 < 31 );
memset(automaptype, 0, 0x400u);
switch ( leveltype )
{
case DTYPE_CATHEDRAL:
v6 = "Levels\\L1Data\\L1.AMP";
break;
case DTYPE_CATACOMBS:
v6 = "Levels\\L2Data\\L2.AMP";
break;
case DTYPE_CAVES:
v6 = "Levels\\L3Data\\L3.AMP";
break;
case DTYPE_HELL:
v6 = "Levels\\L4Data\\L4.AMP";
break;
default:
return;
}
v7 = LoadFileInMem(v6, &size);
size = (unsigned int)size >> 1;
v9 = v7;
for ( i = 1; i <= size; ++i )
{
v11 = *v9;
v12 = v9 + 1;
_LOWORD(v0) = v11;
_LOBYTE(v8) = *v12;
v9 = v12 + 1;
_LOWORD(v8) = (unsigned char)v8;
v8 = v0 + (v8 << 8);
automaptype[i] = v8;
}
mem_free_dbg(v7);
memset(automapview, 0, 0x640u);
v13 = 0;
do
{
v14 = (unsigned char *)dFlags + v13;
v15 = 112;
do
{
*v14 &= 0x7Fu;
v14 += 112;
--v15;
}
while ( v15 );
++v13;
}
while ( v13 < 112 );
}
// 5BB1ED: using guessed type char leveltype;
void __cdecl StartAutomap()
{
AutoMapXOfs = 0;
AutoMapYOfs = 0;
automapflag = 1;
}
// 4B84B0: using guessed type int AutoMapXOfs;
// 4B84B4: using guessed type int AutoMapYOfs;
void __cdecl AutomapUp()
{
--AutoMapXOfs;
--AutoMapYOfs;
}
// 4B84B0: using guessed type int AutoMapXOfs;
// 4B84B4: using guessed type int AutoMapYOfs;
void __cdecl AutomapDown()
{
++AutoMapXOfs;
++AutoMapYOfs;
}
// 4B84B0: using guessed type int AutoMapXOfs;
// 4B84B4: using guessed type int AutoMapYOfs;
void __cdecl AutomapLeft()
{
--AutoMapXOfs;
++AutoMapYOfs;
}
// 4B84B0: using guessed type int AutoMapXOfs;
// 4B84B4: using guessed type int AutoMapYOfs;
void __cdecl AutomapRight()
{
++AutoMapXOfs;
--AutoMapYOfs;
}
// 4B84B0: using guessed type int AutoMapXOfs;
// 4B84B4: using guessed type int AutoMapYOfs;
void __cdecl AutomapZoomIn()
{
if ( AutoMapScale < 200 )
{
AutoMapScale += 5;
AutoMapPosBits = (AutoMapScale << 6) / 100;
AutoMapXPos = AutoMapPosBits >> 1;
AutoMapYPos = AutoMapPosBits >> 2;
AMPlayerX = AutoMapPosBits >> 3;
AMPlayerY = AutoMapPosBits >> 4;
}
}
// 4B84B8: using guessed type int AutoMapPosBits;
// 4B84BC: using guessed type int AutoMapXPos;
// 4B84C0: using guessed type int AutoMapYPos;
// 4B84C4: using guessed type int AMPlayerX;
// 4B84C8: using guessed type int AMPlayerY;
void __cdecl AutomapZoomOut()
{
if ( AutoMapScale > 50 )
{
AutoMapScale -= 5;
AutoMapPosBits = (AutoMapScale << 6) / 100;
AutoMapXPos = AutoMapPosBits >> 1;
AutoMapYPos = AutoMapPosBits >> 2;
AMPlayerX = AutoMapPosBits >> 3;
AMPlayerY = AutoMapPosBits >> 4;
}
}
// 4B84B8: using guessed type int AutoMapPosBits;
// 4B84BC: using guessed type int AutoMapXPos;
// 4B84C0: using guessed type int AutoMapYPos;
// 4B84C4: using guessed type int AMPlayerX;
// 4B84C8: using guessed type int AMPlayerY;
void __cdecl DrawAutomap()
{
int v0; // eax
int v1; // ecx
int v2; // edx
int v3; // edx
int v4; // ecx
int v5; // eax
int v6; // esi
int v7; // edx
int v8; // edx
int v9; // esi
int v10; // ebx
int v11; // edi
int v12; // esi
int v13; // edi
int v14; // esi
int v15; // ebp
short v16; // ax
int v17; // ebp
short v18; // ax
int v19; // [esp+0h] [ebp-18h]
int screen_x; // [esp+4h] [ebp-14h]
int screen_xa; // [esp+4h] [ebp-14h]
int v22; // [esp+8h] [ebp-10h]
int ty; // [esp+Ch] [ebp-Ch]
int tya; // [esp+Ch] [ebp-Ch]
int v25; // [esp+10h] [ebp-8h]
int screen_y; // [esp+14h] [ebp-4h]
if ( leveltype != DTYPE_TOWN )
{
gpBufEnd = (unsigned char *)&gpBuffer->row[352];
v0 = AutoMapXOfs;
v1 = (ViewX - 16) >> 1;
v2 = AutoMapXOfs + v1;
if ( AutoMapXOfs + v1 < 0 )
{
do
{
++v0;
++v2;
}
while ( v2 < 0 );
AutoMapXOfs = v0;
}
v3 = v0 + v1;
if ( v0 + v1 >= 40 )
{
do
{
--v0;
--v3;
}
while ( v3 >= 40 );
AutoMapXOfs = v0;
}
v4 = v0 + v1;
AMdword_4B7E40 = v4;
v5 = AutoMapYOfs;
v6 = (ViewY - 16) >> 1;
v7 = AutoMapYOfs + v6;
if ( AutoMapYOfs + v6 < 0 )
{
do
{
++v5;
++v7;
}
while ( v7 < 0 );
AutoMapYOfs = v5;
}
v8 = v5 + v6;
if ( v5 + v6 >= 40 )
{
do
{
--v5;
--v8;
}
while ( v8 >= 40 );
AutoMapYOfs = v5;
}
v9 = v5 + v6;
AMdword_4B7E44 = v9;
v10 = AMbyte_4B7E4C[(AutoMapScale - 50) / 5];
if ( ScrollInfo._sxoff + ScrollInfo._syoff )
++v10;
v22 = v4 - v10;
v19 = v9 - 1;
if ( v10 & 1 )
{
v11 = 384 - AutoMapPosBits * ((v10 - 1) >> 1);
v12 = 336 - AutoMapXPos * ((v10 + 1) >> 1);
}
else
{
v11 = AutoMapXPos - AutoMapPosBits * (v10 >> 1) + 384;
v12 = 336 - AutoMapXPos * (v10 >> 1) - AutoMapYPos;
}
if ( ViewX & 1 )
{
v11 -= AutoMapYPos;
v12 -= AMPlayerX;
}
if ( ViewY & 1 )
{
v11 += AutoMapYPos;
v12 -= AMPlayerX;
}
v13 = (AutoMapScale * ScrollInfo._sxoff / 100 >> 1) + v11;
v14 = (AutoMapScale * ScrollInfo._syoff / 100 >> 1) + v12;
if ( invflag || sbookflag )
v13 -= 160;
if ( chrflag || questlog )
v13 += 160;
if ( v10 + 1 >= 0 )
{
v25 = v10 + 2;
do
{
v15 = 0;
screen_x = v13;
if ( v10 > 0 )
{
ty = v19;
do
{
v16 = GetAutomapType(v22 + v15, ty, 1);
if ( v16 )
DrawAutomapType(screen_x, v14, v16);
screen_x += AutoMapPosBits;
++v15;
--ty;
}
while ( v15 < v10 );
}
++v19;
screen_xa = 0;
v17 = v13 - AutoMapXPos;
screen_y = v14 + AutoMapYPos;
if ( v10 >= 0 )
{
tya = v19;
do
{
v18 = GetAutomapType(v22 + screen_xa, tya, 1);
if ( v18 )
DrawAutomapType(v17, screen_y, v18);
v17 += AutoMapPosBits;
++screen_xa;
--tya;
}
while ( screen_xa <= v10 );
}
++v22;
v14 += AutoMapXPos;
--v25;
}
while ( v25 );
}
DrawAutomapPlr();
DrawAutomapGame();
}
else
{
DrawAutomapGame();
}
}
// 4B7E40: using guessed type int AMdword_4B7E40;
// 4B7E44: using guessed type int AMdword_4B7E44;
// 4B84B0: using guessed type int AutoMapXOfs;
// 4B84B4: using guessed type int AutoMapYOfs;
// 4B84B8: using guessed type int AutoMapPosBits;
// 4B84BC: using guessed type int AutoMapXPos;
// 4B84C0: using guessed type int AutoMapYPos;
// 4B84C4: using guessed type int AMPlayerX;
// 4B8968: using guessed type int sbookflag;
// 5BB1ED: using guessed type char leveltype;
// 69BD04: using guessed type int questlog;
// 69CF0C: using guessed type int gpBufEnd;
void __fastcall DrawAutomapType(int screen_x, int screen_y, short automap_type)
{
short v3; // al
int v4; // ebx
int v5; // edi
int a3; // ST2C_4
int a1; // ST28_4
int a2; // ST24_4
int v9; // edx
int v10; // ST28_4
int v11; // ST2C_4
int v12; // ST24_4
int v13; // ST2C_4
int v14; // ST28_4
int v15; // ST24_4
int v16; // ST28_4
int v17; // ST24_4
int v18; // ST2C_4
int v19; // ST2C_4
int v20; // ST28_4
int v21; // ST24_4
int v22; // ST28_4
int v23; // ST2C_4
int v24; // ST24_4
int v25; // ST28_4
int v26; // ST24_4
int v27; // ST2C_4
int v28; // [esp-Ch] [ebp-34h]
int v29; // [esp-8h] [ebp-30h]
signed int v30; // [esp+Ch] [ebp-1Ch]
signed int v31; // [esp+10h] [ebp-18h]
signed int v32; // [esp+14h] [ebp-14h]
char v33; // [esp+27h] [ebp-1h]
int automap_typea; // [esp+30h] [ebp+8h]
int automap_typeb; // [esp+30h] [ebp+8h]
int automap_typec; // [esp+30h] [ebp+8h]
int automap_typed; // [esp+30h] [ebp+8h]
int automap_typee; // [esp+30h] [ebp+8h]
int automap_typef; // [esp+30h] [ebp+8h]
int automap_typeg; // [esp+30h] [ebp+8h]
v3 = automap_type;
v4 = screen_x;
v5 = screen_y;
v33 = _HIBYTE(automap_type);
if ( automap_type & 0x4000 )
{
ENG_set_pixel(screen_x, screen_y, 200);
ENG_set_pixel(v4 - AMPlayerX, v5 - AMPlayerY, 200);
ENG_set_pixel(v4 - AMPlayerX, AMPlayerY + v5, 200);
ENG_set_pixel(AMPlayerX + v4, v5 - AMPlayerY, 200);
ENG_set_pixel(AMPlayerX + v4, AMPlayerY + v5, 200);
ENG_set_pixel(v4 - AutoMapYPos, v5, 200);
ENG_set_pixel(AutoMapYPos + v4, v5, 200);
ENG_set_pixel(v4, v5 - AMPlayerX, 200);
ENG_set_pixel(v4, AMPlayerX + v5, 200);
ENG_set_pixel(v4 + AMPlayerX - AutoMapXPos, AMPlayerY + v5, 200);
ENG_set_pixel(v4 + AutoMapXPos - AMPlayerX, AMPlayerY + v5, 200);
ENG_set_pixel(v4 - AutoMapYPos, AMPlayerX + v5, 200);
ENG_set_pixel(AutoMapYPos + v4, AMPlayerX + v5, 200);
ENG_set_pixel(v4 - AMPlayerX, v5 + AutoMapYPos - AMPlayerY, 200);
ENG_set_pixel(AMPlayerX + v4, v5 + AutoMapYPos - AMPlayerY, 200);
ENG_set_pixel(v4, AutoMapYPos + v5, 200);
v3 = automap_type;
}
if ( automap_type < 0 )
{
DrawLine(v4 - AMPlayerX, v5 - AMPlayerX - AMPlayerY, v4 + AMPlayerX + AutoMapYPos, AMPlayerY + v5, 144);
DrawLine(v4 - AutoMapYPos, v5 - AMPlayerX, AutoMapYPos + v4, AMPlayerX + v5, 144);
DrawLine(v4 - AutoMapYPos - AMPlayerX, v5 - AMPlayerY, AMPlayerX + v4, v5 + AMPlayerX + AMPlayerY, 144);
DrawLine(v4 - AutoMapXPos, v5, v4, v5 + AutoMapYPos, 144);
v3 = automap_type;
}
v31 = 0;
v30 = 0;
v32 = 0;
switch ( v3 & 0xF )
{
case 1:
a3 = v4 - AutoMapYPos + AutoMapXPos;
a1 = v4 - AutoMapYPos;
a2 = v5 - AutoMapYPos;
automap_typea = v5 - AMPlayerX;
DrawLine(v4, v5 - AutoMapYPos, v4 - AutoMapYPos, v5 - AMPlayerX, 200);
DrawLine(v4, a2, a3, automap_typea, 200);
DrawLine(v4, v5, a1, automap_typea, 200);
v9 = v5;
v29 = automap_typea;
v28 = a3;
goto LABEL_36;
case 2:
case 5:
goto LABEL_8;
case 3:
case 6:
goto LABEL_17;
case 4:
v31 = 1;
goto LABEL_8;
case 7:
goto LABEL_25;
case 8:
v30 = 1;
LABEL_8:
if ( automap_type & 0x100 )
{
v10 = v4 - AutoMapXPos;
v11 = v4 - AutoMapYPos;
v12 = v5 - AutoMapYPos;
automap_typeb = v5 - AMPlayerX;
DrawLine(v4, v5 - AutoMapYPos, v4 - AMPlayerX, v5 - AutoMapYPos + AMPlayerY, 200);
DrawLine(v10, v5, v10 + AMPlayerX, v5 - AMPlayerY, 200);
DrawLine(v11, v12, v10, automap_typeb, 144);
DrawLine(v11, v12, v4, automap_typeb, 144);
DrawLine(v11, v5, v10, automap_typeb, 144);
DrawLine(v11, v5, v4, automap_typeb, 144);
}
if ( v33 & 0x10 )
{
DrawLine(v4 - AutoMapYPos, v5 - AMPlayerX, v4 - AutoMapXPos, v5, 200);
v33 |= 4u;
}
if ( v33 & 4 )
{
v13 = v4 - AutoMapYPos + AutoMapXPos;
v14 = v4 - AutoMapYPos;
v15 = v5 - AutoMapYPos;
automap_typec = v5 - AMPlayerX;
DrawLine(v4, v5 - AutoMapYPos, v4 - AutoMapYPos, v5 - AMPlayerX, 200);
DrawLine(v4, v15, v13, automap_typec, 200);
DrawLine(v4, v5, v14, automap_typec, 200);
DrawLine(v4, v5, v13, automap_typec, 200);
}
if ( !(v33 & 0x15) )
DrawLine(v4, v5 - AutoMapYPos, v4 - AutoMapXPos, v5, 200);
if ( v31 )
goto LABEL_17;
goto LABEL_25;
case 9:
v32 = 1;
LABEL_17:
if ( v33 & 2 )
{
v16 = AutoMapYPos + v4;
v17 = v5 - AutoMapYPos;
v18 = v4 + AutoMapXPos;
automap_typed = v5 - AMPlayerX;
DrawLine(v4, v5 - AutoMapYPos, v4 + AMPlayerX, v5 - AutoMapYPos + AMPlayerY, 200);
DrawLine(v18, v5, v18 - AMPlayerX, v5 - AMPlayerY, 200);
DrawLine(v16, v17, v4, automap_typed, 144);
DrawLine(v16, v17, v18, automap_typed, 144);
DrawLine(v16, v5, v4, automap_typed, 144);
DrawLine(v16, v5, v18, automap_typed, 144);
}
if ( v33 & 0x20 )
{
DrawLine(AutoMapYPos + v4, v5 - AMPlayerX, v4 + AutoMapXPos, v5, 200);
v33 |= 8u;
}
if ( v33 & 8 )
{
v19 = v4 - AutoMapYPos + AutoMapXPos;
v20 = v4 - AutoMapYPos;
v21 = v5 - AutoMapYPos;
automap_typee = v5 - AMPlayerX;
DrawLine(v4, v5 - AutoMapYPos, v4 - AutoMapYPos, v5 - AMPlayerX, 200);
DrawLine(v4, v21, v19, automap_typee, 200);
DrawLine(v4, v5, v20, automap_typee, 200);
DrawLine(v4, v5, v19, automap_typee, 200);
}
if ( !(v33 & 0x2A) )
DrawLine(v4, v5 - AutoMapYPos, v4 + AutoMapXPos, v5, 200);
LABEL_25:
if ( v30 )
goto LABEL_26;
goto LABEL_32;
case 0xA:
goto LABEL_26;
case 0xB:
goto LABEL_33;
case 0xC:
v32 = 1;
LABEL_26:
if ( v33 & 1 )
{
v22 = v4 - AutoMapXPos;
v23 = v4 - AutoMapYPos;
v24 = AutoMapYPos + v5;
automap_typef = AMPlayerX + v5;
DrawLine(v4, AutoMapYPos + v5, v4 - AMPlayerX, AutoMapYPos + v5 - AMPlayerY, 200);
DrawLine(v22, v5, v22 + AMPlayerX, v5 + AMPlayerY, 200);
DrawLine(v23, v24, v22, automap_typef, 144);
DrawLine(v23, v24, v4, automap_typef, 144);
DrawLine(v23, v5, v22, automap_typef, 144);
DrawLine(v23, v5, v4, automap_typef, 144);
}
else
{
DrawLine(v4, AutoMapYPos + v5, v4 - AutoMapXPos, v5, 200);
}
LABEL_32:
if ( v32 )
{
LABEL_33:
if ( v33 & 2 )
{
v25 = AutoMapYPos + v4;
v26 = AutoMapYPos + v5;
v27 = v4 + AutoMapXPos;
automap_typeg = AMPlayerX + v5;
DrawLine(v4, AutoMapYPos + v5, v4 + AMPlayerX, AutoMapYPos + v5 - AMPlayerY, 200);
DrawLine(v27, v5, v27 - AMPlayerX, v5 + AMPlayerY, 200);
DrawLine(v25, v26, v4, automap_typeg, 144);
DrawLine(v25, v26, v27, automap_typeg, 144);
DrawLine(v25, v5, v4, automap_typeg, 144);
DrawLine(v25, v5, v27, automap_typeg, 144);
}
else
{
v29 = v5;
v28 = v4 + AutoMapXPos;
v9 = AutoMapYPos + v5;
LABEL_36:
DrawLine(v4, v9, v28, v29, 200);
}
}
break;
default:
return;
}
}
// 4B84BC: using guessed type int AutoMapXPos;
// 4B84C0: using guessed type int AutoMapYPos;
// 4B84C4: using guessed type int AMPlayerX;
// 4B84C8: using guessed type int AMPlayerY;
void __cdecl DrawAutomapPlr()
{
int v0; // ebx
int v1; // eax
int v2; // ecx
int v3; // esi
int v4; // edi
int v5; // edx
int v6; // ecx
int v7; // eax
int v8; // ecx
int v9; // [esp-Ch] [ebp-20h]
int v10; // [esp-8h] [ebp-1Ch]
int v11; // [esp+Ch] [ebp-8h]
int v12; // [esp+10h] [ebp-4h]
v0 = myplr;
if ( plr[myplr]._pmode == PM_WALK3 )
{
v1 = plr[v0]._px;
v2 = plr[v0]._py;
if ( plr[v0]._pdir == 2 )
++v1;
else
++v2;
}
else
{
v1 = plr[v0].WorldX;
v2 = plr[v0].WorldY;
}
v11 = v1 - 2 * AutoMapXOfs - ViewX;
v12 = v2 - 2 * AutoMapYOfs - ViewY;
v3 = (AutoMapScale * ScrollInfo._sxoff / 100 >> 1)
+ (AutoMapScale * plr[v0]._pxoff / 100 >> 1)
+ AutoMapYPos * (v11 - v12)
+ 384;
if ( invflag || sbookflag )
v3 = (AutoMapScale * ScrollInfo._sxoff / 100 >> 1)
+ (AutoMapScale * plr[v0]._pxoff / 100 >> 1)
+ AutoMapYPos * (v11 - v12)
+ 224;
if ( chrflag || questlog )
v3 += 160;
v4 = AMPlayerX * (v12 + v11)
+ (AutoMapScale * ScrollInfo._syoff / 100 >> 1)
+ (AutoMapScale * plr[v0]._pyoff / 100 >> 1)
+ 336
- AMPlayerX;
switch ( plr[v0]._pdir )
{
case DIR_S:
DrawLine(v3, v4, v3, v4 + AutoMapYPos, 153);
DrawLine(v3, AutoMapYPos + v4, v3 + AMPlayerY, v4 + AMPlayerX, 153);
v10 = v4 + AMPlayerX;
v9 = v3 - AMPlayerY;
v5 = AutoMapYPos + v4;
goto LABEL_19;
case DIR_SW:
DrawLine(
v3,
AMPlayerX * (v12 + v11)
+ (AutoMapScale * ScrollInfo._syoff / 100 >> 1)
+ (AutoMapScale * plr[v0]._pyoff / 100 >> 1)
+ 336
- AMPlayerX,
v3 - AutoMapYPos,
AMPlayerX * (v12 + v11)
+ (AutoMapScale * ScrollInfo._syoff / 100 >> 1)
+ (AutoMapScale * plr[v0]._pyoff / 100 >> 1)
+ 336,
153);
DrawLine(v3 - AutoMapYPos, AMPlayerX + v4, v3 - AMPlayerY - AMPlayerX, v4, 153);
v7 = AMPlayerX;
v8 = v3;
v5 = AMPlayerX + v4;
v10 = AMPlayerX + v4;
goto LABEL_23;
case DIR_W:
DrawLine(v3, v4, v3 - AutoMapYPos, v4, 153);
DrawLine(v3 - AutoMapYPos, v4, v3 - AMPlayerX, v4 - AMPlayerY, 153);
v5 = v4;
v10 = v4 + AMPlayerY;
v9 = v3 - AMPlayerX;
goto LABEL_24;
case DIR_NW:
DrawLine(v3, v4, v3 - AutoMapYPos, v4 - AMPlayerX, 153);
DrawLine(v3 - AutoMapYPos, v4 - AMPlayerX, v3 - AMPlayerX, v4 - AMPlayerX, 153);
v7 = AMPlayerX;
v8 = v3 - AMPlayerY;
v10 = v4;
v5 = v4 - AMPlayerX;
LABEL_23:
v9 = v8 - v7;
LABEL_24:
v6 = v3 - AutoMapYPos;
goto LABEL_25;
case DIR_N:
DrawLine(v3, v4, v3, v4 - AutoMapYPos, 153);
DrawLine(v3, v4 - AutoMapYPos, v3 - AMPlayerY, v4 - AMPlayerX, 153);
v10 = v4 - AMPlayerX;
v5 = v4 - AutoMapYPos;
v9 = v3 + AMPlayerY;
LABEL_19:
v6 = v3;
goto LABEL_25;
case DIR_NE:
DrawLine(v3, v4, v3 + AutoMapYPos, v4 - AMPlayerX, 153);
DrawLine(AutoMapYPos + v3, v4 - AMPlayerX, v3 + AMPlayerX, v4 - AMPlayerX, 153);
v10 = v4;
v9 = v3 + AMPlayerX + AMPlayerY;
v5 = v4 - AMPlayerX;
goto LABEL_17;
case DIR_E:
DrawLine(v3, v4, v3 + AutoMapYPos, v4, 153);
DrawLine(AutoMapYPos + v3, v4, v3 + AMPlayerX, v4 - AMPlayerY, 153);
DrawLine(AutoMapYPos + v3, v4, v3 + AMPlayerX, v4 + AMPlayerY, 153);
break;
case DIR_SE:
DrawLine(
v3,
AMPlayerX * (v12 + v11)
+ (AutoMapScale * ScrollInfo._syoff / 100 >> 1)
+ (AutoMapScale * plr[v0]._pyoff / 100 >> 1)
+ 336
- AMPlayerX,
v3 + AutoMapYPos,
AMPlayerX * (v12 + v11)
+ (AutoMapScale * ScrollInfo._syoff / 100 >> 1)
+ (AutoMapScale * plr[v0]._pyoff / 100 >> 1)
+ 336,
153);
DrawLine(AutoMapYPos + v3, AMPlayerX + v4, v3 + AMPlayerX + AMPlayerY, v4, 153);
v5 = AMPlayerX + v4;
v10 = AMPlayerX + v4;
v9 = v3 + AMPlayerX;
LABEL_17:
v6 = AutoMapYPos + v3;
LABEL_25:
DrawLine(v6, v5, v9, v10, 153);
break;
default:
return;
}
}
// 4B84B0: using guessed type int AutoMapXOfs;
// 4B84B4: using guessed type int AutoMapYOfs;
// 4B84C0: using guessed type int AutoMapYPos;
// 4B84C4: using guessed type int AMPlayerX;
// 4B84C8: using guessed type int AMPlayerY;
// 4B8968: using guessed type int sbookflag;
// 69BD04: using guessed type int questlog;
short __fastcall GetAutomapType(int x, int y, BOOL view)
{
int v3; // edi
int v4; // esi
int v6; // eax
short v7; // bp
v3 = y;
v4 = x;
if ( view )
{
if ( x == -1 && y >= 0 && y < 40 && automapview[0][y] )
{
x = 0;
return ~GetAutomapType(x, y, 0) & 0x4000;
}
if ( y == -1 )
{
if ( x < 0 )
return 0;
if ( x < 40 && automapview[x][0] )
{
y = 0;
return ~GetAutomapType(x, y, 0) & 0x4000;
}
}
}
if ( x < 0 )
return 0;
if ( x >= 40 )
return 0;
if ( y < 0 )
return 0;
if ( y >= 40 )
return 0;
v6 = y + 40 * x;
if ( !automapview[0][v6] && view )
return 0;
v7 = automaptype[(unsigned char)dungeon[0][v6]];
if ( v7 == 7 && ((unsigned short)GetAutomapType(x - 1, y, 0) >> 8) & 8 )
{
if ( ((unsigned short)GetAutomapType(v4, v3 - 1, 0) >> 8) & 4 )
v7 = 1;
}
return v7;
}
void __cdecl DrawAutomapGame()
{
int v0; // esi
char *v1; // eax
char *v2; // eax
char v3[256]; // [esp+4h] [ebp-100h]
v0 = 20;
if ( (unsigned char)gbMaxPlayers > 1u )
{
v1 = strcpy(v3, "game: ");
strcat(v1, szPlayerName);
PrintGameStr(8, 20, v3, 3);
v0 = 35;
if ( szPlayerDescript[0] )
{
v2 = strcpy(v3, "password: ");
strcat(v2, szPlayerDescript);
PrintGameStr(8, 35, v3, 3);
v0 = 50;
}
}
if ( setlevel )
{
PrintGameStr(8, v0, quest_level_names[(unsigned char)setlvlnum], 3);
}
else if ( currlevel )
{
sprintf(v3, "Level: %i", currlevel);
PrintGameStr(8, v0, v3, 3);
}
}
// 5CCB10: using guessed type char setlvlnum;
// 5CF31D: using guessed type char setlevel;
// 679660: using guessed type char gbMaxPlayers;
void __fastcall SetAutomapView(int x, int y)
{
int xx = (x - 16) >> 1;
int yy = (y - 16) >> 1;
if ( xx < 0 || xx >= DMAXX || yy < 0 || yy >= DMAXY ) {
return;
}
automapview[xx][yy] = 1;
USHORT maptype = GetAutomapType(xx, yy, FALSE);
USHORT solid = maptype & 0x4000;
switch ( maptype & 0xF ) {
case 2:
if ( solid ) {
if ( GetAutomapType(xx, yy + 1, FALSE) == 0x4007 )
automapview[xx][yy + 1] = 1;
}
else if ( GetAutomapType(xx - 1, yy, FALSE) & 0x4000 )
automapview[xx - 1][yy] = 1;
break;
case 3:
if ( solid ) {
if ( GetAutomapType(xx + 1, yy, FALSE) == 0x4007 )
automapview[xx + 1][yy] = 1;
}
else if ( GetAutomapType(xx, yy - 1, FALSE) & 0x4000 )
automapview[xx][yy - 1] = 1;
break;
case 4:
if ( solid ) {
if ( GetAutomapType(xx, yy + 1, FALSE) == 0x4007 )
automapview[xx][yy + 1] = 1;
if ( GetAutomapType(xx + 1, yy, FALSE) == 0x4007 )
automapview[xx + 1][yy] = 1;
}
else {
if ( GetAutomapType(xx - 1, yy, FALSE) & 0x4000 )
automapview[xx - 1][yy] = 1;
if ( GetAutomapType(xx, yy - 1, FALSE) & 0x4000 )
automapview[xx][yy - 1] = 1;
if ( GetAutomapType(xx - 1, yy - 1, FALSE) & 0x4000 )
automapview[xx - 1][yy - 1] = 1;
}
break;
case 5:
if ( solid ) {
if ( GetAutomapType(xx, yy - 1, FALSE) & 0x4000 )
automapview[xx][yy - 1] = 1;
if ( GetAutomapType(xx, yy + 1, FALSE) == 0x4007 )
automapview[xx][yy + 1] = 1;
}
else if ( GetAutomapType(xx - 1, yy, FALSE) & 0x4000 )
automapview[xx - 1][yy] = 1;
break;
case 6:
if ( solid ) {
if ( GetAutomapType(xx - 1, yy, FALSE) & 0x4000 )
automapview[xx - 1][yy] = 1;
if ( GetAutomapType(xx + 1, yy, FALSE) == 0x4007 )
automapview[xx + 1][yy] = 1;
}
else if ( GetAutomapType(xx, yy - 1, FALSE) & 0x4000 )
automapview[xx][yy - 1] = 1;
}
}
void __cdecl AutomapZoomReset()
{
AutoMapXOfs = 0;
AutoMapYOfs = 0;
AutoMapPosBits = (AutoMapScale << 6) / 100;
AutoMapXPos = AutoMapPosBits >> 1;
AutoMapYPos = AutoMapPosBits >> 2;
AMPlayerX = AutoMapPosBits >> 3;
AMPlayerY = AutoMapPosBits >> 4;
}
// 4B84B0: using guessed type int AutoMapXOfs;
// 4B84B4: using guessed type int AutoMapYOfs;
// 4B84B8: using guessed type int AutoMapPosBits;
// 4B84BC: using guessed type int AutoMapXPos;
// 4B84C0: using guessed type int AutoMapYPos;
// 4B84C4: using guessed type int AMPlayerX;
// 4B84C8: using guessed type int AMPlayerY;

37
Source/automap.h

@ -0,0 +1,37 @@
//HEADER_GOES_HERE
#ifndef __AUTOMAP_H__
#define __AUTOMAP_H__
extern short automaptype[512];
extern int AMdword_4B7E40; // weak
extern int AMdword_4B7E44; // weak
extern bool automapflag; // idb
extern char AMbyte_4B7E4C[32];
extern char automapview[DMAXX][DMAXY];
extern int AutoMapScale; // idb
extern int AutoMapXOfs; // weak
extern int AutoMapYOfs; // weak
extern int AutoMapPosBits; // weak
extern int AutoMapXPos; // weak
extern int AutoMapYPos; // weak
extern int AMPlayerX; // weak
extern int AMPlayerY; // weak
void __cdecl InitAutomapOnce();
void __cdecl InitAutomap();
void __cdecl StartAutomap();
void __cdecl AutomapUp();
void __cdecl AutomapDown();
void __cdecl AutomapLeft();
void __cdecl AutomapRight();
void __cdecl AutomapZoomIn();
void __cdecl AutomapZoomOut();
void __cdecl DrawAutomap();
void __fastcall DrawAutomapType(int screen_x, int screen_y, short automap_type);
void __cdecl DrawAutomapPlr();
short __fastcall GetAutomapType(int x, int y, BOOL view);
void __cdecl DrawAutomapGame();
void __fastcall SetAutomapView(int x, int y);
void __cdecl AutomapZoomReset();
#endif /* __AUTOMAP_H__ */

173
Source/capture.cpp

@ -0,0 +1,173 @@
//HEADER_GOES_HERE
#include "../types.h"
void __cdecl CaptureScreen()
{
PALETTEENTRY palette[256];
char FileName[MAX_PATH];
HANDLE hObject = CaptureFile(FileName);
if ( hObject != INVALID_HANDLE_VALUE)
{
DrawAndBlit();
lpDDPalette->GetEntries(0, 0, 256, palette);
RedPalette(palette);
lock_buf_priv();
bool success = CaptureHdr(hObject, 640, 480);
if (success)
{
success = CapturePix(hObject, 640, 480, 768, (BYTE*)gpBuffer->row[0].pixels);
if (success)
{
success = CapturePal(hObject, palette);
}
}
unlock_buf_priv();
CloseHandle(hObject);
if (!success)
DeleteFile(FileName);
Sleep(300);
lpDDPalette->SetEntries(0, 0, 256, palette);
}
}
bool __fastcall CaptureHdr(HANDLE hFile, short width, short height)
{
PCXHeader Buffer;
memset(&Buffer, 0, sizeof(Buffer));
Buffer.xmax = width - 1;
Buffer.vertRes = height;
Buffer.manufacturer = 10;
Buffer.version = 5;
Buffer.encoding = 1;
Buffer.bitsPerPixel = 8;
Buffer.ymax = height - 1;
Buffer.horzRes = width;
Buffer.numColorPlanes = 1;
Buffer.bytesPerScanLine = width;
DWORD lpNumBytes;
return WriteFile(hFile, &Buffer, sizeof(Buffer), &lpNumBytes, NULL) && lpNumBytes == sizeof(Buffer);
}
bool __fastcall CapturePal(HANDLE hFile, PALETTEENTRY *palette)
{
char *v3;
char Buffer[769];
Buffer[0] = 12;
v3 = &Buffer[1];
for (int i = 256; i != 0; --i)
{
v3[0] = palette->peRed;
v3[1] = palette->peGreen;
v3[2] = palette->peBlue;
palette++;
v3 += 3;
}
DWORD lpNumBytes;
return WriteFile(hFile, Buffer, sizeof(Buffer), &lpNumBytes, NULL) && lpNumBytes == sizeof(Buffer);
}
bool __fastcall CapturePix(HANDLE hFile, WORD width, WORD height, WORD stride, BYTE *pixels)
{
int writeSize;
DWORD lpNumBytes;
BYTE *pBuffer = (BYTE *)DiabloAllocPtr(2 * width);
do
{
if ( !height )
{
mem_free_dbg(pBuffer);
return 1;
}
height--;
BYTE *pBufferEnd = CaptureEnc(pixels, pBuffer, width);
pixels += stride;
writeSize = pBufferEnd - pBuffer;
}
while (WriteFile(hFile, pBuffer, writeSize, &lpNumBytes, 0) && lpNumBytes == writeSize);
return 0;
}
BYTE *__fastcall CaptureEnc(BYTE *src, BYTE *dst, int width)
{
do
{
BYTE rlePixel = *src++;
--width;
int rleLength = 1;
while (rlePixel == *src)
{
if (rleLength >= 63)
break;
if (!width)
break;
++rleLength;
--width;
++src;
}
if (rlePixel > 0xBF || rleLength > 1)
{
*dst++ = rleLength | 0xC0;
}
*dst++ = rlePixel;
} while (width);
return dst;
}
HANDLE __fastcall CaptureFile(char *dst_path)
{
bool num_used[100] = { false };
_finddata_t finder;
int hFind = _findfirst("screen??.PCX", &finder);
if (hFind != -1)
{
do
{
if (isdigit(finder.name[6]) && isdigit(finder.name[7]))
{
num_used[10 * (finder.name[6] - '0') + (finder.name[7] - '0')] = true;
}
}
while (_findnext(hFind, &finder) == 0);
}
int free_num = 0;
while (num_used[free_num])
{
++free_num;
if (free_num >= 100)
return INVALID_HANDLE_VALUE;
}
sprintf(dst_path, "screen%02d.PCX", free_num);
return CreateFile(dst_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
void __fastcall RedPalette(PALETTEENTRY *pal)
{
PALETTEENTRY red[256];
for(int i = 0; i < 256; i++)
{
red[i].peRed = pal[i].peRed;
red[i].peGreen = 0;
red[i].peBlue = 0;
red[i].peFlags = 0;
}
lpDDPalette->SetEntries(0, 0, 256, red);
}

13
Source/capture.h

@ -0,0 +1,13 @@
//HEADER_GOES_HERE
#ifndef __CAPTURE_H__
#define __CAPTURE_H__
void __cdecl CaptureScreen();
bool __fastcall CaptureHdr(HANDLE hFile, short width, short height);
bool __fastcall CapturePal(HANDLE hFile, PALETTEENTRY *palette);
bool __fastcall CapturePix(HANDLE hFile, WORD width, WORD height, WORD stride, BYTE *pixels);
BYTE *__fastcall CaptureEnc(BYTE *src, BYTE *dst, int width);
HANDLE __fastcall CaptureFile(char *dst_path);
void __fastcall RedPalette(PALETTEENTRY *pal);
#endif /* __CAPTURE_H__ */

191
Source/codec.cpp

@ -0,0 +1,191 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifdef MINIWIN
#define srand srand_miniwin
#define rand rand_miniwin
#endif
int __fastcall codec_decode(void *pbSrcDst, int size, char *pszPassword)
{
unsigned int v3; // ebx
char *v4; // esi
int v5; // ebx
signed int v7; // ecx
int v8; // esi
char v9[128]; // [esp+8h] [ebp-98h]
char dst[20]; // [esp+88h] [ebp-18h]
int v11; // [esp+9Ch] [ebp-4h]
char *passworda; // [esp+A8h] [ebp+8h]
v3 = size;
v4 = (char *)pbSrcDst;
codec_init_key(0, pszPassword);
if ( v3 <= 8 )
return 0;
v5 = v3 - 8;
v11 = v5;
if ( v5 & 0x3F )
return 0;
passworda = (char *)v5;
if ( v5 )
{
do
{
memcpy(v9, v4, 0x40u);
SHA1Result(0, dst);
v7 = 0;
do
{
v9[v7] ^= dst[v7 % 20];
++v7;
}
while ( v7 < 64 );
SHA1Calculate(0, v9, 0);
memset(dst, 0, 0x14u);
memcpy(v4, v9, 0x40u);
v4 += 64;
passworda -= 64;
}
while ( passworda );
v5 = v11;
}
memset(v9, 0, 0x80u);
if ( !v4[4] )
{
SHA1Result(0, dst);
if ( *(_DWORD *)v4 == *(_DWORD *)dst )
{
v8 = v5 + (unsigned char)v4[5] - 64;
goto LABEL_14;
}
memset(dst, 0, 0x14u);
}
v8 = 0;
LABEL_14:
SHA1Clear();
return v8;
}
// 4034D9: using guessed type char var_98[128];
void __fastcall codec_init_key(int unused, char *pszPassword)
{
char *v2; // edi
char *v3; // esi
int v4; // eax
signed int v5; // ecx
char v6; // dl
unsigned int v7; // ecx
signed int v8; // esi
char v9[136]; // [esp+Ch] [ebp-E0h]
char v10[64]; // [esp+94h] [ebp-58h]
char dst[20]; // [esp+D4h] [ebp-18h]
int v12; // [esp+E8h] [ebp-4h]
v2 = pszPassword;
srand(0x7058u);
v3 = v9;
v12 = 136;
do
{
*v3++ = rand();
--v12;
}
while ( v12 );
v4 = 0;
v5 = 0;
do
{
if ( !v2[v4] )
v4 = 0;
v6 = v2[v4++];
v10[v5++] = v6;
}
while ( v5 < 64 );
SHA1Reset(0);
SHA1Calculate(0, v10, dst);
SHA1Clear();
v7 = 0;
do
{
v9[v7] ^= dst[(signed int)v7 % 20];
++v7;
}
while ( v7 < 0x88 );
memset(v10, 0, 0x40u);
memset(dst, 0, 0x14u);
v8 = 0;
do
{
SHA1Reset(v8);
SHA1Calculate(v8++, &v9[72], 0);
}
while ( v8 < 3 );
memset(v9, 0, 0x88u);
}
// 4035DB: using guessed type char var_E0[72];
// 4035DB: using guessed type char var_58[64];
// 4035DB: using guessed type char dst[20];
int __fastcall codec_get_encoded_len(int dwSrcBytes)
{
if ( dwSrcBytes & 0x3F )
dwSrcBytes += 64 - (dwSrcBytes & 0x3F);
return dwSrcBytes + 8;
}
void __fastcall codec_encode(void *pbSrcDst, int size, int size_64, char *pszPassword)
{
char *v4; // esi
char v5; // bl
size_t v6; // edi
signed int v7; // ecx
char v9[128]; // [esp+8h] [ebp-ACh]
char v10[20]; // [esp+88h] [ebp-2Ch]
char dst[20]; // [esp+9Ch] [ebp-18h]
size_t v12; // [esp+B0h] [ebp-4h]
v4 = (char *)pbSrcDst;
v12 = size;
if ( size_64 != codec_get_encoded_len(size) )
TermMsg("Invalid encode parameters");
codec_init_key(1, pszPassword);
v5 = 0;
if ( v12 )
{
do
{
v6 = v12;
if ( v12 >= 0x40 )
v6 = 64;
memcpy(v9, v4, v6);
if ( v6 < 0x40 )
memset(&v9[v6], 0, 64 - v6);
SHA1Result(0, dst);
SHA1Calculate(0, v9, 0);
v7 = 0;
do
{
v9[v7] ^= dst[v7 % 20];
++v7;
}
while ( v7 < 64 );
memset(dst, 0, 0x14u);
memcpy(v4, v9, 0x40u);
v4 += 64;
v12 -= v6;
}
while ( v12 );
v5 = v6;
}
memset(v9, 0, 0x80u);
SHA1Result(0, v10);
v4[4] = 0;
*((_WORD *)v4 + 3) = 0;
*(_DWORD *)v4 = *(_DWORD *)v10;
v4[5] = v5;
SHA1Clear();
}
// 4036BE: using guessed type char var_AC[128];
// 4036BE: using guessed type char dst[20];

10
Source/codec.h

@ -0,0 +1,10 @@
//HEADER_GOES_HERE
#ifndef __CODEC_H__
#define __CODEC_H__
int __fastcall codec_decode(void *pbSrcDst, int size, char *pszPassword);
void __fastcall codec_init_key(int unused, char *pszPassword);
int __fastcall codec_get_encoded_len(int dwSrcBytes);
void __fastcall codec_encode(void *pbSrcDst, int size, int size_64, char *pszPassword);
#endif /* __CODEC_H__ */

3431
Source/control.cpp

File diff suppressed because it is too large Load Diff

141
Source/control.h

@ -0,0 +1,141 @@
//HEADER_GOES_HERE
#ifndef __CONTROL_H__
#define __CONTROL_H__
extern char sgbNextTalkSave; // weak
extern char sgbTalkSavePos; // weak
extern void *pDurIcons;
extern void *pChrButtons;
extern int drawhpflag; // idb
extern int dropGoldFlag; // weak
extern int panbtn[8];
extern int chrbtn[4];
extern void *pMultiBtns;
extern void *pPanelButtons;
extern void *pChrPanel;
extern int lvlbtndown; // weak
extern char sgszTalkSave[8][80];
extern int dropGoldValue; // idb
extern int drawmanaflag; // idb
extern int chrbtnactive; // weak
extern char sgszTalkMsg[80];
extern void *pPanelText;
extern int frame_4B8800; // idb
extern void *pLifeBuff;
extern void *pBtmBuff;
extern void *pTalkBtns;
extern int pstrjust[4];
extern int pnumlines; // idb
extern int pinfoflag; // weak
extern int talkbtndown[3];
extern int pSpell; // weak
extern void *pManaBuff;
extern int infoclr; // weak
extern int sgbPlrTalkTbl; // weak // should be char [4]
extern void *pGBoxBuff;
extern void *pSBkBtnCel;
extern char tempstr[260];
extern int sbooktab; // weak
extern int pSplType; // weak
extern int frame; // idb
extern int initialDropGoldIndex; // idb
extern int talkflag; // weak
extern void *pSBkIconCels;
extern int sbookflag; // weak
extern int chrflag;
extern int drawbtnflag; // idb
extern void *pSpellBkCel;
extern char infostr[260];
extern int numpanbtns; // weak
extern void *pStatusPanel;
extern char panelstr[256];
extern int panelflag; // weak
extern char byte_4B8B88[256];
extern int initialDropGoldValue; // idb
extern void *pSpellCels;
extern int panbtndown; // weak
extern void *pTalkPanel; // idb
extern int spselflag; // weak
void __fastcall DrawSpellCel(int xp, int yp, char *Trans, int nCel, int w);
void __fastcall SetSpellTrans(char t);
void __cdecl DrawSpell();
void __cdecl DrawSpellList();
void __cdecl SetSpell();
void __fastcall SetSpeedSpell(int slot);
void __fastcall ToggleSpell(int slot);
void __fastcall CPrintString(int No, unsigned char pszStr, int Just); /* check arg names */
void __fastcall AddPanelString(char *str, int just);
void __cdecl ClearPanel();
void __fastcall DrawPanelBox(int x, int y, int w, int h, int sx, int sy);
void __cdecl InitPanelStr();
void __fastcall SetFlaskHeight(char *buf, int min, int max, int c, int r);
void __fastcall DrawFlask(void *a1, int a2, int a3, void *a4, int a5, int a6);
void __cdecl DrawLifeFlask();
void __cdecl UpdateLifeFlask();
void __cdecl DrawManaFlask();
void __cdecl control_update_life_mana();
void __cdecl UpdateManaFlask();
void __cdecl InitControlPan();
void __cdecl ClearCtrlPan();
void __cdecl DrawCtrlPan();
void __cdecl DoSpeedBook();
void __cdecl DoPanBtn();
void __fastcall control_set_button_down(int btn_id);
void __cdecl control_check_btn_press();
void __cdecl DoAutoMap();
void __cdecl CheckPanelInfo();
void __cdecl CheckBtnUp();
void __cdecl FreeControlPan();
int __fastcall control_WriteStringToBuffer(char *str);
void __cdecl DrawInfoBox();
void __fastcall control_print_info_str(int y, char *str, bool center, int lines);
void __fastcall PrintGameStr(int x, int y, char *str, int color);
void __cdecl DrawChr();
void __fastcall ADD_PlrStringXY(int x, int y, int width, char *pszStr, char col);
void __fastcall MY_PlrStringXY(int x, int y, int width, char *pszStr, char col, int base);
void __cdecl CheckLvlBtn();
void __cdecl ReleaseLvlBtn();
void __cdecl DrawLevelUpIcon();
void __cdecl CheckChrBtns();
void __cdecl ReleaseChrBtns();
void __cdecl DrawDurIcon();
int __fastcall DrawDurIcon4Item(ItemStruct *pItem, int x, int c);
void __cdecl RedBack();
int __fastcall GetSBookTrans(int ii, unsigned char townok);
void __cdecl DrawSpellBook();
void __fastcall PrintSBookStr(int x, int y, bool cjustflag, char *pszStr, int bright);
void __cdecl CheckSBook();
char *__fastcall get_pieces_str(int nGold);
void __fastcall DrawGoldSplit(int amount);
void __fastcall control_drop_gold(int vkey);
void __fastcall control_remove_gold(int pnum, int gold_index);
void __fastcall control_set_gold_curs(int pnum);
void __cdecl DrawTalkPan();
char *__fastcall control_print_talk_msg(char *msg, int x, int y, int *a4, int just);
int __cdecl control_check_talk_btn();
void __cdecl control_release_talk_btn();
void __cdecl control_reset_talk_msg();
void __cdecl control_type_message();
void __cdecl control_reset_talk();
int __fastcall control_talk_last_key(int a1);
int __fastcall control_presskeys(int a1);
void __cdecl control_press_enter();
void __fastcall control_up_down(char a1);
/* rdata */
extern const unsigned char fontframe[127];
extern const unsigned char fontkern[68];
extern const int lineoffset[25];
extern const unsigned char fontidx[256];
/* data */
extern unsigned char SpellITbl[37];
extern int PanBtnPos[8][5];
extern char *PanBtnHotKey[8];
extern char *PanBtnStr[8];
extern int attribute_inc_rects[4][4];
extern int SpellPages[6][7];
#endif /* __CONTROL_H__ */

1300
Source/cursor.cpp

File diff suppressed because it is too large Load Diff

36
Source/cursor.h

@ -0,0 +1,36 @@
//HEADER_GOES_HERE
#ifndef __CURSOR_H__
#define __CURSOR_H__
extern int cursH; // weak
extern int icursH28; // idb
extern int cursW; // idb
extern int pcursmonst; // idb
extern int icursW28; // idb
extern void *pCursCels;
extern int icursH; // weak
extern char pcursinvitem; // weak
extern int icursW; // weak
extern char pcursitem; // weak
extern char pcursobj; // weak
extern char pcursplr; // weak
extern int cursmx;
extern int cursmy;
extern int dword_4B8CCC; // weak
extern int pcurs; // idb
void __cdecl InitCursor();
void __cdecl FreeCursor();
void __fastcall SetICursor(int i);
void __fastcall SetCursor(int i);
void __fastcall NewCursor(int i);
void __cdecl InitLevelCursor();
void __cdecl CheckTown();
void __cdecl CheckRportal();
void __cdecl CheckCursMove();
/* rdata */
extern const int InvItemWidth[180];
extern const int InvItemHeight[180];
#endif /* __CURSOR_H__ */

151
Source/dead.cpp

@ -0,0 +1,151 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifndef NO_GLOBALS
int spurtndx; // weak
DeadStruct dead[MAXDEAD];
int stonendx;
#endif
void __cdecl InitDead()
{
int v0; // ebx
int *v1; // edx
int *v2; // eax
int v3; // ecx
int v4; // edx
int v5; // eax
int v6; // edx
int v7; // esi
int *v8; // eax
int v9; // edx
CMonster *v10; // ecx
char *v11; // edi
int *v12; // ebx
int mtypes[MAXMONSTERS]; // [esp+Ch] [ebp-330h]
int *v14; // [esp+32Ch] [ebp-10h]
int *v15; // [esp+330h] [ebp-Ch]
int v16; // [esp+334h] [ebp-8h]
int v17; // [esp+338h] [ebp-4h]
memset(mtypes, 0, sizeof(mtypes));
v0 = 0;
if ( nummtypes > 0 )
{
v1 = &dead[0]._deadFrame;
v2 = &Monsters[0].Anims[4].Rate;
v17 = nummtypes;
do
{
v15 = &mtypes[*((unsigned char *)v2 - 216)];
if ( !*v15 )
{
qmemcpy(v1 - 8, v2 - 8, 0x20u);
v3 = *v2;
*((_BYTE *)v1 + 12) = 0;
*v1 = v3;
v1[1] = v2[21];
v1[2] = v2[22];
*((_BYTE *)v2 + 101) = ++v0;
v1 += 12;
*v15 = v0;
}
v2 += 82;
--v17;
}
while ( v17 );
}
v16 = 0;
v4 = v0;
memset32(&dead[v0], (unsigned int)misfiledata[16].mAnimData[0], 8u);
_LOBYTE(dead[v4]._deadtrans) = 0;
dead[v4]._deadFrame = 8;
v5 = (unsigned int)misfiledata[18].mAnimData[0];
dead[v4]._deadWidth = 128;
dead[v4]._deadWidth2 = 32;
v6 = v0 + 1;
spurtndx = v0 + 1;
memset32(&dead[v6], v5, 8u);
_LOBYTE(dead[v6]._deadtrans) = 0;
stonendx = v0 + 2;
v7 = nummonsters;
dead[v6]._deadFrame = 12;
dead[v6]._deadWidth = 128;
dead[v6]._deadWidth2 = 32;
v17 = v0 + 2;
if ( v7 > 0 )
{
v8 = &dead[v0 + 2]._deadFrame;
do
{
v9 = monstactive[v16];
if ( monster[v9]._uniqtype )
{
v10 = monster[v9].MType;
v11 = (char *)(v8 - 8);
v15 = (int *)8;
v14 = (int *)v10->Anims[4].Frames;
do
{
v12 = v14;
++v14;
*(_DWORD *)v11 = *v12;
v11 += 4;
v15 = (int *)((char *)v15 - 1);
}
while ( v15 );
*v8 = v10->Anims[4].Rate;
v8[1] = v10->flags_1;
v8[2] = v10->flags_2;
*((_BYTE *)v8 + 12) = monster[v9]._uniqtrans + 4;
monster[v9]._udeadval = ++v17;
v8 += 12;
}
++v16;
}
while ( v16 < v7 );
}
}
// 4B8CD8: using guessed type int spurtndx;
void __fastcall AddDead(int dx, int dy, char dv, int ddir)
{
dDead[dx][dy] = (dv & 0x1F) + 32 * ddir;
}
void __cdecl SetDead()
{
int v0; // eax
int v1; // esi
int v2; // ebp
char (*v3)[112]; // ebx
int v4; // edi
int i; // [esp+0h] [ebp-4h]
v0 = 0;
for ( i = 0; i < nummonsters; ++i )
{
v1 = monstactive[v0];
if ( monster[v1]._uniqtype )
{
v2 = 0;
v3 = dDead;
do
{
v4 = 0;
do
{
if ( ((*v3)[v4] & 0x1F) == monster[v1]._udeadval )
ChangeLightXY((unsigned char)monster[v1].mlid, v2, v4);
++v4;
}
while ( v4 < 112 );
++v3;
++v2;
}
while ( (signed int)v3 < (signed int)&dDead[112][0] );
}
v0 = i + 1;
}
}

13
Source/dead.h

@ -0,0 +1,13 @@
//HEADER_GOES_HERE
#ifndef __DEAD_H__
#define __DEAD_H__
extern int spurtndx; // weak
extern DeadStruct dead[MAXDEAD];
extern int stonendx;
void __cdecl InitDead();
void __fastcall AddDead(int dx, int dy, char dv, int ddir);
void __cdecl SetDead();
#endif /* __DEAD_H__ */

247
Source/debug.cpp

@ -0,0 +1,247 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifndef NO_GLOBALS
void *pSquareCel;
char dMonsDbg[NUMLEVELS][MAXDUNX][MAXDUNY];
char dFlagDbg[NUMLEVELS][MAXDUNX][MAXDUNY];
#endif
void __cdecl LoadDebugGFX()
{
if ( visiondebug )
pSquareCel = LoadFileInMem("Data\\Square.CEL", 0);
}
// 525720: using guessed type int visiondebug;
void __cdecl FreeDebugGFX()
{
void *v0; // ecx
v0 = pSquareCel;
pSquareCel = 0;
mem_free_dbg(v0);
}
void __cdecl CheckDungeonClear()
{
int i;
int j;
for(i = 0; i < MAXDUNX; i++)
{
for(j = 0; j < MAXDUNY; j++)
{
if ( dMonster[i][j] )
TermMsg("Monsters not cleared");
if ( dPlayer[i][j] )
TermMsg("Players not cleared");
dMonsDbg[currlevel][i][j] = dFlags[i][j] & 2;
dFlagDbg[currlevel][i][j] = dFlags[i][j] & 8;
}
}
}
#ifdef _DEBUG
void __cdecl GiveGoldCheat()
{
int i; // esi
int ni; // ebp
for(i = 0; i < 40; i++)
{
if ( !plr[myplr].InvGrid[i] )
{
ni = plr[myplr]._pNumInv++;
SetPlrHandItem(&plr[myplr].InvList[ni], IDI_GOLD);
GetPlrHandSeed(&plr[myplr].InvList[ni]);
plr[myplr].InvList[ni]._ivalue = 5000;
plr[myplr].InvList[ni]._iCurs = 6;
plr[myplr]._pGold += 5000;
plr[myplr].InvGrid[i] = plr[myplr]._pNumInv;
}
}
}
void __cdecl StoresCheat()
{
int i; // eax
numpremium = 0;
for(i = 0; i < 6; i++)
premiumitem[i]._itype = -1;
SpawnPremium(30);
for(i = 0; i < 20; i++)
witchitem[i]._itype = -1;
SpawnWitch(30);
}
void __cdecl TakeGoldCheat()
{
int i; // esi
char ig; // cl
for(i = 0; i < 40; i++)
{
ig = plr[myplr].InvGrid[i];
if ( ig > 0 && plr[myplr].InvList[ig - 1]._itype == ITYPE_GOLD )
RemoveInvItem(myplr, ig - 1);
}
for(i = 0; i < 8; i++)
{
if ( plr[myplr].SpdList[i]._itype == ITYPE_GOLD )
plr[myplr].SpdList[i]._itype = -1;
}
plr[myplr]._pGold = 0;
}
void __cdecl MaxSpellsCheat()
{
int i; // ebp
for(i = 1; i < 37; i++)
{
if ( spelldata[i].sBookLvl != -1 )
{
*(_QWORD *)plr[myplr]._pMemSpells |= (__int64)1 << (i - 1);
plr[myplr]._pSplLvl[i] = 10;
}
}
}
void __fastcall SetSpellLevelCheat(char spl, int spllvl)
{
*(_QWORD *)plr[myplr]._pMemSpells |= (__int64)1 << (spl - 1);
plr[myplr]._pSplLvl[spl] = spllvl;
}
void __cdecl SetAllSpellsCheat()
{
SetSpellLevelCheat(SPL_FIREBOLT, 8);
SetSpellLevelCheat(SPL_CBOLT, 11);
SetSpellLevelCheat(SPL_HBOLT, 10);
SetSpellLevelCheat(SPL_HEAL, 7);
SetSpellLevelCheat(SPL_HEALOTHER, 5);
SetSpellLevelCheat(SPL_LIGHTNING, 9);
SetSpellLevelCheat(SPL_FIREWALL, 5);
SetSpellLevelCheat(SPL_TELEKINESIS, 3);
SetSpellLevelCheat(SPL_TOWN, 3);
SetSpellLevelCheat(SPL_FLASH, 3);
SetSpellLevelCheat(SPL_RNDTELEPORT, 2);
SetSpellLevelCheat(SPL_MANASHIELD, 2);
SetSpellLevelCheat(SPL_WAVE, 4);
SetSpellLevelCheat(SPL_FIREBALL, 3);
SetSpellLevelCheat(SPL_STONE, 1);
SetSpellLevelCheat(SPL_CHAIN, 1);
SetSpellLevelCheat(SPL_GUARDIAN, 4);
SetSpellLevelCheat(SPL_ELEMENT, 3);
SetSpellLevelCheat(SPL_NOVA, 1);
SetSpellLevelCheat(SPL_GOLEM, 2);
SetSpellLevelCheat(SPL_FLARE, 1);
SetSpellLevelCheat(SPL_BONESPIRIT, 1);
}
void __fastcall PrintDebugPlayer(bool bNextPlayer)
{
char dstr[128]; // [esp+Ch] [ebp-80h]
if ( bNextPlayer )
dbgplr = ((_BYTE)dbgplr + 1) & 3;
sprintf(dstr, "Plr %i : Active = %i", dbgplr, plr[dbgplr].plractive);
NetSendCmdString(1 << myplr, dstr);
if ( plr[dbgplr].plractive )
{
sprintf(dstr, " Plr %i is %s", dbgplr, plr[dbgplr]._pName);
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, " Lvl = %i : Change = %i", plr[dbgplr].plrlevel, plr[dbgplr]._pLvlChanging);
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, " x = %i, y = %i : tx = %i, ty = %i", plr[dbgplr].WorldX, plr[dbgplr].WorldY, plr[dbgplr]._ptargx, plr[dbgplr]._ptargy);
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, " mode = %i : daction = %i : walk[0] = %i", plr[dbgplr]._pmode, plr[dbgplr].destAction, plr[dbgplr].walkpath[0]);
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, " inv = %i : hp = %i", plr[dbgplr]._pInvincible, plr[dbgplr]._pHitPoints);
NetSendCmdString(1 << myplr, dstr);
}
}
void __cdecl PrintDebugQuest()
{
char dstr[128]; // [esp+0h] [ebp-80h]
sprintf(dstr, "Quest %i : Active = %i, Var1 = %i", dbgqst, quests[dbgqst]._qactive, quests[dbgqst]._qvar1);
NetSendCmdString(1 << myplr, dstr);
if ( ++dbgqst == MAXQUESTS )
dbgqst = 0;
}
void __fastcall PrintDebugMonster(int m)
{
bool bActive; // ecx
int i; // eax
char dstr[128]; // [esp+Ch] [ebp-80h]
sprintf(dstr, "Monster %i = %s", m, monster[m].mName);
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, "X = %i, Y = %i", monster[m]._mx, monster[m]._my);
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, "Enemy = %i, HP = %i", monster[m]._menemy, monster[m]._mhitpoints);
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, "Mode = %i, Var1 = %i", monster[m]._mmode, monster[m]._mVar1);
NetSendCmdString(1 << myplr, dstr);
bActive = 0;
for(i = 0; i < nummonsters; i++)
{
if ( monstactive[i] == m )
bActive = 1;
}
sprintf(dstr, "Active List = %i, Squelch = %i", bActive, monster[m]._msquelch);
NetSendCmdString(1 << myplr, dstr);
}
void __cdecl GetDebugMonster()
{
int v0; // ecx
int v1; // eax
v0 = pcursmonst;
if ( pcursmonst == -1 )
{
v1 = dMonster[cursmx][cursmy];
if ( v1 )
{
v0 = v1 - 1;
if ( v1 <= 0 )
v0 = -1 - v1;
}
else
{
v0 = dbgmon;
}
}
PrintDebugMonster(v0);
}
void __cdecl NextDebugMonster()
{
char dstr[128]; // [esp+0h] [ebp-80h]
if ( dbgmon++ == MAXMONSTERS )
dbgmon = 0;
sprintf(dstr, "Current debug monster = %i", dbgmon);
NetSendCmdString(1 << myplr, dstr);
}
#endif

26
Source/debug.h

@ -0,0 +1,26 @@
//HEADER_GOES_HERE
#ifndef __DEBUG_H__
#define __DEBUG_H__
extern void *pSquareCel;
extern char dMonsDbg[NUMLEVELS][MAXDUNX][MAXDUNY];
extern char dFlagDbg[NUMLEVELS][MAXDUNX][MAXDUNY];
void __cdecl LoadDebugGFX();
void __cdecl FreeDebugGFX();
void __cdecl CheckDungeonClear();
#ifdef _DEBUG
void __cdecl GiveGoldCheat();
void __cdecl StoresCheat();
void __cdecl TakeGoldCheat();
void __cdecl MaxSpellsCheat();
void __fastcall SetSpellLevelCheat(char spl, int spllvl);
void __cdecl SetAllSpellsCheat();
void __fastcall PrintDebugPlayer(bool bNextPlayer);
void __cdecl PrintDebugQuest();
void __fastcall PrintDebugMonster(int m);
void __cdecl GetDebugMonster();
void __cdecl NextDebugMonster();
#endif
#endif /* __DEBUG_H__ */

2303
Source/diablo.cpp

File diff suppressed because it is too large Load Diff

102
Source/diablo.h

@ -0,0 +1,102 @@
//HEADER_GOES_HERE
#ifndef __DIABLO_H__
#define __DIABLO_H__
extern int diablo_cpp_init_value; // weak
extern HWND ghMainWnd;
extern int glMid1Seed[NUMLEVELS];
extern int glMid2Seed[NUMLEVELS];
extern int gnLevelTypeTbl[NUMLEVELS];
extern int MouseY; // idb
extern int MouseX; // idb
extern bool gbGameLoopStartup; // idb
extern int glSeedTbl[NUMLEVELS];
extern int gbRunGame; // weak
extern int glMid3Seed[NUMLEVELS];
extern int gbRunGameResult; // weak
extern int zoomflag; // weak
extern int gbProcessPlayers; // weak
extern int glEndSeed[NUMLEVELS];
extern int dword_5256E8; // weak
extern HINSTANCE ghInst; // idb
extern int DebugMonsters[10];
extern char cineflag; // weak
extern int drawpanflag; // weak
extern int visiondebug; // weak
extern int scrollflag; /* unused */
extern int light4flag; // weak
extern int leveldebug; // weak
extern int monstdebug; // weak
extern int trigdebug; /* unused */
extern int setseed; // weak
extern int debugmonsttypes; // weak
extern int PauseMode; // weak
extern int sgnTimeoutCurs;
extern char sgbMouseDown; // weak
extern int color_cycle_timer; // weak
void __cdecl diablo_cpp_init();
void __cdecl FreeGameMem();
int __fastcall diablo_init_menu(int a1, int bSinglePlayer);
void __fastcall run_game_loop(int uMsg);
void __fastcall start_game(int uMsg);
void __cdecl free_game();
bool __cdecl diablo_get_not_running();
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
void __fastcall diablo_parse_flags(char *args);
void __cdecl diablo_init_screen();
BOOL __fastcall diablo_find_window(LPCSTR lpClassName);
void __fastcall diablo_reload_process(HMODULE hModule);
int __cdecl PressEscKey();
LRESULT __stdcall DisableInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT __stdcall GM_Game(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
bool __fastcall LeftMouseDown(int a1);
bool __cdecl TryIconCurs();
void __cdecl LeftMouseUp();
void __cdecl RightMouseDown();
void __fastcall j_gmenu_on_mouse_move(LPARAM lParam);
bool __fastcall PressSysKey(int wParam);
void __fastcall diablo_hotkey_msg(int dwMsg);
void __fastcall ReleaseKey(int vkey);
void __fastcall PressKey(int vkey);
void __cdecl diablo_pause_game();
void __fastcall PressChar(int vkey);
void __cdecl LoadLvlGFX();
void __cdecl LoadAllGFX();
void __fastcall CreateLevel(int lvldir);
void __fastcall LoadGameLevel(BOOL firstflag, int lvldir);
void __fastcall game_loop(bool bStartup);
void __cdecl game_logic();
void __fastcall timeout_cursor(bool bTimeout);
void __cdecl diablo_color_cyc_logic();
/* data */
extern int diablo_inf; // weak
/* rdata */
extern int fullscreen; // weak
#ifdef _DEBUG
extern int showintrodebug;
extern int questdebug;
extern int debug_mode_key_s;
extern int debug_mode_key_w;
extern int debug_mode_key_inverted_v;
extern int debug_mode_dollar_sign;
extern int debug_mode_key_d;
extern int debug_mode_key_i;
extern int dbgplr;
extern int dbgqst;
extern int dbgmon;
extern int arrowdebug;
extern int frameflag;
extern int frameend;
extern int framerate;
extern int framestart;
#endif
extern int FriendlyMode; // weak
extern char *spszMsgTbl[4]; // weak
extern char *spszMsgKeyTbl[4]; // weak
#endif /* __DIABLO_H__ */

113
Source/doom.cpp

@ -0,0 +1,113 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifndef NO_GLOBALS
int doom_quest_time; // weak
int doom_stars_drawn; // weak
void *pDoomCel;
int doomflag; // weak
int DoomQuestState; // idb
#endif
/*
void __cdecl doom_reset_state()
{
if ( DoomQuestState <= 0 ) {
DoomQuestState = 0;
}
}
void __cdecl doom_play_movie()
{
if ( DoomQuestState < 36001 ) {
DoomQuestState++;
if ( DoomQuestState == 36001 ) {
PlayInGameMovie("gendata\\doom.smk");
DoomQuestState++;
}
}
}
*/
int __cdecl doom_get_frame_from_time()
{
if ( DoomQuestState == 36001 ) {
return 31;
}
return DoomQuestState / 1200;
}
void __cdecl doom_alloc_cel()
{
pDoomCel = DiabloAllocPtr(229376);
}
void __cdecl doom_cleanup()
{
void *ptr = pDoomCel;
pDoomCel = NULL;
mem_free_dbg(ptr);
}
void __cdecl doom_load_graphics()
{
if ( doom_quest_time == 31 )
{
strcpy(tempstr, "Items\\Map\\MapZDoom.CEL");
}
else if ( doom_quest_time < 10 )
{
sprintf(tempstr, "Items\\Map\\MapZ000%i.CEL", doom_quest_time);
}
else
{
sprintf(tempstr, "Items\\Map\\MapZ00%i.CEL", doom_quest_time);
}
LoadFileWithMem(tempstr, pDoomCel);
}
// 525750: using guessed type int doom_quest_time;
void __cdecl doom_init()
{
doomflag = 1;
doom_alloc_cel();
doom_quest_time = doom_get_frame_from_time() == 31 ? 31 : 0;
doom_load_graphics();
}
// 525750: using guessed type int doom_quest_time;
// 52575C: using guessed type int doomflag;
void __cdecl doom_close()
{
if ( doomflag ) {
doomflag = 0;
doom_cleanup();
}
}
// 52575C: using guessed type int doomflag;
void __cdecl doom_draw()
{
if ( !doomflag ) {
return;
}
if ( doom_quest_time != 31 ) {
doom_stars_drawn++;
if ( doom_stars_drawn >= 5 ) {
doom_stars_drawn = 0;
doom_quest_time++;
if ( doom_quest_time > doom_get_frame_from_time() ) {
doom_quest_time = 0;
}
doom_load_graphics();
}
}
CelDecodeOnly(64, 511, pDoomCel, 1, 640);
}
// 525750: using guessed type int doom_quest_time;
// 525754: using guessed type int doom_stars_drawn;
// 52575C: using guessed type int doomflag;

23
Source/doom.h

@ -0,0 +1,23 @@
//HEADER_GOES_HERE
#ifndef __DOOM_H__
#define __DOOM_H__
extern int doom_quest_time; // weak
extern int doom_stars_drawn; // weak
extern void *pDoomCel;
extern int doomflag; // weak
extern int DoomQuestState; // idb
/*
void __cdecl doom_reset_state();
void __cdecl doom_play_movie();
*/
int __cdecl doom_get_frame_from_time();
void __cdecl doom_alloc_cel();
void __cdecl doom_cleanup();
void __cdecl doom_load_graphics();
void __cdecl doom_init();
void __cdecl doom_close();
void __cdecl doom_draw();
#endif /* __DOOM_H__ */

2910
Source/drlg_l1.cpp

File diff suppressed because it is too large Load Diff

68
Source/drlg_l1.h

@ -0,0 +1,68 @@
//HEADER_GOES_HERE
#ifndef __DRLG_L1_H__
#define __DRLG_L1_H__
extern char L5dungeon[80][80];
extern char mydflags[40][40];
extern int setloadflag; // weak
extern int HR1;
extern int HR2;
extern int HR3;
extern int VR1;
extern int VR2;
extern int VR3;
extern void *pSetPiece; // idb
void __cdecl DRLG_Init_Globals();
void __fastcall LoadL1Dungeon(char *sFileName, int vx, int vy);
void __cdecl DRLG_L1Floor();
void __cdecl DRLG_L1Pass3();
void __cdecl DRLG_InitL1Vals();
void __fastcall LoadPreL1Dungeon(char *sFileName, int vx, int vy);
void __fastcall CreateL5Dungeon(int rseed, int entry);
void __cdecl DRLG_LoadL1SP();
void __cdecl DRLG_FreeL1SP();
void __fastcall DRLG_L5(int entry);
void __fastcall DRLG_PlaceDoor(int x, int y);
void __cdecl DRLG_L1Shadows();
int __fastcall DRLG_PlaceMiniSet(const unsigned char *miniset, int tmin, int tmax, int cx, int cy, bool setview, int noquad, int ldir);
void __cdecl InitL5Dungeon();
void __cdecl L5ClearFlags();
void __cdecl L5firstRoom();
void __fastcall L5drawRoom(int x, int y, int w, int h);
void __fastcall L5roomGen(int x, int y, int w, int h, BOOL dir);
bool __fastcall L5checkRoom(int x, int y, int width, int height);
int __cdecl L5GetArea();
void __cdecl L5makeDungeon();
void __cdecl L5makeDmt();
void __cdecl L5AddWall();
int __fastcall L5HWallOk(int i, int j);
int __fastcall L5VWallOk(int i, int j);
void __fastcall L5HorizWall(int i, int j, char p, int dx);
void __fastcall L5VertWall(int i, int j, char p, int dy);
void __cdecl L5tileFix();
void __cdecl DRLG_L5Subs();
void __cdecl L5FillChambers();
void __fastcall DRLG_L5GChamber(int sx, int sy, bool topflag, bool bottomflag, bool leftflag, bool rightflag);
void __fastcall DRLG_L5GHall(int x1, int y1, int x2, int y2);
void __fastcall DRLG_L5SetRoom(int rx1, int ry1);
void __cdecl DRLG_L5FloodTVal();
void __fastcall DRLG_L5FTVR(int i, int j, int x, int y, int d);
void __cdecl DRLG_L5TransFix();
void __cdecl DRLG_L5DirtFix();
void __cdecl DRLG_L5CornerFix();
/* rdata */
extern const ShadowStruct SPATS[37];
extern const unsigned char BSTYPES[206];
extern const unsigned char L5BTYPES[206];
extern const unsigned char STAIRSUP[];
extern const unsigned char L5STAIRSUP[];
extern const unsigned char STAIRSDOWN[];
extern const unsigned char LAMPS[];
extern const unsigned char PWATERIN[];
/* data */
extern unsigned char L5ConvTbl[16];
#endif /* __DRLG_L1_H__ */

3376
Source/drlg_l2.cpp

File diff suppressed because it is too large Load Diff

173
Source/drlg_l2.h

@ -0,0 +1,173 @@
//HEADER_GOES_HERE
#ifndef __DRLG_L2_H__
#define __DRLG_L2_H__
extern int nSx1;
extern int nSx2; // weak
extern int nSy1;
extern int nSy2; // weak
extern int nRoomCnt;
extern char predungeon[40][40];
extern ROOMNODE RoomList[81];
extern HALLNODE *pHallList;
void __cdecl InitDungeon();
void __cdecl L2LockoutFix();
void __cdecl L2DoorFix();
void __fastcall LoadL2Dungeon(char *sFileName, int vx, int vy);
void __cdecl DRLG_L2Pass3();
void __fastcall LoadPreL2Dungeon(char *sFileName, int vx, int vy);
void __fastcall CreateL2Dungeon(int rseed, int entry);
void __cdecl DRLG_LoadL2SP();
void __cdecl DRLG_FreeL2SP();
void __fastcall DRLG_L2(int entry);
bool __fastcall DRLG_L2PlaceMiniSet(unsigned char *miniset, int tmin, int tmax, int cx, int cy, bool setview, int ldir);
void __fastcall DRLG_L2PlaceRndSet(unsigned char *miniset, int rndper);
void __cdecl DRLG_L2Subs();
void __cdecl DRLG_L2Shadows();
void __fastcall DRLG_L2SetRoom(int rx1, int ry1);
void __cdecl L2TileFix();
bool __cdecl CreateDungeon();
void __fastcall CreateRoom(int nX1, int nY1, int nX2, int nY2, int nRDest, int nHDir, int ForceHW, int nH, int nW);
void __fastcall DefineRoom(int nX1, int nY1, int nX2, int nY2, int ForceHW);
void __fastcall AddHall(int nX1, int nY1, int nX2, int nY2, int nHd);
void __fastcall GetHall(int *nX1, int *nY1, int *nX2, int *nY2, int *nHd);
void __fastcall ConnectHall(int nX1, int nY1, int nX2, int nY2, int nHd);
void __fastcall CreateDoorType(int nX, int nY);
void __fastcall PlaceHallExt(int nX, int nY);
void __fastcall DoPatternCheck(int i, int j);
bool __cdecl DL2_FillVoids();
bool __fastcall DL2_Cont(bool x1f, bool y1f, bool x2f, bool y2f);
int __cdecl DL2_NumNoChar();
void __fastcall DL2_DrawRoom(int x1, int y1, int x2, int y2);
void __fastcall DL2_KnockWalls(int x1, int y1, int x2, int y2);
void __cdecl DRLG_L2FloodTVal();
void __fastcall DRLG_L2FTVR(int i, int j, int x, int y, int d);
void __cdecl DRLG_L2TransFix();
void __cdecl L2DirtFix();
void __cdecl DRLG_InitL2Vals();
/* rdata */
extern int Area_Min; // weak
extern int Room_Max; // weak
extern int Room_Min; // weak
extern int Dir_Xadd[5];
extern int Dir_Yadd[5];
extern ShadowStruct SPATSL2[2];
//short word_48489A;
extern unsigned char BTYPESL2[161];
extern unsigned char BSTYPESL2[161];
extern unsigned char VARCH1[];
extern unsigned char VARCH2[];
extern unsigned char VARCH3[];
extern unsigned char VARCH4[];
extern unsigned char VARCH5[];
extern unsigned char VARCH6[];
extern unsigned char VARCH7[];
extern unsigned char VARCH8[];
extern unsigned char VARCH9[];
extern unsigned char VARCH10[];
extern unsigned char VARCH11[];
extern unsigned char VARCH12[];
extern unsigned char VARCH13[];
extern unsigned char VARCH14[];
extern unsigned char VARCH15[];
extern unsigned char VARCH16[];
extern unsigned char VARCH17[];
extern unsigned char VARCH18[];
extern unsigned char VARCH19[];
extern unsigned char VARCH20[];
extern unsigned char VARCH21[];
extern unsigned char VARCH22[];
extern unsigned char VARCH23[];
extern unsigned char VARCH24[];
extern unsigned char VARCH25[];
extern unsigned char VARCH26[];
extern unsigned char VARCH27[];
extern unsigned char VARCH28[];
extern unsigned char VARCH29[];
extern unsigned char VARCH30[];
extern unsigned char VARCH31[];
extern unsigned char VARCH32[];
extern unsigned char VARCH33[];
extern unsigned char VARCH34[];
extern unsigned char VARCH35[];
extern unsigned char VARCH36[];
extern unsigned char VARCH37[];
extern unsigned char VARCH38[];
extern unsigned char VARCH39[];
extern unsigned char VARCH40[];
extern unsigned char HARCH1[];
extern unsigned char HARCH2[];
extern unsigned char HARCH3[];
extern unsigned char HARCH4[];
extern unsigned char HARCH5[];
extern unsigned char HARCH6[];
extern unsigned char HARCH7[];
extern unsigned char HARCH8[];
extern unsigned char HARCH9[];
extern unsigned char HARCH10[];
extern unsigned char HARCH11[];
extern unsigned char HARCH12[];
extern unsigned char HARCH13[];
extern unsigned char HARCH14[];
extern unsigned char HARCH15[];
extern unsigned char HARCH16[];
extern unsigned char HARCH17[];
extern unsigned char HARCH18[];
extern unsigned char HARCH19[];
extern unsigned char HARCH20[];
extern unsigned char HARCH21[];
extern unsigned char HARCH22[];
extern unsigned char HARCH23[];
extern unsigned char HARCH24[];
extern unsigned char HARCH25[];
extern unsigned char HARCH26[];
extern unsigned char HARCH27[];
extern unsigned char HARCH28[];
extern unsigned char HARCH29[];
extern unsigned char HARCH30[];
extern unsigned char HARCH31[];
extern unsigned char HARCH32[];
extern unsigned char HARCH33[];
extern unsigned char HARCH34[];
extern unsigned char HARCH35[];
extern unsigned char HARCH36[];
extern unsigned char HARCH37[];
extern unsigned char HARCH38[];
extern unsigned char HARCH39[];
extern unsigned char HARCH40[];
extern unsigned char USTAIRS[];
extern unsigned char DSTAIRS[];
extern unsigned char WARPSTAIRS[];
extern unsigned char CRUSHCOL[];
extern unsigned char BIG1[];
extern unsigned char BIG2[];
extern unsigned char BIG3[];
extern unsigned char BIG4[];
extern unsigned char BIG5[];
extern unsigned char BIG6[];
extern unsigned char BIG7[];
extern unsigned char BIG8[];
extern unsigned char BIG9[];
extern unsigned char BIG10[];
extern unsigned char RUINS1[];
extern unsigned char RUINS2[];
extern unsigned char RUINS3[];
extern unsigned char RUINS4[];
extern unsigned char RUINS5[];
extern unsigned char RUINS6[];
extern unsigned char RUINS7[];
extern unsigned char PANCREAS1[];
extern unsigned char PANCREAS2[];
extern unsigned char CTRDOOR1[];
extern unsigned char CTRDOOR2[];
extern unsigned char CTRDOOR3[];
extern unsigned char CTRDOOR4[];
extern unsigned char CTRDOOR5[];
extern unsigned char CTRDOOR6[];
extern unsigned char CTRDOOR7[];
extern unsigned char CTRDOOR8[];
extern int Patterns[100][10];
#endif /* __DRLG_L2_H__ */

2946
Source/drlg_l3.cpp

File diff suppressed because it is too large Load Diff

87
Source/drlg_l3.h

@ -0,0 +1,87 @@
//HEADER_GOES_HERE
#ifndef __DRLG_L3_H__
#define __DRLG_L3_H__
extern char lavapool; // weak
extern int abyssx; // weak
extern int lockoutcnt; // weak
extern char lockout[40][40];
void __cdecl AddFenceDoors();
void __cdecl FenceDoorFix();
int __cdecl DRLG_L3Anvil();
void __cdecl FixL3Warp();
void __cdecl FixL3HallofHeroes();
void __fastcall DRLG_L3LockRec(int x, int y);
bool __cdecl DRLG_L3Lockout();
void __fastcall CreateL3Dungeon(int rseed, int entry);
void __fastcall DRLG_L3(int entry);
void __cdecl InitL3Dungeon();
int __fastcall DRLG_L3FillRoom(int x1, int y1, int x2, int y2);
void __fastcall DRLG_L3CreateBlock(int x, int y, int obs, int dir);
void __fastcall DRLG_L3FloorArea(int x1, int y1, int x2, int y2);
void __cdecl DRLG_L3FillDiags();
void __cdecl DRLG_L3FillSingles();
void __cdecl DRLG_L3FillStraights();
void __cdecl DRLG_L3Edges();
int __cdecl DRLG_L3GetFloorArea();
void __cdecl DRLG_L3MakeMegas();
void __cdecl DRLG_L3River();
void __cdecl DRLG_L3Pool();
int __fastcall DRLG_L3SpawnEdge(int x, int y, int *totarea);
int __fastcall DRLG_L3Spawn(int x, int y, int *totarea);
void __cdecl DRLG_L3PoolFix();
int __fastcall DRLG_L3PlaceMiniSet(const unsigned char *miniset, int tmin, int tmax, int cx, int cy, bool setview, int ldir);
void __fastcall DRLG_L3PlaceRndSet(const unsigned char *miniset, int rndper);
void __cdecl DRLG_L3Wood();
bool __fastcall WoodVertU(int i, int y);
bool __fastcall WoodVertD(int i, int y);
bool __fastcall WoodHorizL(int x, int j);
bool __fastcall WoodHorizR(int x, int j);
void __cdecl DRLG_L3Pass3();
void __fastcall LoadL3Dungeon(char *sFileName, int vx, int vy);
void __fastcall LoadPreL3Dungeon(char *sFileName, int vx, int vy);
/* rdata */
extern const unsigned char L3ConvTbl[16];
extern const unsigned char L3UP[20];
extern const unsigned char L3DOWN[20];
extern const unsigned char L3HOLDWARP[20];
extern const unsigned char L3TITE1[34];
extern const unsigned char L3TITE2[34];
extern const unsigned char L3TITE3[34];
extern const unsigned char L3TITE6[42];
extern const unsigned char L3TITE7[42];
extern const unsigned char L3TITE8[20];
extern const unsigned char L3TITE9[20];
extern const unsigned char L3TITE10[20];
extern const unsigned char L3TITE11[20];
extern const unsigned char L3TITE12[6];
extern const unsigned char L3TITE13[6];
extern const unsigned char L3CREV1[6];
extern const unsigned char L3CREV2[6];
extern const unsigned char L3CREV3[6];
extern const unsigned char L3CREV4[6];
extern const unsigned char L3CREV5[6];
extern const unsigned char L3CREV6[6];
extern const unsigned char L3CREV7[6];
extern const unsigned char L3CREV8[6];
extern const unsigned char L3CREV9[6];
extern const unsigned char L3CREV10[6];
extern const unsigned char L3CREV11[6];
extern const unsigned char L3ISLE1[14];
extern const unsigned char L3ISLE2[14];
extern const unsigned char L3ISLE3[14];
extern const unsigned char L3ISLE4[14];
extern const unsigned char L3ISLE5[10];
extern const unsigned char L3XTRA1[4];
extern const unsigned char L3XTRA2[4];
extern const unsigned char L3XTRA3[4];
extern const unsigned char L3XTRA4[4];
extern const unsigned char L3XTRA5[4];
extern const unsigned char L3ANVIL[244];
extern const unsigned char L3SpawnTbl1[15]; /* local spawntable? */
extern const unsigned char L3SpawnTbl2[15]; /* local spawntable? */
extern const unsigned char L3PoolSub[15]; /* local poolsub? */
#endif /* __DRLG_L3_H__ */

3339
Source/drlg_l4.cpp

File diff suppressed because it is too large Load Diff

69
Source/drlg_l4.h

@ -0,0 +1,69 @@
//HEADER_GOES_HERE
#ifndef __DRLG_L4_H__
#define __DRLG_L4_H__
extern int diabquad1x; // weak
extern int diabquad1y; // weak
extern int diabquad3x; // idb
extern int diabquad3y; // idb
extern int diabquad2x; // idb
extern int diabquad2y; // idb
extern int diabquad4x; // idb
extern int diabquad4y; // idb
extern int hallok[20];
extern int l4holdx; // weak
extern int l4holdy; // weak
extern int SP4x1; // idb
extern int SP4x2; // weak
extern int SP4y1; // idb
extern int SP4y2; // weak
extern char L4dungeon[80][80];
extern char dung[20][20];
//int dword_52A4DC; // weak
void __cdecl DRLG_LoadL4SP();
void __cdecl DRLG_FreeL4SP();
void __fastcall DRLG_L4SetSPRoom(int rx1, int ry1);
void __cdecl L4SaveQuads();
void __fastcall DRLG_L4SetRoom(unsigned char *pSetPiece, int rx1, int ry1);
void __fastcall DRLG_LoadDiabQuads(bool preflag);
bool __fastcall IsDURWall(char d);
bool __fastcall IsDLLWall(char dd);
void __cdecl L4FixRim();
void __cdecl DRLG_L4GeneralFix();
void __fastcall CreateL4Dungeon(int rseed, int entry);
void __fastcall DRLG_L4(int entry);
void __cdecl DRLG_L4Shadows();
void __cdecl InitL4Dungeon();
void __cdecl L4makeDmt();
void __cdecl L4AddWall();
int __fastcall L4HWallOk(int i, int j);
int __fastcall L4VWallOk(int i, int j);
void __fastcall L4HorizWall(int i, int j, int dx);
void __fastcall L4VertWall(int i, int j, int dy);
void __cdecl L4tileFix();
void __cdecl DRLG_L4Subs();
void __cdecl L4makeDungeon();
void __cdecl uShape();
int __cdecl GetArea();
void __cdecl L4firstRoom();
void __fastcall L4drawRoom(int x, int y, int width, int height);
void __fastcall L4roomGen(int x, int y, int w, int h, int dir);
bool __fastcall L4checkRoom(int x, int y, int width, int height);
bool __fastcall DRLG_L4PlaceMiniSet(const unsigned char *miniset, int tmin, int tmax, int cx, int cy, int setview, int ldir);
void __cdecl DRLG_L4FloodTVal();
void __fastcall DRLG_L4FTVR(int i, int j, int x, int y, int d);
void __cdecl DRLG_L4TransFix();
void __cdecl DRLG_L4Corners();
void __cdecl DRLG_L4Pass3();
/* rdata */
extern const unsigned char L4ConvTbl[16];
extern const unsigned char L4USTAIRS[42];
extern const unsigned char L4TWARP[42];
extern const unsigned char L4DSTAIRS[52];
extern const unsigned char L4PENTA[52];
extern const unsigned char L4PENTA2[52];
extern const unsigned char L4BTYPES[140];
#endif /* __DRLG_L4_H__ */

200
Source/dthread.cpp

@ -0,0 +1,200 @@
//HEADER_GOES_HERE
#include "../types.h"
int dthread_cpp_init_value; // weak
static CRITICAL_SECTION sgMemCrit; // idb
unsigned int glpDThreadId; // idb
TMegaPkt *sgpInfoHead; /* may not be right struct */
char byte_52A508; // weak
HANDLE sghWorkToDoEvent; // idb
int dthread_inf = 0x7F800000; // weak
/* rdata */
static HANDLE sghThread = (HANDLE)0xFFFFFFFF; // idb
struct dthread_cpp_init_1
{
dthread_cpp_init_1()
{
dthread_cpp_init_value = dthread_inf;
}
} _dthread_cpp_init_1;
// 47A460: using guessed type int dthread_inf;
// 52A4E0: using guessed type int dthread_cpp_init_value;
struct dthread_cpp_init_2
{
dthread_cpp_init_2()
{
dthread_init_mutex();
dthread_cleanup_mutex_atexit();
}
} _dthread_cpp_init_2;
void __cdecl dthread_init_mutex()
{
InitializeCriticalSection(&sgMemCrit);
}
void __cdecl dthread_cleanup_mutex_atexit()
{
atexit(dthread_cleanup_mutex);
}
void __cdecl dthread_cleanup_mutex()
{
DeleteCriticalSection(&sgMemCrit);
}
void __fastcall dthread_remove_player(int pnum)
{
int v1; // edi
TMegaPkt *i; // eax
v1 = pnum;
EnterCriticalSection(&sgMemCrit);
for ( i = sgpInfoHead; i; i = i->pNext )
{
if ( i->dwSpaceLeft == v1 )
i->dwSpaceLeft = 4;
}
LeaveCriticalSection(&sgMemCrit);
}
void __fastcall dthread_send_delta(int pnum, char cmd, void *pbSrc, int dwLen)
{
TMegaPkt *v5; // eax
TMegaPkt *v6; // esi
TMegaPkt *v7; // eax
TMegaPkt **v8; // ecx
int v9; // [esp+4h] [ebp-4h]
v9 = pnum;
if ( gbMaxPlayers != 1 )
{
v5 = (TMegaPkt *)DiabloAllocPtr(dwLen + 20);
v6 = v5;
v5->pNext = 0;
v5->dwSpaceLeft = v9;
v5->data[0] = cmd;
*(_DWORD *)&v5->data[4] = dwLen;
memcpy(&v5->data[8], pbSrc, dwLen);
EnterCriticalSection(&sgMemCrit);
v7 = sgpInfoHead;
v8 = &sgpInfoHead;
while ( v7 )
{
v8 = &v7->pNext;
v7 = v7->pNext;
}
*v8 = v6;
SetEvent(sghWorkToDoEvent);
LeaveCriticalSection(&sgMemCrit);
}
}
// 679660: using guessed type char gbMaxPlayers;
void __cdecl dthread_start()
{
char *v0; // eax
char *v1; // eax
if ( gbMaxPlayers != 1 )
{
sghWorkToDoEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if ( !sghWorkToDoEvent )
{
v0 = TraceLastError();
TermMsg("dthread:1\n%s", v0);
}
byte_52A508 = 1;
sghThread = (HANDLE)_beginthreadex(NULL, 0, dthread_handler, NULL, 0, &glpDThreadId);
if ( sghThread == (HANDLE)-1 )
{
v1 = TraceLastError();
TermMsg("dthread2:\n%s", v1);
}
}
}
// 52A508: using guessed type char byte_52A508;
// 679660: using guessed type char gbMaxPlayers;
unsigned int __stdcall dthread_handler(void *a1)
{
char *v1; // eax
TMegaPkt *v2; // esi
int v3; // ecx
unsigned int v4; // edi
while ( byte_52A508 )
{
if ( !sgpInfoHead && WaitForSingleObject(sghWorkToDoEvent, 0xFFFFFFFF) == -1 )
{
v1 = TraceLastError();
TermMsg("dthread4:\n%s", v1);
}
EnterCriticalSection(&sgMemCrit);
v2 = sgpInfoHead;
if ( sgpInfoHead )
sgpInfoHead = sgpInfoHead->pNext;
else
ResetEvent(sghWorkToDoEvent);
LeaveCriticalSection(&sgMemCrit);
if ( v2 )
{
v3 = v2->dwSpaceLeft;
if ( v3 != 4 )
multi_send_zero_packet(v3, v2->data[0], &v2->data[8], *(_DWORD *)&v2->data[4]);
v4 = 1000 * *(_DWORD *)&v2->data[4] / (unsigned int)gdwDeltaBytesSec;
if ( v4 >= 1 )
v4 = 1;
mem_free_dbg(v2);
if ( v4 )
Sleep(v4);
}
}
return 0;
}
// 52A508: using guessed type char byte_52A508;
// 679730: using guessed type int gdwDeltaBytesSec;
void __cdecl dthread_cleanup()
{
char *v0; // eax
TMegaPkt *v1; // eax
TMegaPkt *v2; // esi
if ( sghWorkToDoEvent )
{
byte_52A508 = 0;
SetEvent(sghWorkToDoEvent);
if ( sghThread != (HANDLE)-1 && glpDThreadId != GetCurrentThreadId() )
{
if ( WaitForSingleObject(sghThread, 0xFFFFFFFF) == -1 )
{
v0 = TraceLastError();
TermMsg("dthread3:\n(%s)", v0);
}
CloseHandle(sghThread);
sghThread = (HANDLE)-1;
}
CloseHandle(sghWorkToDoEvent);
v1 = sgpInfoHead;
sghWorkToDoEvent = 0;
if ( sgpInfoHead )
{
do
{
v2 = v1->pNext;
sgpInfoHead = 0;
mem_free_dbg(v1);
v1 = v2;
sgpInfoHead = v2;
}
while ( v2 );
}
}
}
// 52A508: using guessed type char byte_52A508;

25
Source/dthread.h

@ -0,0 +1,25 @@
//HEADER_GOES_HERE
#ifndef __DTHREAD_H__
#define __DTHREAD_H__
extern int dthread_cpp_init_value; // weak
extern unsigned int glpDThreadId; // idb
extern TMegaPkt *sgpInfoHead; /* may not be right struct */
extern char byte_52A508; // weak
extern HANDLE sghWorkToDoEvent; // idb
void __cdecl dthread_cpp_init_1();
void __cdecl dthread_cpp_init_2();
void __cdecl dthread_init_mutex();
void __cdecl dthread_cleanup_mutex_atexit();
void __cdecl dthread_cleanup_mutex();
void __fastcall dthread_remove_player(int pnum);
void __fastcall dthread_send_delta(int pnum, char cmd, void *pbSrc, int dwLen);
void __cdecl dthread_start();
unsigned int __stdcall dthread_handler(void *a1);
void __cdecl dthread_cleanup();
/* data */
extern int dthread_inf; // weak
#endif /* __DTHREAD_H__ */

298
Source/dx.cpp

@ -0,0 +1,298 @@
//HEADER_GOES_HERE
#include "../types.h"
void *sgpBackBuf;
int dx_cpp_init_value; // weak
IDirectDraw *lpDDInterface;
IDirectDrawPalette *lpDDPalette; // idb
int sgdwLockCount;
Screen *gpBuffer;
IDirectDrawSurface *lpDDSBackBuf;
IDirectDrawSurface *lpDDSPrimary;
static CRITICAL_SECTION sgMemCrit;
char gbBackBuf; // weak
char gbEmulate; // weak
HMODULE ghDiabMod; // idb
int dx_inf = 0x7F800000; // weak
struct dx_cpp_init_1
{
dx_cpp_init_1()
{
dx_cpp_init_value = dx_inf;
}
} _dx_cpp_init_1;
// 47A464: using guessed type int dx_inf;
// 52A514: using guessed type int dx_cpp_init_value;
struct dx_cpp_init_2
{
dx_cpp_init_2()
{
dx_init_mutex();
dx_cleanup_mutex_atexit();
}
} _dx_cpp_init_2;
void __cdecl dx_init_mutex()
{
InitializeCriticalSection(&sgMemCrit);
}
void __cdecl dx_cleanup_mutex_atexit()
{
atexit(dx_cleanup_mutex);
}
void __cdecl dx_cleanup_mutex()
{
DeleteCriticalSection(&sgMemCrit);
}
void __fastcall dx_init(HWND hWnd)
{
HWND v1; // esi
GUID *v2; // ecx
int v3; // eax
int v4; // eax
//int v5; // ecx
int v6; // edi
int v7; // eax
int v8; // eax
HWND hWnda; // [esp+1Ch] [ebp-4h]
v1 = hWnd;
hWnda = hWnd;
SetFocus(hWnd);
ShowWindow(v1, SW_SHOWNORMAL);
v2 = NULL;
if ( gbEmulate )
v2 = (GUID *)DDCREATE_EMULATIONONLY;
v3 = dx_DirectDrawCreate(v2, &lpDDInterface, NULL);
if ( v3 )
ErrDlg(IDD_DIALOG1, v3, "C:\\Src\\Diablo\\Source\\dx.cpp", 149);
fullscreen = 1;
v4 = lpDDInterface->SetCooperativeLevel(v1, DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT|DDSCL_FULLSCREEN);
if ( v4 == DDERR_EXCLUSIVEMODEALREADYSET )
{
MI_Dummy(0); // v5
}
else if ( v4 )
{
ErrDlg(IDD_DIALOG1, v4, "C:\\Src\\Diablo\\Source\\dx.cpp", 170);
}
if ( lpDDInterface->SetDisplayMode(640, 480, 8) )
{
v6 = GetSystemMetrics(SM_CXSCREEN);
v7 = GetSystemMetrics(SM_CYSCREEN);
v8 = lpDDInterface->SetDisplayMode(v6, v7, 8);
if ( v8 )
ErrDlg(IDD_DIALOG1, v8, "C:\\Src\\Diablo\\Source\\dx.cpp", 183);
}
dx_create_primary_surface();
palette_init();
GdiSetBatchLimit(1);
dx_create_back_buffer();
SDrawManualInitialize(hWnda, lpDDInterface, lpDDSPrimary, 0, 0, lpDDSBackBuf, lpDDPalette, 0);
}
// 484364: using guessed type int fullscreen;
// 52A549: using guessed type char gbEmulate;
void __cdecl dx_create_back_buffer()
{
int v0; // eax
int v1; // eax
int v2; // eax
int v3; // eax
DDSURFACEDESC v4; // [esp+Ch] [ebp-70h]
DDSCAPS v5; // [esp+78h] [ebp-4h]
v0 = lpDDSPrimary->GetCaps(&v5);
if ( v0 )
DDErrMsg(v0, 59, "C:\\Src\\Diablo\\Source\\dx.cpp");
if ( !gbBackBuf )
{
v4.dwSize = 108;
v1 = lpDDSPrimary->Lock(NULL, &v4, DDLOCK_WRITEONLY|DDLOCK_WAIT, NULL);
if ( !v1 )
{
lpDDSPrimary->Unlock(NULL);
sgpBackBuf = DiabloAllocPtr(0x7B000);
return;
}
if ( v1 != DDERR_CANTLOCKSURFACE )
ErrDlg(IDD_DIALOG1, v1, "C:\\Src\\Diablo\\Source\\dx.cpp", 81);
}
memset(&v4, 0, 0x6Cu);
v4.dwWidth = 768;
v4.lPitch = 768;
v4.dwSize = 108;
v4.dwFlags = DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS;
v4.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN;
v4.dwHeight = 656;
v4.ddpfPixelFormat.dwSize = 32;
v2 = lpDDSPrimary->GetPixelFormat(&v4.ddpfPixelFormat);
if ( v2 )
ErrDlg(IDD_DIALOG1, v2, "C:\\Src\\Diablo\\Source\\dx.cpp", 94);
v3 = lpDDInterface->CreateSurface(&v4, &lpDDSBackBuf, NULL);
if ( v3 )
ErrDlg(IDD_DIALOG1, v3, "C:\\Src\\Diablo\\Source\\dx.cpp", 96);
}
// 52A548: using guessed type char gbBackBuf;
void __cdecl dx_create_primary_surface()
{
int v0; // eax
DDSURFACEDESC v1; // [esp+0h] [ebp-6Ch]
memset(&v1, 0, 0x6Cu);
v1.dwSize = 108;
v1.dwFlags = DDSD_CAPS;
v1.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
v0 = lpDDInterface->CreateSurface(&v1, &lpDDSPrimary, NULL);
if ( v0 )
ErrDlg(IDD_DIALOG1, v0, "C:\\Src\\Diablo\\Source\\dx.cpp", 109);
}
HRESULT __fastcall dx_DirectDrawCreate(GUID *guid, IDirectDraw **DD, void *unknown)
{
IDirectDraw **v3; // ebp
int v4; // eax
FARPROC v5; // ebx
int v6; // eax
GUID *v8; // [esp+10h] [ebp-4h]
v3 = DD;
v8 = guid;
if ( !ghDiabMod )
{
ghDiabMod = LoadLibrary("ddraw.dll");
if ( !ghDiabMod )
{
v4 = GetLastError();
ErrDlg(IDD_DIALOG4, v4, "C:\\Src\\Diablo\\Source\\dx.cpp", 122);
}
}
v5 = GetProcAddress(ghDiabMod, "DirectDrawCreate");
if ( !v5 )
{
v6 = GetLastError();
ErrDlg(IDD_DIALOG4, v6, "C:\\Src\\Diablo\\Source\\dx.cpp", 127);
}
return ((int (__stdcall *)(GUID *, IDirectDraw **, void *))v5)(v8, v3, unknown);
}
void __cdecl lock_buf_priv()
{
Screen *v0; // eax
int v1; // eax
DDSURFACEDESC v2; // [esp+0h] [ebp-6Ch]
EnterCriticalSection(&sgMemCrit);
v0 = (Screen *)sgpBackBuf;
if ( sgpBackBuf )
goto LABEL_8;
if ( lpDDSBackBuf )
{
if ( sgdwLockCount )
goto LABEL_9;
v2.dwSize = 108;
v1 = lpDDSBackBuf->Lock(NULL, &v2, DDLOCK_WAIT, NULL);
if ( v1 )
DDErrMsg(v1, 235, "C:\\Src\\Diablo\\Source\\dx.cpp");
v0 = (Screen *)v2.lpSurface;
gpBufEnd += (unsigned int)v2.lpSurface;
LABEL_8:
gpBuffer = v0;
goto LABEL_9;
}
Sleep(20000);
TermMsg("lock_buf_priv");
LABEL_9:
++sgdwLockCount;
}
// 69CF0C: using guessed type int gpBufEnd;
void __cdecl unlock_buf_priv()
{
Screen *v0; // eax
int v1; // eax
if ( !sgdwLockCount )
TermMsg("draw main unlock error");
if ( !gpBuffer )
TermMsg("draw consistency error");
if ( !--sgdwLockCount )
{
v0 = gpBuffer;
gpBuffer = 0;
gpBufEnd -= (signed int)v0;
if ( !sgpBackBuf )
{
v1 = lpDDSBackBuf->Unlock(NULL);
if ( v1 )
DDErrMsg(v1, 273, "C:\\Src\\Diablo\\Source\\dx.cpp");
}
}
LeaveCriticalSection(&sgMemCrit);
}
// 69CF0C: using guessed type int gpBufEnd;
void __cdecl dx_cleanup()
{
void *v0; // ecx
if ( ghMainWnd )
ShowWindow(ghMainWnd, SW_HIDE);
SDrawDestroy();
EnterCriticalSection(&sgMemCrit);
if ( sgpBackBuf )
{
v0 = sgpBackBuf;
sgpBackBuf = 0;
mem_free_dbg(v0);
}
else if ( lpDDSBackBuf )
{
lpDDSBackBuf->Release();
lpDDSBackBuf = 0;
}
sgdwLockCount = 0;
gpBuffer = 0;
LeaveCriticalSection(&sgMemCrit);
if ( lpDDSPrimary )
{
lpDDSPrimary->Release();
lpDDSPrimary = 0;
}
if ( lpDDPalette )
{
lpDDPalette->Release();
lpDDPalette = 0;
}
if ( lpDDInterface )
{
lpDDInterface->Release();
lpDDInterface = 0;
}
}
void __cdecl dx_reinit()
{
int v0; // esi
EnterCriticalSection(&sgMemCrit);
ClearCursor();
v0 = sgdwLockCount;
while ( sgdwLockCount )
unlock_buf_priv();
dx_cleanup();
drawpanflag = 255;
dx_init(ghMainWnd);
for ( ; v0; --v0 )
lock_buf_priv();
LeaveCriticalSection(&sgMemCrit);
}
// 52571C: using guessed type int drawpanflag;

38
Source/dx.h

@ -0,0 +1,38 @@
//HEADER_GOES_HERE
#ifndef __DX_H__
#define __DX_H__
extern void *sgpBackBuf;
extern int dx_cpp_init_value; // weak
extern IDirectDraw *lpDDInterface;
extern IDirectDrawPalette *lpDDPalette; // idb
extern int sgdwLockCount;
extern Screen *gpBuffer;
extern IDirectDrawSurface *lpDDSBackBuf;
extern IDirectDrawSurface *lpDDSPrimary;
extern char gbBackBuf; // weak
extern char gbEmulate; // weak
extern HMODULE ghDiabMod; // idb
void __cdecl dx_cpp_init_1();
void __cdecl dx_cpp_init_2();
void __cdecl dx_init_mutex();
void __cdecl dx_cleanup_mutex_atexit();
void __cdecl dx_cleanup_mutex();
void __fastcall dx_init(HWND hWnd);
void __cdecl dx_create_back_buffer();
void __cdecl dx_create_primary_surface();
HRESULT __fastcall dx_DirectDrawCreate(GUID *guid, IDirectDraw **DD, void *unknown);
void __cdecl j_lock_buf_priv();
void __cdecl lock_buf_priv();
void __cdecl j_unlock_buf_priv();
void __cdecl unlock_buf_priv();
void __cdecl dx_cleanup();
void __cdecl dx_reinit();
void __cdecl j_dx_reinit();
/* data */
extern int dx_inf; // weak
#endif /* __DX_H__ */

1426
Source/effects.cpp

File diff suppressed because it is too large Load Diff

41
Source/effects.h

@ -0,0 +1,41 @@
//HEADER_GOES_HERE
#ifndef __EFFECTS_H__
#define __EFFECTS_H__
extern int effects_cpp_init_value; // weak
extern int sfxdelay; // weak
extern int sfxdnum;
extern void *sfx_stream;
extern TSFX *sfx_data_cur;
void __cdecl effects_cpp_init();
bool __fastcall effect_is_playing(int nSFX);
void __cdecl sfx_stop();
void __fastcall InitMonsterSND(int monst);
void __cdecl FreeEffects();
void __fastcall PlayEffect(int i, int mode);
int __fastcall calc_snd_position(int x, int y, int *plVolume, int *plPan);
void __fastcall PlaySFX(int psfx);
void __fastcall PlaySFX_priv(TSFX *pSFX, char loc, int x, int y);
void __fastcall stream_play(TSFX *pSFX, int lVolume, int lPan);
int __fastcall RndSFX(int psfx);
void __fastcall PlaySfxLoc(int psfx, int x, int y);
void __cdecl FreeMonsterSnd();
void __cdecl sound_stop();
void __cdecl sound_update();
void __cdecl effects_cleanup_sfx();
void __cdecl stream_update();
void __fastcall priv_sound_init(int bLoadMask);
void __cdecl sound_init();
void __stdcall effects_play_sound(char *snd_file);
/* rdata */
extern const int effects_inf; // weak
extern const char monster_action_sounds[]; // idb
/* data */
extern TSFX sgSFX[NUM_SFX];
#endif /* __EFFECTS_H__ */

210
Source/encrypt.cpp

@ -0,0 +1,210 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifndef NO_GLOBALS
int encrypt_table[1280];
#endif
void __fastcall encrypt_decrypt_block(void *block, int size, int key) // DecryptMPQBlock
{
unsigned int v3; // edx
int v4; // eax
unsigned int v5; // edi
unsigned int v6; // edx
int v7; // eax
int v8; // esi
v3 = (unsigned int)size >> 2;
v4 = 0xEEEEEEEE;
if ( v3 )
{
v5 = v3;
v6 = key;
do
{
v7 = encrypt_table[(unsigned char)v6 + 1024] + v4;
*(_DWORD *)block ^= v7 + v6;
v8 = *(_DWORD *)block;
block = (char *)block + 4;
v4 = 33 * v7 + v8 + 3;
v6 = ((~v6 << 21) + 0x11111111) | (v6 >> 11);
--v5;
}
while ( v5 );
}
}
void __fastcall encrypt_encrypt_block(void *block, int size, int key) // EncryptMPQBlock
{
unsigned int v3; // edx
int v4; // eax
unsigned int v5; // edi
unsigned int v6; // edx
int v7; // eax
int v8; // ebx
v3 = (unsigned int)size >> 2;
v4 = 0xEEEEEEEE;
if ( v3 )
{
v5 = v3;
v6 = key;
do
{
v7 = encrypt_table[(unsigned char)v6 + 1024] + v4;
v8 = *(_DWORD *)block ^ (v7 + v6);
v4 = 33 * v7 + *(_DWORD *)block + 3;
*(_DWORD *)block = v8;
block = (char *)block + 4;
v6 = ((~v6 << 21) + 0x11111111) | (v6 >> 11);
--v5;
}
while ( v5 );
}
}
int __fastcall encrypt_hash(char *s, int type) // HashStringSlash
{
int v2; // ebp
char *v3; // ebx
signed int v4; // esi
int v5; // edi
int v6; // ST00_4
char v7; // al
v2 = type;
v3 = s;
v4 = 0x7FED7FED;
v5 = 0xEEEEEEEE;
while ( v3 && *v3 )
{
v6 = *v3++;
v7 = toupper(v6);
v4 = (v5 + v4) ^ encrypt_table[v7 + (v2 << 8)];
v5 = v7 + 33 * v5 + v4 + 3;
}
return v4;
}
void __cdecl encrypt_init_lookup_table() // InitScratchSpace
{
unsigned int v0; // eax
int *v1; // edi
unsigned int v2; // eax
int v3; // ecx
signed int v4; // [esp+Ch] [ebp-8h]
int *v5; // [esp+10h] [ebp-4h]
v0 = 0x100001;
v5 = encrypt_table;
do
{
v1 = v5;
v4 = 5;
do
{
v2 = (125 * v0 + 3) % 0x2AAAAB;
v3 = (unsigned short)v2 << 16;
v0 = (125 * v2 + 3) % 0x2AAAAB;
*v1 = (unsigned short)v0 | v3;
v1 += 256;
--v4;
}
while ( v4 );
++v5;
}
while ( (signed int)v5 < (signed int)&encrypt_table[256] );
}
int __fastcall encrypt_compress(void *buf, int size) // MPQCompress_PKWare
{
unsigned char *v2; // ebx
unsigned char *v3; // esi
int v4; // ecx
unsigned char *v5; // edi
TDataInfo param; // [esp+Ch] [ebp-20h]
unsigned int type; // [esp+20h] [ebp-Ch]
unsigned int dsize; // [esp+24h] [ebp-8h]
char *ptr; // [esp+28h] [ebp-4h]
v2 = (unsigned char *)buf;
v3 = (unsigned char *)size;
ptr = (char *)DiabloAllocPtr(CMP_BUFFER_SIZE); // 36312
v4 = 2 * (_DWORD)v3;
if ( (unsigned int)(2 * (_DWORD)v3) < 0x2000 )
v4 = 0x2000;
v5 = (unsigned char *)DiabloAllocPtr(v4);
param.pbInBuffEnd = 0;
param.pbOutBuffEnd = 0;
type = 0;
param.pbInBuff = v2;
param.pbOutBuff = v5;
param.pbSize = v3;
dsize = 4096;
implode(
encrypt_pkware_read,
encrypt_pkware_write,
ptr,
&param,
&type,
&dsize);
if ( param.pbOutBuffEnd < v3 )
{
memcpy(v2, v5, (size_t)param.pbOutBuffEnd);
v3 = param.pbOutBuffEnd;
}
mem_free_dbg(ptr);
mem_free_dbg(v5);
return (int)v3;
}
unsigned int __cdecl encrypt_pkware_read(char *buf, unsigned int *size, void *param) // ReadPKWare
{
TDataInfo * pInfo = (TDataInfo *)param;
int v3; // edi
unsigned char *v4; // ecx
v3 = *size;
v4 = pInfo->pbInBuffEnd;
if ( *size >= (unsigned int)(pInfo->pbSize - v4) )
v3 = pInfo->pbSize - v4;
memcpy(buf, &v4[(unsigned int)pInfo->pbInBuff], v3);
pInfo->pbInBuffEnd += v3;
return v3;
}
void __cdecl encrypt_pkware_write(char *buf, unsigned int *size, void *param) // WritePKWare
{
TDataInfo * pInfo = (TDataInfo *)param;
memcpy(&pInfo->pbOutBuffEnd[(unsigned int)pInfo->pbOutBuff], buf, *size);
pInfo->pbOutBuffEnd += *size;
}
void __fastcall encrypt_decompress(void *param, int recv_size, int dwMaxBytes) // MPQDecompress_PKWare
{
unsigned char *v3; // edi
unsigned char *v4; // ebx
unsigned char *v5; // esi
TDataInfo info; // [esp+Ch] [ebp-18h]
char *ptr; // [esp+20h] [ebp-4h]
v3 = (unsigned char *)param;
v4 = (unsigned char *)recv_size;
ptr = (char *)DiabloAllocPtr(CMP_BUFFER_SIZE); // 36312
v5 = (unsigned char *)DiabloAllocPtr(dwMaxBytes);
info.pbInBuffEnd = 0;
info.pbOutBuffEnd = 0;
info.pbInBuff = v3;
info.pbOutBuff = v5;
info.pbSize = v4;
explode(
encrypt_pkware_read,
encrypt_pkware_write,
ptr,
&info);
memcpy(v3, v5, (size_t)info.pbOutBuffEnd);
mem_free_dbg(ptr);
mem_free_dbg(v5);
}

17
Source/encrypt.h

@ -0,0 +1,17 @@
//HEADER_GOES_HERE
#ifndef __ENCRYPT_H__
#define __ENCRYPT_H__
extern int encrypt_table[1280];
//int encrypt_52B564[257];
void __fastcall encrypt_decrypt_block(void *block, int size, int key);
void __fastcall encrypt_encrypt_block(void *block, int size, int key);
int __fastcall encrypt_hash(char *s, int type);
void __cdecl encrypt_init_lookup_table();
int __fastcall encrypt_compress(void *buf, int size);
unsigned int __cdecl encrypt_pkware_read(char *buf, unsigned int *size, void *param);
void __cdecl encrypt_pkware_write(char *buf, unsigned int *size, void *param);
void __fastcall encrypt_decompress(void *param, int recv_size, int dwMaxBytes);
#endif /* __ENCRYPT_H__ */

2920
Source/engine.cpp

File diff suppressed because it is too large Load Diff

80
Source/engine.h

@ -0,0 +1,80 @@
//HEADER_GOES_HERE
#ifndef __ENGINE_H__
#define __ENGINE_H__
//offset 0
//pCelBuff->pFrameTable[0]
extern int engine_cpp_init_value; // weak
extern char gbPixelCol; // automap pixel color 8-bit (palette entry)
extern int dword_52B970; // bool flip - if y < x
extern int orgseed; // weak
extern int sgnWidth;
extern int sglGameSeed; // weak
extern int SeedCount; // weak
extern int dword_52B99C; // bool valid - if x/y are in bounds
void __cdecl engine_cpp_init_1();
void __fastcall CelDrawDatOnly(char *pDecodeTo, char *pRLEBytes, int dwRLESize, int dwRLEWdt);
void __fastcall CelDecodeOnly(int screen_x, int screen_y, void *pCelBuff, int frame, int frame_width);
void __fastcall CelDecDatOnly(char *pBuff, char *pCelBuff, int frame, int frame_width);
void __fastcall CelDrawHdrOnly(int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width, int always_0, int direction);
void __fastcall CelDecodeHdrOnly(char *pBuff, char *pCelBuff, int frame, int frame_width, int always_0, int direction);
void __fastcall CelDecDatLightOnly(char *pDecodeTo, char *pRLEBytes, int frame_content_size, int frame_width);
void __fastcall CelDecDatLightEntry(unsigned char shift, char *LightIndex, char *&pDecodeTo, char *&pRLEBytes); /* __usercall a1@<cl> a2@<ebx> a3@<edi> a4@<esi> */
void __fastcall CelDecDatLightTrans(char *pDecodeTo, char *pRLEBytes, int frame_content_size, int frame_width);
void __fastcall CelDecodeLightOnly(int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width);
void __fastcall CelDecodeHdrLightOnly(int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width, int always_0, int direction);
void __fastcall CelDecodeHdrLightTrans(char *pBuff, char *pCelBuff, int frame, int frame_width, int always_0, int direction);
void __fastcall CelDrawHdrLightRed(int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width, int always_0, int direction, char always_1);
void __fastcall Cel2DecDatOnly(char *pDecodeTo, char *pRLEBytes, int frame_content_size, int frame_width);
void __fastcall Cel2DrawHdrOnly(int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width, int a6, int direction);
void __fastcall Cel2DecodeHdrOnly(char *pBuff, char *pCelBuff, int frame, int frame_width, int a5, int direction);
void __fastcall Cel2DecDatLightOnly(char *pDecodeTo, char *pRLEBytes, int frame_content_size, int frame_width);
void __fastcall Cel2DecDatLightEntry(unsigned char shift, char *LightIndex, char *&pDecodeTo, char *&pRLEBytes); /* __usercall a1@<cl> a2@<ebx> a3@<edi> a4@<esi> */
void __fastcall Cel2DecDatLightTrans(char *pDecodeTo, char *pRLEBytes, int frame_content_size, int frame_width);
void __fastcall Cel2DecodeHdrLight(int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width, int a6, int direction);
void __fastcall Cel2DecodeLightTrans(char *dst_buf, char *pCelBuff, int frame, int frame_width, int a5, int direction);
void __fastcall Cel2DrawHdrLightRed(int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width, int always_0, int direction, char always_1);
void __fastcall CelDecodeRect(char *pBuff, int always_0, int dst_height, int dst_width, char *pCelBuff, int frame, int frame_width);
void __fastcall CelDecodeClr(BYTE colour, int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width, int a7, int direction);
void __fastcall CelDrawHdrClrHL(char colour, int screen_x, int screen_y, char *pCelBuff, int frame, int frame_width, int a7, int direction);
void __fastcall ENG_set_pixel(int screen_x, int screen_y, char pixel);
void __fastcall engine_draw_pixel(int x, int y);
void __fastcall DrawLine(int x0, int y0, int x1, int y1, char col);
int __fastcall GetDirection(int x1, int y1, int x2, int y2);
void __fastcall SetRndSeed(int s);
int __cdecl GetRndSeed();
int __fastcall random(BYTE idx, int v);
void __cdecl engine_cpp_init_2();
void __cdecl mem_init_mutex();
void __cdecl mem_atexit_mutex();
void __cdecl mem_free_mutex();
unsigned char *__fastcall DiabloAllocPtr(int dwBytes);
void __fastcall mem_free_dbg(void *p);
unsigned char *__fastcall LoadFileInMem(char *pszName, int *pdwFileLen);
void __fastcall LoadFileWithMem(char *pszName, void *buf);
void __fastcall Cl2ApplyTrans(unsigned char *p, unsigned char *ttbl, int last_frame);
void __fastcall Cl2DecodeFrm1(int x, int y, char *pCelBuff, int nCel, int width, int dir1, int dir2);
void __fastcall Cl2DecDatFrm1(char *buffer, char *frame_content, int a3, int width);
void __fastcall Cl2DecodeFrm2(char colour, int screen_x, int screen_y, char *pCelBuff, int nCel, int frame_width, int a7, int a8);
void __fastcall Cl2DecDatFrm2(char *buffer, char *a2, int a3, int a4, char a5);
void __fastcall Cl2DecodeFrm3(int screen_x, int screen_y, char *pCelBuff, int nCel, int frame_width, int a6, int a7, char a8);
void __fastcall Cl2DecDatLightTbl1(char *a1, char *a2, int a3, int a4, char *unused_lindex);
void __fastcall Cl2DecodeLightTbl(int screen_x, int screen_y, char *pCelBuff, int nCel, int frame_width, int a6, int a7);
void __fastcall Cl2DecodeFrm4(int screen_x, int screen_y, char *pCelBuff, int nCel, int frame_width, int a6, int a7);
void __fastcall Cl2DecDatFrm4(char *buffer, char *a2, int a3, int frame_width);
void __fastcall Cl2DecodeClrHL(char colour, int screen_x, int screen_y, char *pCelBuff, int nCel, int frame_width, int a7, int a8);
void __fastcall Cl2DecDatClrHL(char *dst_buf, char *frame_content, int a3, int frame_width, char colour);
void __fastcall Cl2DecodeFrm5(int screen_x, int screen_y, char *pCelBuff, int nCel, int frame_width, int a6, int a7, char a8);
void __fastcall Cl2DecDatLightTbl2(char *dst_buf, char *a2, int a3, int frame_width, char *a5);
void __fastcall Cl2DecodeFrm6(int screen_x, int screen_y, char *pCelBuff, int nCel, int frame_width, int a6, int a7);
void __fastcall PlayInGameMovie(char *pszMovie);
/* rdata */
extern const int engine_inf; // weak
extern const int rand_increment; // unused
extern const int rand_multiplier; // unused
#endif /* __ENGINE_H__ */

217
Source/error.cpp

@ -0,0 +1,217 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifndef NO_GLOBALS
char msgtable[80];
char msgdelay; // weak
char msgflag; // weak
char msgcnt; // weak
#endif
char *MsgStrings[44] =
{
&empty_string,
"No automap available in town",
"No multiplayer functions in demo",
"Direct Sound Creation Failed",
"Not available in shareware version",
"Not enough space to save",
"No Pause in town",
"Copying to a hard disk is recommended",
"Multiplayer sync problem",
"No pause in multiplayer",
"Loading...",
"Saving...",
"Some are weakened as one grows strong",
"New strength is forged through destruction",
"Those who defend seldom attack",
"The sword of justice is swift and sharp",
"While the spirit is vigilant the body thrives",
"The powers of mana refocused renews",
"Time cannot diminish the power of steel",
"Magic is not always what it seems to be",
"What once was opened now is closed",
"Intensity comes at the cost of wisdom",
"Arcane power brings destruction",
"That which cannot be held cannot be harmed",
"Crimson and Azure become as the sun",
"Knowledge and wisdom at the cost of self",
"Drink and be refreshed",
"Wherever you go, there you are",
"Energy comes at the cost of wisdom",
"Riches abound when least expected",
"Where avarice fails, patience gains reward",
"Blessed by a benevolent companion!",
"The hands of men may be guided by fate",
"Strength is bolstered by heavenly faith",
"The essence of life flows from within",
"The way is made clear when viewed from above",
"Salvation comes at the cost of wisdom",
"Mysteries are revealed in the light of reason",
"Those who are last may yet be first",
"Generosity brings its own rewards",
"You must be at least level 8 to use this.",
"You must be at least level 13 to use this.",
"You must be at least level 17 to use this.",
"Arcane knowledge gained!"
};
void __fastcall InitDiabloMsg(char e)
{
int i; // edx
bool v2; // sf
unsigned char v3; // of
i = 0;
if ( msgcnt <= 0 )
{
LABEL_4:
v3 = __OFSUB__(msgcnt, 80);
v2 = (char)(msgcnt - 80) < 0;
msgtable[msgcnt] = e;
if ( v2 ^ v3 )
++msgcnt;
msgdelay = 70;
msgflag = msgtable[0];
}
else
{
while ( msgtable[i] != e )
{
if ( ++i >= msgcnt )
goto LABEL_4;
}
}
}
// 52B9F0: using guessed type char msgdelay;
// 52B9F1: using guessed type char msgflag;
// 52B9F2: using guessed type char msgcnt;
void __cdecl ClrDiabloMsg()
{
msgflag = 0;
msgcnt = 0;
memset(msgtable, 0, sizeof(msgtable));
}
// 52B9F1: using guessed type char msgflag;
// 52B9F2: using guessed type char msgcnt;
void __cdecl DrawDiabloMsg()
{
int v0; // esi
signed int v1; // edi
char *v2; // edi
signed int v3; // edx
signed int v4; // ecx
int v5; // edi
signed int v6; // ecx
_BYTE *v7; // edi
int v8; // edi
signed int v9; // ebx
signed int v10; // eax
signed int v11; // ecx
int v12; // esi
signed int v13; // esi
unsigned char v14; // bl
bool v15; // zf
signed int v16; // [esp+Ch] [ebp-8h]
signed int v17; // [esp+Ch] [ebp-8h]
signed int screen_x; // [esp+10h] [ebp-4h]
CelDecodeOnly(165, 318, pSTextSlidCels, 1, 12);
CelDecodeOnly(591, 318, pSTextSlidCels, 4, 12);
CelDecodeOnly(165, 366, pSTextSlidCels, 2, 12);
CelDecodeOnly(591, 366, pSTextSlidCels, 3, 12);
screen_x = 173;
v16 = 35;
do
{
CelDecodeOnly(screen_x, 318, pSTextSlidCels, 5, 12);
CelDecodeOnly(screen_x, 366, pSTextSlidCels, 7, 12);
screen_x += 12;
--v16;
}
while ( v16 );
v0 = 330;
v1 = 3;
do
{
CelDecodeOnly(165, v0, pSTextSlidCels, 6, 12);
CelDecodeOnly(591, v0, pSTextSlidCels, 8, 12);
v0 += 12;
--v1;
}
while ( v1 );
v2 = &gpBuffer->row[203].pixels[104];
v3 = 27;
do
{
v4 = 216;
do
{
*v2 = 0;
v2 += 2;
--v4;
}
while ( v4 );
v5 = (int)(v2 - 1200);
v6 = 216;
do
{
v7 = (_BYTE *)(v5 + 1);
*v7 = 0;
v5 = (int)(v7 + 1);
--v6;
}
while ( v6 );
v2 = (char *)(v5 - 1200);
--v3;
}
while ( v3 );
strcpy(tempstr, MsgStrings[msgflag]);
v8 = screen_y_times_768[342] + 165;
v9 = strlen(tempstr);
v10 = 0;
v11 = 0;
v17 = v9;
if ( v9 <= 0 )
goto LABEL_27;
do
{
v12 = (unsigned char)tempstr[v11++];
v10 += fontkern[fontframe[fontidx[v12]]] + 1;
}
while ( v11 < v9 );
if ( v10 < 442 )
LABEL_27:
v8 += (442 - v10) >> 1;
v13 = 0;
if ( v9 > 0 )
{
do
{
v14 = fontframe[fontidx[(unsigned char)tempstr[v13]]];
if ( v14 )
CPrintString(v8, v14, 3);
++v13;
v8 += fontkern[v14] + 1;
}
while ( v13 < v17 );
}
v15 = msgdelay == 0;
if ( msgdelay > 0 )
v15 = --msgdelay == 0;
if ( v15 )
{
v15 = msgcnt-- == 1;
msgdelay = 70;
if ( v15 )
msgflag = 0;
else
msgflag = msgtable[msgcnt];
}
}
// 52B9F0: using guessed type char msgdelay;
// 52B9F1: using guessed type char msgflag;
// 52B9F2: using guessed type char msgcnt;

17
Source/error.h

@ -0,0 +1,17 @@
//HEADER_GOES_HERE
#ifndef __ERROR_H__
#define __ERROR_H__
extern char msgtable[80];
extern char msgdelay; // weak
extern char msgflag; // weak
extern char msgcnt; // weak
void __fastcall InitDiabloMsg(char e);
void __cdecl ClrDiabloMsg();
void __cdecl DrawDiabloMsg();
/* data */
extern char *MsgStrings[44];
#endif /* __ERROR_H__ */

248
Source/fault.cpp

@ -0,0 +1,248 @@
//HEADER_GOES_HERE
#include "../types.h"
LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter; // idb
struct exception_cpp_init
{
exception_cpp_init()
{
exception_install_filter();
j_exception_init_filter();
}
} _exception_cpp_init;
void __cdecl exception_install_filter()
{
exception_set_filter();
}
void __cdecl j_exception_init_filter()
{
atexit(exception_init_filter);
}
void __cdecl exception_init_filter()
{
exception_set_filter_ptr();
}
LONG __stdcall TopLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo)
{
log_dump_computer_info();
PEXCEPTION_RECORD xcpt = ExceptionInfo->ExceptionRecord;
char szExceptionNameBuf[MAX_PATH]; // [esp+Ch] [ebp-210h]
char *pszExceptionName = exception_get_error_type(ExceptionInfo->ExceptionRecord->ExceptionCode, szExceptionNameBuf, sizeof(szExceptionNameBuf));
log_printf("Exception code: %08X %s\r\n", xcpt->ExceptionCode, pszExceptionName);
char szModuleName[MAX_PATH];
int sectionNumber, sectionOffset;
exception_unknown_module(xcpt->ExceptionAddress, szModuleName, MAX_PATH, &sectionNumber, &sectionOffset);
log_printf("Fault address:\t%08X %02X:%08X %s\r\n", xcpt->ExceptionAddress, sectionNumber, sectionOffset, szModuleName);
PCONTEXT ctx = ExceptionInfo->ContextRecord;
log_printf("\r\nRegisters:\r\n");
log_printf(
"EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n",
ctx->Eax,
ctx->Ebx,
ctx->Ecx,
ctx->Edx,
ctx->Esi,
ctx->Edi);
log_printf("CS:EIP:%04X:%08X\r\n", ctx->SegCs, ctx->Eip);
log_printf("SS:ESP:%04X:%08X EBP:%08X\r\n", ctx->SegSs, ctx->Esp, ctx->Ebp);
log_printf("DS:%04X ES:%04X FS:%04X GS:%04X\r\n", ctx->SegDs, ctx->SegEs, ctx->SegFs, ctx->SegGs);
log_printf("Flags:%08X\r\n", ctx->EFlags);
exception_call_stack((void *)ctx->Eip, (STACK_FRAME*)ctx->Ebp);
log_printf("Stack bytes:\r\n");
exception_hex_format((BYTE *)ctx->Esp, 0);
log_printf("Code bytes:\r\n");
exception_hex_format((BYTE *)ctx->Eip, 16);
log_printf("\r\n");
log_flush(1);
if ( lpTopLevelExceptionFilter )
return lpTopLevelExceptionFilter(ExceptionInfo);
return EXCEPTION_CONTINUE_SEARCH;
}
void __fastcall exception_hex_format(BYTE *ptr, unsigned int numBytes)
{
int i;
while (numBytes > 0)
{
unsigned int bytesRead = 16;
if (numBytes < 16 )
bytesRead = numBytes;
if ( IsBadReadPtr(ptr, bytesRead) )
break;
log_printf("0x%08x: ", ptr);
for (i = 0; i < 16; ++i)
{
const char *fmt = "%02x ";
if (i >= bytesRead)
fmt = " ";
log_printf(fmt, ptr[i]);
if (i % 4 == 3)
log_printf(" ");
}
for (i = 0; i < bytesRead; ++i)
{
char c;
if (isprint(ptr[i]))
c = ptr[i];
else
c = '.';
log_printf("%c", c);
}
log_printf("\r\n");
ptr += bytesRead;
numBytes -= bytesRead;
}
log_printf("\r\n");
}
void __fastcall exception_unknown_module(LPCVOID lpAddress, LPSTR lpModuleName, int iMaxLength, int *sectionNum, int *sectionOffset)
{
lstrcpyn(lpModuleName, "*unknown*", iMaxLength);
*sectionNum = 0;
*sectionOffset = 0;
MEMORY_BASIC_INFORMATION memInfo; // [esp+Ch] [ebp-24h]
if (!VirtualQuery(lpAddress, &memInfo, sizeof(memInfo)))
return;
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)memInfo.AllocationBase;
if ( !memInfo.AllocationBase )
dosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(0);
if (!GetModuleFileName((HMODULE)dosHeader, lpModuleName, iMaxLength))
{
lstrcpyn(lpModuleName, "*unknown*", iMaxLength);
return;
}
if (dosHeader && dosHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
LONG ntOffset = dosHeader->e_lfanew;
if (ntOffset)
{
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + ntOffset);
if (ntHeader->Signature == IMAGE_NT_SIGNATURE)
{
DWORD numSections = ntHeader->FileHeader.NumberOfSections;
DWORD moduleOffset = (_BYTE *)lpAddress - (_BYTE *)dosHeader;
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeader);
for (int i = 0; i < numSections; ++i, ++section)
{
DWORD sectionSize = section->SizeOfRawData;
DWORD sectionAddress = section->VirtualAddress;
if (section->SizeOfRawData <= section->Misc.VirtualSize)
sectionSize = section->Misc.VirtualSize;
if (moduleOffset >= sectionAddress && moduleOffset <= sectionAddress + sectionSize)
{
*sectionNum = i + 1;
*sectionOffset = moduleOffset - sectionAddress;
return;
}
}
}
}
}
}
void __fastcall exception_call_stack(void *instr, STACK_FRAME *stackFrame)
{
STACK_FRAME *oldStackFrame;
log_printf("Call stack:\r\nAddress Frame Logical addr Module\r\n");
do
{
char szModuleName[MAX_PATH];
int sectionNumber, sectionOffset;
exception_unknown_module(instr, szModuleName, MAX_PATH, &sectionNumber, &sectionOffset);
log_printf("%08X %08X %04X:%08X %s\r\n", instr, stackFrame, sectionNumber, sectionOffset, szModuleName);
if ( IsBadWritePtr(stackFrame, 8u) )
break;
instr = stackFrame->pCallRet;
oldStackFrame = stackFrame;
stackFrame = stackFrame->pNext;
if ((int)stackFrame % 4 != 0)
break;
}
while (stackFrame > oldStackFrame && !IsBadWritePtr(stackFrame, 8u) );
log_printf("\r\n");
}
#define CASE_EXCEPTION(v, errName) case EXCEPTION_ ## errName: v = #errName; break;
char *__fastcall exception_get_error_type(DWORD dwMessageId, LPSTR lpString1, DWORD nSize)
{
const char *v4; // eax
switch (dwMessageId) {
CASE_EXCEPTION(v4, STACK_OVERFLOW);
CASE_EXCEPTION(v4, FLT_DIVIDE_BY_ZERO);
CASE_EXCEPTION(v4, FLT_INEXACT_RESULT);
CASE_EXCEPTION(v4, FLT_INVALID_OPERATION);
CASE_EXCEPTION(v4, FLT_OVERFLOW);
CASE_EXCEPTION(v4, FLT_STACK_CHECK);
CASE_EXCEPTION(v4, FLT_UNDERFLOW);
CASE_EXCEPTION(v4, INT_DIVIDE_BY_ZERO);
CASE_EXCEPTION(v4, INT_OVERFLOW);
CASE_EXCEPTION(v4, PRIV_INSTRUCTION);
CASE_EXCEPTION(v4, FLT_DENORMAL_OPERAND);
CASE_EXCEPTION(v4, INVALID_HANDLE);
CASE_EXCEPTION(v4, ILLEGAL_INSTRUCTION);
CASE_EXCEPTION(v4, NONCONTINUABLE_EXCEPTION);
CASE_EXCEPTION(v4, INVALID_DISPOSITION);
CASE_EXCEPTION(v4, ARRAY_BOUNDS_EXCEEDED);
CASE_EXCEPTION(v4, IN_PAGE_ERROR);
CASE_EXCEPTION(v4, GUARD_PAGE);
CASE_EXCEPTION(v4, DATATYPE_MISALIGNMENT);
CASE_EXCEPTION(v4, BREAKPOINT);
CASE_EXCEPTION(v4, SINGLE_STEP);
CASE_EXCEPTION(v4, ACCESS_VIOLATION);
default:
HMODULE ntdll = GetModuleHandle("NTDLL.DLL");
if (!FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, ntdll, dwMessageId, 0, lpString1, nSize, NULL))
{
v4 = "*unknown*";
}
}
lstrcpyn(lpString1, v4, nSize);
return lpString1;
}
void __fastcall exception_set_filter()
{
lpTopLevelExceptionFilter = SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)TopLevelExceptionFilter);
}
LPTOP_LEVEL_EXCEPTION_FILTER __cdecl exception_set_filter_ptr()
{
return SetUnhandledExceptionFilter(lpTopLevelExceptionFilter);
}
LPTOP_LEVEL_EXCEPTION_FILTER __cdecl exception_get_filter()
{
return lpTopLevelExceptionFilter;
}

26
Source/fault.h

@ -0,0 +1,26 @@
//HEADER_GOES_HERE
#ifndef __FAULT_H__
#define __FAULT_H__
struct STACK_FRAME {
STACK_FRAME *pNext;
void *pCallRet;
};
//int dword_52B9F4;
extern LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter; // idb
void __cdecl exception_cpp_init();
void __cdecl exception_install_filter();
void __cdecl j_exception_init_filter();
void __cdecl exception_init_filter();
LONG __stdcall TopLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo);
void __fastcall exception_hex_format(BYTE *ptr, unsigned int numBytes);
void __fastcall exception_unknown_module(LPCVOID lpAddress, LPSTR lpModuleName, int iMaxLength, int *sectionNum, int *sectionOffset);
void __fastcall exception_call_stack(void *instr, STACK_FRAME *stackAddr);
char *__fastcall exception_get_error_type(DWORD dwMessageId, LPSTR lpString1, DWORD nSize);
void __fastcall exception_set_filter();
LPTOP_LEVEL_EXCEPTION_FILTER __cdecl exception_set_filter_ptr();
LPTOP_LEVEL_EXCEPTION_FILTER __cdecl exception_get_filter();
#endif /* __FAULT_H__ */

327
Source/gamemenu.cpp

@ -0,0 +1,327 @@
//HEADER_GOES_HERE
#include "../types.h"
TMenuItem sgSingleMenu[6] =
{
{ 0x80000000, "Save Game", &gamemenu_save_game },
{ 0x80000000, "Options", &gamemenu_options },
{ 0x80000000, "New Game", &gamemenu_new_game },
{ 0x80000000, "Load Game", &gamemenu_load_game },
{ 0x80000000, "Quit Diablo", &gamemenu_quit_game },
{ 0x80000000, NULL, NULL }
};
TMenuItem sgMultiMenu[5] =
{
{ 0x80000000, "Options", &gamemenu_options },
{ 0x80000000, "New Game", &gamemenu_new_game },
{ 0x80000000, "Restart In Town", &gamemenu_restart_town },
{ 0x80000000, "Quit Diablo", &gamemenu_quit_game },
{ 0x80000000, NULL, NULL }
};
TMenuItem sgOptionMenu[6] =
{
{ 0xC0000000, NULL, (void (__cdecl *)(void))&gamemenu_music_volume },
{ 0xC0000000, NULL, (void (__cdecl *)(void))&gamemenu_sound_volume },
{ 0xC0000000, "Gamma", (void (__cdecl *)(void))&gamemenu_gamma },
{ 0x80000000, NULL, &gamemenu_color_cycling },
{ 0x80000000, "Previous Menu", &gamemenu_previous },
{ 0x80000000, NULL, NULL }
};
char *music_toggle_names[] = { "Music", "Music Disabled" };
char *sound_toggle_names[] = { "Sound", "Sound Disabled" };
char *color_cycling_toggle_names[] = { "Color Cycling Off", "Color Cycling On" };
void __cdecl gamemenu_previous()
{
void (__cdecl *v0)(); // edx
TMenuItem *v1; // ecx
if ( gbMaxPlayers == 1 )
{
v0 = gamemenu_enable_single;
v1 = sgSingleMenu;
}
else
{
v0 = gamemenu_enable_multi;
v1 = sgMultiMenu;
}
gmenu_call_proc(v1, v0);
PressEscKey();
}
// 679660: using guessed type char gbMaxPlayers;
void __cdecl gamemenu_enable_single()
{
bool v0; // dl
gmenu_enable(&sgSingleMenu[3], gbValidSaveFile);
v0 = 0;
if ( plr[myplr]._pmode != PM_DEATH && !deathflag )
v0 = 1;
gmenu_enable(sgSingleMenu, v0);
}
void __cdecl gamemenu_enable_multi()
{
gmenu_enable(&sgMultiMenu[2], deathflag);
}
void __cdecl gamemenu_off()
{
gmenu_call_proc(0, 0);
}
void __cdecl gamemenu_handle_previous()
{
if ( gmenu_exception() )
gamemenu_off();
else
gamemenu_previous();
}
void __cdecl gamemenu_new_game()
{
int i; // eax
for(i = 0; i < 4; i++)
{
plr[i]._pmode = PM_QUIT;
plr[i]._pInvincible = 1;
}
deathflag = 0;
drawpanflag = 255;
scrollrt_draw_game_screen(1);
gbRunGame = 0;
gamemenu_off();
}
// 525650: using guessed type int gbRunGame;
// 52571C: using guessed type int drawpanflag;
void __cdecl gamemenu_quit_game()
{
gamemenu_new_game();
gbRunGameResult = 0;
}
// 525698: using guessed type int gbRunGameResult;
void __cdecl gamemenu_load_game()
{
WNDPROC saveProc; // edi
saveProc = SetWindowProc(DisableInputWndProc);
gamemenu_off();
SetCursor(0);
InitDiabloMsg(10);
drawpanflag = 255;
DrawAndBlit();
LoadGame(FALSE);
ClrDiabloMsg();
PaletteFadeOut(8);
deathflag = 0;
drawpanflag = 255;
DrawAndBlit();
PaletteFadeIn(8);
SetCursor(CURSOR_HAND);
interface_msg_pump();
SetWindowProc(saveProc);
}
// 52571C: using guessed type int drawpanflag;
void __cdecl gamemenu_save_game()
{
WNDPROC saveProc; // edi
if ( pcurs == CURSOR_HAND )
{
if ( plr[myplr]._pmode == PM_DEATH || deathflag )
{
gamemenu_off();
}
else
{
saveProc = SetWindowProc(DisableInputWndProc);
SetCursor(0);
gamemenu_off();
InitDiabloMsg(11);
drawpanflag = 255;
DrawAndBlit();
SaveGame();
ClrDiabloMsg();
drawpanflag = 255;
SetCursor(CURSOR_HAND);
interface_msg_pump();
SetWindowProc(saveProc);
}
}
}
// 52571C: using guessed type int drawpanflag;
void __cdecl gamemenu_restart_town()
{
NetSendCmd(1u, CMD_RETOWN);
}
void __cdecl gamemenu_options()
{
gamemenu_get_music();
gamemenu_get_sound();
gamemenu_get_gamma();
gamemenu_get_color_cycling();
gmenu_call_proc(sgOptionMenu, 0);
}
void __cdecl gamemenu_get_music()
{
gamemenu_sound_music_toggle(music_toggle_names, sgOptionMenu, sound_get_or_set_music_volume(1));
}
void __fastcall gamemenu_sound_music_toggle(char **names, TMenuItem *menu_item, int gamma)
{
if ( gbSndInited )
{
menu_item->dwFlags |= 0xC0000000;
menu_item->pszStr = *names;
gmenu_slider_3(menu_item, 17);
gmenu_slider_1(menu_item, -1600, 0, gamma);
}
else
{
menu_item->dwFlags &= 0x3F000000;
menu_item->pszStr = names[1];
}
}
void __cdecl gamemenu_get_sound()
{
gamemenu_sound_music_toggle(sound_toggle_names, &sgOptionMenu[1], sound_get_or_set_sound_volume(1));
}
void __cdecl gamemenu_get_color_cycling()
{
sgOptionMenu[3].pszStr = color_cycling_toggle_names[palette_get_colour_cycling()];
}
void __cdecl gamemenu_get_gamma()
{
gmenu_slider_3(&sgOptionMenu[2], 15);
gmenu_slider_1(&sgOptionMenu[2], 30, 100, UpdateGamma(0));
}
void __fastcall gamemenu_music_volume(int a1)
{
int v1; // esi
if ( a1 )
{
if ( gbMusicOn )
{
gbMusicOn = 0;
music_stop();
sound_get_or_set_music_volume(-1600);
goto LABEL_11;
}
gbMusicOn = 1;
sound_get_or_set_music_volume(0);
LABEL_10:
music_start((unsigned char)leveltype);
goto LABEL_11;
}
v1 = gamemenu_slider_music_sound(sgOptionMenu);
sound_get_or_set_music_volume(v1);
if ( v1 != -1600 )
{
if ( gbMusicOn )
goto LABEL_11;
gbMusicOn = 1;
goto LABEL_10;
}
if ( gbMusicOn )
{
gbMusicOn = 0;
music_stop();
}
LABEL_11:
gamemenu_get_music();
}
// 4A22D4: using guessed type char gbMusicOn;
// 5BB1ED: using guessed type char leveltype;
int __fastcall gamemenu_slider_music_sound(TMenuItem *menu_item)
{
return gmenu_slider_get(menu_item, -1600, 0);
}
void __fastcall gamemenu_sound_volume(int a1)
{
int v1; // ecx
int v2; // esi
if ( a1 )
{
if ( gbSoundOn )
{
gbSoundOn = 0;
FreeMonsterSnd();
v1 = -1600;
}
else
{
gbSoundOn = 1;
v1 = 0;
}
sound_get_or_set_sound_volume(v1);
}
else
{
v2 = gamemenu_slider_music_sound(&sgOptionMenu[1]);
sound_get_or_set_sound_volume(v2);
if ( v2 == -1600 )
{
if ( gbSoundOn )
{
gbSoundOn = 0;
FreeMonsterSnd();
}
}
else if ( !gbSoundOn )
{
gbSoundOn = 1;
}
}
PlaySFX(IS_TITLEMOV);
gamemenu_get_sound();
}
// 4A22D5: using guessed type char gbSoundOn;
void __fastcall gamemenu_gamma(int a1)
{
int v1; // eax
int v2; // eax
if ( a1 )
{
v1 = -(UpdateGamma(0) != 30);
_LOBYTE(v1) = v1 & 0xBA;
v2 = v1 + 100;
}
else
{
v2 = gamemenu_slider_gamma();
}
UpdateGamma(v2);
gamemenu_get_gamma();
}
int __cdecl gamemenu_slider_gamma()
{
return gmenu_slider_get(&sgOptionMenu[2], 30, 100);
}
void __cdecl gamemenu_color_cycling()
{
palette_set_color_cycling(palette_get_colour_cycling() == 0);
sgOptionMenu[3].pszStr = color_cycling_toggle_names[palette_get_colour_cycling() & 1];
}

36
Source/gamemenu.h

@ -0,0 +1,36 @@
//HEADER_GOES_HERE
#ifndef __GAMEMENU_H__
#define __GAMEMENU_H__
void __cdecl gamemenu_previous();
void __cdecl gamemenu_enable_single();
void __cdecl gamemenu_enable_multi();
void __cdecl gamemenu_off();
void __cdecl gamemenu_handle_previous();
void __cdecl gamemenu_new_game();
void __cdecl gamemenu_quit_game();
void __cdecl gamemenu_load_game(); // should have 1-2 args
void __cdecl gamemenu_save_game(); // should have 1-2 args
void __cdecl gamemenu_restart_town();
void __cdecl gamemenu_options();
void __cdecl gamemenu_get_music();
void __fastcall gamemenu_sound_music_toggle(char **names, TMenuItem *menu_item, int gamma);
void __cdecl gamemenu_get_sound();
void __cdecl gamemenu_get_color_cycling();
void __cdecl gamemenu_get_gamma();
void __fastcall gamemenu_music_volume(int a1);
int __fastcall gamemenu_slider_music_sound(TMenuItem *menu_item);
void __fastcall gamemenu_sound_volume(int a1);
void __fastcall gamemenu_gamma(int a1);
int __cdecl gamemenu_slider_gamma();
void __cdecl gamemenu_color_cycling();
/* rdata */
extern TMenuItem sgSingleMenu[6];
extern TMenuItem sgMultiMenu[5];
extern TMenuItem sgOptionMenu[6];
extern char *music_toggle_names[];
extern char *sound_toggle_names[];
extern char *color_cycling_toggle_names[];
#endif /* __GAMEMENU_H__ */

1441
Source/gendung.cpp

File diff suppressed because it is too large Load Diff

95
Source/gendung.h

@ -0,0 +1,95 @@
//HEADER_GOES_HERE
#ifndef __GENDUNG_H__
#define __GENDUNG_H__
extern short level_frame_types[2048];
extern int themeCount;
extern char nTransTable[2049];
//int dword_52D204;
extern int dMonster[MAXDUNX][MAXDUNY];
extern char dungeon[40][40];
extern char dObject[MAXDUNX][MAXDUNY];
extern void *pSpeedCels;
extern int nlevel_frames; // weak
extern char pdungeon[40][40];
extern char dDead[MAXDUNX][MAXDUNY];
extern short dpiece_defs_map_1[16][MAXDUNX][MAXDUNY];
extern char dTransVal2[MAXDUNX][MAXDUNY];
extern char TransVal; // weak
extern int dword_5A5594;
extern char dflags[40][40];
extern int dPiece[MAXDUNX][MAXDUNY];
extern char dTransVal[MAXDUNX][MAXDUNY];
extern int setloadflag_2; // weak
extern int tile_defs[2048];
extern void *pMegaTiles;
extern void *pLevelPieces;
extern int gnDifficulty; // idb
extern char block_lvid[2049];
//char byte_5B78EB;
extern char dung_map[MAXDUNX][MAXDUNY];
extern char nTrapTable[2049];
extern char leveltype; // weak
extern unsigned char currlevel; // idb
extern char TransList[256];
extern UCHAR nSolidTable[2049];
extern int level_frame_count[2048];
extern ScrollStruct ScrollInfo;
extern void *pDungeonCels;
extern int speed_cel_frame_num_from_light_index_frame_num[16][128];
extern THEME_LOC themeLoc[MAXTHEMES];
extern char dPlayer[MAXDUNX][MAXDUNY];
extern int dword_5C2FF8; // weak
extern int dword_5C2FFC; // weak
extern int scr_pix_width; // weak
extern int scr_pix_height; // weak
extern char dArch[MAXDUNX][MAXDUNY];
extern char nBlockTable[2049];
extern void *level_special_cel;
extern char dFlags[MAXDUNX][MAXDUNY];
extern char dItem[MAXDUNX][MAXDUNY];
extern char setlvlnum; // weak
extern int level_frame_sizes[2048];
extern char nMissileTable[2049];
extern char *pSetPiece_2;
extern char setlvltype; // weak
extern char setlevel; // weak
extern int LvlViewY; // weak
extern int LvlViewX; // weak
extern int dmaxx; // weak
extern int dmaxy; // weak
extern int setpc_h; // weak
extern int setpc_w; // weak
extern int setpc_x; // idb
extern int ViewX; // idb
extern int ViewY; // idb
extern int setpc_y; // idb
extern char dMissile[MAXDUNX][MAXDUNY];
extern int dminx; // weak
extern int dminy; // weak
extern short dpiece_defs_map_2[16][MAXDUNX][MAXDUNY];
void __cdecl FillSolidBlockTbls();
void __cdecl gendung_418D91();
void __fastcall gendung_4191BF(int frames);
void __fastcall gendung_4191FB(int a1, int a2);
int __fastcall gendung_get_dpiece_num_from_coord(int x, int y);
void __cdecl gendung_4192C2();
void __cdecl SetDungeonMicros();
void __cdecl DRLG_InitTrans();
void __fastcall DRLG_MRectTrans(int x1, int y1, int x2, int y2);
void __fastcall DRLG_RectTrans(int x1, int y1, int x2, int y2);
void __fastcall DRLG_CopyTrans(int sx, int sy, int dx, int dy);
void __fastcall DRLG_ListTrans(int num, unsigned char *List);
void __fastcall DRLG_AreaTrans(int num, unsigned char *List);
void __cdecl DRLG_InitSetPC();
void __cdecl DRLG_SetPC();
void __fastcall Make_SetPC(int x, int y, int w, int h);
bool __fastcall DRLG_WillThemeRoomFit(int floor, int x, int y, int minSize, int maxSize, int *width, int *height);
void __fastcall DRLG_CreateThemeRoom(int themeIndex);
void __fastcall DRLG_PlaceThemeRooms(int minSize, int maxSize, int floor, int freq, int rndSize);
void __cdecl DRLG_HoldThemeRooms();
bool __fastcall SkipThemeRoom(int x, int y);
void __cdecl InitLevels();
#endif /* __GENDUNG_H__ */

511
Source/gmenu.cpp

@ -0,0 +1,511 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifndef NO_GLOBALS
void *optbar_cel;
bool byte_634464; // weak
void *PentSpin_cel;
TMenuItem *sgpCurrItem;
void *BigTGold_cel;
int dword_634474; // weak
char byte_634478; // weak
void (__cdecl *dword_63447C)();
TMenuItem *dword_634480; // idb
void *option_cel;
void *sgpLogo;
int dword_63448C; // weak
#endif
const unsigned char lfontframe[127] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 37, 49, 38, 0, 39, 40, 47,
42, 43, 41, 45, 52, 44, 53, 55, 36, 27,
28, 29, 30, 31, 32, 33, 34, 35, 51, 50,
0, 46, 0, 54, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 42, 0, 43, 0, 0, 0, 1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 20, 0, 21, 0
};
const unsigned char lfontkern[56] =
{
18, 33, 21, 26, 28, 19, 19, 26, 25, 11,
12, 25, 19, 34, 28, 32, 20, 32, 28, 20,
28, 36, 35, 46, 33, 33, 24, 11, 23, 22,
22, 21, 22, 21, 21, 21, 32, 10, 20, 36,
31, 17, 13, 12, 13, 18, 16, 11, 20, 21,
11, 10, 12, 11, 21, 23
};
void __cdecl gmenu_draw_pause()
{
if ( currlevel )
RedBack();
if ( !dword_634480 )
{
light_table_index = 0;
gmenu_print_text(316, 336, "Pause");
}
}
// 69BEF8: using guessed type int light_table_index;
void __fastcall gmenu_print_text(int x, int y, char *pszStr)
{
char *v3; // edi
int v4; // ebp
int v5; // esi
unsigned char i; // al
unsigned char v7; // bl
v3 = pszStr;
v4 = y;
v5 = x;
for ( i = *pszStr; *v3; i = *v3 )
{
++v3;
v7 = lfontframe[fontidx[i]];
if ( v7 )
CelDecodeLightOnly(v5, v4, (char *)BigTGold_cel, v7, 46);
v5 += lfontkern[v7] + 2;
}
}
void __cdecl FreeGMenu()
{
void *v0; // ecx
void *v1; // ecx
void *v2; // ecx
void *v3; // ecx
void *v4; // ecx
v0 = sgpLogo;
sgpLogo = 0;
mem_free_dbg(v0);
v1 = BigTGold_cel;
BigTGold_cel = 0;
mem_free_dbg(v1);
v2 = PentSpin_cel;
PentSpin_cel = 0;
mem_free_dbg(v2);
v3 = option_cel;
option_cel = 0;
mem_free_dbg(v3);
v4 = optbar_cel;
optbar_cel = 0;
mem_free_dbg(v4);
}
void __cdecl gmenu_init_menu()
{
byte_634478 = 1;
dword_634480 = 0;
sgpCurrItem = 0;
dword_63447C = 0;
dword_63448C = 0;
byte_634464 = 0;
sgpLogo = LoadFileInMem("Data\\Diabsmal.CEL", 0);
BigTGold_cel = LoadFileInMem("Data\\BigTGold.CEL", 0);
PentSpin_cel = LoadFileInMem("Data\\PentSpin.CEL", 0);
option_cel = LoadFileInMem("Data\\option.CEL", 0);
optbar_cel = LoadFileInMem("Data\\optbar.CEL", 0);
}
// 634464: using guessed type char byte_634464;
// 634478: using guessed type char byte_634478;
// 63448C: using guessed type int dword_63448C;
bool __cdecl gmenu_exception()
{
return dword_634480 != 0;
}
void __fastcall gmenu_call_proc(TMenuItem *pItem, void (__cdecl *gmFunc)())
{
TMenuItem *v2; // eax
int v3; // ecx
void (__cdecl **v4)(); // edx
PauseMode = 0;
byte_634464 = 0;
v2 = pItem;
dword_63447C = gmFunc;
dword_634480 = pItem;
if ( gmFunc )
{
gmFunc();
v2 = dword_634480;
}
v3 = 0;
dword_63448C = 0;
if ( v2 )
{
v4 = &v2->fnMenu;
while ( *v4 )
{
++v3;
v4 += 3;
dword_63448C = v3;
}
}
sgpCurrItem = &v2[v3 - 1];
gmenu_up_down(1);
}
// 525740: using guessed type int PauseMode;
// 634464: using guessed type char byte_634464;
// 63448C: using guessed type int dword_63448C;
void __fastcall gmenu_up_down(int a1)
{
TMenuItem *v1; // eax
int v2; // edi
v1 = sgpCurrItem;
if ( sgpCurrItem )
{
byte_634464 = 0;
v2 = dword_63448C;
while ( v2 )
{
--v2;
if ( a1 )
{
++v1;
sgpCurrItem = v1;
if ( v1->fnMenu )
goto LABEL_10;
v1 = dword_634480;
}
else
{
if ( v1 == dword_634480 )
v1 = &dword_634480[dword_63448C];
--v1;
}
sgpCurrItem = v1;
LABEL_10:
if ( (v1->dwFlags & 0x80000000) != 0 )
{
if ( v2 )
PlaySFX(IS_TITLEMOV);
return;
}
}
}
}
// 634464: using guessed type char byte_634464;
// 63448C: using guessed type int dword_63448C;
void __cdecl gmenu_draw()
{
int v0; // edi
TMenuItem *i; // esi
DWORD v2; // eax
if ( dword_634480 )
{
if ( dword_63447C )
dword_63447C();
CelDecodeOnly(236, 262, sgpLogo, 1, 296);
v0 = 320;
for ( i = dword_634480; i->fnMenu; v0 += 45 )
{
gmenu_draw_menu_item(i, v0);
++i;
}
v2 = GetTickCount();
if ( (signed int)(v2 - dword_634474) > 25 )
{
if ( ++byte_634478 == 9 )
byte_634478 = 1;
dword_634474 = v2;
}
}
}
// 634474: using guessed type int dword_634474;
// 634478: using guessed type char byte_634478;
void __fastcall gmenu_draw_menu_item(TMenuItem *pItem, int a2)
{
int v2; // edi
TMenuItem *v3; // ebx
unsigned int v4; // eax
unsigned int v5; // ebp
int v6; // esi
unsigned int v7; // ecx
unsigned int v8; // eax
int v9; // ecx
unsigned int v10; // ebp
int v11; // esi
int v12; // eax
int v13; // edi
unsigned int v14; // [esp+10h] [ebp-4h]
v2 = a2;
v3 = pItem;
v4 = gmenu_get_lfont(pItem);
v5 = v4;
v14 = v4;
if ( v3->dwFlags & 0x40000000 )
{
v6 = (v4 >> 1) + 80;
CelDecodeOnly(v6, v2 - 10, optbar_cel, 1, 287);
v7 = (v3->dwFlags >> 12) & 0xFFF;
if ( v7 < 2 )
v7 = 2;
v8 = ((v3->dwFlags & 0xFFF) << 8) / v7;
v9 = (v5 >> 1) + 82;
v10 = v8;
gmenu_clear_buffer(v9, v2 - 12, v8 + 13, 28);
CelDecodeOnly(v6 + v10 + 2, v2 - 12, option_cel, 1, 27);
v5 = v14;
}
v11 = 384 - (v5 >> 1);
v12 = -((v3->dwFlags & 0x80000000) != 0);
_LOBYTE(v12) = v12 & 0xF1;
light_table_index = v12 + 15;
gmenu_print_text(384 - (v5 >> 1), v2, v3->pszStr);
if ( v3 == sgpCurrItem )
{
v13 = v2 + 1;
CelDecodeOnly(v11 - 54, v13, PentSpin_cel, (unsigned char)byte_634478, 48);
CelDecodeOnly(v11 + v5 + 4, v13, PentSpin_cel, (unsigned char)byte_634478, 48);
}
}
// 634478: using guessed type char byte_634478;
// 69BEF8: using guessed type int light_table_index;
void __fastcall gmenu_clear_buffer(int x, int y, int width, int height)
{
int v4; // edi
char *i; // esi
v4 = height;
for ( i = (char *)gpBuffer + screen_y_times_768[y] + x; v4; --v4 )
{
memset(i, 205, width);
i -= 768;
}
}
int __fastcall gmenu_get_lfont(TMenuItem *pItem)
{
char *v2; // eax
int i; // edx
unsigned char v4; // cl
if ( pItem->dwFlags & 0x40000000 )
return 490;
v2 = pItem->pszStr;
for ( i = 0; ; i += lfontkern[lfontframe[fontidx[v4]]] + 2 )
{
v4 = *v2;
if ( !*v2 )
break;
++v2;
}
return i - 2;
}
int __fastcall gmenu_presskeys(int a1)
{
int v1; // ecx
int v2; // ecx
if ( !dword_634480 )
return 0;
switch ( a1 )
{
case VK_RETURN:
if ( (sgpCurrItem->dwFlags & 0x80000000) != 0 )
{
PlaySFX(IS_TITLEMOV);
((void (__fastcall *)(signed int))sgpCurrItem->fnMenu)(1);
}
return 1;
case VK_ESCAPE:
PlaySFX(IS_TITLEMOV);
gmenu_call_proc(0, 0);
return 1;
case VK_SPACE:
return 0;
case VK_LEFT:
v2 = 0;
goto LABEL_12;
case VK_UP:
v1 = 0;
goto LABEL_10;
case VK_RIGHT:
v2 = 1;
LABEL_12:
gmenu_left_right(v2);
return 1;
case VK_DOWN:
v1 = 1;
LABEL_10:
gmenu_up_down(v1);
break;
}
return 1;
}
void __fastcall gmenu_left_right(int a1)
{
signed int v1; // edx
unsigned int v2; // eax
int v3; // eax
v1 = sgpCurrItem->dwFlags;
if ( sgpCurrItem->dwFlags & 0x40000000 )
{
v2 = sgpCurrItem->dwFlags & 0xFFF;
if ( a1 )
{
if ( v2 == ((v1 >> 12) & 0xFFF) )
return;
v3 = v2 + 1;
}
else
{
if ( !(v1 & 0xFFF) )
return;
v3 = v2 - 1;
}
_LOWORD(v1) = v1 & 0xF000;
sgpCurrItem->dwFlags = v1;
sgpCurrItem->dwFlags |= v3;
((void (__fastcall *)(_DWORD))sgpCurrItem->fnMenu)(0);
}
}
int __fastcall gmenu_on_mouse_move(LPARAM lParam)
{
int v2; // edx
int a1; // [esp+0h] [ebp-4h]
a1 = lParam;
if ( !byte_634464 )
return 0;
gmenu_valid_mouse_pos(&a1);
v2 = a1 * ((sgpCurrItem->dwFlags >> 12) & 0xFFF) % 256;
a1 = a1 * ((sgpCurrItem->dwFlags >> 12) & 0xFFF) / 256;
_LOWORD(sgpCurrItem->dwFlags) &= 0xF000u;
sgpCurrItem->dwFlags |= a1;
((void (__fastcall *)(_DWORD, int))sgpCurrItem->fnMenu)(0, v2);
return 1;
}
// 41A37A: could not find valid save-restore pair for esi
// 634464: using guessed type char byte_634464;
bool __fastcall gmenu_valid_mouse_pos(int *plOffset)
{
*plOffset = 282;
if ( MouseX < 282 )
{
*plOffset = 0;
return 0;
}
if ( MouseX > 538 )
{
*plOffset = 256;
return 0;
}
*plOffset = MouseX - 282;
return 1;
}
int __fastcall gmenu_left_mouse(int a1)
{
int result; // eax
unsigned int v2; // eax
unsigned int v3; // eax
TMenuItem *v4; // esi
unsigned int v5; // eax
//LPARAM v6; // ecx
int a1a; // [esp+4h] [ebp-4h]
if ( a1 )
{
if ( !dword_634480 || MouseY >= 352 )
return 0;
if ( MouseY - 117 >= 0 )
{
v2 = (MouseY - 117) / 45;
if ( v2 < dword_63448C )
{
v3 = v2;
v4 = &dword_634480[v3];
if ( (v4->dwFlags & 0x80000000) != 0 )
{
v5 = (unsigned int)gmenu_get_lfont(&dword_634480[v3]) >> 1;
if ( MouseX >= 320 - v5 && MouseX <= v5 + 320 )
{
sgpCurrItem = v4;
PlaySFX(IS_TITLEMOV);
if ( v4->dwFlags & 0x40000000 )
{
byte_634464 = gmenu_valid_mouse_pos(&a1a);
gmenu_on_mouse_move(a1); /* v6 */
}
else
{
((void (__fastcall *)(signed int))sgpCurrItem->fnMenu)(1);
}
}
}
}
}
}
else
{
result = 0;
if ( !byte_634464 )
return result;
byte_634464 = 0;
}
return 1;
}
// 634464: using guessed type char byte_634464;
// 63448C: using guessed type int dword_63448C;
void __fastcall gmenu_enable(TMenuItem *pMenuItem, bool enable)
{
if ( enable )
pMenuItem->dwFlags |= 0x80000000;
else
pMenuItem->dwFlags &= 0x7F000000;
}
void __fastcall gmenu_slider_1(TMenuItem *pItem, int min, int max, int gamma)
{
unsigned int v4; // esi
int v5; // eax
v4 = pItem->dwFlags;
v5 = (pItem->dwFlags >> 12) & 0xFFF;
if ( v5 < 2 )
v5 = 2;
_LOWORD(v4) = v4 & 0xF000;
pItem->dwFlags = v4 | (v5 * (gamma - min) + (max - min - 1) / 2) / (max - min);
}
int __fastcall gmenu_slider_get(TMenuItem *pItem, int min, int max)
{
int v3; // eax
unsigned int v4; // ecx
v3 = (pItem->dwFlags >> 12) & 0xFFF;
v4 = pItem->dwFlags & 0xFFF;
if ( v3 < 2 )
v3 = 2;
return min + (v4 * (max - min) + (v3 - 1) / 2) / v3;
}
void __fastcall gmenu_slider_3(TMenuItem *pItem, int dwTicks)
{
pItem->dwFlags ^= (pItem->dwFlags ^ (dwTicks << 12)) & 0xFFF000;
}

44
Source/gmenu.h

@ -0,0 +1,44 @@
//HEADER_GOES_HERE
#ifndef __GMENU_H__
#define __GMENU_H__
extern void *optbar_cel;
extern bool byte_634464; // weak
extern void *PentSpin_cel;
extern TMenuItem *sgpCurrItem;
extern void *BigTGold_cel;
extern int dword_634474; // weak
extern char byte_634478; // weak
extern void (__cdecl *dword_63447C)();
extern TMenuItem *dword_634480; // idb
extern void *option_cel;
extern void *sgpLogo;
extern int dword_63448C; // weak
void __cdecl gmenu_draw_pause();
void __fastcall gmenu_print_text(int x, int y, char *pszStr);
void __cdecl FreeGMenu();
void __cdecl gmenu_init_menu();
bool __cdecl gmenu_exception();
void __fastcall gmenu_call_proc(TMenuItem *pItem, void (__cdecl *gmFunc)());
void __fastcall gmenu_up_down(int a1);
void __cdecl gmenu_draw();
void __fastcall gmenu_draw_menu_item(TMenuItem *pItem, int a2);
void __fastcall gmenu_clear_buffer(int x, int y, int width, int height);
int __fastcall gmenu_get_lfont(TMenuItem *pItem);
int __fastcall gmenu_presskeys(int a1);
void __fastcall gmenu_left_right(int a1);
int __fastcall gmenu_on_mouse_move(LPARAM lParam);
bool __fastcall gmenu_valid_mouse_pos(int *plOffset);
int __fastcall gmenu_left_mouse(int a1);
void __fastcall gmenu_enable(TMenuItem *pMenuItem, bool enable);
void __fastcall gmenu_slider_1(TMenuItem *pItem, int min, int max, int gamma);
int __fastcall gmenu_slider_get(TMenuItem *pItem, int min, int max);
void __fastcall gmenu_slider_3(TMenuItem *pItem, int dwTicks);
/* rdata */
extern const unsigned char lfontframe[127];
extern const unsigned char lfontkern[56];
#endif /* __GMENU_H__ */

272
Source/help.cpp

@ -0,0 +1,272 @@
//HEADER_GOES_HERE
#include "../types.h"
#ifndef NO_GLOBALS
int help_select_line; // weak
int dword_634494; // weak
int helpflag;
int displayinghelp[22]; /* check, does nothing? */
int HelpTop; // weak
#endif
const char gszHelpText[] =
{
"$Keyboard Shortcuts:|"
"F1: Open Help Screen|"
"Esc: Display Main Menu|"
"Tab: Display Auto-map|"
"Space: Hide all info screens|"
"S: Open Speedbook|"
"B: Open Spellbook|"
"I: Open Inventory screen|"
"C: Open Character screen|"
"Q: Open Quest log|"
"F: Reduce screen brightness|"
"G: Increase screen brightness|"
"Z: Zoom Game Screen|"
"+ / -: Zoom Automap|"
"1 - 8: Use Belt item|"
"F5, F6, F7, F8: Set hot key for skill or spell|"
"Shift + Left Click: Attack without moving|"
"|"
"$Movement:|"
"If you hold the mouse button down while moving, the character "
"will continue to move in that direction.|"
"|"
"$Combat:|"
"Holding down the shift key and then left-clicking allows the "
"character to attack without moving.|"
"|"
"$Auto-map:|"
"To access the auto-map, click the 'MAP' button on the "
"Information Bar or press 'TAB' on the keyboard. Zooming in and "
"out of the map is done with the + and - keys. Scrolling the map "
"uses the arrow keys.|"
"|"
"$Picking up Objects:|"
"Useable items that are small in size, such as potions or scrolls, "
"are automatically placed in your 'belt' located at the top of "
"the Interface bar . When an item is placed in the belt, a small "
"number appears in that box. Items may be used by either pressing "
"the corresponding number or right-clicking on the item.|"
"|"
"$Gold|"
"You can select a specific amount of gold to drop by right "
"clicking on a pile of gold in your inventory.|"
"|"
"$Skills & Spells:|"
"You can access your list of skills and spells by left-clicking on "
"the 'SPELLS' button in the interface bar. Memorized spells and "
"those available through staffs are listed here. Left-clicking on "
"the spell you wish to cast will ready the spell. A readied spell "
"may be cast by simply right-clicking in the play area.|"
"|"
"$Using the Speedbook for Spells|"
"Left-clicking on the 'readied spell' button will open the 'Speedbook' "
"which allows you to select a skill or spell for immediate use. "
"To use a readied skill or spell, simply right-click in the main play "
"area.|"
"|"
"$Setting Spell Hotkeys|"
"You can assign up to four Hot Keys for skills, spells or scrolls. "
"Start by opening the 'speedbook' as described in the section above. "
"Press the F5, F6, F7 or F8 keys after highlighting the spell you "
"wish to assign.|"
"|"
"$Spell Books|"
"Reading more than one book increases your knowledge of that "
"spell, allowing you to cast the spell more effectively.|"
"&"
};
void __cdecl InitHelp()
{
helpflag = 0;
dword_634494 = 0;
displayinghelp[0] = 0;
}
// 634494: using guessed type int dword_634494;
void __cdecl DrawHelp()
{
int v0; // edi
const char *v1; // esi
int v2; // edx
signed int v3; // ecx
char v4; // al
unsigned char v5; // al
_BYTE *i; // eax
int v7; // eax
signed int v8; // edx
char v9; // cl
unsigned char v10; // cl
text_color color; // [esp+Ch] [ebp-8h]
int help_line_nr; // [esp+10h] [ebp-4h]
signed int help_line_nra; // [esp+10h] [ebp-4h]
DrawSTextHelp();
DrawQTextBack();
PrintSString(0, 2, 1u, "Diablo Help", COL_GOLD, 0);
DrawSLine(5);
v0 = help_select_line;
v1 = gszHelpText;
if ( help_select_line > 0 )
{
help_line_nr = help_select_line;
do
{
v2 = 0;
v3 = 0;
while ( !*v1 )
++v1;
if ( *v1 == '$' )
++v1;
v4 = *v1;
if ( *v1 != '&' )
{
if ( v4 == ('|') )
goto LABEL_47;
while ( v3 < 577 )
{
if ( !v4 )
{
do
++v1;
while ( !*v1 );
}
v5 = *v1;
tempstr[v2++] = *v1++;
v3 += fontkern[fontframe[fontidx[v5]]] + 1;
v4 = *v1;
if ( *v1 == ('|') )
{
if ( v3 < 577 )
goto LABEL_18;
break;
}
}
for ( i = (unsigned char *)&tempstr[v2]-1; *i != ' '; --i )
--v1;
LABEL_18:
if ( *v1 == ('|') )
LABEL_47:
++v1;
}
--help_line_nr;
}
while ( help_line_nr );
}
help_line_nra = 7;
do
{
v7 = 0;
v8 = 0;
while ( !*v1 )
++v1;
if ( *v1 == '$' )
{
++v1;
_LOBYTE(color) = COL_RED;
}
else
{
_LOBYTE(color) = COL_WHITE;
}
v9 = *v1;
if ( *v1 == '&' )
{
HelpTop = v0;
}
else
{
if ( v9 == ('|') )
goto LABEL_48;
while ( v8 < 577 )
{
if ( !v9 )
{
do
++v1;
while ( !*v1 );
}
v10 = *v1;
tempstr[v7++] = *v1++;
v8 += fontkern[fontframe[fontidx[v10]]] + 1;
v9 = *v1;
if ( *v1 == ('|') )
{
if ( v8 < 577 )
goto LABEL_39;
break;
}
}
while ( tempstr[--v7] != ' ' )
--v1;
LABEL_39:
if ( v7 )
{
tempstr[v7] = 0;
DrawHelpLine(0, help_line_nra, tempstr, color);
v0 = help_select_line;
}
if ( *v1 == ('|') )
LABEL_48:
++v1;
}
++help_line_nra;
}
while ( help_line_nra < 22 );
PrintSString(0, 23, 1u, "Press ESC to end or the arrow keys to scroll.", COL_GOLD, 0);
}
// 634490: using guessed type int help_select_line;
// 634960: using guessed type int HelpTop;
void __fastcall DrawHelpLine(int always_0, int help_line_nr, char *text, text_color color)
{
signed int v4; // ebx
int v5; // edi
unsigned char i; // al
unsigned char v7; // al
int v8; // esi
v4 = 0;
v5 = screen_y_times_768[SStringY[help_line_nr] + 204] + always_0 + 96;
for ( i = *text; *text; i = *text )
{
++text;
v7 = fontframe[fontidx[i]];
v8 = v7;
v4 += fontkern[v7] + 1;
if ( v7 )
{
if ( v4 <= 577 )
CPrintString(v5, v7, color);
}
v5 += fontkern[v8] + 1;
}
}
void __cdecl DisplayHelp()
{
help_select_line = 0;
helpflag = 1;
HelpTop = 5000;
}
// 634490: using guessed type int help_select_line;
// 634960: using guessed type int HelpTop;
void __cdecl HelpScrollUp()
{
if ( help_select_line > 0 )
--help_select_line;
}
// 634490: using guessed type int help_select_line;
void __cdecl HelpScrollDown()
{
if ( help_select_line < HelpTop )
++help_select_line;
}
// 634490: using guessed type int help_select_line;
// 634960: using guessed type int HelpTop;

21
Source/help.h

@ -0,0 +1,21 @@
//HEADER_GOES_HERE
#ifndef __HELP_H__
#define __HELP_H__
extern int help_select_line; // weak
extern int dword_634494; // weak
extern int helpflag;
extern int displayinghelp[22];
extern int HelpTop; // weak
void __cdecl InitHelp();
void __cdecl DrawHelp();
void __fastcall DrawHelpLine(int always_0, int help_line_nr, char *text, text_color color);
void __cdecl DisplayHelp();
void __cdecl HelpScrollUp();
void __cdecl HelpScrollDown();
/* rdata */
extern const char gszHelpText[];
#endif /* __HELP_H__ */

530
Source/init.cpp

@ -0,0 +1,530 @@
//HEADER_GOES_HERE
#include "../types.h"
_SNETVERSIONDATA fileinfo;
int init_cpp_init_value; // weak
int gbActive; // weak
char diablo_exe_path[260];
void *unused_mpq;
char patch_rt_mpq_path[260];
WNDPROC CurrentProc;
void *diabdat_mpq;
char diabdat_mpq_path[260];
void *patch_rt_mpq;
int killed_mom_parent; // weak
bool screensaver_enabled_prev;
const int init_inf = 0x7F800000; // weak
/* data */
char gszVersionNumber[260] = "internal version unknown";
char gszProductName[260] = "Diablo v1.09";
struct init_cpp_init
{
init_cpp_init()
{
init_cpp_init_value = init_inf;
}
} _init_cpp_init;
// 47AE20: using guessed type int init_inf;
// 63497C: using guessed type int init_cpp_init_value;
void __fastcall init_cleanup(bool show_cursor)
{
int v1; // edi
v1 = show_cursor;
pfile_flush_W();
init_disable_screensaver(0);
init_run_office_from_start_menu();
if ( diabdat_mpq )
{
SFileCloseArchive(diabdat_mpq);
diabdat_mpq = 0;
}
if ( patch_rt_mpq )
{
SFileCloseArchive(patch_rt_mpq);
patch_rt_mpq = 0;
}
if ( unused_mpq )
{
SFileCloseArchive(unused_mpq);
unused_mpq = 0;
}
UiDestroy();
effects_cleanup_sfx();
sound_cleanup();
NetClose();
dx_cleanup();
MI_Dummy(v1);
StormDestroy();
if ( v1 )
ShowCursor(1);
}
void __cdecl init_run_office_from_start_menu()
{
HWND v0; // eax
char pszPath[256]; // [esp+0h] [ebp-104h]
LPITEMIDLIST ppidl; // [esp+100h] [ebp-4h]
if ( killed_mom_parent )
{
*pszPath = empty_string;
killed_mom_parent = 0;
memset(pszPath + 1, 0, sizeof(pszPath) - 1);
// *(_WORD *)&pszPath[253] = 0;
//pszPath[255] = 0;
ppidl = 0;
v0 = GetDesktopWindow();
if ( !SHGetSpecialFolderLocation(v0, CSIDL_STARTMENU, &ppidl) )
{
SHGetPathFromIDList(ppidl, pszPath);
init_run_office(pszPath);
}
}
}
// 634CA0: using guessed type int killed_mom_parent;
void __fastcall init_run_office(char *dir)
{
char *v1; // esi
HANDLE v2; // ebx
bool v3; // zf
HWND v4; // eax
char Directory[260]; // [esp+8h] [ebp-348h]
char FileName[260]; // [esp+10Ch] [ebp-244h]
struct _WIN32_FIND_DATAA FindFileData; // [esp+210h] [ebp-140h]
v1 = dir;
strcpy(FileName, dir);
if ( FileName[0] && Directory[strlen(FileName) + 259] == '\\' )
strcat(FileName, "*");
else
strcat(FileName, "\\*");
v2 = FindFirstFile(FileName, &FindFileData);
if ( v2 != (HANDLE)-1 )
{
do
{
if ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if ( strcmp(FindFileData.cFileName, ".") && strcmp(FindFileData.cFileName, "..") )
{
*Directory = empty_string;
memset(Directory + 1, 0, sizeof(Directory) - 1);
v3 = *v1 == 0;
// *(_WORD *)&Directory[257] = 0;
//Directory[259] = 0;
if ( v3 || v1[strlen(v1) - 1] != '\\' )
sprintf(Directory, "%s\\%s\\", v1, FindFileData.cFileName);
else
sprintf(Directory, "%s%s\\", v1, FindFileData.cFileName);
init_run_office(Directory);
}
}
else if ( !_strcmpi(FindFileData.cFileName, "Microsoft Office Shortcut Bar.lnk") )
{
v4 = GetDesktopWindow();
ShellExecute(v4, "open", FindFileData.cFileName, &empty_string, v1, SW_SHOWNORMAL);
}
}
while ( FindNextFile(v2, &FindFileData) );
FindClose(v2);
}
}
void __fastcall init_disable_screensaver(bool disable)
{
bool v1; // al
char Data[16]; // [esp+4h] [ebp-20h]
DWORD Type; // [esp+14h] [ebp-10h]
DWORD cbData; // [esp+18h] [ebp-Ch]
HKEY phkResult; // [esp+1Ch] [ebp-8h]
bool v6; // [esp+20h] [ebp-4h]
// BUGFIX: this is probably the worst possible way to do this. Alternatives: ExtEscape() with SETPOWERMANAGEMENT,
// SystemParametersInfo() with SPI_SETSCREENSAVEACTIVE/SPI_SETPOWEROFFACTIVE/SPI_SETLOWPOWERACTIVE
v6 = disable;
if ( !RegOpenKeyEx(HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_READ|KEY_WRITE, &phkResult) )
{
if ( v6 )
{
cbData = 16;
if ( !RegQueryValueEx(phkResult, "ScreenSaveActive", 0, &Type, (LPBYTE)Data, &cbData) )
screensaver_enabled_prev = Data[0] != '0';
v1 = 0;
}
else
{
v1 = screensaver_enabled_prev;
}
Data[1] = 0;
Data[0] = (v1 != 0) + '0';
RegSetValueEx(phkResult, "ScreenSaveActive", 0, REG_SZ, (const BYTE *)Data, 2u);
RegCloseKey(phkResult);
}
}
void __fastcall init_create_window(int nCmdShow)
{
int nHeight; // eax
HWND hWnd; // esi
WNDCLASSEXA wcex; // [esp+8h] [ebp-34h]
int nWidth; // [esp+38h] [ebp-4h]
init_kill_mom_parent();
pfile_init_save_directory();
memset(&wcex, 0, sizeof(wcex));
wcex.cbSize = sizeof(wcex);
wcex.style = CS_HREDRAW|CS_VREDRAW;
wcex.lpfnWndProc = WindowProc;
wcex.hInstance = ghInst;
wcex.hIcon = LoadIcon(ghInst, MAKEINTRESOURCE(IDI_ICON1));
wcex.hCursor = LoadCursor(0, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = "DIABLO";
wcex.lpszClassName = "DIABLO";
wcex.hIconSm = (HICON)LoadImage(ghInst, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
if ( !RegisterClassEx(&wcex) )
TermMsg("Unable to register window class");
if ( GetSystemMetrics(SM_CXSCREEN) >= 640 )
nWidth = GetSystemMetrics(SM_CXSCREEN);
else
nWidth = 640;
if ( GetSystemMetrics(SM_CYSCREEN) >= 480 )
nHeight = GetSystemMetrics(SM_CYSCREEN);
else
nHeight = 480;
hWnd = CreateWindowEx(0, "DIABLO", "DIABLO", WS_POPUP, 0, 0, nWidth, nHeight, NULL, NULL, ghInst, NULL);
if ( !hWnd )
TermMsg("Unable to create main window");
ShowWindow(hWnd, SW_SHOWNORMAL); // nCmdShow used only in beta: ShowWindow(hWnd, nCmdShow)
UpdateWindow(hWnd);
init_await_mom_parent_exit();
dx_init(hWnd);
BlackPalette();
snd_init(hWnd);
init_archives();
init_disable_screensaver(1);
}
void __cdecl init_kill_mom_parent()
{
HWND v0; // eax
v0 = init_find_mom_parent();
if ( v0 )
{
PostMessage(v0, WM_CLOSE, 0, 0);
killed_mom_parent = 1;
}
}
// 634CA0: using guessed type int killed_mom_parent;
HWND __cdecl init_find_mom_parent()
{
HWND i; // eax
HWND v1; // esi
char ClassName[256]; // [esp+4h] [ebp-100h]
for ( i = GetForegroundWindow(); ; i = GetWindow(v1, GW_HWNDNEXT) )
{
v1 = i;
if ( !i )
break;
GetClassName(i, ClassName, 255);
if ( !_strcmpi(ClassName, "MOM Parent") )
break;
}
return v1;
}
void __cdecl init_await_mom_parent_exit()
{
DWORD v0; // edi
v0 = GetTickCount();
do
{
if ( !init_find_mom_parent() )
break;
Sleep(250);
}
while ( GetTickCount() - v0 <= 4000 );
}
void __cdecl init_archives()
{
void *a1; // [esp+8h] [ebp-8h]
#ifdef COPYPROT
int v1; // [esp+Ch] [ebp-4h]
#endif
fileinfo.size = 20;
fileinfo.versionstring = gszVersionNumber;
fileinfo.executablefile = diablo_exe_path;
fileinfo.originalarchivefile = diabdat_mpq_path;
fileinfo.patcharchivefile = patch_rt_mpq_path;
init_get_file_info();
#ifdef COPYPROT
while ( 1 )
{
#endif
diabdat_mpq = init_test_access(diabdat_mpq_path, "\\diabdat.mpq", "DiabloCD", 1000, 1);
#ifdef COPYPROT
if ( diabdat_mpq )
break;
UiCopyProtError((int)&v1);
if ( v1 == COPYPROT_CANCEL )
FileErrDlg("diabdat.mpq");
}
#endif
if ( !WOpenFile("ui_art\\title.pcx", &a1, 1) )
FileErrDlg("Main program archive: diabdat.mpq");
WCloseFile(a1);
patch_rt_mpq = init_test_access(patch_rt_mpq_path, "\\patch_rt.mpq", "DiabloInstall", 2000, 0);
}
void *__fastcall init_test_access(char *mpq_path, char *mpq_name, char *reg_loc, int flags, bool on_cd)
{
char *v5; // esi
char *v7; // eax
char Filename[260]; // [esp+Ch] [ebp-314h]
char Buffer[260]; // [esp+110h] [ebp-210h]
char v15[260]; // [esp+214h] [ebp-10Ch]
char *mpq_namea; // [esp+318h] [ebp-8h]
void *archive; // [esp+31Ch] [ebp-4h]
mpq_namea = mpq_name;
v5 = mpq_path;
if ( !GetCurrentDirectory(0x104u, Buffer) )
TermMsg("Can't get program path");
init_strip_trailing_slash(Buffer);
if ( !SFileSetBasePath(Buffer) )
TermMsg("SFileSetBasePath");
if ( !GetModuleFileName(ghInst, Filename, 0x104u) )
TermMsg("Can't get program name");
v7 = strrchr(Filename, '\\');
if ( v7 )
*v7 = 0;
init_strip_trailing_slash(Filename);
strcpy(v5, Buffer);
strcat(v5, mpq_namea);
#ifdef COPYPROT
if ( SFileOpenArchive(v5, flags, on_cd, &archive) )
#else
if ( SFileOpenArchive(v5, flags, 0, &archive) )
#endif
return archive;
if ( strcmp(Filename, Buffer) )
{
strcpy(v5, Filename);
strcat(v5, mpq_namea);
#ifdef COPYPROT
if ( SFileOpenArchive(v5, flags, on_cd, &archive) )
#else
if ( SFileOpenArchive(v5, flags, 0, &archive) )
#endif
return archive;
}
v15[0] = 0;
if ( reg_loc )
{
if ( SRegLoadString("Archives", (const char *)reg_loc, 0, v15, 260) )
{
init_strip_trailing_slash(v15);
strcpy(v5, v15);
strcat(v5, mpq_namea);
#ifdef COPYPROT
if ( SFileOpenArchive(v5, flags, on_cd, &archive) )
#else
if ( SFileOpenArchive(v5, flags, 0, &archive) )
#endif
return archive;
}
}
if ( on_cd && init_read_test_file(v15, mpq_namea, flags, &archive) )
{
strcpy(v5, v15);
return archive;
}
return 0;
}
char *__fastcall init_strip_trailing_slash(char *path)
{
char *result; // eax
result = strrchr(path, '\\');
if ( result )
{
if ( !result[1] )
*result = 0;
}
return result;
}
int __fastcall init_read_test_file(char *mpq_path, char *mpq_name, int flags, void **archive)
{
char *v4; // edi
DWORD v5; // eax
const char *v7; // ebx
const char *v8; // esi
char Buffer[260]; // [esp+Ch] [ebp-108h]
char *mpq_patha; // [esp+110h] [ebp-4h]
v4 = mpq_name;
mpq_patha = mpq_path;
v5 = GetLogicalDriveStrings(0x104u, Buffer);
if ( !v5 || v5 > 0x104 )
return 0;
while ( *v4 == '\\' )
++v4;
v7 = Buffer;
if ( !Buffer[0] )
return 0;
while ( 1 )
{
v8 = v7;
v7 += strlen(v7) + 1;
if ( GetDriveType(v8) == DRIVE_CDROM )
{
strcpy(mpq_patha, v8);
strcat(mpq_patha, v4);
if ( SFileOpenArchive(mpq_patha, flags, 1, archive) )
break;
}
if ( !*v7 )
return 0;
}
return 1;
}
void __cdecl init_get_file_info()
{
int v0; // eax
DWORD v1; // edi
void *v2; // ebx
unsigned int uBytes; // [esp+8h] [ebp-Ch]
DWORD dwHandle; // [esp+Ch] [ebp-8h]
VS_FIXEDFILEINFO *lpBuffer; // [esp+10h] [ebp-4h]
if ( GetModuleFileName(ghInst, diablo_exe_path, 0x104u) )
{
v0 = GetFileVersionInfoSize(diablo_exe_path, &dwHandle);
v1 = v0;
if ( v0 )
{
v2 = DiabloAllocPtr(v0);
if ( GetFileVersionInfo(diablo_exe_path, 0, v1, v2) )
{
if ( VerQueryValue(v2, "\\", (LPVOID *)&lpBuffer, &uBytes) )
sprintf(
gszVersionNumber,
"version %d.%d.%d.%d",
lpBuffer->dwProductVersionMS >> 16,
lpBuffer->dwProductVersionMS & 0xFFFF,
lpBuffer->dwProductVersionLS >> 16,
lpBuffer->dwProductVersionLS & 0xFFFF);
}
mem_free_dbg(v2);
}
}
}
LRESULT __stdcall MainWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if ( Msg > WM_ERASEBKGND )
{
if ( Msg == WM_ACTIVATEAPP )
{
init_activate_window(hWnd, wParam);
}
else
{
if ( Msg == WM_QUERYNEWPALETTE )
{
SDrawRealizePalette();
return 1;
}
if ( Msg == WM_PALETTECHANGED && (HWND)wParam != hWnd )
SDrawRealizePalette();
}
}
else
{
switch ( Msg )
{
case WM_ERASEBKGND:
return 0;
case WM_CREATE:
ghMainWnd = hWnd;
break;
case WM_DESTROY:
init_cleanup(1);
ghMainWnd = 0;
PostQuitMessage(0);
break;
case WM_PAINT:
drawpanflag = 255;
break;
case WM_CLOSE:
return 0;
}
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
// 52571C: using guessed type int drawpanflag;
void __fastcall init_activate_window(HWND hWnd, bool bActive)
{
LONG dwNewLong; // eax
gbActive = bActive;
UiAppActivate(bActive);
dwNewLong = GetWindowLong(hWnd, GWL_STYLE);
if ( gbActive && fullscreen )
dwNewLong &= ~WS_SYSMENU;
else
dwNewLong |= WS_SYSMENU;
SetWindowLong(hWnd, GWL_STYLE, dwNewLong);
if ( gbActive )
{
drawpanflag = 255;
ResetPal();
}
}
// 484364: using guessed type int fullscreen;
// 52571C: using guessed type int drawpanflag;
// 634980: using guessed type int gbActive;
LRESULT __stdcall WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
LRESULT result; // eax
if ( CurrentProc )
result = CurrentProc(hWnd, Msg, wParam, lParam);
else
result = MainWndProc(hWnd, Msg, wParam, lParam);
return result;
}
WNDPROC __stdcall SetWindowProc(WNDPROC NewProc)
{
WNDPROC OldProc; // eax
OldProc = CurrentProc;
CurrentProc = NewProc;
return OldProc;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save