├── .dockerignore ├── .github └── workflows │ ├── ccpp.yml │ └── release.yml ├── .gitignore ├── .gitlab-ci.yml ├── CHANGELOG.txt ├── CMakeLists.txt ├── Dockerfile ├── LICENSE ├── README.md ├── _NscLib ├── .gitignore ├── CMakeLists.txt ├── Nsc.h ├── NscCodeGenerator.cpp ├── NscCodeGenerator.h ├── NscCompat.h ├── NscCompiler.cpp ├── NscContext.cpp ├── NscContext.h ├── NscDecompiler.cpp ├── NscIntrinsicDefs.h ├── NscPCodeEnumerator.cpp ├── NscPCodeEnumerator.h ├── NscPStackEntry.cpp ├── NscPStackEntry.h ├── NscParser.ypp ├── NscParserRoutines.cpp ├── NscSymbolTable.h ├── NwnDefines.cpp ├── NwnDefines.h ├── NwnDoubleLinkList.h ├── NwnLoader.cpp ├── NwnLoader.h ├── NwnStreams.h └── Precomp.h ├── _NwnBaseLib ├── BaseConstants.h ├── BaseTypes.cpp ├── BaseTypes.h ├── CMakeLists.txt ├── ModelSystem.h └── NWNBaseLib.h ├── _NwnDataLib ├── BifFileReader.cpp ├── BifFileReader.h ├── CMakeLists.txt ├── FileWrapper.h ├── KeyFileReader.cpp ├── KeyFileReader.h ├── NWNDataLib.h ├── NWScriptReader.cpp ├── NWScriptReader.h ├── Precomp.h ├── ResourceAccessor.h ├── ResourceManager.cpp ├── ResourceManager.h └── TextOut.h ├── _NwnUtilLib ├── .gitignore ├── BufferParser.cpp ├── BufferParser.h ├── CMakeLists.txt ├── JSON.cpp ├── JSON.h ├── JSONValue.cpp ├── JSONValue.h ├── NWNUtilLib.h ├── OsCompat.cpp ├── OsCompat.h ├── Precomp.h ├── ProjGlobalDefs.h ├── Ref.h ├── VersionConstants.h ├── easylogging++.cc ├── easylogging++.h ├── findfirst.cpp ├── findfirst.h ├── optionparser.h ├── spec.cpp ├── spec.h └── version.h ├── cmake └── modules │ ├── GetGitRevisionDescription.cmake │ ├── GetGitRevisionDescription.cmake.in │ └── version.cpp.in ├── extras └── Makefile ├── hooks └── post_push ├── nwnsc ├── .gitignore ├── CMakeLists.txt └── nwnsc.cpp └── scripts ├── buildnwnsc.sh └── run-linux-build.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .git 3 | CHANGELOG.txt 4 | *.md 5 | LICENSE 6 | logs 7 | .dockerignore 8 | Dockerfile -------------------------------------------------------------------------------- /.github/workflows/ccpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Build 12 | uses: docker://nwneetools/nwnsc-docker-builder:071c269 13 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Nwnsc Binaries 2 | 3 | on: 4 | pull_request: 5 | push: 6 | release: 7 | types: published 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | os: [ubuntu-latest, macos-latest, windows-latest] 14 | include: 15 | - os: ubuntu-latest 16 | zip_name: nwnsc-linux 17 | - os: macos-latest 18 | zip_name: nwnsc-mac 19 | - os: windows-latest 20 | zip_name: nwnsc-win 21 | runs-on: ${{ matrix.os }} 22 | 23 | steps: 24 | - uses: actions/checkout@v2 25 | - name: Set up repository and variables 26 | run: | 27 | git fetch --prune --unshallow --tags -f 28 | echo "NWNSC_VERSION=`git describe --tags --dirty=-dirty --always`" >> $GITHUB_ENV 29 | shell: bash 30 | 31 | # Install OS specific dependencies 32 | - name: Install Linux dependencies 33 | if: matrix.os == 'ubuntu-latest' 34 | run: sudo apt-get install bison 35 | - name: Install macos dependencies 36 | if: matrix.os == 'macos-latest' 37 | run: brew install bison cmake p7zip 38 | - name: Install Windows dependencies 39 | if: matrix.os == 'windows-latest' 40 | run: choco install winflexbison 41 | 42 | - name: Build nwnsc 43 | env: 44 | CFLAGS/CXXFLAGS: -g -O2 -fvisibility=hidden 45 | shell: bash 46 | run: | 47 | cmake . 48 | cmake --build . --config Release 49 | 50 | - name: Create nwnsc archive 51 | shell: bash 52 | env: 53 | ZIP_NAME: ${{ matrix.zip_name }} 54 | run: | 55 | mkdir artifact 56 | 7z a artifact/${ZIP_NAME}-${NWNSC_VERSION}.zip $(find ./nwnsc -name nwnsc -type f -or -name nwnsc.exe -type f) 57 | 58 | # Upload nwnsc binary archive as an artifact 59 | - name: Upload artifact 60 | uses: actions/upload-artifact@v1 61 | with: 62 | name: nwnsc-binary-archives 63 | path: artifact 64 | 65 | - name: Upload release asset 66 | if: github.event.action == 'published' 67 | uses: actions/upload-release-asset@v1.0.1 68 | env: 69 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 70 | with: 71 | upload_url: ${{ github.event.release.upload_url }} 72 | asset_path: ./artifact/${{ matrix.zip_name }}-${{ env.NWNSC_VERSION }}.zip 73 | asset_name: ${{ matrix.zip_name }}-${{ env.NWNSC_VERSION }}.zip 74 | asset_content_type: application/zip 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CLion 2 | .idea 3 | 4 | # Visual Studio Files 5 | .vs 6 | 7 | # Visual Studio Code 8 | .vscode 9 | 10 | # CMake - Make 11 | Makefile 12 | CMakeCache.txt 13 | CMakeFiles 14 | cmake_install.cmake 15 | build 16 | 17 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 18 | [Bb]in/ 19 | [Oo]bj/ 20 | 21 | # Generated Version file 22 | # version.cpp 23 | 24 | # mstest test results 25 | TestResults 26 | 27 | ## Ignore Visual Studio temporary files, build results, and 28 | ## files generated by popular Visual Studio add-ons. 29 | 30 | # User-specific files 31 | *.suo 32 | *.user 33 | *.sln.docstates 34 | 35 | # Build results 36 | [Dd]ebug/ 37 | [Rr]elease/ 38 | x64/ 39 | *_i.c 40 | *_p.c 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.log 55 | *.vspscc 56 | *.vssscc 57 | .builds 58 | *.a 59 | 60 | # Visual C++ cache files 61 | ipch/ 62 | *.aps 63 | *.ncb 64 | *.opensdf 65 | *.sdf 66 | 67 | # Visual Studio profiler 68 | *.psess 69 | *.vsp 70 | *.vspx 71 | 72 | # Guidance Automation Toolkit 73 | *.gpState 74 | 75 | # ReSharper is a .NET coding add-in 76 | _ReSharper* 77 | 78 | # NCrunch 79 | *.ncrunch* 80 | .*crunch*.local.xml 81 | 82 | # Installshield output folder 83 | [Ee]xpress 84 | 85 | # DocProject is a documentation generator add-in 86 | DocProject/buildhelp/ 87 | DocProject/Help/*.HxT 88 | DocProject/Help/*.HxC 89 | DocProject/Help/*.hhc 90 | DocProject/Help/*.hhk 91 | DocProject/Help/*.hhp 92 | DocProject/Help/Html2 93 | DocProject/Help/html 94 | 95 | # Click-Once directory 96 | publish 97 | 98 | # Publish Web Output 99 | *.Publish.xml 100 | 101 | # NuGet Packages Directory 102 | packages 103 | 104 | # Windows Azure Build Output 105 | csx 106 | *.build.csdef 107 | 108 | # Windows Store app package directory 109 | AppPackages/ 110 | 111 | # Others 112 | [Bb]in 113 | [Oo]bj 114 | sql 115 | TestResults 116 | [Tt]est[Rr]esult* 117 | *.Cache 118 | ClientBin 119 | [Ss]tyle[Cc]op.* 120 | ~$* 121 | *.dbmdl 122 | Generated_Code #added for RIA/Silverlight projects 123 | *.cbp 124 | 125 | # Backup & report files from converting an old project file to a newer 126 | # Visual Studio version. Backup files are not needed, because we have git ;-) 127 | _UpgradeReport_Files/ 128 | Backup*/ 129 | UpgradeLog*.XML 130 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build 3 | build: 4 | stage: build 5 | image: glorwinger/holy-build-box-32:2.0.0 6 | script: 7 | - /hbb_exe/activate-exec 8 | - export CC=/opt/rh/devtoolset-7/root/usr/bin/gcc 9 | - export CPP=/opt/rh/devtoolset-7/root/usr/bin/cpp 10 | - export CXX=/opt/rh/devtoolset-7/root/usr/bin/c++ 11 | - cmake . 12 | - make all 13 | artifacts: 14 | paths: 15 | - nwnsc/nwnsc 16 | 17 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | Changes 2 | ------- 3 | 4 | Version 20110507-01 5 | ------------------- 6 | 7 | - Fixed TimerRegistration::Stop returning the wrong amount of time left on the 8 | timer. 9 | 10 | - Fixed incorrect timer logic in the TimerManager relating to due time caching. 11 | 12 | - swutil::SharedPtr and swutil::SharedBuffer now evaluate the deleter 13 | for their input pointer in the constructor, should the shared state not be 14 | created successfully. Previously, the deleter was not evaluated in this case 15 | and the caller was responsible for deleting the input pointer. The new 16 | behavior is more consistent with boost and C++0x shared_ptr. 17 | 18 | - Imported Edward T. Smith's NWScript compiler with various improvements. 19 | 20 | - Added DLL version of NWScript compiler, and NWN2 toolset plugin wrapper to 21 | allow the toolset to use the script compiler. 22 | 23 | - Added new compiler shell (NWNScriptCompiler) to replace nwnnsscomp. 24 | 25 | - Added on demand compilation from source text to NWNScriptConsole. 26 | 27 | - Added option to load base resources only to ResourceManager. 28 | 29 | - Added UnloadAllResources API to ResourceManager. 30 | 31 | - Fixed incorrect behavior of ResourceManager::OpenFileByIndex. 32 | 33 | - Added ResourceManager::ForceCloseOpenHandles API. 34 | 35 | - Added APIs to query prototype data for scripts to script compiler library. 36 | 37 | - Added option to use Granny2 out of process even on x86 (for stability). 38 | 39 | - Added custom "first chance" and "last chance" IResourceAccessor support to 40 | the ResourceManager. This allows the user to easily plug in an arbitrary new 41 | resource backend to the resource system. 42 | 43 | - Added build system support for compiling NWScript scripts. 44 | 45 | Version 20101228-01 46 | ------------------- 47 | 48 | - Fixed incorrect tint set reading and writing helper functions in the 49 | GffFileReader and GffFileWriter classes. 50 | 51 | - Fixed I_BOOLAND emitting OpCodes::Xor instead of OpCodes::And in the 52 | MSIL/.NET NWScript JIT backend. 53 | 54 | - By default, NWNScriptLib now includes action service handler names in its 55 | data tables. The NWScript JIT backend now uses these names (if present) to 56 | name direct fast action service handler call stubs, for easier debugging. 57 | 58 | - Fixed RESREF parsing in the GffFileReader (security fix). 59 | 60 | - Added NWN1 BIF/KEY processing support and NWN1 ERF processing support. To 61 | load NWN1-style datafiles, the user must supply the appropriate new values in 62 | the ResourceManager::ModuleLoadParams struct, and LoadModuleResources must be 63 | used instead of LoadModuleResourcesLite. 64 | 65 | - Fixed pathfinding intersection issues in straight path detection. 66 | 67 | - Added mesh manager notification callouts, fix mesh manager list iterator 68 | support (thanks to Chris Darken). 69 | 70 | - 64-bit builds will now prefer to use memory mapped file I/O when reading HAK, 71 | BIF, and ZIP archives. This significantly improves loading performance, 72 | especially for ZIP archives (up to several times faster in some cases). 73 | 74 | - Added various additional math support routines, such as cone intersection. 75 | 76 | - Added new "ListModuleAreas" sample program that prints a list of all areas in 77 | a module. 78 | 79 | - Added new "ListModuleModels" sample program that prints a list of all model 80 | pieces present in a module and its HAKs (and the default game install files). 81 | 82 | - Added new "UpdateModTemplates" sample program that performs bulk updates of 83 | placed object instances in a module with new data from their source 84 | templates. 85 | 86 | - Users of the ResourceManager may now supply a custom search directory for any 87 | application-specific resources that they wish to load through the resource 88 | system. The CustomSearchPath member of the ResourceManager::ModuleLoadParams 89 | structure may optionally be used to establish the custom search path. 90 | 91 | - Users of the ResourceManager may now request that granny2 support not be 92 | enabled, and may request that only core module resources be loaded, via the 93 | new ResourceManager::ResManFlags options specified in the module load params 94 | structure. 95 | 96 | Version 20100815-01 97 | ------------------- 98 | 99 | - Significant improvements to the GffFileWriter class have been made, 100 | including List editing APIs and a fix for compatibility with the NWN2 101 | Toolset's GFF reader. 102 | 103 | - Added a just-in-time (JIT) compilation system for NWScript. An initial JIT 104 | backend that emits MSIL (requires the .NET Framework) is included. The JIT 105 | backend must be built with Visual Studio and not the WDK. 106 | 107 | - Added a static analysis package for NWScript to the NWNScriptLib 108 | (NWScriptAnalyzer). Credit goes to Justin Olbrantz for significant work on 109 | the code analysis / IR raising phase of the NWScriptAnalyzer. 110 | 111 | - Added NWScript action data tables for NWN2 1.23 and NWN1 1.69. 112 | 113 | - Users of NWScriptVM can now provide data table pointers for action handlers 114 | implemented by the script host. If provided, the data tables can be used to 115 | enable static analysis to determine the real argument counts for 116 | parameterized scripts. 117 | 118 | - Fixed a bug where empty strings were not properly converted to OBJECT_INVALID 119 | correctly when passed as dynamic parameters and interpreted as type object. 120 | 121 | - Added support for indirecting through a standalone program (Gr2Conv.exe) to 122 | Granny2Lib. This enables non-x86 builds to decompress *.gr2 files. 123 | 124 | - Fixed alignment faults on ia64 builds in Granny2Lib. 125 | 126 | Version 20100621-01 127 | ------------------- 128 | 129 | - A standalone NWScript host applet (NWNScriptConsole) has been added. This 130 | program demonstrates how to use NWNScriptLib in order to run a script. 131 | 132 | - Various improvements to the GffFileReader and GffFileWriter have been added 133 | in order to better support online editing. 134 | 135 | 136 | Version 20100612-01 137 | ------------------- 138 | 139 | - A writer for generic file format (GFF) files has been added. This writer is 140 | accessible by creating a GffFileWriter object. GFF contents can be created 141 | on the fly, or initialized from a GffFileReader. 142 | 143 | - The ErfFileReader was returning incorrect data if the same file logical 144 | handle was read from multiple times in a row. This has been corrected. 145 | 146 | - NWScriptVM::ExecuteScript now takes an additional default parameter, the 147 | DefaultReturnCode, which is the return value of NWScriptVM::ExecuteScript 148 | should script execution fail (or should the script not return a value). 149 | 150 | Previously, the return code in these cases was always zero. 151 | 152 | - NWScriptVM::ExecuteScript now takes a flags parameter. This allows extended 153 | control over the script VM's behavior. 154 | 155 | - The implementation of the CPDOWNSP NWScript instruction was not properly 156 | masking off SET_ENGINE_STRUCTURE when checking for dynamic typed parameters. 157 | This has been fixed. 158 | 159 | - There was a typo in CPDOWNSP's implementation that interfered with string 160 | copies. This has been fixed. 161 | 162 | - There was a bug in CPDOWNSP that prevented engine structures from being 163 | correctly copied. This has been fixed. 164 | 165 | - The script VM debugger now prints the contents of a string on the stack in 166 | addition to the string handle. 167 | 168 | - Script parameters were not being correctly passed to parameterized scripts 169 | that did not return a value and did not use global variables. This has been 170 | fixed. 171 | 172 | - Parameterized scripts that modified their parameters with CPDOWNSP were not 173 | being permitted to do so. This has been fixed. 174 | 175 | - LOGANDII/LOGORII were not always correctly removing the right number of 176 | values from the stack. This has been fixed. 177 | 178 | - Nested script calls within the same script VM stack were not returning 179 | properly. This has been fixed. 180 | 181 | - The executed instruction count was not being reset when unwinding through the 182 | outermost call to NWScriptVM::ExecuteScriptInternal. This has been fixed. 183 | 184 | 185 | Version 20100528-01 186 | ------------------- 187 | 188 | - The GffFileReader was not properly handling CExoLocStrings that contained 189 | only a STRREf and no other data. This has been fixed. 190 | 191 | - The NWNScriptLib, a complete virtual machine for the core language features 192 | implemented in the compiled NWScript instruction set (*.ncs), has been added 193 | to the project distribution. 194 | 195 | 196 | Version 20100522-01 197 | ------------------- 198 | 199 | - Builds for amd64 (64-bit) are now fully supported. 200 | 201 | - Various warnings fixed for amd64 (64-bit) build. Note that the 64-bit build 202 | requires a 64-bit version of granny2.dll (which NWN2 does not ship with) in 203 | order to load *.gr2 files. 204 | 205 | - SRT matrix decomposition routine added to math library. 206 | 207 | - AreaSurfaceMesh::StraightPathExists now optionally returns the face that the 208 | straight path search terminated at (i.e. as far as we got in a straight line 209 | before we ran into something). 210 | 211 | 212 | Version 20100515-01 213 | ------------------- 214 | 215 | - Generic File Format (GFF) files are now supported by the datafile accessor 216 | system. The GffFileReader object allows validating parsing of these data 217 | structures. 218 | 219 | - The 2DA file reader is now compatible with broken 2DA files missing the first 220 | blank line after the header (such as creaturespeed.2da). 221 | 222 | - More verbose 2DA load failure debugging is now available. 223 | 224 | - MeshManager abstraction added. The MeshManager and MeshLinkage support logic 225 | allows easy typed access to all meshes instantiated by a particular instance 226 | of a ResourceManager. They are intended to allow data (such as hardware- 227 | defined resources) to be attached to each mesh, and to be easily retrieved or 228 | updated. 229 | 230 | - All mesh objects (including the AreaSurfaceMesh) will now register themselves 231 | with the MeshManager through an embedded MeshLinkage object. 232 | 233 | - The TrxFileReader can now be configured to skip loading of display meshes for 234 | .trx and .mdb files. 235 | 236 | - New resource type mappings added for ERF files. 237 | 238 | - Support for partial module resource loads has been added to the resource 239 | manager system. 240 | 241 | - DemandResource-based template classes now behave correctly when copied. 242 | 243 | - Fixed incorrect case sensitivity for file extensions when the resource system 244 | is loading data from raw directories via the DirectoryFileReader. 245 | 246 | 247 | Version 20100320-01 248 | ------------------- 249 | 250 | Initial release. 251 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | project(nwnsc) 3 | 4 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | if(NOT CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 11) 8 | set(CMAKE_CXX_STANDARD 11) 9 | endif() 10 | 11 | # Appends the cmake/modules path to MAKE_MODULE_PATH variable. 12 | set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH}) 13 | 14 | # 15 | # Make a version file containing the current version from git. 16 | # 17 | include(GetGitRevisionDescription) 18 | git_describe(VERSION --tags --dirty=-dirty) 19 | 20 | #parse the version information into pieces. 21 | string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}") 22 | string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}") 23 | string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION}") 24 | string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+(.*)" "\\1" VERSION_SHA1 "${VERSION}") 25 | set(VERSION_SHORT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") 26 | 27 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/version.cpp.in 28 | ${CMAKE_CURRENT_SOURCE_DIR}/_NwnUtilLib/version.cpp) 29 | set(version_file "${CMAKE_CURRENT_SOURCE_DIR}/_NwnUtilLib/version.cpp") 30 | 31 | if (APPLE) 32 | set(CMAKE_MACOSX_RPATH 1) 33 | set(CMAKE_OSX_ARCHITECTURES arm64;x86_64) 34 | endif() 35 | 36 | find_package(BISON) 37 | if (NOT BISON_FOUND) 38 | message(FATAL_ERROR "Cannot find bison, need bison installed to generate Parser/Lexer") 39 | endif (NOT BISON_FOUND) 40 | 41 | if (UNIX OR APPLE) 42 | #set(CMAKE_CXX_FLAGS "-Wall -Wno-unused -Wno-write-strings -Wno-deprecated -std=c++11") 43 | set(CMAKE_CXX_FLAGS " -g -w -O2 -std=c++11 -DELPP_FEATURE_CRASH_LOG -DELPP_IGNORE_SIGINT -DELPP_LOGGING_FLAGS_FROM_ARG -DELPP_NO_DEFAULT_LOG_FILE") 44 | #set(CMAKE_CXX_FLAGS "-g -w -m32 -std=c++11 -DELPP_FEATURE_CRASH_LOG -DELPP_IGNORE_SIGINT -DELPP_LOGGING_FLAGS_FROM_ARG -DELPP_NO_DEFAULT_LOG_FILE") 45 | #set(CMAKE_CXX_FLAGS "-w /EHsc") 46 | endif() 47 | 48 | if (MINGW OR CYGWIN) 49 | #set(CMAKE_CXX_FLAGS "-Wall -Wno-unused -Wno-write-strings -Wno-deprecated -std=c++11 -static") 50 | set(CMAKE_CXX_FLAGS " -w -O2 -std=c++11 -static -DELPP_FEATURE_CRASH_LOG -DELPP_IGNORE_SIGINT -DELPP_LOGGING_FLAGS_FROM_ARG -DELPP_NO_DEFAULT_LOG_FILE") 51 | #set(CMAKE_CXX_FLAGS "-g -w -m32 -std=c++11 -static") 52 | #set(CMAKE_CXX_FLAGS "-w /EHsc") 53 | endif() 54 | 55 | if (MSVC) 56 | add_compile_options(/DELPP_LOGGING_FLAGS_FROM_ARG /DELPP_NO_DEFAULT_LOG_FILE /DNOMINMAX) 57 | foreach(flag_var 58 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 59 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) 60 | if(${flag_var} MATCHES "/MD") 61 | string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") 62 | endif(${flag_var} MATCHES "/MD") 63 | if(${flag_var} MATCHES "/O2") 64 | string(REGEX REPLACE "/O2" "/Ox" ${flag_var} "${${flag_var}}") 65 | endif(${flag_var} MATCHES "/O2") 66 | endforeach(flag_var) 67 | endif() 68 | 69 | if (BISON_VERSION VERSION_GREATER "3.6.0") 70 | add_definitions(-DNWN_BISON_3_6=1) 71 | elseif (BISON_VERSION VERSION_GREATER "3.0.0") 72 | add_definitions(-DNWN_BISON_3=1) 73 | endif (BISON_VERSION VERSION_GREATER "3.6.0") 74 | 75 | add_subdirectory(_NwnBaseLib) 76 | add_subdirectory(_NwnDataLib) 77 | add_subdirectory(_NwnUtilLib) 78 | add_subdirectory(_NscLib) 79 | add_subdirectory(nwnsc) 80 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM beamdog/nwserver:latest as nwserver 2 | LABEL maintainers "jakobknutsen@gmail.com" 3 | 4 | FROM nwneetools/nwnsc-docker-builder:latest as nwnsc 5 | COPY ./ /tmp/nwnsc/ 6 | WORKDIR /tmp/nwnsc 7 | RUN /hbb_exe/activate-exec cmake . && make all 8 | 9 | FROM i386/ubuntu:latest 10 | COPY --from=nwnsc /tmp/nwnsc/nwnsc/nwnsc /usr/local/bin/ 11 | COPY --from=nwserver /nwn/data /nwn/data 12 | WORKDIR /tmp 13 | ENTRYPOINT ["nwnsc", "-on", "/nwn/data"] 14 | CMD ["*.nss"] 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2008-2014 Ken Johnson (Skywing) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | 21 | 22 | 23 | The following applies to "_NscLib" which contains content from 24 | Edward T. Smith and The Open Knights Consortium (see further acknowledgement 25 | in README.TXT for details). 26 | 27 | 28 | Copyright (c) 2002-2003, Edward T. Smith. All rights reserved. 29 | Copyright (c) 2003, The Open Knights Consortium. All rights reserved. 30 | 31 | Redistribution and use in source and binary forms, with or without 32 | modification, are permitted provided that the following conditions are met: 33 | 34 | 1. Redistributions of source code must retain the above copyright notice, this 35 | list of conditions, the following disclaimer, and acknowledgements. 36 | 37 | 2. Redistributions in binary form must reproduce the above copyright notice, 38 | this list of conditions, the following disclaimer, and acknowledgements in 39 | the documentation and/or other materials provided with the distribution. 40 | 41 | 3. Neither the name of the Open Knights, Edward T. Smith, this project 42 | (NWN Tools) nor the names of its contributors may be used to endorse or 43 | promote products derived from this software without specific prior written 44 | permission. 45 | 46 | DISCLAIMER: 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 48 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 49 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 51 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 52 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 53 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 54 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 56 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | 58 | Acknowledgement of Bioware's Contribution and Intellectual Property: 59 | This program and material is intended to examine, produce or modify data 60 | structures which may be used by Bioware's Neverwinter Nights programs. Inputs 61 | to this program may include data produced by Bioware or its partners as part of 62 | the Neverwinter Nights product or its expansions and sequals. When the output 63 | data structures from this program are so used and/or are made with such inputs, 64 | then the terms of the Bioware Neverwinter Nights End User License Agreements 65 | governing the production and use of such data structures still apply. 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /_NscLib/.gitignore: -------------------------------------------------------------------------------- 1 | NscParser.cpp 2 | NscParser.hpp 3 | *.hh 4 | -------------------------------------------------------------------------------- /_NscLib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(nsclib 2 | Nsc.h 3 | NscCodeGenerator.cpp 4 | NscCodeGenerator.h 5 | NscCompat.h 6 | NscCompiler.cpp 7 | NscContext.cpp 8 | NscContext.h 9 | NscDecompiler.cpp 10 | NscIntrinsicDefs.h 11 | NscParser.cpp 12 | NscParser.hpp 13 | NscParserRoutines.cpp 14 | NscPCodeEnumerator.cpp 15 | NscPCodeEnumerator.h 16 | NscPStackEntry.cpp 17 | NscPStackEntry.h 18 | NscSymbolTable.h 19 | NwnDefines.cpp 20 | NwnDefines.h 21 | NwnDoubleLinkList.h 22 | NwnLoader.cpp 23 | NwnLoader.h 24 | NwnStreams.h 25 | Precomp.h 26 | ) 27 | 28 | if (WIN32 OR WIN64) 29 | add_custom_command( 30 | OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/NscParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/NscParser.hpp 31 | DEPENDS NscParser.ypp 32 | COMMAND "${BISON_EXECUTABLE}" -S lalr1.cc ${CMAKE_CURRENT_SOURCE_DIR}/NscParser.ypp -o ${CMAKE_CURRENT_SOURCE_DIR}/NscParser.cpp 33 | ) 34 | else () 35 | add_custom_command( 36 | OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/NscParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/NscParser.hpp 37 | DEPENDS NscParser.ypp 38 | COMMAND "${BISON_EXECUTABLE}" -S lalr1.cc ${CMAKE_CURRENT_SOURCE_DIR}/NscParser.ypp -o ${CMAKE_CURRENT_SOURCE_DIR}/NscParser.cpp 39 | ) 40 | endif (WIN32 OR WIN64) 41 | -------------------------------------------------------------------------------- /_NscLib/NscCompat.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* Bison 3 does not define some of these 4 | values. YYEMPTY is needed in all cases 5 | the NWN_BISON_3 macro is defined by the CMakeLists.txt 6 | based on the version of bison found 7 | */ 8 | #ifdef NWN_BISON_3_6 9 | # define YYCHAR_NAME yyla.kind() 10 | # define YYLA_EMPTY yyla.clear() 11 | # define YYLVAL yyla.value 12 | # define YYLA_CHARNAME_LEX yyla.kind_ = yytranslate_(yylex(&YYLVAL,context)) 13 | #else 14 | # define YYEMPTY (-2) 15 | # ifdef NWN_BISON_3 16 | # define YYLVAL yyla.value 17 | # define YYCHAR_NAME yyla.type 18 | # else 19 | # define YYCHAR_NAME yychar 20 | # define YYLVAL yylval 21 | # endif 22 | # define YYLA_EMPTY YYCHAR_NAME = YYEMPTY 23 | # define YYLA_CHARNAME_LEX YYCHAR_NAME = yylex(&YYLVAL, context) 24 | #endif 25 | 26 | 27 | enum nwtoken { 28 | IDENTIFIER = 258, 29 | INTEGER_CONST = 259, 30 | FLOAT_CONST = 260, 31 | STRING_CONST = 261, 32 | ADDEQ = 262, 33 | SUBEQ = 263, 34 | MULEQ = 264, 35 | DIVEQ = 265, 36 | MODEQ = 266, 37 | XOREQ = 267, 38 | ANDEQ = 268, 39 | OREQ = 269, 40 | SL = 270, 41 | SR = 271, 42 | USR = 272, 43 | SLEQ = 273, 44 | SREQ = 274, 45 | USREQ = 275, 46 | EQ = 276, 47 | NOTEQ = 277, 48 | LTEQ = 278, 49 | GTEQ = 279, 50 | ANDAND = 280, 51 | OROR = 281, 52 | PLUSPLUS = 282, 53 | MINUSMINUS = 283, 54 | FLOAT_TYPE = 284, 55 | INT_TYPE = 285, 56 | OBJECT_TYPE = 286, 57 | STRING_TYPE = 287, 58 | VOID_TYPE = 288, 59 | STRUCT_TYPE = 289, 60 | VECTOR_TYPE = 290, 61 | ENGINE_TYPE = 291, 62 | ACTION_TYPE = 292, 63 | OBJECT_SELF_CONST = 293, 64 | OBJECT_INVALID_CONST = 294, 65 | BREAK = 295, 66 | CASE = 296, 67 | CONTINUE = 297, 68 | DEFAULT = 298, 69 | DO = 299, 70 | ELSE = 300, 71 | FOR = 301, 72 | IF = 302, 73 | RETURN = 303, 74 | SWITCH = 304, 75 | WHILE = 305, 76 | NWCONST = 306, 77 | LOCATION_INVALID_CONST = 307, 78 | JSON_NULL_CONST = 308, 79 | JSON_FALSE_CONST = 309, 80 | JSON_TRUE_CONST = 310, 81 | JSON_OBJECT_CONST = 311, 82 | JSON_ARRAY_CONST = 312, 83 | JSON_STRING_CONST = 313 84 | }; 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /_NscLib/NscIntrinsicDefs.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // @doc 4 | // 5 | // @module NscIntrinsicDefs.h - Script built-in intrinsic definitions | 6 | // 7 | // This module contains the definition of the script support intrinsics that 8 | // are injected into nwscript.nss compilation 9 | // 10 | // Copyright (c) 2008-2011 - Ken Johnson (Skywing) 11 | // 12 | // All rights reserved. 13 | // 14 | // Redistribution and use in source and binary forms, with or without 15 | // modification, are permitted provided that the following conditions are 16 | // met: 17 | // 18 | // 1. Redistributions of source code must retain the above copyright notice, 19 | // this list of conditions and the following disclaimer. 20 | // 2. Neither the name of Edward T. Smith nor the names of its contributors 21 | // may be used to endorse or promote products derived from this software 22 | // without specific prior written permission. 23 | // 24 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 30 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | // 36 | // @end 37 | // 38 | // $History: NscIntrinsicDefs.h $ 39 | // 40 | //----------------------------------------------------------------------------- 41 | 42 | // 43 | // Globals 44 | // 45 | 46 | static const char g_szNscIntrinsicsText [] = 47 | "/*++\n" 48 | "\n" 49 | "Copyright (c) Ken Johnson (Skywing). All rights reserved.\n" 50 | "\n" 51 | "Module Name:\n" 52 | "\n" 53 | " NscIntrinsics.nss\n" 54 | "\n" 55 | "Abstract:\n" 56 | "\n" 57 | " This module houses definitions related to compiler internal intrinsics.\n" 58 | "\n" 59 | "--*/\n" 60 | "\n" 61 | "#pragma nsc_intrinsics\n" 62 | "\n" 63 | "int __readbp ();\n" 64 | "void __writebp (int BP);\n" 65 | "int __readrelativesp ();\n" 66 | "int __readsp ();\n" 67 | "int __readpc ();\n" 68 | "\n"; 69 | 70 | static const size_t g_nNscIntrinsicsTextSize = sizeof (g_szNscIntrinsicsText) - 71 | sizeof (g_szNscIntrinsicsText [0]); 72 | -------------------------------------------------------------------------------- /_NscLib/NscPCodeEnumerator.h: -------------------------------------------------------------------------------- 1 | #ifndef ETS_NSCPCODEENUMERATOR_H 2 | #define ETS_NSCPCODEENUMERATOR_H 3 | 4 | //----------------------------------------------------------------------------- 5 | // 6 | // @doc 7 | // 8 | // @module NscPCodeEnumerator.h - Recursive enumeration of PCode opcodes | 9 | // 10 | // This module contains the definition of the PCode enumerator base classes, 11 | // which allow logic to be applied across all PCode contributions within a 12 | // containing PCode block (i.e. including all sub-blocks). The ability to 13 | // apply logic to an entire PCode block is useful for certain optimizations 14 | // as an example. 15 | // 16 | // Copyright (c) 2008-2011 - Ken Johnson (Skywing) 17 | // 18 | // All rights reserved. 19 | // 20 | // Redistribution and use in source and binary forms, with or without 21 | // modification, are permitted provided that the following conditions are 22 | // met: 23 | // 24 | // 1. Redistributions of source code must retain the above copyright notice, 25 | // this list of conditions and the following disclaimer. 26 | // 2. Neither the name of Edward T. Smith nor the names of its contributors 27 | // may be used to endorse or promote products derived from this software 28 | // without specific prior written permission. 29 | // 30 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 31 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 32 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 33 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 34 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 36 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 37 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | // 42 | // @end 43 | // 44 | // $History: NscPCodeEnumerator.h $ 45 | // 46 | //----------------------------------------------------------------------------- 47 | 48 | //----------------------------------------------------------------------------- 49 | // 50 | // Required include files 51 | // 52 | //----------------------------------------------------------------------------- 53 | 54 | //----------------------------------------------------------------------------- 55 | // 56 | // Forward definitions 57 | // 58 | //----------------------------------------------------------------------------- 59 | 60 | class CNscContext; 61 | 62 | //----------------------------------------------------------------------------- 63 | // 64 | // Class definition 65 | // 66 | //----------------------------------------------------------------------------- 67 | 68 | class CNscPCodeEnumerator 69 | { 70 | 71 | // @access Constructors and destructors 72 | public: 73 | 74 | enum Constants 75 | { 76 | Max_Symbols_Referenced = 1 // Maximum symbol operands in leaf code 77 | }; 78 | 79 | // @cmember General constructor 80 | 81 | CNscPCodeEnumerator (CNscContext *pCtx); 82 | 83 | // @cmember Delete the object 84 | 85 | ~CNscPCodeEnumerator (); 86 | 87 | // @access Public methods 88 | public: 89 | 90 | // @cmember Process the PCode block, calling the derived class processor 91 | 92 | bool ProcessPCodeBlock (const unsigned char *pauchData, size_t nDataSize); 93 | 94 | // @cmember Set whether calls are inspected (user must break recursion!) 95 | 96 | void SetInspectCalledFunctions (bool fInspectCalledFunctions) 97 | { 98 | m_fInspectCalledFunctions = fInspectCalledFunctions; 99 | } 100 | 101 | // @cmember Get whether calls are inspected 102 | 103 | bool GetInspectCalledFunctions () const 104 | { 105 | return m_fInspectCalledFunctions; 106 | } 107 | 108 | // @access Derived class implemented protected methods 109 | protected: 110 | 111 | // 112 | // Each recursion into ProcessPCodeBlockInternal creates a new 113 | // PCodeEntryParameters that allows the user to examine the current chain of 114 | // containing PCode entries which lead to the current opcode. 115 | // 116 | 117 | struct PCodeEntryParameters 118 | { 119 | const NscPCodeHeader *pHeader; 120 | PCodeEntryParameters *pContainingEntry; 121 | void *pUserDefinedContext; 122 | bool fIsLeafBlock; 123 | size_t nSymbolImmediates [Max_Symbols_Referenced]; 124 | int nStackOffsets [Max_Symbols_Referenced]; 125 | int nElements [Max_Symbols_Referenced]; 126 | UINT32 ulSymbolFlags [Max_Symbols_Referenced]; 127 | size_t nSymbolsReferenced; 128 | }; 129 | 130 | // @cmember Perform the enumerator-specific action on the current code entry 131 | 132 | virtual bool OnPCodeEntry (PCodeEntryParameters *pEntry) = 0; 133 | 134 | // @cmember Check whether it is ok to recurse into this call site 135 | 136 | virtual bool GetIsCallSiteInspectable (PCodeEntryParameters *pEntry) 137 | { 138 | pEntry; 139 | 140 | return true; 141 | } 142 | 143 | // @access Protected inline methods 144 | protected: 145 | 146 | // @cmember Return the CNscContext (which may be NULL) 147 | 148 | CNscContext *GetNscContext () 149 | { 150 | return m_pCtx; 151 | } 152 | 153 | // @cmember Check whether we are inside a called function body 154 | 155 | static bool IsInsideCalledFunction (PCodeEntryParameters *pCurrentEntry) 156 | { 157 | // 158 | // If the containing PCode set has a call instruction 159 | // 160 | 161 | return IsContainedWithinOpcode (pCurrentEntry, NscPCode_Call); 162 | } 163 | 164 | // @cmember Check whether an opcode is present in the containing PCodes 165 | 166 | static bool IsContainedWithinOpcode (PCodeEntryParameters *pCurrentEntry, 167 | NscPCode nOpCode) 168 | { 169 | // 170 | // Loop through the containing opcodes 171 | // 172 | 173 | for (const PCodeEntryParameters *pEntry = pCurrentEntry; 174 | pEntry != NULL; 175 | pEntry = pEntry ->pContainingEntry) 176 | { 177 | if (pEntry ->pHeader ->nOpCode == nOpCode) 178 | return true; 179 | } 180 | 181 | return false; 182 | } 183 | 184 | // @cmember Get the first (if any) containing PCode matching a given opcode 185 | 186 | static PCodeEntryParameters *GetContainingPCodeEntry ( 187 | PCodeEntryParameters *pCurrentEntry, NscPCode nOpCode) 188 | { 189 | // 190 | // Loop through the containing opcodes 191 | // 192 | 193 | for (PCodeEntryParameters *pEntry = pCurrentEntry; 194 | pEntry != NULL; 195 | pEntry = pEntry ->pContainingEntry) 196 | { 197 | if (pEntry ->pHeader ->nOpCode == nOpCode) 198 | return pEntry; 199 | } 200 | 201 | return NULL; 202 | } 203 | 204 | // @access Private methods 205 | private: 206 | 207 | // @cmember Internal recursive processor for PCode blocks 208 | 209 | bool ProcessPCodeBlockInternal (const unsigned char *pauchData, 210 | size_t nDataSIze, PCodeEntryParameters *pContainingEntry); 211 | 212 | // @access Private members 213 | private: 214 | 215 | // @cmember CNscContext (for function recursion) 216 | 217 | CNscContext *m_pCtx; 218 | 219 | // @cmember Whether we will recurse into called functions 220 | 221 | bool m_fInspectCalledFunctions; 222 | }; 223 | 224 | //----------------------------------------------------------------------------- 225 | // 226 | // Class definition 227 | // 228 | //----------------------------------------------------------------------------- 229 | 230 | class CNscPCodeSideEffectChecker : public CNscPCodeEnumerator 231 | { 232 | 233 | // @access Constructors and destructors 234 | public: 235 | 236 | // @cmember General constructor 237 | 238 | CNscPCodeSideEffectChecker (CNscContext *pCtx) 239 | : CNscPCodeEnumerator (pCtx) 240 | { 241 | } 242 | 243 | // @cmember Delete the object 244 | 245 | ~CNscPCodeSideEffectChecker () 246 | { 247 | } 248 | 249 | // @access Private members 250 | private: 251 | 252 | // @cmember Returns false if the entry may have side effects 253 | 254 | virtual bool OnPCodeEntry (PCodeEntryParameters *pEntry); 255 | }; 256 | 257 | //----------------------------------------------------------------------------- 258 | // 259 | // Class definition 260 | // 261 | //----------------------------------------------------------------------------- 262 | 263 | class CNscPCodePrinter : public CNscPCodeEnumerator 264 | { 265 | 266 | // @access Constructors and destructors 267 | public: 268 | 269 | // @cmember General constructor 270 | 271 | CNscPCodePrinter (CNscContext *pCtx) 272 | : CNscPCodeEnumerator (pCtx) 273 | { 274 | } 275 | 276 | // @cmember Delete the object 277 | 278 | ~CNscPCodePrinter () 279 | { 280 | } 281 | 282 | // @access Private members 283 | private: 284 | 285 | // @cmember Prints PCode to the console 286 | 287 | virtual bool OnPCodeEntry (PCodeEntryParameters *pEntry); 288 | 289 | // @cmemeber Get the name for a PCode opcode 290 | 291 | static const char * GetPCodeOpName (NscPCode nOpCode); 292 | 293 | }; 294 | #endif // ETS_NSCPCODEENUMERATOR_H 295 | 296 | -------------------------------------------------------------------------------- /_NscLib/NscSymbolTable.h: -------------------------------------------------------------------------------- 1 | #ifndef ETS_NSCSYMBOLTABLE_H 2 | #define ETS_NSCSYMBOLTABLE_H 3 | 4 | //----------------------------------------------------------------------------- 5 | // 6 | // @doc 7 | // 8 | // @module NscSymbolTable.h - Global symbol table | 9 | // 10 | // This module contains the definition for the symbol table. 11 | // 12 | // Copyright (c) 2002-2003 - Edward T. Smith 13 | // 14 | // All rights reserved. 15 | // 16 | // Redistribution and use in source and binary forms, with or without 17 | // modification, are permitted provided that the following conditions are 18 | // met: 19 | // 20 | // 1. Redistributions of source code must retain the above copyright notice, 21 | // this list of conditions and the following disclaimer. 22 | // 2. Neither the name of Edward T. Smith nor the names of its contributors 23 | // may be used to endorse or promote products derived from this software 24 | // without specific prior written permission. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 32 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | // 38 | // @end 39 | // 40 | // $History: CnfMainWnd.h $ 41 | // 42 | //----------------------------------------------------------------------------- 43 | 44 | //----------------------------------------------------------------------------- 45 | // 46 | // Required include files 47 | // 48 | //----------------------------------------------------------------------------- 49 | 50 | //----------------------------------------------------------------------------- 51 | // 52 | // Forward definitions 53 | // 54 | //----------------------------------------------------------------------------- 55 | 56 | //----------------------------------------------------------------------------- 57 | // 58 | // Class definition 59 | // 60 | //----------------------------------------------------------------------------- 61 | 62 | #include "NwnDefines.h" 63 | 64 | class CNscSymbolTable 65 | { 66 | // @access Constructors and destructors 67 | public: 68 | 69 | // @cmember General constructor 70 | 71 | CNscSymbolTable (size_t nGrowSize = 0x40000) 72 | { 73 | m_pauchData = NULL; 74 | m_nSize = 0; 75 | m_nAllocated = 0; 76 | m_nGrowSize = nGrowSize; 77 | m_nGlobalIdentifierCount = 0; 78 | memset (&m_sFence, 0, sizeof (m_sFence)); 79 | } 80 | 81 | // @cmember Delete the streams 82 | 83 | ~CNscSymbolTable () 84 | { 85 | if (m_pauchData) 86 | delete [] m_pauchData; 87 | } 88 | 89 | // @access Public methods 90 | public: 91 | 92 | // @cmember Get the offset of a symbol 93 | 94 | size_t GetSymbolOffset (NscSymbol *pSymbol) 95 | { 96 | return (size_t) ((unsigned char *) pSymbol - m_pauchData); 97 | } 98 | 99 | // @cmember Get a symbol from an offset 100 | 101 | NscSymbol *GetSymbol (size_t nOffset) 102 | { 103 | return (NscSymbol *) GetData (nOffset); 104 | } 105 | 106 | // @cmember Save the symbol table to another table 107 | 108 | void CopyFrom (CNscSymbolTable *pTable) 109 | { 110 | m_nSize = 0; 111 | MakeRoom (pTable ->m_nSize); 112 | memcpy (m_pauchData, pTable ->m_pauchData, pTable ->m_nSize); 113 | memcpy (&m_sFence, &pTable ->m_sFence, sizeof (m_sFence)); 114 | m_nSize = pTable ->m_nSize; 115 | m_nGlobalIdentifierCount = pTable ->m_nGlobalIdentifierCount; 116 | } 117 | 118 | // @cmember Reset the symbol table 119 | 120 | void Reset () 121 | { 122 | if (m_nSize > 0) 123 | m_nSize = 1; 124 | memset (&m_sFence, 0, sizeof (m_sFence)); 125 | m_nGlobalIdentifierCount = 0; 126 | } 127 | 128 | // @cmember Get a pointer to symbol table data 129 | 130 | unsigned char *GetData (size_t nOffset = 0) 131 | { 132 | return &m_pauchData [nOffset]; 133 | } 134 | 135 | // @cmember Get the current fence 136 | 137 | void GetFence (NscSymbolFence *pFence) 138 | { 139 | memcpy (pFence, &m_sFence, sizeof (m_sFence)); 140 | pFence ->nSize = m_nSize; 141 | } 142 | 143 | // @cmember Restore the given fence 144 | 145 | void RestoreFence (NscSymbolFence *pFence) 146 | { 147 | memcpy (&m_sFence, pFence, sizeof (m_sFence)); 148 | m_nSize = pFence ->nSize; 149 | } 150 | 151 | // @cmember Find a symbol 152 | 153 | NscSymbol *Find (const char *psz, size_t nLength, UINT32 ulHash, UINT32 ulSymTypeMask = (UINT32) -1) 154 | { 155 | 156 | // 157 | // Search for a match 158 | // 159 | 160 | UINT32 ulHashIndex = ulHash % NscMaxHash; 161 | size_t nIndex = m_sFence .anHashStart [ulHashIndex]; 162 | while (nIndex != 0) 163 | { 164 | NscSymbol *pSymbol = (NscSymbol *) &m_pauchData [nIndex]; 165 | if (pSymbol ->ulHash == ulHash && 166 | pSymbol ->nLength == nLength && 167 | ((1 << pSymbol ->nSymType) & ulSymTypeMask) != 0 && 168 | memcmp (psz, pSymbol ->szString, 169 | nLength * sizeof (char)) == 0) 170 | { 171 | return pSymbol; 172 | } 173 | nIndex = pSymbol ->nNext; 174 | } 175 | return NULL; 176 | } 177 | 178 | // @cmember Find a symbol 179 | 180 | NscSymbol *Find (const char *psz, size_t nLength) 181 | { 182 | return Find (psz, nLength, GetHash (psz, nLength)); 183 | } 184 | 185 | // @cmember Find a symbol 186 | 187 | NscSymbol *Find (const char *psz) 188 | { 189 | size_t nLength = strlen (psz); 190 | return Find (psz, nLength, GetHash (psz, nLength)); 191 | } 192 | 193 | // @cmember Find a symbol 194 | 195 | NscSymbol *FindByType (const char *psz, UINT32 ulSymTypeMask) 196 | { 197 | size_t nLength = strlen (psz); 198 | return Find (psz, nLength, GetHash (psz, nLength), ulSymTypeMask); 199 | } 200 | // @cmember Add a new symbol 201 | 202 | NscSymbol *Add (const char *psz, NscSymType nSymType) 203 | { 204 | 205 | // 206 | // Get the hash code and index 207 | // 208 | 209 | size_t nLength = strlen (psz); 210 | UINT32 ulHash = GetHash (psz, nLength); 211 | UINT32 ulHashIndex = ulHash % NscMaxHash; 212 | 213 | // 214 | // If no match was found, we will have to create a new one 215 | // 216 | 217 | size_t nSize = sizeof (NscSymbol) + ((nLength) * sizeof (char)); 218 | MakeRoom (nSize); 219 | NscSymbol *pSymbol = (NscSymbol *) &m_pauchData [m_nSize]; 220 | pSymbol ->nNext = m_sFence .anHashStart [ulHashIndex]; 221 | pSymbol ->ulHash = ulHash; 222 | pSymbol ->nSymType = nSymType; 223 | pSymbol ->nLength = nLength; 224 | memcpy (pSymbol ->szString, psz, nLength); 225 | pSymbol ->szString [nLength] = 0; 226 | m_sFence .anHashStart [ulHashIndex] = m_nSize; 227 | #ifdef _DEBUG 228 | m_sFence .anHashDepth [ulHashIndex]++; 229 | #endif 230 | 231 | m_nSize += nSize; 232 | return pSymbol; 233 | } 234 | 235 | // @cmember Add a new symbol 236 | 237 | NscSymbol *AddNoHash (const char *psz, NscSymType nSymType) 238 | { 239 | 240 | // 241 | // Blindly add a symbol without updating the hash 242 | // 243 | 244 | size_t nLength = strlen (psz); 245 | size_t nSize = sizeof (NscSymbol) + ((nLength) * sizeof (char)); 246 | MakeRoom (nSize); 247 | NscSymbol *pSymbol = (NscSymbol *) &m_pauchData [m_nSize]; 248 | pSymbol ->nNext = 0; 249 | pSymbol ->ulHash = 0; 250 | pSymbol ->nSymType = nSymType; 251 | pSymbol ->nLength = nLength; 252 | memcpy (pSymbol ->szString, psz, nLength); 253 | pSymbol ->szString [nLength] = 0; 254 | m_nSize += nSize; 255 | return pSymbol; 256 | } 257 | 258 | static UINT32 GetHash (const char *psz, size_t nLength) 259 | { 260 | UINT32 hash = 0; 261 | while (nLength-- > 0) 262 | { 263 | int c = *psz++; 264 | hash = c + (hash << 6) + (hash << 16) - hash; 265 | } 266 | return hash; 267 | } 268 | 269 | // @cmember Get the hash value 270 | 271 | static UINT32 GetHash (const char *psz) 272 | { 273 | UINT32 hash = 0; 274 | int c; 275 | while ((c = *psz++) != 0) 276 | hash = c + (hash << 6) + (hash << 16) - hash; 277 | return hash; 278 | } 279 | 280 | // @cmember Append raw data 281 | 282 | size_t AppendData (void *pData, size_t nSize) 283 | { 284 | size_t nPos = m_nSize; 285 | MakeRoom (nSize); 286 | memcpy (&m_pauchData [m_nSize], pData, nSize); 287 | m_nSize += nSize; 288 | return nPos; 289 | } 290 | 291 | // @cmember Get the fence 292 | 293 | NscSymbolFence &GetFence () 294 | { 295 | return m_sFence; 296 | } 297 | 298 | // @cmember Get the number of global identifier symbols (arbitrary) 299 | 300 | size_t GetGlobalIdentifierCount () 301 | { 302 | return m_nGlobalIdentifierCount; 303 | } 304 | 305 | // @cmember Set the number of global identifier symbols (arbitrary) 306 | void SetGlobalIdentifierCount (size_t nGlobalIdentifierCount) 307 | { 308 | m_nGlobalIdentifierCount = nGlobalIdentifierCount; 309 | } 310 | 311 | // @access Public inline methods 312 | public: 313 | 314 | // @access Protected methods 315 | protected: 316 | 317 | // @cmember Insure there is room 318 | 319 | void MakeRoom (size_t nSize) 320 | { 321 | if (m_nSize + nSize > m_nAllocated) 322 | { 323 | do 324 | { 325 | m_nAllocated += m_nGrowSize; 326 | } while (m_nSize + nSize > m_nAllocated); 327 | unsigned char *pauchNew = new unsigned char [m_nAllocated]; 328 | if (m_nSize == 0) 329 | m_nSize = 1; 330 | else 331 | { 332 | memmove (pauchNew, m_pauchData, m_nSize); 333 | delete [] m_pauchData; 334 | } 335 | m_pauchData = pauchNew; 336 | } 337 | } 338 | 339 | // @cmember Protected members 340 | protected: 341 | 342 | // @cmember Pointer to the symbol table data 343 | 344 | unsigned char *m_pauchData; 345 | 346 | // @cmember Size of the symbol table 347 | 348 | size_t m_nSize; 349 | 350 | // @cmember Allocated size of the symbol table 351 | 352 | size_t m_nAllocated; 353 | 354 | // @cmember Grow amount 355 | 356 | size_t m_nGrowSize; 357 | 358 | // @cmember Number of global identifiers represented by the symbol table 359 | 360 | size_t m_nGlobalIdentifierCount; 361 | 362 | // @cmember Current fence 363 | 364 | NscSymbolFence m_sFence; 365 | }; 366 | 367 | #endif // ETS_NSCSYMBOLTABLE_H 368 | -------------------------------------------------------------------------------- /_NscLib/NwnDefines.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // @doc 4 | // 5 | // @module NwnDefiles.cpp - General helper routines | 6 | // 7 | // This module contains the general NWN helper routines. 8 | // 9 | // Copyright (c) 2002-2003 - Edward T. Smith 10 | // 11 | // All rights reserved. 12 | // 13 | // Redistribution and use in source and binary forms, with or without 14 | // modification, are permitted provided that the following conditions are 15 | // met: 16 | // 17 | // 1. Redistributions of source code must retain the above copyright notice, 18 | // this list of conditions and the following disclaimer. 19 | // 2. Neither the name of Edward T. Smith nor the names of its contributors 20 | // may be used to endorse or promote products derived from this software 21 | // without specific prior written permission. 22 | // 23 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | // 35 | // @end 36 | // 37 | // $History: Cnf.cpp $ 38 | // 39 | //----------------------------------------------------------------------------- 40 | 41 | #include "Precomp.h" 42 | #include "NwnDefines.h" 43 | 44 | //----------------------------------------------------------------------------- 45 | // 46 | // @mfunc BASENAME helper routine 47 | // 48 | // @parm const char * | pszFile | Input file name 49 | // 50 | // @rdesc Pointer to the file name 51 | // 52 | //----------------------------------------------------------------------------- 53 | 54 | const char *NwnBasename (const char *pszFile) 55 | { 56 | #if !defined (HAVE_BASENAME) 57 | if (pszFile == NULL) 58 | return NULL; 59 | for (const char *psz = pszFile; *psz; ++psz) 60 | { 61 | if (*psz == '\\' || *psz == '/' || *psz == ':') 62 | pszFile = psz + 1; 63 | } 64 | return pszFile; 65 | #else 66 | return basename ((char *) pszFile); 67 | #endif 68 | } 69 | 70 | //----------------------------------------------------------------------------- 71 | // 72 | // @mfunc STRICMP helper routine 73 | // 74 | // @parm const char * | string1 | First string 75 | // 76 | // @parm const char * | string2 | Second string 77 | // 78 | // @rdesc Results of the compare 79 | // 80 | //----------------------------------------------------------------------------- 81 | 82 | #if !defined (HAVE_STRICMP) && !defined (HAVE_STRCASECMP) 83 | int stricmp (const char *string1, const char *string2) 84 | { 85 | int c1, c2; 86 | do 87 | { 88 | c1 = tolower ((unsigned char) (*(string1++))); 89 | c2 = tolower ((unsigned char) (*(string2++))); 90 | } while (c1 && (c1 == c2)); 91 | return (c1 - c2); 92 | } 93 | #endif 94 | 95 | //----------------------------------------------------------------------------- 96 | // 97 | // @mfunc STRNICMP helper routine 98 | // 99 | // @parm const char * | string1 | First string 100 | // 101 | // @parm const char * | string2 | Second string 102 | // 103 | // @parm size_t | count | Length of the string 104 | // 105 | // @rdesc Results of the compare 106 | // 107 | //----------------------------------------------------------------------------- 108 | 109 | 110 | #if !defined (HAVE_STRNICMP) && !defined (HAVE_STRNCASECMP) 111 | int strnicmp (const char *string1, const char *string2, size_t count) 112 | { 113 | if (count) 114 | { 115 | int c1, c2; 116 | do 117 | { 118 | c1 = tolower ((unsigned char) (*(string1++))); 119 | c2 = tolower ((unsigned char) (*(string2++))); 120 | } while (--count && c1 && (c1 == c2)); 121 | return (c1 - c2); 122 | } 123 | else 124 | return 0; 125 | } 126 | #endif 127 | 128 | 129 | 130 | //----------------------------------------------------------------------------- 131 | // 132 | // @mfunc STRLWR helper routine 133 | // 134 | // @parm char * | string | Input string 135 | // 136 | // @rdesc Pointer to the string 137 | // 138 | //----------------------------------------------------------------------------- 139 | 140 | #ifndef HAVE_STRLWR 141 | char *strlwr (char *string) 142 | { 143 | char *psz = string; 144 | while (*psz) 145 | { 146 | *psz = (char) tolower (*psz); 147 | ++psz; 148 | } 149 | return psz; 150 | } 151 | #endif 152 | -------------------------------------------------------------------------------- /_NscLib/NwnDoubleLinkList.h: -------------------------------------------------------------------------------- 1 | #ifndef ETS_NWNDOUBLELINKLIST_H 2 | #define ETS_NWNDOUBLELINKLIST_H 3 | 4 | //----------------------------------------------------------------------------- 5 | // 6 | // @doc 7 | // 8 | // @module NwnDoubleLinkList.h - Absolute double link list | 9 | // 10 | // This module contains the definition of an absolute double link list. 11 | // 12 | // Copyright (c) 2002-2003 - Edward T. Smith 13 | // 14 | // All rights reserved. 15 | // 16 | // Redistribution and use in source and binary forms, with or without 17 | // modification, are permitted provided that the following conditions are 18 | // met: 19 | // 20 | // 1. Redistributions of source code must retain the above copyright notice, 21 | // this list of conditions and the following disclaimer. 22 | // 2. Neither the name of Edward T. Smith nor the names of its contributors 23 | // may be used to endorse or promote products derived from this software 24 | // without specific prior written permission. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 32 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | // 38 | // @end 39 | // 40 | // $History: NwnDoubleLinkList.h $ 41 | // 42 | //----------------------------------------------------------------------------- 43 | 44 | //----------------------------------------------------------------------------- 45 | // 46 | // Required include files 47 | // 48 | //----------------------------------------------------------------------------- 49 | 50 | //----------------------------------------------------------------------------- 51 | // 52 | // Forward definitions 53 | // 54 | //----------------------------------------------------------------------------- 55 | 56 | //----------------------------------------------------------------------------- 57 | // 58 | // Class definition 59 | // 60 | //----------------------------------------------------------------------------- 61 | 62 | class CNwnDoubleLinkList 63 | { 64 | 65 | // @access Construction and destruction 66 | public: 67 | 68 | // @cmember General constructor 69 | 70 | CNwnDoubleLinkList () 71 | { 72 | Initialize (); 73 | } 74 | 75 | // @cmember General destructor 76 | 77 | ~CNwnDoubleLinkList () 78 | { 79 | Remove (); 80 | } 81 | 82 | // @access Public methods 83 | public: 84 | 85 | // @cmember Insert a new item after given one 86 | 87 | void InsertAfter (CNwnDoubleLinkList *pLink); 88 | 89 | // @cmember Remove an item from a list 90 | 91 | void Remove (); 92 | 93 | // @access Public inline methods 94 | public: 95 | 96 | // @cmember Initialize 97 | 98 | void Initialize () 99 | { 100 | m_pNext = this; 101 | m_pPrev = this; 102 | } 103 | 104 | // @cmember Insert a new item at tail of list 105 | 106 | void InsertTail (CNwnDoubleLinkList *pLink) 107 | { 108 | InsertAfter (pLink ->m_pPrev); 109 | } 110 | 111 | // @cmember Insert a new item at head of list 112 | 113 | void InsertHead (CNwnDoubleLinkList *pLink) 114 | { 115 | InsertAfter (pLink); 116 | } 117 | 118 | // @cmember Test to see if empty 119 | 120 | bool IsEmpty () const 121 | { 122 | return m_pNext == this; 123 | } 124 | 125 | // @cmember Return the next item 126 | 127 | CNwnDoubleLinkList *GetNext () 128 | { 129 | return m_pNext; 130 | } 131 | 132 | // @cmember Return the next item 133 | 134 | const CNwnDoubleLinkList *GetNext () const 135 | { 136 | return m_pNext; 137 | } 138 | 139 | // @cmember Return prev item in a list 140 | 141 | CNwnDoubleLinkList *GetPrev () 142 | { 143 | return m_pPrev; 144 | } 145 | 146 | // @cmember Return prev item in a list 147 | 148 | const CNwnDoubleLinkList *GetPrev () const 149 | { 150 | return m_pPrev; 151 | } 152 | 153 | // @cmember Private methods 154 | private: 155 | 156 | // @cmember Copy operator 157 | 158 | CNwnDoubleLinkList &operator = (CNwnDoubleLinkList &src); 159 | 160 | // @access Protected members 161 | protected: 162 | 163 | // @cmember Next link in the list 164 | 165 | CNwnDoubleLinkList *m_pNext; 166 | 167 | // @cmember Previous link in the list 168 | 169 | CNwnDoubleLinkList *m_pPrev; 170 | }; 171 | 172 | //----------------------------------------------------------------------------- 173 | // 174 | // @mfunc Insert an item after current list entry 175 | // 176 | // @parm CNwnDoubleLinkList * | pLink | Link to insert after 177 | // 178 | // @rdesc None. 179 | // 180 | //----------------------------------------------------------------------------- 181 | 182 | inline void CNwnDoubleLinkList::InsertAfter (CNwnDoubleLinkList *pLink) 183 | { 184 | 185 | // 186 | // If the list is the same as the chain being deleted, move backwards 187 | // to avoid attaching to a detached chain (don't used the Prev function 188 | // since it will not return the root) 189 | // 190 | 191 | if (pLink == this) 192 | pLink = pLink ->m_pPrev; 193 | 194 | 195 | // 196 | // If the object is currently linked to another chain, 197 | // remove the link from the chain 198 | // 199 | 200 | if (m_pNext != this) 201 | Remove (); 202 | 203 | // 204 | // Get the current next and prev pointer of the list 205 | // 206 | 207 | CNwnDoubleLinkList *pNext = pLink ->m_pNext; 208 | //CNwnDoubleLinkList *pPrev = pLink ->m_pPrev; 209 | 210 | // 211 | // Chain the entries together 212 | // 213 | 214 | m_pNext = pNext; 215 | m_pPrev = pLink; 216 | pLink ->m_pNext = this; 217 | pNext ->m_pPrev = this; 218 | return; 219 | } 220 | 221 | //----------------------------------------------------------------------------- 222 | // 223 | // @mfunc Remove a link from the list 224 | // 225 | // @rdesc None. 226 | // 227 | //----------------------------------------------------------------------------- 228 | 229 | inline void CNwnDoubleLinkList::Remove () 230 | { 231 | 232 | // 233 | // Return if we currently aren't in a link 234 | // 235 | 236 | if (m_pNext == this) 237 | return; 238 | 239 | // 240 | // Get the current next and prev pointer of the list 241 | // 242 | 243 | CNwnDoubleLinkList *pNext = m_pNext; 244 | CNwnDoubleLinkList *pPrev = m_pPrev; 245 | 246 | // 247 | // Unchain the list 248 | // 249 | 250 | pNext ->m_pPrev = pPrev; 251 | pPrev ->m_pNext = pNext; 252 | 253 | // 254 | // Initialize the unlinked item 255 | // 256 | 257 | m_pNext = this; 258 | m_pPrev = this; 259 | return; 260 | } 261 | 262 | #endif // ETS_NWNDOUBLELINKLIST_H 263 | -------------------------------------------------------------------------------- /_NscLib/NwnLoader.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // @doc 4 | // 5 | // @module NwnLoader.cpp - NWN game file loader | 6 | // 7 | // This module contains the definition of the NwnLoader. It provides a 8 | // method of requesting resources from NWN. 9 | // 10 | // Copyright (c) 2002-2003 - Edward T. Smith 11 | // 12 | // All rights reserved. 13 | // 14 | // Redistribution and use in source and binary forms, with or without 15 | // modification, are permitted provided that the following conditions are 16 | // met: 17 | // 18 | // 1. Redistributions of source code must retain the above copyright notice, 19 | // this list of conditions and the following disclaimer. 20 | // 2. Neither the name of Edward T. Smith nor the names of its contributors 21 | // may be used to endorse or promote products derived from this software 22 | // without specific prior written permission. 23 | // 24 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 30 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | // 36 | // @end 37 | // 38 | // $History: CnfMainWnd.h $ 39 | // 40 | //----------------------------------------------------------------------------- 41 | 42 | #include "Precomp.h" 43 | #include "NwnLoader.h" 44 | 45 | //----------------------------------------------------------------------------- 46 | // 47 | // @mfunc constructor. 48 | // 49 | // @rdesc None. 50 | // 51 | //----------------------------------------------------------------------------- 52 | 53 | CNwnLoader::CNwnLoader () 54 | { 55 | } 56 | 57 | //----------------------------------------------------------------------------- 58 | // 59 | // @mfunc denstructor. 60 | // 61 | // @rdesc None. 62 | // 63 | //----------------------------------------------------------------------------- 64 | 65 | CNwnLoader::~CNwnLoader () 66 | { 67 | } 68 | -------------------------------------------------------------------------------- /_NscLib/NwnLoader.h: -------------------------------------------------------------------------------- 1 | #ifndef ETS_NWNLOADER_H 2 | #define ETS_NWNLOADER_H 3 | 4 | //----------------------------------------------------------------------------- 5 | // 6 | // @doc 7 | // 8 | // @module NwnLoader.h - NWN game file loader | 9 | // 10 | // This module contains the definition of the NwnLoader. It provides a 11 | // method of requesting resources from NWN. 12 | // 13 | // Copyright (c) 2002-2003 - Edward T. Smith 14 | // 15 | // All rights reserved. 16 | // 17 | // Redistribution and use in source and binary forms, with or without 18 | // modification, are permitted provided that the following conditions are 19 | // met: 20 | // 21 | // 1. Redistributions of source code must retain the above copyright notice, 22 | // this list of conditions and the following disclaimer. 23 | // 2. Neither the name of Edward T. Smith nor the names of its contributors 24 | // may be used to endorse or promote products derived from this software 25 | // without specific prior written permission. 26 | // 27 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 33 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 34 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | // 39 | // @end 40 | // 41 | // $History: CnfMainWnd.h $ 42 | // 43 | //----------------------------------------------------------------------------- 44 | 45 | //----------------------------------------------------------------------------- 46 | // 47 | // Required include files 48 | // 49 | //----------------------------------------------------------------------------- 50 | 51 | #include "NwnDefines.h" 52 | //#include "../_NwnBaseLib/BaseTypes.h" 53 | 54 | typedef NWN::ResType NwnResType; 55 | 56 | //----------------------------------------------------------------------------- 57 | // 58 | // Forward definitions 59 | // 60 | //----------------------------------------------------------------------------- 61 | 62 | //----------------------------------------------------------------------------- 63 | // 64 | // Class definition 65 | // 66 | //----------------------------------------------------------------------------- 67 | 68 | class CNwnLoader 69 | { 70 | 71 | // @access Constructors and destructors 72 | public: 73 | 74 | // @cmember General constructor 75 | 76 | CNwnLoader (); 77 | 78 | // @cmember Delete the streams 79 | 80 | ~CNwnLoader (); 81 | 82 | // @access Public methods 83 | public: 84 | 85 | // @cmember Load a resource 86 | 87 | virtual unsigned char *LoadResource (const char *pszName, 88 | NwnResType nResType, UINT32 *pulSize, bool *pfAllocated) = 0; 89 | }; 90 | 91 | #endif // ETS_NWNLOADER_H 92 | -------------------------------------------------------------------------------- /_NscLib/NwnStreams.h: -------------------------------------------------------------------------------- 1 | #ifndef ETS_NWNSTREAMS_H 2 | #define ETS_NWNSTREAMS_H 3 | 4 | //----------------------------------------------------------------------------- 5 | // 6 | // @doc 7 | // 8 | // @module NwnStreams.h - Stream support for general IO | 9 | // 10 | // This module contains the definition of the NwnStreams. 11 | // 12 | // Copyright (c) 2002-2003 - Edward T. Smith 13 | // 14 | // All rights reserved. 15 | // 16 | // Redistribution and use in source and binary forms, with or without 17 | // modification, are permitted provided that the following conditions are 18 | // met: 19 | // 20 | // 1. Redistributions of source code must retain the above copyright notice, 21 | // this list of conditions and the following disclaimer. 22 | // 2. Neither the name of Edward T. Smith nor the names of its contributors 23 | // may be used to endorse or promote products derived from this software 24 | // without specific prior written permission. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 32 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | // 38 | // @end 39 | // 40 | // $History: CnfMainWnd.h $ 41 | // 42 | //----------------------------------------------------------------------------- 43 | 44 | //----------------------------------------------------------------------------- 45 | // 46 | // Required include files 47 | // 48 | //----------------------------------------------------------------------------- 49 | 50 | #ifdef _MSC_VER 51 | #pragma warning(push) 52 | #pragma warning(disable:4296) // C4296: '<': expression is always false 53 | #endif 54 | 55 | //----------------------------------------------------------------------------- 56 | // 57 | // Forward definitions 58 | // 59 | //----------------------------------------------------------------------------- 60 | 61 | //----------------------------------------------------------------------------- 62 | // 63 | // Class definition 64 | // 65 | //----------------------------------------------------------------------------- 66 | 67 | class CNwnStream 68 | { 69 | // Public enumerations 70 | public: 71 | 72 | enum SeekPosition 73 | { 74 | begin = 0, 75 | end = 1, 76 | current = 2, 77 | }; 78 | 79 | // @access Constructors and destructors 80 | public: 81 | 82 | // @cmember Destructor 83 | 84 | virtual ~CNwnStream () 85 | { 86 | } 87 | 88 | // @access Public input routines 89 | public: 90 | 91 | // @cmember Read data from the input 92 | 93 | virtual size_t Read (void *pBuffer, size_t nCount) = 0; 94 | 95 | // @cmember Read a line from the input 96 | 97 | virtual char *ReadLine (char *pachBuffer, size_t nCount) = 0; 98 | 99 | // @access Public output routines 100 | public: 101 | 102 | // @cmember Flush any data to the output 103 | 104 | virtual bool Flush () = 0; 105 | 106 | // @cmember Write data to the output 107 | 108 | virtual size_t Write (void *pBuffer, size_t nCount) = 0; 109 | 110 | // @cmember Write a line to the output 111 | 112 | virtual size_t WriteLine (const char *pszBuffer, bool fAppendCRLF = true) = 0; 113 | 114 | // @access Public general routines 115 | public: 116 | 117 | // @cmember Get the length of the file 118 | 119 | virtual size_t GetLength () = 0; 120 | 121 | // @cmember Seek file position 122 | 123 | virtual size_t Seek (size_t nPosition, SeekPosition nStart) = 0; 124 | 125 | // @cmember Seek from beginning 126 | 127 | virtual size_t SeekFromBegining (size_t nPosition) 128 | { 129 | return Seek (nPosition, begin); 130 | } 131 | 132 | // @cmember Seek from end 133 | 134 | virtual size_t SeekFromEnd (size_t nPosition) 135 | { 136 | return Seek (nPosition, end); 137 | } 138 | 139 | // @cmember Seek from current 140 | 141 | virtual size_t SeekFromCurrent (size_t nPosition) 142 | { 143 | return Seek (nPosition, current); 144 | } 145 | 146 | // @cmember Get current position 147 | 148 | virtual size_t GetPosition () = 0; 149 | 150 | // @cmember Get the file name 151 | 152 | virtual const char *GetFileName () = 0; 153 | 154 | // @cmember Test for end of file 155 | 156 | virtual bool IsEndOfFile () const = 0; 157 | }; 158 | 159 | //----------------------------------------------------------------------------- 160 | // 161 | // Class definition 162 | // 163 | //----------------------------------------------------------------------------- 164 | 165 | class CNwnMemoryStream : public CNwnStream 166 | { 167 | // @access Constructors and destructors 168 | public: 169 | 170 | // @cmember Constructor 171 | 172 | CNwnMemoryStream () 173 | { 174 | m_pauchStart = NULL; 175 | m_pauchPos = NULL; 176 | m_pauchEnd = NULL; 177 | m_pauchAllocEnd = NULL; 178 | m_fManaged = true; 179 | } 180 | 181 | // @cmember Constructor 182 | 183 | CNwnMemoryStream (const char *pszFileName, unsigned char *pauchData, 184 | size_t nSize, bool fManaged = true) 185 | { 186 | m_strFileName = pszFileName; 187 | m_pauchStart = pauchData; 188 | m_pauchPos = pauchData; 189 | m_pauchEnd = &pauchData [nSize]; 190 | m_pauchAllocEnd = m_pauchEnd; 191 | m_fManaged = fManaged; 192 | } 193 | 194 | // @cmember Destructor 195 | 196 | virtual ~CNwnMemoryStream () 197 | { 198 | if (m_pauchStart && m_fManaged) 199 | free (m_pauchStart); 200 | } 201 | 202 | // @access Other routines 203 | public: 204 | 205 | // @cmember Get the data of the stream 206 | 207 | unsigned char *GetData () 208 | { 209 | return m_pauchStart; 210 | } 211 | 212 | // @access Public input routines 213 | public: 214 | 215 | // @cmember Read data from the input 216 | 217 | virtual size_t Read (void *pBuffer, size_t nCount) 218 | { 219 | size_t nRemaining = m_pauchEnd - m_pauchPos; 220 | if (nRemaining < nCount) 221 | nCount = nRemaining; 222 | memcpy (pBuffer, m_pauchPos, nCount); 223 | m_pauchPos += nCount; 224 | return nCount; 225 | } 226 | 227 | // @cmember Read a line from the input 228 | 229 | virtual char *ReadLine (char *pachBuffer, size_t nCount) 230 | { 231 | char *pachOut = pachBuffer; 232 | while (--nCount > 0 && m_pauchPos < m_pauchEnd) 233 | { 234 | unsigned char c = *m_pauchPos++; 235 | *pachOut++ = (char) c; 236 | if (c == '\n') 237 | break; 238 | } 239 | *pachOut = 0; 240 | return pachOut == pachBuffer ? NULL : pachBuffer; 241 | } 242 | 243 | // @access Public output routines 244 | public: 245 | 246 | // @cmember Flush any data to the output 247 | 248 | virtual bool Flush () 249 | { 250 | return true; 251 | } 252 | 253 | // @cmember Write data to the output 254 | 255 | virtual size_t Write (void *pBuffer, size_t nCount) 256 | { 257 | if(!WriteMakeRoom (nCount)) 258 | return 0; 259 | memcpy (m_pauchPos, pBuffer, nCount); 260 | m_pauchPos += nCount; 261 | if (m_pauchPos > m_pauchEnd) 262 | m_pauchEnd = m_pauchPos; 263 | return nCount; 264 | } 265 | 266 | // @cmember Write a line to the output 267 | 268 | virtual size_t WriteLine (const char *pszBuffer, bool fAppendCRLF = true) 269 | { 270 | 271 | // 272 | // Compute the amount of space we need 273 | // 274 | 275 | if (pszBuffer == NULL) 276 | pszBuffer = ""; 277 | size_t nStringCount = strlen (pszBuffer); 278 | size_t nCount = nStringCount; 279 | if (fAppendCRLF) 280 | nCount += 2; 281 | 282 | // 283 | // Make sure we have the room 284 | // 285 | 286 | if (!WriteMakeRoom (nCount)) 287 | return 0; 288 | 289 | // 290 | // Write the data 291 | // 292 | 293 | memmove (m_pauchPos, pszBuffer, nStringCount); 294 | m_pauchPos += nStringCount; 295 | if (fAppendCRLF) 296 | { 297 | *m_pauchPos++ = '\r'; 298 | *m_pauchPos++ = '\n'; 299 | } 300 | if (m_pauchPos > m_pauchEnd) 301 | m_pauchEnd = m_pauchPos; 302 | return nCount; 303 | } 304 | 305 | // @access Public general routines 306 | public: 307 | 308 | // @cmember Get the length of the file 309 | 310 | virtual size_t GetLength () 311 | { 312 | return m_pauchEnd - m_pauchStart; 313 | } 314 | 315 | // @cmember Seek file position 316 | 317 | virtual size_t Seek (size_t nPosition, SeekPosition nStart) 318 | { 319 | if (nStart == current) 320 | nPosition += GetPosition (); 321 | else if (nStart == end) 322 | nPosition = GetLength () - nPosition; 323 | 324 | if (nPosition < 0) 325 | nPosition = 0; 326 | else if (nPosition > GetLength ()) 327 | nPosition = GetLength (); 328 | m_pauchPos = &m_pauchStart [nPosition]; 329 | return GetPosition (); 330 | } 331 | 332 | // @cmember Get current position 333 | 334 | virtual size_t GetPosition () 335 | { 336 | return m_pauchPos - m_pauchStart; 337 | } 338 | 339 | // @cmember Get the file name 340 | 341 | virtual const char *GetFileName () 342 | { 343 | return m_strFileName .c_str (); 344 | } 345 | 346 | // @cmember Test for end of file 347 | 348 | virtual bool IsEndOfFile () const 349 | { 350 | return m_pauchPos >= m_pauchEnd; 351 | } 352 | 353 | // @access Protected methods 354 | protected: 355 | 356 | // @cmember Make sure we have room 357 | 358 | bool WriteMakeRoom (size_t nCount) 359 | { 360 | static const int nBlockSize = 0x10000; 361 | if (nCount < 0) 362 | return false; 363 | if (nCount == 0) 364 | return true; 365 | if (m_pauchPos + nCount > m_pauchAllocEnd) 366 | { 367 | size_t nOffset = m_pauchPos - m_pauchStart; 368 | size_t nUsed = m_pauchEnd - m_pauchStart; 369 | size_t nBlocks = (nOffset + nCount + nBlockSize - 1) / nBlockSize; 370 | size_t nNewSize = nBlocks * nBlockSize; 371 | unsigned char *pauchNew = (unsigned char *) malloc (nNewSize); 372 | if (pauchNew == NULL) 373 | return false; 374 | memmove (pauchNew, m_pauchStart, m_pauchEnd - m_pauchStart); 375 | if (m_pauchStart != NULL && m_fManaged) 376 | free (m_pauchStart); 377 | m_pauchStart = pauchNew; 378 | m_pauchAllocEnd = &m_pauchStart [nNewSize]; 379 | m_pauchEnd = &m_pauchStart [nUsed]; 380 | m_pauchPos = &m_pauchStart [nOffset]; 381 | m_fManaged = true; 382 | } 383 | return true; 384 | } 385 | 386 | // @access Protected variables 387 | protected: 388 | 389 | // @cmember File name 390 | 391 | std::string m_strFileName; 392 | 393 | // @cmember Pointer to the buffer start 394 | 395 | unsigned char *m_pauchStart; 396 | 397 | // @cmember Pointer to the current position 398 | 399 | unsigned char *m_pauchPos; 400 | 401 | // @cmember Pointer to the end position 402 | 403 | unsigned char *m_pauchEnd; 404 | 405 | // @cmember Pointer to the end of the allocated data 406 | 407 | unsigned char *m_pauchAllocEnd; 408 | 409 | // @cmember If true, we own the memory 410 | 411 | bool m_fManaged; 412 | }; 413 | 414 | #ifdef _MSC_VER 415 | #pragma warning(pop) 416 | #endif 417 | 418 | #endif // ETS_NWNSTREAMS_H 419 | -------------------------------------------------------------------------------- /_NscLib/Precomp.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | precomp.h 8 | 9 | Abstract: 10 | 11 | This module acts as the precompiled header that pulls in all common 12 | dependencies that typically do not change. 13 | 14 | --*/ 15 | 16 | #ifndef _PROGRAMS_NWNSCRIPTCOMPILERLIB_PRECOMP_H 17 | #define _PROGRAMS_NWNSCRIPTCOMPILERLIB_PRECOMP_H 18 | 19 | #ifdef _MSC_VER 20 | #pragma once 21 | #endif 22 | 23 | #define _CRT_SECURE_NO_DEPRECATE 24 | #define _CRT_SECURE_NO_DEPRECATE_GLOBALS 25 | #define STRSAFE_NO_DEPRECATE 26 | 27 | #if defined(_WINDOWS) 28 | 29 | //#include 30 | //#include 31 | #else 32 | #include 33 | #endif 34 | 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | 48 | #ifdef ENCRYPT 49 | #include 50 | #endif 51 | 52 | #if defined(_WINDOWS) 53 | #include 54 | #include 55 | 56 | #include 57 | #include 58 | #endif 59 | 60 | #include "../_NwnUtilLib/ProjGlobalDefs.h" 61 | #include "../_NwnUtilLib/NWNUtilLib.h" 62 | #include "../_NwnBaseLib/NWNBaseLib.h" 63 | #include "../_NwnDataLib/NWNDataLib.h" 64 | 65 | #undef assert 66 | #define assert NWN_ASSERT 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /_NwnBaseLib/BaseTypes.cpp: -------------------------------------------------------------------------------- 1 | #include "BaseTypes.h" 2 | 3 | const NWN::Matrix44 NWN::Matrix44::IDENTITY = 4 | { 5 | 1.0f, 0.0f, 0.0f, 0.0f , 6 | 0.0f, 1.0f, 0.0f, 0.0f , 7 | 0.0f, 0.0f, 1.0f, 0.0f , 8 | 0.0f, 0.0f, 0.0f, 1.0f 9 | }; 10 | 11 | const NWN::Matrix33 NWN::Matrix33::IDENTITY = 12 | { 13 | 1.0f, 0.0f, 0.0f, 14 | 0.0f, 1.0f, 0.0f, 15 | 0.0f, 0.0f, 1.0f 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /_NwnBaseLib/BaseTypes.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | BaseTypes.h 8 | 9 | Abstract: 10 | 11 | This module defines the base types used in the NWN game system and which are 12 | used in data files and over the network as basic components for composite 13 | structures. 14 | 15 | --*/ 16 | 17 | #ifndef _SOURCE_PROGRAMS_NWNBASELIB_BASETYPES_H 18 | #define _SOURCE_PROGRAMS_NWNBASELIB_BASETYPES_H 19 | 20 | #include 21 | #include "../_NwnUtilLib/OsCompat.h" 22 | 23 | #ifdef _MSC_VER 24 | #pragma once 25 | #endif 26 | 27 | #ifdef _WIN32 28 | #include 29 | #endif 30 | 31 | namespace NWN 32 | { 33 | // 34 | // Define game object ids and player ids. 35 | // 36 | 37 | typedef unsigned long OBJECTID; 38 | typedef unsigned long PLAYERID; 39 | 40 | // 41 | // Define the resource type code and associated resource type IDs. 42 | // These type IDs are assigned by BioWare and come from the BioWare 43 | // Aurora engine documentation as well as NWN2 game files. 44 | // 45 | 46 | typedef unsigned short ResType; 47 | 48 | static const ResType ResRES = 0; 49 | static const ResType ResBMP = 1; 50 | static const ResType ResTGA = 3; 51 | static const ResType ResWAV = 4; 52 | static const ResType ResPLT = 6; 53 | static const ResType ResINI = 7; 54 | static const ResType ResBMU = 8; 55 | static const ResType ResTXT = 10; 56 | static const ResType ResMDL = 2002; 57 | static const ResType ResNSS = 2009; 58 | static const ResType ResNCS = 2010; 59 | static const ResType ResARE = 2012; 60 | static const ResType ResSET = 2013; 61 | static const ResType ResIFO = 2014; 62 | static const ResType ResBIC = 2015; 63 | static const ResType ResWOK = 2016; 64 | static const ResType Res2DA = 2017; 65 | static const ResType ResTXI = 2022; 66 | static const ResType ResGIT = 2023; 67 | static const ResType ResUTI = 2025; 68 | static const ResType ResUTC = 2027; 69 | static const ResType ResDLG = 2029; 70 | static const ResType ResITP = 2030; 71 | static const ResType ResUTT = 2032; 72 | static const ResType ResDDS = 2033; 73 | static const ResType ResUTS = 2035; 74 | static const ResType ResLTR = 2036; 75 | static const ResType ResGFF = 2037; 76 | static const ResType ResFAC = 2038; 77 | static const ResType ResUTE = 2040; 78 | static const ResType ResUTD = 2042; 79 | static const ResType ResUTP = 2044; 80 | static const ResType ResDFT = 2045; 81 | static const ResType ResGIC = 2046; 82 | static const ResType ResGUI = 2047; 83 | static const ResType ResUTM = 2051; 84 | static const ResType ResDWK = 2052; 85 | static const ResType ResPWK = 2053; 86 | static const ResType ResJRL = 2056; 87 | static const ResType ResUTW = 2058; 88 | static const ResType ResSSF = 2060; 89 | static const ResType ResNDB = 2064; 90 | static const ResType ResPTM = 2065; 91 | static const ResType ResPTT = 2066; 92 | static const ResType ResUSC = 3001; 93 | static const ResType ResTRN = 3002; 94 | static const ResType ResUTR = 3003; 95 | static const ResType ResUEN = 3004; 96 | static const ResType ResULT = 3005; 97 | static const ResType ResSEF = 3006; 98 | static const ResType ResPFX = 3007; 99 | static const ResType ResCAM = 3008; 100 | static const ResType ResUPE = 3011; 101 | static const ResType ResPFB = 3015; 102 | static const ResType ResBBX = 3018; 103 | static const ResType ResWLK = 3020; 104 | static const ResType ResXML = 3021; 105 | static const ResType ResTRX = 3035; 106 | static const ResType ResTRn = 3036; 107 | static const ResType ResTRx = 3037; 108 | 109 | static const ResType ResMDB = 4000; 110 | static const ResType ResSPT = 4002; 111 | static const ResType ResGR2 = 4003; 112 | static const ResType ResFXA = 4004; 113 | static const ResType ResFXE = 4005; 114 | static const ResType ResJPG = 4007; 115 | static const ResType ResPWC = 4008; 116 | 117 | static const ResType ResINVALID = 0xFFFF; 118 | 119 | // 120 | // Define 32-byte and 16-byte RESREFs. NWN1 uses 16-byte RESREFs, whereas 121 | // NWN2 uses 32-byte RESREFs. 122 | // 123 | 124 | struct ResRef32 125 | { 126 | char RefStr[ 32 ]; 127 | }; 128 | 129 | struct ResRef16 130 | { 131 | char RefStr[ 16 ]; 132 | }; 133 | 134 | // 135 | // Define the on-network format of a localizable string which may contain 136 | // either a raw string or a STRREF. 137 | // 138 | 139 | struct ExoLocString 140 | { 141 | bool IsStrRef; 142 | std::string String; 143 | bool Flag; 144 | ULONG StrRef; 145 | }; 146 | 147 | // 148 | // Define the on-network format of a 3-tuple of floats typically, though not 149 | // always, used to represent three spatial coordinates. 150 | // 151 | 152 | struct Vector3 153 | { 154 | float x; 155 | float y; 156 | float z; 157 | }; 158 | 159 | // 160 | // Define the on-network format of a 2-tuple of floats typically, though not 161 | // always, used to represent two spatial coordinates. 162 | // 163 | 164 | struct Vector2 165 | { 166 | float x; 167 | float y; 168 | }; 169 | 170 | // 171 | // Define a 4x4 matrix (raw data only). 172 | // 173 | 174 | struct Matrix44 175 | { 176 | float _00; 177 | float _01; 178 | float _02; 179 | float _03; 180 | float _10; 181 | float _11; 182 | float _12; 183 | float _13; 184 | float _20; 185 | float _21; 186 | float _22; 187 | float _23; 188 | float _30; 189 | float _31; 190 | float _32; 191 | float _33; 192 | 193 | const static Matrix44 IDENTITY; 194 | }; 195 | 196 | // 197 | // Define a 3x3 matrix (raw data only). 198 | // 199 | 200 | struct Matrix33 201 | { 202 | float _00; 203 | float _01; 204 | float _02; 205 | float _10; 206 | float _11; 207 | float _12; 208 | float _20; 209 | float _21; 210 | float _22; 211 | 212 | const static Matrix33 IDENTITY; 213 | }; 214 | 215 | // 216 | // Define the wire format of a Quaternion. 217 | // 218 | 219 | struct Quaternion 220 | { 221 | float x; 222 | float y; 223 | float z; 224 | float w; 225 | }; 226 | 227 | // 228 | // Define simple float-based rectangle and triangle types. 229 | // 230 | 231 | struct Rect 232 | { 233 | float left; 234 | float top; 235 | float right; 236 | float bottom; 237 | }; 238 | 239 | struct Triangle 240 | { 241 | NWN::Vector2 points[ 3 ]; 242 | }; 243 | 244 | // 245 | // Define the on-network representation of color values (range 0.0f..1.0f). 246 | // 247 | 248 | struct NWNCOLOR // D3DXCOLOR 249 | { 250 | float r; 251 | float g; 252 | float b; 253 | float a; 254 | }; 255 | 256 | // 257 | // Define the on-network representation of alphaless color value (range 258 | // 0.0f..1.0f). 259 | // 260 | 261 | struct NWNRGB 262 | { 263 | float r; 264 | float g; 265 | float b; 266 | }; 267 | 268 | // 269 | // Define scroll parameters for a UVScroll property as represented over the 270 | // network. 271 | // 272 | 273 | struct NWN2_UVScrollSet 274 | { 275 | bool Scroll; 276 | float U; 277 | float V; 278 | }; 279 | 280 | // 281 | // Define tint parameters for a TintSet property as represented over the 282 | // network. 283 | // 284 | 285 | struct NWN2_TintSet 286 | { 287 | NWNCOLOR Colors[ 3 ]; 288 | }; 289 | 290 | // 291 | // Armor accessory set and associated components. 292 | // 293 | 294 | struct NWN2_ArmorAccessory 295 | { 296 | unsigned char Variation; 297 | NWN2_TintSet Tint; 298 | NWN2_UVScrollSet UVScroll; 299 | }; 300 | 301 | struct NWN2_ArmorPiece 302 | { 303 | unsigned char Variation; 304 | unsigned char VisualType; 305 | NWN2_TintSet Tint; 306 | }; 307 | 308 | // 309 | // N.B. Class layout is assumed such that the armor piece header comes 310 | // before the accessory parameter block. 311 | // 312 | 313 | struct NWN2_ArmorPieceWithAccessories : public NWN2_ArmorPiece 314 | { 315 | // 316 | // N.B. Accessories indexed by NWN2_Accessory. 317 | // 318 | 319 | NWN2_ArmorAccessory Accessories[ 22 ]; 320 | }; 321 | 322 | // 323 | // Define the base armor accessory set, which represents the visual 324 | // parameters for an item (model variation ids, visual types, flags for 325 | // whether certain model pieces are present in the model, as well as 326 | // tinting parameters). 327 | 328 | struct NWN2_ArmorAccessorySet 329 | { 330 | NWN2_ArmorPieceWithAccessories Chest; 331 | NWN2_ArmorPiece Helm; 332 | NWN2_ArmorPiece Gloves; 333 | NWN2_ArmorPiece Boots; 334 | NWN2_ArmorPiece Belt; 335 | NWN2_ArmorPiece Cloak; 336 | unsigned char HasHelm; 337 | unsigned char HasGloves; 338 | unsigned char HasBoots; 339 | unsigned char HasBelt; 340 | unsigned char HasCloak; 341 | }; 342 | 343 | // 344 | // Item property data. 345 | // 346 | 347 | struct NWItemProperty 348 | { 349 | unsigned short PropertyName; 350 | unsigned short SubType; 351 | unsigned short CostTableValue; 352 | unsigned char ChanceOfAppearing; 353 | }; 354 | 355 | // 356 | // Location data. 357 | // 358 | 359 | struct ObjectLocation 360 | { 361 | NWN::OBJECTID Area; 362 | NWN::Vector3 Orientation; 363 | NWN::Vector3 Position; 364 | }; 365 | 366 | struct NWN2_LightIntensityPair 367 | { 368 | NWN::NWNCOLOR DiffuseColor; 369 | NWN::NWNCOLOR SpecularColor; 370 | NWN::NWNCOLOR AmbientColor; 371 | float Intensity; 372 | }; 373 | 374 | } 375 | 376 | #endif 377 | 378 | -------------------------------------------------------------------------------- /_NwnBaseLib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(nwnbaselib 2 | BaseConstants.h 3 | BaseTypes.cpp 4 | BaseTypes.h 5 | ModelSystem.h 6 | NWNBaseLib.h 7 | ) -------------------------------------------------------------------------------- /_NwnBaseLib/ModelSystem.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | ModelSystem.h 8 | 9 | Abstract: 10 | 11 | This model defines types and constants used in the model system. 12 | 13 | --*/ 14 | 15 | #ifndef _SOURCE_PROGRAMS_NWNBASELIB_MODELSYSTEM_H 16 | #define _SOURCE_PROGRAMS_NWNBASELIB_MODELSYSTEM_H 17 | 18 | #ifdef _MSC_VER 19 | #pragma once 20 | #endif 21 | 22 | namespace NWN 23 | { 24 | 25 | // 26 | // Item model type enumeration, used to select which model type was 27 | // referenced in a message as well as identify how the model is 28 | // built. 29 | // 30 | 31 | enum NWN2_ItemModelType 32 | { 33 | CNWITEM_MODEL_TYPE_SIMPLE = 0, 34 | CNWITEM_MODEL_TYPE_LAYERED = 1, 35 | CNWITEM_MODEL_TYPE_COMPOSITE = 2, 36 | CNWITEM_MODEL_TYPE_ARMOR = 3, 37 | 38 | LAST_CNWITEM_MODEL_TYPE 39 | }; 40 | 41 | // 42 | // Define the creature model type parameter. Currently, only CMT_DEFAULT 43 | // and CMT_HEAD_AND_BODY are used. CMT_DEFAULT models have only one 44 | // component model, which CMT_HEAD_AND_BODY models have separate head and 45 | // body models (and allow armor sets), with fixed skeleton indicies for 46 | // head, cloak, and tail. 47 | // 48 | // CMT_SEGMENT models allow an unstructured set of skeletons and models to 49 | // be glued together; this feature is not implemented here (though it 50 | // appears to be present and unused in the stock client). 51 | // 52 | 53 | enum NWN2_CreatureModelType 54 | { 55 | CMT_DEFAULT = 0, 56 | CMT_HEAD_AND_BODY = 1, 57 | CMT_SEGMENT = 2, 58 | 59 | LAST_CMT 60 | }; 61 | 62 | // 63 | // Define placeable model types. 64 | // 65 | // Currently, PMT_ALLRIGID (no skeleton) and PMT_RIGIDWITHSKELETON (one 66 | // skeleton) are the only placeable model types used. 67 | // 68 | // N.B. Placeable-like objects (environmentals, doors, etc) inherit the 69 | // same PMT_* type codes. 70 | // 71 | 72 | enum NWN2_PlaceableModelType 73 | { 74 | PMT_ALLRIGID = 0, 75 | PMT_SKINNED = 1, 76 | PMT_RIGIDWITHSKELETON = 2, 77 | 78 | LAST_PMT 79 | }; 80 | 81 | // 82 | // Define body piece indicies into the model. 83 | // 84 | // For a CMT_DEFAULT model, only the BPS_BODY piece is used. 85 | // 86 | // For a CMT_HEAD_AND_BODY model, each piece has a specific meaning 87 | // according to the below type enumeration. 88 | // 89 | // For a CMT_SEGMENTED model, BPS_MAX pieces may be present in an 90 | // unstructured form with no particular meaning assigned to any piece in 91 | // question. 92 | // 93 | 94 | enum NWN2_BodyPieceSlot 95 | { 96 | BPS_BODY = 0, 97 | BPS_HEAD = 1, 98 | BPS_HELM = 2, 99 | BPS_CHEST = 3, 100 | BPS_CLOAK = 4, 101 | BPS_WING = 5, 102 | BPS_TAIL = 6, 103 | BPS_BELT = 7, 104 | BPS_SKIRT = 8, 105 | BPS_FEET = 9, 106 | BPS_GLOVES = 10, 107 | BPS_LEFT_SHOULDER_ACCESSORY = 11, 108 | BPS_RIGHT_SHOULDER_ACCESSORY = 12, 109 | BPS_LEFT_BRACER_ACCESSORY = 13, 110 | BPS_RIGHT_BRACER_ACCESSORY = 14, 111 | BPS_LEFT_ELBOW_ACCESSORY = 15, 112 | BPS_RIGHT_ELBOW_ACCESSORY = 16, 113 | BPS_LEFT_ARM_ACCESSORY = 17, 114 | BPS_RIGHT_ARM_ACCESSORY = 18, 115 | BPS_LEFT_HIP_ACCESSORY = 19, 116 | BPS_RIGHT_HIP_ACCESSORY = 20, 117 | BPS_FRONT_HIP_ACCESSORY = 21, 118 | BPS_BACK_HIP_ACCESSORY = 22, 119 | BPS_LEFT_LEG_ACCESSORY = 23, 120 | BPS_RIGHT_LEG_ACCESSORY = 24, 121 | BPS_LEFT_SHIN_ACCESSORY = 25, 122 | BPS_RIGHT_SHIN_ACCESSORY = 26, 123 | BPS_LEFT_KNEE_ACCESSORY = 27, 124 | BPS_RIGHT_KNEE_ACCESSORY = 28, 125 | BPS_LEFT_FOOT_ACCESSORY = 29, 126 | BPS_RIGHT_FOOT_ACCESSORY = 30, 127 | BPS_LEFT_ANKLE_ACCESSORY = 31, 128 | BPS_RIGHT_ANKLE_ACCESSORY = 32, 129 | BPS_EYES = 33, 130 | BPS_HAIR = 34, 131 | BPS_FACIAL_HAIR = 35, 132 | BPS_EXTRA_A = 36, 133 | BPS_EXTRA_B = 37, 134 | BPS_EXTRA_C = 38, 135 | 136 | BPS_MAX, 137 | 138 | BPS_DEFAULT = BPS_BODY 139 | }; 140 | 141 | // 142 | // Define accessory indicies into the armor set. This enumeration indexes 143 | // the Accessories array of an NWN2_ArmorPieceWithAccessories. 144 | // 145 | 146 | enum NWN2_Accessory 147 | { 148 | Accessory_LShoulder = 0, 149 | Accessory_RShoulder, 150 | Accessory_LBracer, 151 | Accessory_RBracer, 152 | Accessory_LElbow, 153 | Accessory_RElbow, 154 | Accessory_LUpArm, 155 | Accessory_RUpArm, 156 | Accessory_LHip, 157 | Accessory_RHip, 158 | Accessory_FHip, 159 | Accessory_BHip, 160 | Accessory_LUpLeg, 161 | Accessory_RUpLeg, 162 | Accessory_LLowLeg, 163 | Accessory_RLowLeg, 164 | Accessory_LKnee, 165 | Accessory_RKnee, 166 | Accessory_LFoot, 167 | Accessory_RFoot, 168 | Accessory_LAnkle, 169 | Accessory_RAnkle, 170 | 171 | Num_Accessories 172 | }; 173 | 174 | // 175 | // Animation system parameters. 176 | // 177 | 178 | enum NWN2_AnimationStance 179 | { 180 | ANIMSTANCE_NONE = 0, 181 | ANIMSTANCE_UNA = 1, 182 | ANIMSTANCE_1HSS = 2, 183 | ANIMSTANCE_1HS = 3, 184 | ANIMSTANCE_DHS = 4, 185 | ANIMSTANCE_BOW = 5, 186 | ANIMSTANCE_C2H = 6, 187 | ANIMSTANCE_O2HT = 7, 188 | ANIMSTANCE_O2HS = 8, 189 | ANIMSTANCE_CBOW = 9, 190 | ANIMSTANCE_THRW = 10, 191 | ANIMSTANCE_M1HSS = 11, 192 | ANIMSTANCE_M1HLS = 12, 193 | ANIMSTANCE_MBOW = 13, 194 | ANIMSTANCE_MUNA = 14, 195 | 196 | ANIMSTANCE_END = 15 197 | }; 198 | 199 | // 200 | // Define the animatable slots present in a model (a.k.a. skeleton slots). 201 | // 202 | // For a CMT_HEAD_AND_BODY model, the animatable indicies below are used 203 | // and taken to have specific well-defined meanings. 204 | // 205 | // For a CMT_SEGMENTED model, up to 4 animatables may be attached to a model 206 | // with no particular meaning assigned to each animatable (skeleton). 207 | // 208 | 209 | enum NWN2_AnimatableSlot 210 | { 211 | AS_BASE = 0, 212 | AS_CLOAK = 1, 213 | AS_WING = 2, 214 | AS_TAIL = 3, 215 | 216 | AS_HEAD = 4, // XXX: New enum, really the right spot for this? 217 | 218 | AS_MAX, 219 | 220 | AS_DEFAULT = AS_BASE 221 | }; 222 | 223 | // 224 | // VFX system parameters. 225 | // 226 | 227 | enum NWN2_GameModelEffectType 228 | { 229 | GMET_INVALID = 0, 230 | GMET_TEXTURE_SWAP_DIFFUSE = 1, 231 | GMET_TEXTURE_SWAP_NORMAL = 2, 232 | GMET_TEXTURE_SWAP_TINT = 3, 233 | GMET_TEXTURE_SWAP_GLOW = 4, 234 | GMET_SKIN_TINT_COLOR = 5, 235 | GMET_ALPHA = 6, 236 | GMET_LIGHT = 7, 237 | 238 | LAST_GMET 239 | }; 240 | 241 | enum NWN2_GameModelEffectPriority 242 | { 243 | GMEP_DEFAULT = 0, 244 | GMEP_SPECIAL_EFFECT = 1, 245 | GMEP_PERCEPTION_INDICATOR = 2, 246 | 247 | LAST_GMEP 248 | }; 249 | 250 | enum NWN2_SpecialEffectType 251 | { 252 | SPECIALEFFECT_TYPE_NONE = 0, 253 | SPECIALEFFECT_TYPE_PARTICLE_EMITTER = 1, 254 | SPECIALEFFECT_TYPE_PARTICLE_MESH = 2, 255 | SPECIALEFFECT_TYPE_LIGHTNING = 3, 256 | SPECIALEFFECT_TYPE_BEAM = 4, 257 | SPECIALEFFECT_TYPE_LINE_PARTICLE_EMITTER = 5, 258 | SPECIALEFFECT_TYPE_BILLBOARD = 6, 259 | SPECIALEFFECT_TYPE_MODEL = 7, 260 | SPECIALEFFECT_TYPE_SOUND = 8, 261 | SPECIALEFFECT_TYPE_TRAIL = 9, 262 | SPECIALEFFECT_TYPE_PROJECTED_TEXTURE = 10, 263 | SPECIALEFFECT_TYPE_LIGHT = 11, 264 | SPECIALEFFECT_TYPE_GAME_MODEL_EFFECT = 12, 265 | 266 | SPECIALEFFECT_TYPE_TOTAL 267 | 268 | }; 269 | 270 | // 271 | // Define armor piece slot indicies for CMT_HEAD_AND_BODY models. 272 | // 273 | 274 | enum NWN2_ArmorPieceSlot 275 | { 276 | ArmorPieceSlotBody, 277 | ArmorPieceSlotHelm, 278 | ArmorPieceSlotGloves, 279 | ArmorPieceSlotBoots, 280 | ArmorPieceSlotBelt, 281 | ArmorPieceSlotExtraA, 282 | ArmorPieceSlotExtraB, 283 | ArmorPieceSlotExtraC, 284 | 285 | ArmorPieceSlotCloak, // XXX: New enum, really the right spot for this? 286 | 287 | Num_ArmorPieceSlots 288 | }; 289 | 290 | // 291 | // MDB Hair shortening types. 292 | // 293 | 294 | typedef enum _MDB_HAIR_SHORTENING_BEHAVIOR 295 | { 296 | HSB_LOW = 0, 297 | HSB_SHORT = 1, 298 | HSB_PONYTAIL = 2, 299 | 300 | HSB_NORMAL = 3, // XXX: New 301 | 302 | LAST_HSB, 303 | 304 | LAST_HSB_FILE = HSB_NORMAL 305 | } MDB_HAIR_SHORTENING_BEHAVIOR; 306 | 307 | typedef const enum _MDB_HAIR_SHORTENING_BEHAVIOR * PCMDB_HAIR_SHORTENING_BEHAVIOR; 308 | 309 | // 310 | // MDB Helm/Hair hiding behavior. 311 | // 312 | 313 | typedef enum _MDB_HELM_HAIR_HIDING_BEHAVIOR 314 | { 315 | HHHB_NONE_HIDDEN = 0, 316 | HHHB_HAIR_HIDDEN = 1, 317 | HHHB_PARTIAL_HAIR = 2, 318 | HHHB_HEAD_HIDDEN = 3, 319 | 320 | LAST_HHHB 321 | } MDB_HELM_HAIR_HIDING_BEHAVIOR, * PMDB_HELM_HAIR_HIDING_BEHAVIOR; 322 | 323 | typedef const enum _MDB_HELM_HAIR_HIDING_BEHAVIOR * PCMDB_HELM_HAIR_HIDING_BEHAVIOR; 324 | 325 | // 326 | // Define day/night staging data for the sky modeling system. 327 | // 328 | 329 | typedef enum _DAY_NIGHT_STATE 330 | { 331 | DayNightStateDay = 1, 332 | DayNightStateNight = 2, 333 | DayNightStateDawn = 3, 334 | DayNightStateDusk = 4, 335 | 336 | LastDayNightState 337 | } DAY_NIGHT_STATE, * PDAY_NIGHT_STATE; 338 | 339 | typedef const enum _DAY_NIGHT_STATE * PCDAY_NIGHT_STATE; 340 | 341 | } 342 | 343 | #endif 344 | 345 | -------------------------------------------------------------------------------- /_NwnBaseLib/NWNBaseLib.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | NWNBaseLib.h 8 | 9 | Abstract: 10 | 11 | This module defines the public interface of the NWNBaseLib library, exposing 12 | APIs and related declarations to external users. 13 | 14 | --*/ 15 | 16 | #ifndef _SOURCE_PROGRAMS_NWNBASELIB_NWNBASELIB_H 17 | #define _SOURCE_PROGRAMS_NWNBASELIB_NWNBASELIB_H 18 | 19 | #ifdef _MSC_VER 20 | #pragma once 21 | #endif 22 | #include "BaseTypes.h" 23 | #include "BaseConstants.h" 24 | #include "ModelSystem.h" 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /_NwnDataLib/BifFileReader.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | BifFileReader.h 8 | 9 | Abstract: 10 | 11 | This module defines the intBiface to the BIF reader. BIFs represent a raw 12 | data store of file contents (with directory indexing provided by external 13 | KEY files). 14 | 15 | --*/ 16 | 17 | #ifndef _PROGRAMS_NWN2DATALIB_BIFFILEREADER_H 18 | #define _PROGRAMS_NWN2DATALIB_BIFFILEREADER_H 19 | 20 | #ifdef _MSC_VER 21 | #pragma once 22 | #endif 23 | 24 | #include "ResourceAccessor.h" 25 | #include "FileWrapper.h" 26 | 27 | // 28 | // Define the BIF file reader object, used to access BIF files. 29 | // 30 | 31 | template< typename ResRefT > 32 | class BifFileReader : public IResourceAccessor< ResRefT > 33 | { 34 | 35 | public: 36 | 37 | typedef unsigned long ResID; 38 | 39 | // 40 | // Constructor. Raises an std::exception on parse failure. 41 | // 42 | 43 | BifFileReader( 44 | const std::string & FileName 45 | ); 46 | 47 | // 48 | // Destructor. 49 | // 50 | 51 | virtual 52 | ~BifFileReader( 53 | ); 54 | 55 | // 56 | // Open an encapsulated file by resref. Note that this method is not 57 | // supported on BIF files as the directory index is stored external to the 58 | // BIF. 59 | // 60 | 61 | virtual 62 | typename BifFileReader< ResRefT >::FileHandle 63 | OpenFile( 64 | const ResRefT & ResRef, 65 | NWN::ResType Type 66 | ); 67 | 68 | // 69 | // Open an encapsulated file by file index. 70 | // 71 | 72 | virtual 73 | typename BifFileReader< ResRefT >::FileHandle 74 | OpenFileByIndex( 75 | typename BifFileReader< ResRefT >::FileId FileIndex 76 | ); 77 | 78 | // 79 | // Close an encapsulated file. 80 | // 81 | 82 | virtual 83 | bool 84 | CloseFile( 85 | typename BifFileReader< ResRefT >::FileHandle File 86 | ); 87 | 88 | // 89 | // Read an encapsulated file by file handle. The routine is optimized to 90 | // operate for sequential file reads. 91 | // 92 | 93 | virtual 94 | bool 95 | ReadEncapsulatedFile( 96 | typename BifFileReader< ResRefT >::FileHandle File, 97 | size_t Offset, 98 | size_t BytesToRead, 99 | size_t * BytesRead, 100 | void * Buffer 101 | ); 102 | 103 | // 104 | // Return the size of a file. 105 | // 106 | 107 | virtual 108 | size_t 109 | GetEncapsulatedFileSize( 110 | typename BifFileReader< ResRefT >::FileHandle File 111 | ); 112 | 113 | // 114 | // Return the resource type of a file. 115 | // 116 | 117 | virtual 118 | NWN::ResType 119 | GetEncapsulatedFileType( 120 | typename BifFileReader< ResRefT >::FileHandle File 121 | ); 122 | 123 | // 124 | // Iterate through resources in this resource accessor. The routine 125 | // returns false on failure. 126 | // 127 | 128 | virtual 129 | bool 130 | GetEncapsulatedFileEntry( 131 | typename BifFileReader< ResRefT >::FileId FileIndex, 132 | ResRefT & ResRef, 133 | NWN::ResType & Type 134 | ); 135 | 136 | // 137 | // Return the count of encapsulated files in this accessor. 138 | // 139 | 140 | virtual 141 | typename BifFileReader< ResRefT >::FileId 142 | GetEncapsulatedFileCount( 143 | ); 144 | 145 | // 146 | // Get the logical name of this accessor. 147 | // 148 | 149 | virtual 150 | typename BifFileReader< ResRefT >::AccessorType 151 | GetResourceAccessorName( 152 | typename BifFileReader< ResRefT >::FileHandle File, 153 | std::string & AccessorName 154 | ); 155 | 156 | private: 157 | 158 | // 159 | // Parse the on-disk format and read the base directory data in. 160 | // 161 | 162 | void 163 | ParseBifFile( 164 | ); 165 | 166 | // 167 | // Define the BIF on-disk file structures. This data is based on the 168 | // BioWare Aurora engine documentation. 169 | // 170 | // http://nwn.bioware.com/developers/Bioware_Aurora_KeyBIF_Format.pdf 171 | // 172 | 173 | //#include 174 | #pragma pack (push,1) 175 | #pragma pack (1) 176 | typedef struct _BIF_HEADER 177 | { 178 | uint32_t FileType; // "BIFF" 179 | uint32_t Version; // "V1.0" 180 | uint32_t VariableResourceCount; // # of variable resources in the file 181 | uint32_t LocalizedStringSize; // # of fixed resources in the file 182 | uint32_t VariableTableOffset; // from beginning of file 183 | } BIF_HEADER, * PBIF_HEADER; 184 | 185 | typedef const struct _BIF_HEADER * PCBIF_HEADER; 186 | 187 | typedef struct _BIF_RESOURCE 188 | { 189 | uint32_t ID; 190 | uint32_t Offset; 191 | uint32_t FileSize; 192 | uint32_t ResourceType; 193 | } BIF_RESOURCE, * PBIF_RESOURCE; 194 | 195 | typedef const struct _BIF_RESOURCE * PCBIF_RESOURCE; 196 | #pragma pack (pop) 197 | //#include 198 | 199 | typedef std::vector< BIF_RESOURCE > BifResourceVec; 200 | 201 | // 202 | // Define helper routines for looking up resource data. 203 | // 204 | 205 | // 206 | // Locate a resource by its resource id. 207 | // 208 | 209 | inline 210 | PCBIF_RESOURCE 211 | LookupResourceKey( 212 | ResID ResourceId 213 | ) const 214 | { 215 | if (ResourceId >= m_ResDir.size( )) 216 | return NULL; 217 | 218 | return &m_ResDir[ ResourceId ]; 219 | } 220 | 221 | // 222 | // Define file book-keeping data. 223 | // 224 | 225 | HANDLE m_File; 226 | ULONGLONG m_FileSize; 227 | FileWrapper m_FileWrapper; 228 | ULONGLONG m_NextOffset; 229 | std::string m_BifFileName; 230 | 231 | // 232 | // Resource list data. 233 | // 234 | 235 | BifResourceVec m_ResDir; 236 | 237 | }; 238 | 239 | typedef BifFileReader< NWN::ResRef32 > BifFileReader32; 240 | typedef BifFileReader< NWN::ResRef16 > BifFileReader16; 241 | 242 | 243 | #endif 244 | -------------------------------------------------------------------------------- /_NwnDataLib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(nwndatalib 2 | BifFileReader.cpp 3 | BifFileReader.h 4 | FileWrapper.h 5 | KeyFileReader.cpp 6 | KeyFileReader.h 7 | NWNDataLib.h 8 | NWScriptReader.cpp 9 | NWScriptReader.h 10 | Precomp.h 11 | ResourceAccessor.h 12 | ResourceManager.cpp 13 | ResourceManager.h 14 | TextOut.h 15 | ) -------------------------------------------------------------------------------- /_NwnDataLib/FileWrapper.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | FileWrapper.h 8 | 9 | Abstract: 10 | 11 | This module defines the file wrapper object, which provides various common 12 | wrapper operations for file I/O. 13 | 14 | --*/ 15 | 16 | #ifndef _PROGRAMS_NWN2DATALIB_FILEWRAPPER_H 17 | #define _PROGRAMS_NWN2DATALIB_FILEWRAPPER_H 18 | 19 | #include "../_NwnUtilLib/OsCompat.h" 20 | 21 | #if !defined(_WIN32) && !defined(_WIN64) 22 | #include 23 | #endif 24 | 25 | #if defined(__linux__) 26 | #include 27 | #include 28 | #endif 29 | 30 | #ifdef _MSC_VER 31 | #pragma once 32 | #endif 33 | 34 | class FileWrapper 35 | { 36 | 37 | public: 38 | 39 | inline 40 | FileWrapper( 41 | HANDLE File = nullptr 42 | ) 43 | : m_File( File ), 44 | m_View( nullptr ), 45 | m_Offset( 0 ), 46 | m_Size( 0 ), 47 | m_ExternalView( false ) 48 | 49 | { 50 | if (File != nullptr) 51 | m_Offset = GetFilePointer( ); 52 | } 53 | 54 | inline 55 | ~FileWrapper( 56 | ) 57 | { 58 | if ((m_View != nullptr) && (!m_ExternalView)) 59 | { 60 | #if defined(_WINDOWS) 61 | UnmapViewOfFile( m_View ); 62 | #else 63 | munmap(m_View,m_Size); 64 | #endif 65 | 66 | m_View = nullptr; 67 | } 68 | else if (m_View != nullptr) 69 | { 70 | m_View = nullptr; 71 | } 72 | } 73 | 74 | inline 75 | void 76 | SetFileHandle( 77 | HANDLE File, 78 | bool AsSection = true 79 | ) 80 | { 81 | m_File = File; 82 | m_ExternalView = false; 83 | 84 | if (m_View != nullptr) 85 | { 86 | #if defined(_WINDOWS) 87 | UnmapViewOfFile( m_View ); 88 | #else 89 | munmap(m_View,m_Size); 90 | #endif 91 | m_View = nullptr; 92 | } 93 | 94 | if ((m_File != nullptr) && 95 | (AsSection)) 96 | { 97 | HANDLE Section; 98 | unsigned char * View; 99 | 100 | #if defined(_WINDOWS) 101 | Section = CreateFileMapping( 102 | m_File, 103 | nullptr, 104 | PAGE_READONLY, 105 | 0, 106 | 0, 107 | nullptr); 108 | 109 | if (Section != nullptr) 110 | { 111 | View = (unsigned char *) MapViewOfFile( 112 | Section, 113 | FILE_MAP_READ, 114 | 0, 115 | 0, 116 | 0); 117 | CloseHandle( Section ); 118 | 119 | if (View != nullptr) 120 | { 121 | m_Offset = GetFilePointer( ); 122 | m_Size = GetFileSize( ); 123 | m_View = View; 124 | } 125 | } 126 | 127 | #else 128 | fseek(m_File, 0 , SEEK_END); 129 | m_Size = ftell(m_File); 130 | fseek(m_File, 0 , SEEK_SET);// needed for next read from beginning of file 131 | 132 | View = static_cast(mmap(0, m_Size, PROT_READ, MAP_SHARED, fileno(File), 0)); 133 | 134 | if (View != nullptr) 135 | { 136 | m_Offset = GetFilePointer( ); 137 | m_View = View; 138 | } 139 | #endif 140 | } 141 | } 142 | 143 | // inline 144 | // void 145 | // SetExternalView( 146 | // const unsigned char * View, 147 | // ULONGLONG ViewSize 148 | // ) 149 | // { 150 | // m_Offset = 0; 151 | // m_Size = ViewSize; 152 | // m_View = (unsigned char *) View; // Still const 153 | // m_ExternalView = true; 154 | // } 155 | 156 | // 157 | // ReadFile wrapper with descriptive exception raising on failure. 158 | // 159 | 160 | inline 161 | void 162 | ReadFile( 163 | void * Buffer, 164 | size_t Length, 165 | const char * Description 166 | ) 167 | { 168 | DWORD Transferred; 169 | char ExMsg[ 64 ]; 170 | 171 | if (Length == 0) 172 | return; 173 | 174 | if (m_View != nullptr) 175 | { 176 | if ((m_Offset + Length < m_Offset) || 177 | (m_Offset + Length > m_Size)) 178 | { 179 | snprintf( 180 | ExMsg, 181 | sizeof( ExMsg ), 182 | "ReadFile( %s ) failed.", 183 | Description); 184 | 185 | throw std::runtime_error( ExMsg ); 186 | } 187 | 188 | xmemcpy( 189 | Buffer, 190 | &m_View[ m_Offset ], 191 | Length); 192 | 193 | m_Offset += Length; 194 | return; 195 | } 196 | 197 | #if defined(_WINDOWS) 198 | if (::ReadFile( 199 | m_File, 200 | Buffer, 201 | (DWORD) Length, 202 | &Transferred, 203 | nullptr) && (Transferred == (DWORD) Length)) 204 | return; 205 | #else 206 | size_t len = fread(Buffer,sizeof(char),Length,m_File); 207 | 208 | if (len == Length) 209 | return; 210 | #endif 211 | 212 | snprintf( 213 | ExMsg, 214 | sizeof( ExMsg ), 215 | "ReadFile( %s ) failed.", 216 | Description); 217 | throw std::runtime_error( ExMsg ); 218 | } 219 | 220 | // 221 | // Seek to a particular file offset. 222 | // 223 | 224 | inline 225 | void 226 | SeekOffset( 227 | ULONGLONG Offset, 228 | const char * Description 229 | ) 230 | { 231 | LONG Low; 232 | LONG High; 233 | LONGLONG NewPtrLow; 234 | char ExMsg[ 64 ]; 235 | 236 | if (m_View != nullptr) 237 | { 238 | if (Offset >= m_Size) 239 | { 240 | snprintf( 241 | ExMsg, 242 | sizeof( ExMsg ), 243 | "SeekOffset( %s ) failed.", 244 | Description); 245 | throw std::runtime_error( ExMsg ); 246 | } 247 | 248 | m_Offset = Offset; 249 | return; 250 | } 251 | 252 | Low = (LONG) ((Offset >> 0) & 0xFFFFFFFF); 253 | High = (LONG) ((Offset >> 32) & 0xFFFFFFFF); 254 | 255 | #if defined(_WINDOWS) 256 | 257 | NewPtrLow = SetFilePointer( m_File, Low, &High, FILE_BEGIN ); 258 | #else 259 | NewPtrLow = lseek(fileno(m_File), Offset, SEEK_SET); 260 | #endif 261 | 262 | if ((NewPtrLow == INVALID_SET_FILE_POINTER)) 263 | { 264 | snprintf( 265 | ExMsg, 266 | sizeof( ExMsg ), 267 | "SeekOffset( %s ) failed.", 268 | Description); 269 | throw std::runtime_error( ExMsg ); 270 | } 271 | } 272 | 273 | inline 274 | ULONGLONG 275 | GetFileSize( 276 | ) const 277 | { 278 | 279 | ULONGLONG Size = 0; 280 | DWORD SizeHigh; 281 | 282 | if (m_View != nullptr) 283 | return m_Size; 284 | 285 | #if defined(_WINDOWS) 286 | Size = ::GetFileSize( m_File, &SizeHigh ); 287 | 288 | if ((Size == INVALID_FILE_SIZE) && (GetLastError( ) != NO_ERROR)) 289 | { 290 | throw std::runtime_error( "GetFileSize failed" ); 291 | } 292 | #else 293 | if (m_File != nullptr) { 294 | fseek(m_File, 0, SEEK_END); 295 | Size = ftell(m_File); 296 | fseek(m_File, 0, SEEK_SET);// needed for next read from beginning of file 297 | } 298 | #endif 299 | return Size; // | ((ULONGLONG) SizeHigh) << 32; 300 | } 301 | 302 | inline 303 | LONGLONG 304 | GetFilePointer( 305 | ) const 306 | { 307 | LARGE_INTEGER Fp; 308 | 309 | if (m_View != nullptr) 310 | return m_Offset; 311 | 312 | Fp.QuadPart = 0; 313 | 314 | #if defined(_WINDOWS) 315 | if (!SetFilePointerEx( m_File, Fp, &Fp, FILE_CURRENT )) 316 | throw std::runtime_error( "SetFilePointerEx failed" ); 317 | 318 | #else 319 | Fp.QuadPart = ftell(m_File); 320 | #endif 321 | return Fp.QuadPart; 322 | 323 | } 324 | 325 | private: 326 | 327 | #if defined(_WINDOWS) 328 | DECLSPEC_NORETURN 329 | #endif 330 | inline 331 | void 332 | ThrowInPageError( 333 | ) 334 | { 335 | throw std::runtime_error( "In-page I/O error accessing file" ); 336 | } 337 | 338 | inline 339 | void * 340 | xmemcpy( 341 | void * _Dst, 342 | const void * _Src, 343 | size_t _Size 344 | ) 345 | { 346 | #if defined(_WINDOWS) 347 | __try 348 | { 349 | return (memcpy( _Dst, _Src, _Size )); 350 | } 351 | __except( (GetExceptionCode( ) == EXCEPTION_IN_PAGE_ERROR ) ? 352 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) 353 | { 354 | ThrowInPageError( ); 355 | } 356 | #else 357 | return (memcpy( _Dst, _Src, _Size )); 358 | #endif 359 | } 360 | 361 | HANDLE m_File; 362 | unsigned char * m_View; 363 | ULONGLONG m_Offset; 364 | ULONGLONG m_Size; 365 | bool m_ExternalView; 366 | 367 | }; 368 | 369 | #endif 370 | -------------------------------------------------------------------------------- /_NwnDataLib/KeyFileReader.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | KeyFileReader.h 8 | 9 | Abstract: 10 | 11 | This module defines the interface to the Key File (KEY) reader. Key files 12 | represent directory index listings for associated BIF data archives. 13 | 14 | --*/ 15 | 16 | #ifndef _PROGRAMS_NWN2DATALIB_KEYFILEREADER_H 17 | #define _PROGRAMS_NWN2DATALIB_KEYFILEREADER_H 18 | 19 | #ifdef _MSC_VER 20 | #pragma once 21 | #endif 22 | 23 | #include "ResourceAccessor.h" 24 | #include "FileWrapper.h" 25 | #include "../_NwnUtilLib/NWNUtilLib.h" 26 | 27 | template< typename ResRefT > class BifFileReader; 28 | 29 | // 30 | // Define the KEY file reader object, used to access KEY files. 31 | // 32 | 33 | template< typename ResRefT > 34 | class KeyFileReader: public IResourceAccessor< NWN::ResRef32 > 35 | { 36 | 37 | public: 38 | 39 | typedef unsigned long ResID; 40 | 41 | // 42 | // Define the type of resref used in the public interface, regardless of 43 | // the internal on-disk representation. 44 | // 45 | 46 | typedef NWN::ResRef32 ResRefIf; 47 | 48 | // 49 | // Constructor. Raises an std::exception on parse failure. 50 | // 51 | 52 | KeyFileReader( 53 | const std::string & FileName, 54 | const std::string & InstallDir 55 | ); 56 | 57 | // 58 | // Destructor. 59 | // 60 | 61 | virtual 62 | ~KeyFileReader( 63 | ); 64 | 65 | // 66 | // Open an encapsulated file by resref. 67 | // 68 | 69 | virtual 70 | FileHandle 71 | OpenFile( 72 | const ResRefIf & FileName, 73 | ResType Type 74 | ); 75 | 76 | // 77 | // Open an encapsulated file by file index. 78 | // 79 | 80 | virtual 81 | FileHandle 82 | OpenFileByIndex( 83 | FileId FileIndex 84 | ); 85 | 86 | // 87 | // Close an encapsulated file. 88 | // 89 | 90 | virtual 91 | bool 92 | CloseFile( 93 | FileHandle File 94 | ); 95 | 96 | // 97 | // Read an encapsulated file by file handle. The routine is optimized to 98 | // operate for sequential file reads. 99 | // 100 | 101 | virtual 102 | bool 103 | ReadEncapsulatedFile( 104 | FileHandle File, 105 | size_t Offset, 106 | size_t BytesToRead, 107 | size_t * BytesRead, 108 | void * Buffer 109 | ); 110 | 111 | // 112 | // Return the size of a file. 113 | // 114 | 115 | virtual 116 | size_t 117 | GetEncapsulatedFileSize( 118 | FileHandle File 119 | ); 120 | 121 | // 122 | // Return the resource type of a file. 123 | // 124 | 125 | virtual 126 | ResType 127 | GetEncapsulatedFileType( 128 | FileHandle File 129 | ); 130 | 131 | // 132 | // Iterate through resources in this resource accessor. The routine 133 | // returns false on failure. 134 | // 135 | 136 | virtual 137 | bool 138 | GetEncapsulatedFileEntry( 139 | FileId FileIndex, 140 | ResRefIf & ResRef, 141 | ResType & Type 142 | ); 143 | 144 | // 145 | // Return the count of encapsulated files in this accessor. 146 | // 147 | 148 | virtual 149 | FileId 150 | GetEncapsulatedFileCount( 151 | ); 152 | 153 | // 154 | // Get the logical name of this accessor. 155 | // 156 | 157 | virtual 158 | AccessorType 159 | GetResourceAccessorName( 160 | FileHandle File, 161 | std::string & AccessorName 162 | ); 163 | 164 | private: 165 | 166 | // 167 | // Parse the on-disk format and read the base directory data in. 168 | // 169 | 170 | void 171 | ParseKeyFile( 172 | HANDLE File, 173 | const std::string & InstallDir 174 | ); 175 | 176 | typedef BifFileReader< ResRefT > BifFileReaderT; 177 | typedef swutil::SharedPtr< BifFileReaderT > BifFileReaderTPtr; 178 | typedef std::vector< BifFileReaderTPtr > BifFileVec; 179 | 180 | // 181 | // Define the KEY on-disk file structures. This data is based on the 182 | // BioWare Aurora engine documentation. 183 | // 184 | // http://nwn.bioware.com/developers/Bioware_Aurora_KeyBIF_Format.pdf 185 | // 186 | 187 | //#include 188 | #pragma pack (push,1) 189 | #pragma pack (1) 190 | typedef struct _KEY_HEADER 191 | { 192 | uint32_t FileType; // "KEY " 193 | uint32_t FileVersion; // "V1 " 194 | uint32_t BIFCount; // # of BIF files indexed by this KEY file 195 | uint32_t KeyCount; // # of resources in all BIF files indexed 196 | uint32_t OffsetToFileTable; // from beginning of file 197 | uint32_t OffsetToKeyTable; // from beginning of file 198 | uint32_t BuildYear; // Since 1900 199 | uint32_t BuildDay; // Since January 1 200 | uint8_t Reserved[ 32 ]; // Reserved for future use [MBZ] 201 | } KEY_HEADER, * PKEY_HEADER; 202 | 203 | typedef const struct _KEY_HEADER * PCKEY_HEADER; 204 | 205 | typedef struct _KEY_FILE 206 | { 207 | uint32_t FileSize; // Size of the BIF on disk 208 | uint32_t FilenameOffset; // from beginning of file (in FileNameTable) 209 | uint16_t FilenameSize; // Size of filename in characters 210 | uint16_t Drives; // Bitmask of drives applicable (0x1 -> install directory) 211 | } KEY_FILE, * PKEY_FILE; 212 | 213 | typedef const struct _KEY_FILE * PCKEY_FILE; 214 | 215 | typedef struct _KEY_RESOURCE 216 | { 217 | ResRefT ResRef; 218 | ResType ResourceType; 219 | uint32_t ResID; // Bits 0-19 -> BIF file index (within BIF's resource table), bits 20-31 -> BIF index (within key file table) 220 | } KEY_RESOURCE, * PKEY_RESOURCE; 221 | 222 | //typedef const struct _KEY_FILE * PCKEY_FILE; 223 | #pragma pack (pop) 224 | 225 | //#include 226 | 227 | typedef struct _KEY_RESOURCE_DESCRIPTOR 228 | { 229 | KEY_RESOURCE Res; 230 | BifFileReaderT * BifFile; 231 | size_t DirectoryIndex; // Index into m_KeyResDir 232 | } KEY_RESOURCE_DESCRIPTOR, * PKEY_RESOURCE_DESCRIPTOR; 233 | 234 | typedef const struct _KEY_RESOURCE_DESCRIPTOR * PCKEY_RESOURCE_DESCRIPTOR; 235 | 236 | typedef std::vector< KEY_RESOURCE_DESCRIPTOR > KeyResVec; 237 | 238 | // 239 | // Define helper routines for looking up resource data. 240 | // 241 | 242 | // 243 | // Look up a key file descriptor by its resref name. 244 | // 245 | 246 | inline 247 | PCKEY_RESOURCE_DESCRIPTOR 248 | LookupResourceKey( 249 | const ResRefIf & Name, 250 | ResType Type 251 | ) const 252 | { 253 | for (typename KeyResVec::const_iterator it = m_KeyResDir.begin( ); 254 | it != m_KeyResDir.end( ); 255 | ++it) 256 | { 257 | if (it->Res.ResourceType != Type) 258 | continue; 259 | 260 | if (!memcmp( &Name, &it->Res.ResRef, sizeof( ResRefT ) )) 261 | return &*it; 262 | } 263 | 264 | return NULL; 265 | } 266 | 267 | // 268 | // Look up a key file descriptor by resource index. The resource index is 269 | // the index into the resource table. 270 | // 271 | 272 | inline 273 | PCKEY_RESOURCE_DESCRIPTOR 274 | LookupResourceKey( 275 | ResID ResourceId 276 | ) const 277 | { 278 | if (ResourceId >= m_KeyResDir.size( )) 279 | return NULL; 280 | 281 | return &m_KeyResDir[ ResourceId ]; 282 | } 283 | 284 | // 285 | // Resource list data. 286 | // 287 | 288 | KeyResVec m_KeyResDir; 289 | BifFileVec m_BifFiles; 290 | std::string m_KeyFileName; 291 | 292 | }; 293 | 294 | typedef KeyFileReader< NWN::ResRef32 > KeyFileReader32; 295 | typedef KeyFileReader< NWN::ResRef16 > KeyFileReader16; 296 | 297 | 298 | #endif 299 | -------------------------------------------------------------------------------- /_NwnDataLib/NWNDataLib.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | NWN2DataLib.h 8 | 9 | Abstract: 10 | 11 | This module houses include definitions for all public APIs and types that 12 | are exposed by the datafile accessor library. 13 | 14 | --*/ 15 | 16 | #ifndef _PROGRAMS_NWN2DATALIB_NWN2DATALIB_H 17 | #define _PROGRAMS_NWN2DATALIB_NWN2DATALIB_H 18 | 19 | #ifdef _MSC_VER 20 | #pragma once 21 | #endif 22 | 23 | #include "TextOut.h" 24 | #include "ResourceManager.h" 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /_NwnDataLib/NWScriptReader.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | NWScriptReader.h 8 | 9 | Abstract: 10 | 11 | This module defines the compiled NWScript (*.ncs) reader. The reader 12 | facilitates loading of the instruction byte code and data retrieval. 13 | 14 | --*/ 15 | 16 | #ifndef _SOURCE_PROGRAMS_NWN2DATALIB_NWSCRIPTREADER_H 17 | #define _SOURCE_PROGRAMS_NWN2DATALIB_NWSCRIPTREADER_H 18 | 19 | #include "../_NwnUtilLib/BufferParser.h" 20 | #include "../_NwnUtilLib/Ref.h" 21 | 22 | #ifdef _MSC_VER 23 | #pragma once 24 | #endif 25 | 26 | class NWScriptReader 27 | { 28 | 29 | public: 30 | 31 | struct SymbolTableRawEntry 32 | { 33 | ULONG PC; 34 | const char * Name; 35 | }; 36 | 37 | typedef std::vector< SymbolTableRawEntry > SymbolTableRawEntryVec; 38 | 39 | // 40 | // Keep state for the return value hack and what we have done with it in 41 | // the shareable reader object. It is up to the script VM to use (and set) 42 | // these values. 43 | // 44 | 45 | enum NCSPatchState 46 | { 47 | NCSPatchState_Unknown, 48 | NCSPatchState_Normal, 49 | NCSPatchState_UsesGlobals, 50 | NCSPatchState_PatchReturnValue 51 | }; 52 | 53 | // 54 | // Create a reader context given a compiled script. The script is read 55 | // entirely into memory. 56 | // 57 | 58 | NWScriptReader( 59 | const char * NcsFileName 60 | ); 61 | 62 | // 63 | // Create a reader context given a serialized NWScriptReader object. Note 64 | // that not all fields are serialized (in particular, patch state and other 65 | // VM state attributes are not). Only the name, instruction data, and the 66 | // symbol table are available. 67 | // 68 | 69 | NWScriptReader( 70 | const char * ScriptName, 71 | const unsigned char * ScriptInstructions, 72 | size_t ScriptInstructionLen, 73 | const SymbolTableRawEntry * SymTab, 74 | size_t SymbolTableSize 75 | ); 76 | 77 | ~NWScriptReader( 78 | ); 79 | 80 | // 81 | // Create a reader context that is a full copy of another. 82 | // 83 | 84 | NWScriptReader( 85 | NWScriptReader & other 86 | ); 87 | 88 | // 89 | // Serialization APIs, to store a NWScriptReader's internal contents into 90 | // a portable form for the JIT engine. 91 | // 92 | // N.B. Only a subset of fields are stored. Additonally, the serialized 93 | // data points into the parent script reader; no changes to the 94 | // parent's symbol table or instruction stream may be made while an 95 | // external user retains a pointer to any packaged fields. 96 | // 97 | 98 | void 99 | StoreInternalState( 100 | const unsigned char * & ScriptInstructions, 101 | size_t & ScriptInstructionLen, 102 | SymbolTableRawEntryVec & SymTab 103 | ); 104 | 105 | // 106 | // Reset the instruction buffer pointer for the script. 107 | // 108 | 109 | void 110 | ResetInstructionBuffer( 111 | const unsigned char * ScriptInstructions, 112 | size_t ScriptInstructionsLen 113 | ); 114 | 115 | // 116 | // Data access APIs. Note that these APIs raise an std::exception if the 117 | // read fails (i.e. ran past the end of file). 118 | // 119 | 120 | // 121 | // Read an instruction from the current PC (and advance the current PC 122 | // appropriately). 123 | // 124 | 125 | void 126 | ReadInstruction( 127 | UCHAR & Opcode, 128 | UCHAR & TypeOpcode 129 | ); 130 | 131 | // 132 | // Read an 8-bit auxiliary integer. 133 | // 134 | 135 | UCHAR 136 | ReadINT8( 137 | ); 138 | 139 | // 140 | // Read a 16-bit auxiliary integer. 141 | // 142 | 143 | USHORT 144 | ReadINT16( 145 | ); 146 | 147 | // 148 | // Read a 32-bit auxiliary integer. 149 | // 150 | 151 | ULONG 152 | ReadINT32( 153 | ); 154 | 155 | // 156 | // Read a 32-bit auxiliary floating point value. 157 | // 158 | 159 | float 160 | ReadFLOAT( 161 | ); 162 | 163 | // 164 | // Read an auxiliary string value. 165 | // 166 | 167 | std::string 168 | ReadString( 169 | ULONG Length 170 | ); 171 | 172 | // 173 | // Data write routines, used to patch new instruction data into the script 174 | // opcode stream itself. 175 | // 176 | // Note that these routines raise an std::exception on failure. All users 177 | // of the NWScriptReader object see the patched opcode data. 178 | // 179 | 180 | void 181 | PatchBYTE( 182 | ULONG Offset, 183 | UCHAR Byte 184 | ); 185 | 186 | // 187 | // Change to a new instruction pointer. The routine may raise an 188 | // std::exception on a control transfer to an invalid address. 189 | // 190 | 191 | void 192 | SetInstructionPointer( 193 | ULONG InstructionPointer 194 | ); 195 | 196 | // 197 | // Advance the instruction pointer. 198 | // 199 | 200 | void 201 | AdvanceInstructionPointer( 202 | ULONG Increment 203 | ); 204 | 205 | // 206 | // Return the current instruction pointer. 207 | // 208 | 209 | inline 210 | ULONG 211 | GetInstructionPointer( 212 | ) const 213 | { 214 | return (ULONG) m_Parser->GetBytePos( ); 215 | } 216 | 217 | // 218 | // Store and retrieve the patch state. 219 | // 220 | 221 | inline 222 | NCSPatchState 223 | GetPatchState( 224 | ) const 225 | { 226 | return m_PatchState; 227 | } 228 | 229 | inline 230 | void 231 | SetPatchState( 232 | NCSPatchState PatchState 233 | ) 234 | { 235 | m_PatchState = PatchState; 236 | } 237 | 238 | // 239 | // Return true if the script has has ran to the end of file (relative to 240 | // the current program counter). 241 | // 242 | 243 | inline 244 | bool 245 | ScriptIsEof( 246 | ) const 247 | { 248 | return (m_Parser->GetBytesRemaining( ) == 0); 249 | } 250 | 251 | // 252 | // Assign or retrieve a script name (for debugging purposes only). 253 | // 254 | 255 | inline 256 | const std::string & 257 | GetScriptName( 258 | ) const 259 | { 260 | return m_Name; 261 | } 262 | 263 | inline 264 | void 265 | SetScriptName( 266 | const std::string & Name 267 | ) 268 | { 269 | m_Name = Name; 270 | } 271 | 272 | // 273 | // Script analysis state cache (for parameter numbering). 274 | // 275 | 276 | struct ScriptAnalyzeState 277 | { 278 | // 279 | // Define the count of stack cells used by the entry point for return 280 | // value storage. 281 | // 282 | 283 | unsigned long ReturnCells; 284 | 285 | // 286 | // Define the count of stack cells used by the entry point for 287 | // parameter inputs. 288 | // 289 | 290 | unsigned long ParameterCells; 291 | 292 | // 293 | // Define the types for each argument (optional). The memory for this 294 | // field must come from operator new[]< unsigned long > and if the 295 | // array is present, its size must be equal to ParameterCells. 296 | // 297 | 298 | unsigned long * ArgumentTypes; 299 | }; 300 | 301 | inline 302 | const ScriptAnalyzeState * 303 | GetAnalyzeState( 304 | ) const 305 | { 306 | if (!m_Analyzed) 307 | return NULL; 308 | 309 | return &m_AnalyzeState; 310 | } 311 | 312 | inline 313 | void 314 | SetAnalyzeState( 315 | ScriptAnalyzeState * AnalyzeState 316 | ) 317 | { 318 | if (m_AnalyzeState.ArgumentTypes != NULL) 319 | { 320 | delete [] m_AnalyzeState.ArgumentTypes; 321 | m_AnalyzeState.ArgumentTypes = NULL; 322 | } 323 | 324 | m_AnalyzeState = *AnalyzeState; 325 | m_Analyzed = true; 326 | } 327 | 328 | // 329 | // Look up a subroutine name (exact match) from the symbol table, if any 330 | // was loaded. 331 | // 332 | 333 | bool 334 | GetSymbolName( 335 | ULONG PC, 336 | std::string & SymbolName, 337 | bool FindNearest = false 338 | ); 339 | 340 | // 341 | // Load the symbol table (optional) from the standard NDB format. 342 | // 343 | 344 | bool 345 | LoadSymbols( 346 | const std::string & NDBFileName 347 | ); 348 | 349 | private: 350 | 351 | //#include 352 | typedef struct _NCS_HEADER 353 | { 354 | unsigned char FileType[ 4 ]; // "NCS " 355 | unsigned char FileVer[ 4 ]; // "V1.0" 356 | unsigned char TOpCode; // 0x42 357 | unsigned long FileSize; // Whole filesize (Big Endian) 358 | } NCS_HEADER, * PNCS_HEADER; 359 | //#include 360 | 361 | typedef const struct _NCS_HEADER * PCNCS_HEADER; 362 | 363 | typedef swutil::SharedPtr< swutil::BufferParser > BufferParserPtr; 364 | 365 | typedef std::map< ULONG, std::string > SymbolNameMap; 366 | 367 | 368 | // 369 | // Define the instruction content of the file. While generally identical 370 | // to the file, the instruction stream may be altered with the PatchBYTE 371 | // routine. 372 | // 373 | 374 | std::vector< UCHAR > m_Instructions; 375 | 376 | // 377 | // Define alternate instruction storage, used if we are initialized without 378 | // opening a file. 379 | // 380 | 381 | const unsigned char * m_ExternalInstructions; 382 | 383 | // 384 | // Define the size of the alternate instruction storage region. 385 | // 386 | 387 | size_t m_ExternalInstructionsSize; 388 | 389 | // 390 | // Define the parse context used to fetch instructions from the current 391 | // logical instruction stream. 392 | // 393 | 394 | BufferParserPtr m_Parser; 395 | 396 | // 397 | // Define the patch state bookkeeping for the script VM. This is the hack 398 | // to support parameterized conditional scripts (i.e. that return an int). 399 | // 400 | 401 | NCSPatchState m_PatchState; 402 | 403 | // 404 | // Define an optional name of the script for debugging purposes. 405 | // 406 | 407 | std::string m_Name; 408 | 409 | // 410 | // Define script analysis state, used to cache legal parameter information 411 | // for the script. 412 | // 413 | 414 | ScriptAnalyzeState m_AnalyzeState; 415 | bool m_Analyzed; 416 | 417 | // 418 | // Define the symbol table for the script. 419 | // 420 | 421 | SymbolNameMap m_SymbolTable; 422 | 423 | }; 424 | 425 | #endif 426 | -------------------------------------------------------------------------------- /_NwnDataLib/Precomp.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | precomp.h 8 | 9 | Abstract: 10 | 11 | This module acts as the precompiled header that pulls in all common 12 | dependencies that typically do not change. 13 | 14 | --*/ 15 | 16 | #ifndef _PROGRAMS_NWN2DATALIB_PRECOMP_H 17 | #define _PROGRAMS_NWN2DATALIB_PRECOMP_H 18 | 19 | #ifdef _MSC_VER 20 | #pragma once 21 | #endif 22 | 23 | #if defined(_WINDOWS) 24 | 25 | #define _CRT_SECURE_NO_DEPRECATE 26 | #define _CRT_SECURE_NO_DEPRECATE_GLOBALS 27 | #define STRSAFE_NO_DEPRECATE 28 | 29 | //#include 30 | //#include 31 | 32 | #endif 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | 45 | #ifdef ENCRYPT 46 | #include 47 | #endif 48 | 49 | #if defined(_WINDOWS) 50 | #include 51 | #include 52 | 53 | #include 54 | #include 55 | 56 | #endif 57 | 58 | #include 59 | #include 60 | 61 | #include 62 | 63 | #include "../_NwnUtilLib/ProjGlobalDefs.h" 64 | #include "../_NwnUtilLib/NWNUtilLib.h" 65 | #include "../_NwnBaseLib/NWNBaseLib.h" 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /_NwnDataLib/ResourceAccessor.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | ResourceAccessor.h 8 | 9 | Abstract: 10 | 11 | This module defines the IResourceAccessor interface, which is used to 12 | abstract away the concept of a resource reference from its various 13 | implementations (i.e. ERF, directory, ZIP file). 14 | 15 | --*/ 16 | 17 | #ifndef _PROGRAMS_NWN2DATALIB_RESOURCEACCESSOR_H 18 | #define _PROGRAMS_NWN2DATALIB_RESOURCEACCESSOR_H 19 | 20 | #include "../_NwnBaseLib/BaseTypes.h" 21 | 22 | //typedef NWN::ResRef32 ResRefT; 23 | 24 | 25 | #ifdef _MSC_VER 26 | #pragma once 27 | #endif 28 | 29 | // 30 | // Define the resource accessor abstraction. All resource providers implement 31 | // this interface, as does the resource manager. It provides a uniform 32 | // mechanism to access resource files independent of their raw storage backing 33 | // system. 34 | // 35 | 36 | 37 | 38 | template< typename ResRefT > 39 | struct IResourceAccessor 40 | { 41 | 42 | typedef ULONG64 FileHandle; 43 | typedef NWN::ResType ResType; 44 | typedef ULONG64 FileId; 45 | 46 | static const FileHandle INVALID_FILE = 0; 47 | 48 | 49 | enum AccessorType 50 | { 51 | AccessorTypeBif, 52 | AccessorTypeErf, 53 | AccessorTypeDirectory, 54 | AccessorTypeKey, 55 | AccessorTypeZip, 56 | AccessorTypeResourceManager, 57 | AccessorTypeCustom 58 | }; 59 | 60 | // 61 | // Open an encapsulated file by resref. 62 | // 63 | 64 | virtual 65 | FileHandle 66 | OpenFile( 67 | const ResRefT & ResRef, 68 | ResType Type 69 | ) = 0; 70 | 71 | // 72 | // Open an encapsulated file by file index. 73 | // 74 | 75 | virtual 76 | FileHandle 77 | OpenFileByIndex( 78 | FileId FileIndex 79 | ) = 0; 80 | 81 | // 82 | // Close an encapsulated file. 83 | // 84 | 85 | virtual 86 | bool 87 | CloseFile( 88 | FileHandle File 89 | ) = 0; 90 | 91 | // 92 | // Read an encapsulated file by file handle. The routine is optimized to 93 | // operate for sequential file reads. 94 | // 95 | 96 | virtual 97 | bool 98 | ReadEncapsulatedFile( 99 | FileHandle File, 100 | size_t Offset, 101 | size_t BytesToRead, 102 | size_t * BytesRead, 103 | void * Buffer 104 | ) = 0; 105 | 106 | // 107 | // Return the size of a file. 108 | // 109 | 110 | virtual 111 | size_t 112 | GetEncapsulatedFileSize( 113 | FileHandle File 114 | ) = 0; 115 | 116 | // 117 | // Return the resource type of a file. 118 | // 119 | 120 | virtual 121 | ResType 122 | GetEncapsulatedFileType( 123 | FileHandle File 124 | ) = 0; 125 | 126 | // 127 | // Iterate through resources in this resource accessor. The routine 128 | // returns false on failure. 129 | // 130 | 131 | virtual 132 | bool 133 | GetEncapsulatedFileEntry( 134 | FileId FileIndex, 135 | ResRefT & ResRef, 136 | ResType & Type 137 | ) = 0; 138 | 139 | // 140 | // Return the count of encapsulated files in this accessor. 141 | // 142 | 143 | virtual 144 | FileId 145 | GetEncapsulatedFileCount( 146 | ) = 0; 147 | 148 | // 149 | // Get the logical name of this accessor. 150 | // 151 | 152 | virtual 153 | AccessorType 154 | GetResourceAccessorName( 155 | FileHandle File, 156 | std::string & AccessorName 157 | ) = 0; 158 | 159 | static 160 | const char * 161 | ResTypeToExt( 162 | ResType Type 163 | ) 164 | { 165 | // 166 | // N.B. MUST keep in sync with ExtToResType! 167 | // 168 | 169 | switch (Type) 170 | { 171 | 172 | case NWN::ResBMP: 173 | return "bmp"; 174 | 175 | case NWN::ResTGA: 176 | return "tga"; 177 | 178 | case NWN::ResWAV: 179 | return "wav"; 180 | 181 | case NWN::ResINI: 182 | return "ini"; 183 | 184 | case NWN::ResTXT: 185 | return "txt"; 186 | 187 | case NWN::ResNSS: 188 | return "nss"; 189 | 190 | case NWN::ResNCS: 191 | return "ncs"; 192 | 193 | case NWN::ResNDB: 194 | return "ndb"; 195 | 196 | case NWN::ResARE: 197 | return "are"; 198 | 199 | case NWN::ResGIT: 200 | return "git"; 201 | 202 | case NWN::ResIFO: 203 | return "ifo"; 204 | 205 | case NWN::ResJRL: 206 | return "jrl"; 207 | 208 | case NWN::Res2DA: 209 | return "2da"; 210 | 211 | case NWN::ResSSF: 212 | return "ssf"; 213 | 214 | case NWN::ResUSC: 215 | return "usc"; 216 | 217 | case NWN::ResTRN: 218 | return "trn"; 219 | 220 | case NWN::ResTRX: 221 | return "trx"; 222 | 223 | case NWN::ResTRn: // TRN surrogate 224 | return "tro"; 225 | 226 | case NWN::ResTRx: // TRx surrogate 227 | return "try"; 228 | 229 | case NWN::ResMDB: 230 | return "mdb"; 231 | 232 | case NWN::ResGR2: 233 | return "gr2"; 234 | 235 | case NWN::ResFXA: 236 | return "fxa"; 237 | 238 | case NWN::ResJPG: 239 | return "jpg"; 240 | 241 | case NWN::ResBIC: 242 | return "bic"; 243 | 244 | case NWN::ResGFF: 245 | return "gff"; 246 | 247 | case NWN::ResUTI: 248 | return "uti"; 249 | 250 | case NWN::ResUTC: 251 | return "utc"; 252 | 253 | case NWN::ResUTP: 254 | return "utp"; 255 | 256 | case NWN::ResUTD: 257 | return "utd"; 258 | 259 | case NWN::ResUTW: 260 | return "utw"; 261 | 262 | case NWN::ResUTS: 263 | return "uts"; 264 | 265 | case NWN::ResULT: 266 | return "ult"; 267 | 268 | case NWN::ResUTE: 269 | return "ute"; 270 | 271 | case NWN::ResUTM: 272 | return "utm"; 273 | 274 | case NWN::ResUTR: 275 | return "utr"; 276 | 277 | case NWN::ResUEN: 278 | return "uen"; 279 | 280 | case NWN::ResSEF: 281 | return "sef"; 282 | 283 | case NWN::ResPFX: 284 | return "pfx"; 285 | 286 | case NWN::ResXML: 287 | return "xml"; 288 | 289 | case NWN::ResWLK: 290 | return "wlk"; 291 | 292 | case NWN::ResBMU: 293 | return "bmu"; 294 | 295 | case NWN::ResCAM: 296 | return "cam"; 297 | 298 | case NWN::ResUPE: 299 | return "upe"; 300 | 301 | case NWN::ResPFB: 302 | return "pfb"; 303 | 304 | case NWN::ResBBX: 305 | return "bbx"; 306 | 307 | case NWN::ResSPT: 308 | return "spt"; 309 | 310 | case NWN::ResPWC: 311 | return "pwc"; 312 | 313 | case NWN::ResDLG: 314 | return "dlg"; 315 | 316 | case NWN::ResITP: 317 | return "itp"; 318 | 319 | case NWN::ResUTT: 320 | return "utt"; 321 | 322 | case NWN::ResDDS: 323 | return "dds"; 324 | 325 | case NWN::ResFAC: 326 | return "fac"; 327 | 328 | case NWN::ResWOK: 329 | return "wok"; 330 | 331 | case NWN::ResMDL: 332 | return "mdl"; 333 | 334 | case NWN::ResGIC: 335 | return "gic"; 336 | 337 | case NWN::ResFXE: 338 | return "fxe"; 339 | 340 | case NWN::ResRES: 341 | return "res"; 342 | 343 | default: 344 | return "???"; 345 | 346 | } 347 | } 348 | 349 | static 350 | ResType 351 | ExtToResType( 352 | const char * Ext 353 | ) 354 | { 355 | char ExtL[ 4 ]; 356 | 357 | ZeroMemory( ExtL, sizeof( ExtL ) ); 358 | 359 | for (size_t i = 0; i < sizeof( ExtL ); i += 1) 360 | { 361 | ExtL[ i ] = (char) tolower( (int) Ext[ i ] ); 362 | 363 | if (!ExtL[ i ]) 364 | break; 365 | } 366 | 367 | // 368 | // N.B. MUST keep in sync with ResTypeToExt! 369 | // 370 | 371 | if (!strcmp( ExtL, "bmp" )) 372 | return NWN::ResBMP; 373 | else if (!strcmp( ExtL, "tga" )) 374 | return NWN::ResTGA; 375 | else if (!strcmp( ExtL, "wav" )) 376 | return NWN::ResWAV; 377 | else if (!strcmp( ExtL, "ini" )) 378 | return NWN::ResINI; 379 | else if (!strcmp( ExtL, "txt" )) 380 | return NWN::ResTXT; 381 | else if (!strcmp( ExtL, "nss" )) 382 | return NWN::ResNSS; 383 | else if (!strcmp( ExtL, "ncs" )) 384 | return NWN::ResNCS; 385 | else if (!strcmp( ExtL, "ndb" )) 386 | return NWN::ResNDB; 387 | else if (!strcmp( ExtL, "are" )) 388 | return NWN::ResARE; 389 | else if (!strcmp( ExtL, "git" )) 390 | return NWN::ResGIT; 391 | else if (!strcmp( ExtL, "ifo" )) 392 | return NWN::ResIFO; 393 | else if (!strcmp( ExtL, "jrl" )) 394 | return NWN::ResJRL; 395 | else if (!strcmp( ExtL, "2da" )) 396 | return NWN::Res2DA; 397 | else if (!strcmp( ExtL, "ssf" )) 398 | return NWN::ResSSF; 399 | else if (!strcmp( ExtL, "usc" )) 400 | return NWN::ResUSC; 401 | else if (!strcmp( ExtL, "trn" )) 402 | return NWN::ResTRN; 403 | else if (!strcmp( ExtL, "trx" )) 404 | return NWN::ResTRX; 405 | else if (!strcmp( ExtL, "tro" )) 406 | return NWN::ResTRn; 407 | else if (!strcmp( ExtL, "try" )) 408 | return NWN::ResTRx; 409 | else if (!strcmp( ExtL, "mdb" )) 410 | return NWN::ResMDB; 411 | else if (!strcmp( ExtL, "gr2" )) 412 | return NWN::ResGR2; 413 | else if (!strcmp( ExtL, "fxa" )) 414 | return NWN::ResFXA; 415 | else if (!strcmp( ExtL, "jpg" )) 416 | return NWN::ResJPG; 417 | else if (!strcmp( ExtL, "bic" )) 418 | return NWN::ResBIC; 419 | else if (!strcmp( ExtL, "gff" )) 420 | return NWN::ResGFF; 421 | else if (!strcmp( ExtL, "uti" )) 422 | return NWN::ResUTI; 423 | else if (!strcmp( ExtL, "utc" )) 424 | return NWN::ResUTC; 425 | else if (!strcmp( ExtL, "utp" )) 426 | return NWN::ResUTP; 427 | else if (!strcmp( ExtL, "utd" )) 428 | return NWN::ResUTD; 429 | else if (!strcmp( ExtL, "utw" )) 430 | return NWN::ResUTW; 431 | else if (!strcmp( ExtL, "uts" )) 432 | return NWN::ResUTS; 433 | else if (!strcmp( ExtL, "ult" )) 434 | return NWN::ResULT; 435 | else if (!strcmp( ExtL, "ute" )) 436 | return NWN::ResUTE; 437 | else if (!strcmp( ExtL, "utm" )) 438 | return NWN::ResUTM; 439 | else if (!strcmp( ExtL, "utr" )) 440 | return NWN::ResUTR; 441 | else if (!strcmp( ExtL, "uen" )) 442 | return NWN::ResUEN; 443 | else if (!strcmp( ExtL, "sef" )) 444 | return NWN::ResSEF; 445 | else if (!strcmp( ExtL, "pfx" )) 446 | return NWN::ResPFX; 447 | else if (!strcmp( ExtL, "xml" )) 448 | return NWN::ResXML; 449 | else if (!strcmp( ExtL, "wlk" )) 450 | return NWN::ResWLK; 451 | else if (!strcmp( ExtL, "bmu" )) 452 | return NWN::ResBMU; 453 | else if (!strcmp( ExtL, "cam" )) 454 | return NWN::ResCAM; 455 | else if (!strcmp( ExtL, "upe" )) 456 | return NWN::ResUPE; 457 | else if (!strcmp( ExtL, "pfb" )) 458 | return NWN::ResPFB; 459 | else if (!strcmp( ExtL, "bbx" )) 460 | return NWN::ResBBX; 461 | else if (!strcmp( ExtL, "spt" )) 462 | return NWN::ResSPT; 463 | else if (!strcmp( ExtL, "pwc" )) 464 | return NWN::ResPWC; 465 | else if (!strcmp( ExtL, "dlg" )) 466 | return NWN::ResDLG; 467 | else if (!strcmp( ExtL, "itp" )) 468 | return NWN::ResITP; 469 | else if (!strcmp( ExtL, "utt" )) 470 | return NWN::ResUTT; 471 | else if (!strcmp( ExtL, "dds" )) 472 | return NWN::ResDDS; 473 | else if (!strcmp( ExtL, "fac" )) 474 | return NWN::ResFAC; 475 | else if (!strcmp( ExtL, "wok" )) 476 | return NWN::ResWOK; 477 | else if (!strcmp( ExtL, "mdl" )) 478 | return NWN::ResMDL; 479 | else if (!strcmp( ExtL, "gic" )) 480 | return NWN::ResGIC; 481 | else if (!strcmp( ExtL, "fxe" )) 482 | return NWN::ResFXE; 483 | else if (!strcmp( ExtL, "res" )) 484 | return NWN::ResRES; 485 | else 486 | return NWN::ResINVALID; 487 | } 488 | 489 | }; 490 | 491 | #endif 492 | -------------------------------------------------------------------------------- /_NwnDataLib/TextOut.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | TextOut.h 8 | 9 | Abstract: 10 | 11 | This module houses the IDebugTextOut interface, which is used by 12 | the resource manager and datafile accessor library for purposes of writing 13 | debug log messages. 14 | 15 | --*/ 16 | 17 | #ifndef _PROGRAMS_NWN2DATALIB_TEXTOUT_H 18 | #define _PROGRAMS_NWN2DATALIB_TEXTOUT_H 19 | 20 | 21 | #ifdef _MSC_VER 22 | #pragma once 23 | #endif 24 | 25 | // 26 | // Define the debug text output interface, used to write debug or log messages 27 | // to the user. 28 | // 29 | 30 | struct IDebugTextOut 31 | { 32 | 33 | virtual 34 | void 35 | WriteText( 36 | const char* fmt, 37 | ... 38 | ) = 0; 39 | 40 | virtual 41 | void 42 | WriteTextV( 43 | const char* fmt, 44 | va_list ap 45 | ) = 0; 46 | 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /_NwnUtilLib/.gitignore: -------------------------------------------------------------------------------- 1 | version.cpp -------------------------------------------------------------------------------- /_NwnUtilLib/BufferParser.cpp: -------------------------------------------------------------------------------- 1 | #include "BufferParser.h" 2 | 3 | using swutil::BufferParser; 4 | 5 | // 6 | // Define to 1 to break into the debugger on parse failure. 7 | // 8 | 9 | #define BUFFERPARSE_BREAK_ON_FAIL 0 10 | 11 | BufferParser::BufferParser( 12 | const void *Data, 13 | size_t Length, 14 | BitOrderMode BitOrder /* = BitOrderLowToHigh */ 15 | ) 16 | : m_Data( reinterpret_cast< const unsigned char * >( Data ) ), 17 | m_DataLength( Length ), 18 | m_DataPos( m_Data ), 19 | m_DataPosRemaining( m_DataLength ), 20 | m_BitPos( 8 ), 21 | m_HighestValidBitPos( 8 ), 22 | m_BitOrderMode( BitOrder ) 23 | { 24 | } 25 | 26 | BufferParser::~BufferParser() 27 | { 28 | } 29 | 30 | bool 31 | BufferParser::GetDataPtr( 32 | size_t FieldLength, 33 | const void **Field 34 | ) 35 | { 36 | if (m_DataPosRemaining < FieldLength) 37 | { 38 | #if BUFFERPARSE_BREAK_ON_FAIL 39 | __debugbreak( ); 40 | #endif 41 | return false; 42 | } 43 | 44 | if (m_BitPos != 8) 45 | { 46 | #if BUFFERPARSE_BREAK_ON_FAIL 47 | __debugbreak( ); 48 | #endif 49 | return false; 50 | } 51 | 52 | // 53 | // If we have an output pointer, update it to point into the packet. 54 | // Otherwise, we'll just advance the buffer pointer and discard the data. 55 | // 56 | 57 | if (Field) 58 | *Field = reinterpret_cast< const void *>( m_DataPos ); 59 | 60 | m_DataPosRemaining -= FieldLength; 61 | m_DataPos += FieldLength; 62 | 63 | return true; 64 | } 65 | 66 | bool 67 | BufferParser::GetData( 68 | size_t FieldLength, 69 | void *Field 70 | ) 71 | { 72 | if (m_DataPosRemaining < FieldLength) 73 | { 74 | #if BUFFERPARSE_BREAK_ON_FAIL 75 | __debugbreak( ); 76 | #endif 77 | return false; 78 | } 79 | 80 | if (m_BitPos != 8) 81 | { 82 | #if BUFFERPARSE_BREAK_ON_FAIL 83 | __debugbreak( ); 84 | #endif 85 | return false; 86 | } 87 | 88 | // 89 | // If we have an output pointer, update it to point into the packet. 90 | // Otherwise, we'll just advance the buffer pointer and discard the data. 91 | // 92 | 93 | if (Field) 94 | { 95 | memcpy( Field, m_DataPos, FieldLength ); 96 | } 97 | 98 | m_DataPosRemaining -= FieldLength; 99 | m_DataPos += FieldLength; 100 | 101 | return true; 102 | } 103 | 104 | bool 105 | BufferParser::GetFieldBits( 106 | size_t NumBits, 107 | uint64_t &FieldBits 108 | ) 109 | { 110 | if (NumBits > 64) 111 | { 112 | #if BUFFERPARSE_BREAK_ON_FAIL 113 | __debugbreak( ); 114 | #endif 115 | return false; 116 | } 117 | 118 | // 119 | // No bytes left? All done. 120 | // 121 | 122 | if (!m_DataPosRemaining) 123 | { 124 | #if BUFFERPARSE_BREAK_ON_FAIL 125 | __debugbreak( ); 126 | #endif 127 | return false; 128 | } 129 | 130 | // 131 | // Calculate the number of bits remaining in this byte. This is normally 132 | // 8, but if we are the last byte, then we may have a lesser set of valid 133 | // bits. 134 | // 135 | 136 | size_t BitsThisByte = ((m_DataPosRemaining > 1) ? 8 : m_HighestValidBitPos); 137 | size_t BitsRemaining = BitsThisByte - ((m_BitPos == 8) ? 0 : m_BitPos); 138 | size_t CurrOutBit = 0; 139 | 140 | if (NumBits > BitsRemaining) 141 | { 142 | size_t BitsExtra = NumBits - BitsRemaining; 143 | size_t BytesRequired = 1 + (BitsExtra / 8) + ((BitsExtra % 8) ? 1 : 0); 144 | 145 | // 146 | // N.B. 1 + above as m_DataPosRemaining includes the current byte that 147 | // is being worked on. 148 | // 149 | 150 | if (m_DataPosRemaining < BytesRequired) 151 | { 152 | #if BUFFERPARSE_BREAK_ON_FAIL 153 | __debugbreak( ); 154 | #endif 155 | return false; 156 | } 157 | 158 | // 159 | // If we are going to be operating on the last byte, then ensure that 160 | // we don't extend past the last valid bit. 161 | // 162 | 163 | if ((m_DataPosRemaining == BytesRequired) && 164 | ((BitsExtra % 8) > m_HighestValidBitPos)) 165 | { 166 | #if BUFFERPARSE_BREAK_ON_FAIL 167 | __debugbreak( ); 168 | #endif 169 | return false; 170 | } 171 | } 172 | 173 | FieldBits = 0; 174 | 175 | while (CurrOutBit < NumBits) 176 | { 177 | // 178 | // If we haven't claimed any data for bit reading yet, then we shall 179 | // need to do so first. Note that after having done this we need to 180 | // keep on reading bits until we finish with a byte before the normal 181 | // byte-oriented read operations will function. 182 | // 183 | 184 | if (m_BitPos == 8) 185 | m_BitPos = 0; 186 | 187 | // 188 | // Grab the current bit. 189 | // 190 | 191 | switch (m_BitOrderMode) 192 | { 193 | 194 | case BitOrderLowToHigh: 195 | FieldBits <<= 1; 196 | FieldBits |= static_cast< uint64_t >( ((*m_DataPos >> ( m_BitPos)) & 1ull) ); 197 | // FieldBits |= static_cast< uint64_t >( (*m_DataPos & (1ull << ( m_BitPos))) << CurrOutBit ); 198 | break; 199 | 200 | case BitOrderHighToLow: 201 | FieldBits <<= 1; 202 | FieldBits |= static_cast< uint64_t >( ((*m_DataPos >> (7 - m_BitPos)) & 1ull) ); 203 | // FieldBits |= static_cast< uint64_t >( (*m_DataPos & (1ull << (7 - m_BitPos))) << CurrOutBit ); 204 | break; 205 | 206 | default: 207 | #ifdef _MSC_VER 208 | __assume( 0 ); 209 | #endif 210 | break; 211 | 212 | } 213 | 214 | CurrOutBit += 1; 215 | m_BitPos += 1; 216 | 217 | // 218 | // If we're at the last bit in this byte, then increment the current 219 | // read position, but don't claim the first bit just yet. This allows 220 | // us to use byte-level addressing until we're called to read a sub- 221 | // byte quantity once more. 222 | // 223 | 224 | if (m_BitPos == 8) 225 | { 226 | m_DataPos += 1; 227 | m_DataPosRemaining -= 1; 228 | } 229 | 230 | } 231 | 232 | return true; 233 | } 234 | 235 | bool 236 | BufferParser::SkipData( 237 | size_t FieldLength 238 | ) 239 | { 240 | if (m_BitPos != 8) 241 | { 242 | #if BUFFERPARSE_BREAK_ON_FAIL 243 | __debugbreak( ); 244 | #endif 245 | return false; 246 | } 247 | 248 | if (m_DataPosRemaining < FieldLength) 249 | { 250 | #if BUFFERPARSE_BREAK_ON_FAIL 251 | __debugbreak( ); 252 | #endif 253 | return false; 254 | } 255 | 256 | m_DataPosRemaining -= FieldLength; 257 | m_DataPos += FieldLength; 258 | 259 | return true; 260 | } 261 | 262 | bool 263 | BufferParser::SkipBits( 264 | size_t NumBits 265 | ) 266 | { 267 | 268 | // 269 | // Calculate the number of bits remaining in this byte. This is normally 270 | // 8, but if we are the last byte, then we may have a lesser set of valid 271 | // bits. 272 | // 273 | 274 | size_t BitsThisByte = ((m_DataPosRemaining > 1) ? 8 : m_HighestValidBitPos); 275 | size_t BitsRemaining = BitsThisByte - ((m_BitPos == 8) ? 0 : m_BitPos); 276 | 277 | if (NumBits > BitsRemaining) 278 | { 279 | size_t BitsExtra = NumBits - BitsRemaining; 280 | size_t BytesRequired = 1 + (BitsExtra / 8) + ((BitsExtra % 8) ? 1 : 0); 281 | 282 | // 283 | // N.B. 1 + above as m_DataPosRemaining includes the current byte that 284 | // is being worked on. 285 | // 286 | 287 | if (m_DataPosRemaining < BytesRequired) 288 | { 289 | #if BUFFERPARSE_BREAK_ON_FAIL 290 | __debugbreak( ); 291 | #endif 292 | return false; 293 | } 294 | 295 | // 296 | // If we are going to be operating on the last byte, then ensure that 297 | // we don't extend past the last valid bit. 298 | // 299 | 300 | if ((m_DataPosRemaining == BytesRequired) && 301 | ((BitsExtra % 8) > m_HighestValidBitPos)) 302 | { 303 | #if BUFFERPARSE_BREAK_ON_FAIL 304 | __debugbreak( ); 305 | #endif 306 | return false; 307 | } 308 | 309 | m_DataPosRemaining -= BytesRequired; 310 | m_DataPos += BytesRequired; 311 | m_BitPos = BitsExtra % 8; 312 | } 313 | else 314 | { 315 | if (m_BitPos == 8) 316 | m_BitPos = 0; 317 | 318 | m_BitPos += NumBits; 319 | } 320 | 321 | return true; 322 | } 323 | 324 | void 325 | BufferParser::Reset( 326 | ) 327 | { 328 | m_DataPos = m_Data; 329 | m_DataPosRemaining = m_DataLength; 330 | m_BitPos = 8; 331 | m_HighestValidBitPos = 8; 332 | } 333 | 334 | void 335 | BufferParser::SetHighestValidBitPos( 336 | size_t HighestValidBitPos 337 | ) 338 | { 339 | // if (HighestValidBitPos > 8) 340 | // __debugbreak( ); 341 | m_HighestValidBitPos = HighestValidBitPos; 342 | } 343 | 344 | void 345 | BufferParser::RebaseBuffer( 346 | const void *Data 347 | ) 348 | { 349 | ptrdiff_t PtrDiff; 350 | 351 | PtrDiff = (ptrdiff_t) Data - (ptrdiff_t) m_Data; 352 | 353 | m_Data = (const unsigned char *) ((ptrdiff_t) m_Data + PtrDiff); 354 | m_DataPos = (const unsigned char *) ((ptrdiff_t) m_DataPos + PtrDiff); 355 | } 356 | -------------------------------------------------------------------------------- /_NwnUtilLib/BufferParser.h: -------------------------------------------------------------------------------- 1 | #ifndef _SOURCE_PROGRAMS_SKYWINGUTILS_PARSERS_BUFFERPARSER_H 2 | #define _SOURCE_PROGRAMS_SKYWINGUTILS_PARSERS_BUFFERPARSER_H 3 | 4 | #include "Precomp.h" 5 | 6 | #ifdef _MSC_VER 7 | #pragma once 8 | #elif(__linux__) 9 | #include 10 | #include 11 | #include 12 | #endif 13 | 14 | namespace swutil 15 | { 16 | class IBufferParser 17 | { 18 | 19 | public: 20 | 21 | template< class T > 22 | inline 23 | bool 24 | GetField( 25 | T &Field 26 | ) 27 | { 28 | return GetData( 29 | sizeof( T ), 30 | &Field 31 | ); 32 | } 33 | 34 | virtual 35 | bool 36 | GetDataPtr( 37 | size_t FieldLength, 38 | const void **Field 39 | ) = 0; 40 | 41 | virtual 42 | bool 43 | GetData( 44 | size_t FieldLength, 45 | void *Field 46 | ) = 0; 47 | 48 | inline 49 | bool 50 | GetFieldBit( 51 | bool &FieldBit 52 | ) 53 | { 54 | uint64_t Bits; 55 | 56 | if (!GetFieldBits( 1, Bits )) 57 | return false; 58 | 59 | FieldBit = Bits ? true : false; 60 | 61 | return true; 62 | } 63 | 64 | inline 65 | bool 66 | GetFieldBits( 67 | size_t NumBits, 68 | unsigned char &FieldBits 69 | ) 70 | { 71 | uint64_t Bits; 72 | 73 | if (NumBits > 8) 74 | return false; 75 | 76 | if (!GetFieldBits( NumBits, Bits )) 77 | return false; 78 | 79 | FieldBits = static_cast< unsigned char >( Bits ); 80 | 81 | return true; 82 | } 83 | 84 | inline 85 | bool 86 | GetFieldBits( 87 | size_t NumBits, 88 | unsigned short &FieldBits 89 | ) 90 | { 91 | uint64_t Bits; 92 | 93 | if (NumBits > 16) 94 | return false; 95 | 96 | if (!GetFieldBits( NumBits, Bits )) 97 | return false; 98 | 99 | FieldBits = static_cast< unsigned short >( Bits ); 100 | 101 | return true; 102 | } 103 | 104 | inline 105 | bool 106 | GetFieldBits( 107 | size_t NumBits, 108 | uint32_t &FieldBits 109 | ) 110 | { 111 | uint64_t Bits; 112 | 113 | if (NumBits > 32) 114 | return false; 115 | 116 | if (!GetFieldBits( NumBits, Bits )) 117 | return false; 118 | 119 | FieldBits = static_cast< uint32_t >( Bits ); 120 | 121 | return true; 122 | } 123 | 124 | virtual 125 | bool 126 | GetFieldBits( 127 | size_t NumBits, 128 | uint64_t &FieldBits 129 | ) = 0; 130 | 131 | virtual 132 | bool 133 | AtEndOfStream( 134 | ) const = 0; 135 | 136 | // 137 | // Debugging routine to get the current byte position. 138 | // 139 | 140 | virtual 141 | size_t 142 | GetBytePos( 143 | ) const = 0; 144 | 145 | // 146 | // Debugging routine to get the base data pointer for the parser. 147 | // 148 | 149 | virtual 150 | const unsigned char * 151 | GetBaseDataPointer( 152 | ) const = 0; 153 | 154 | // 155 | // Debugging routine to get the current bit position. 156 | // 157 | 158 | virtual 159 | size_t 160 | GetBitPos( 161 | ) const = 0; 162 | 163 | // 164 | // Debugging routine to get the highest legal bit number in the last 165 | // byte of the bit stream. 166 | // 167 | 168 | virtual 169 | size_t 170 | GetHighestValidBitPos( 171 | ) const = 0; 172 | 173 | virtual 174 | inline 175 | size_t 176 | GetBytesRemaining( 177 | ) const = 0; 178 | 179 | virtual 180 | bool 181 | SkipData( 182 | size_t FieldLength 183 | ) = 0; 184 | 185 | virtual 186 | bool 187 | SkipBits( 188 | size_t NumBits 189 | ) = 0; 190 | 191 | virtual 192 | void 193 | Reset( 194 | ) = 0; 195 | 196 | virtual 197 | void 198 | SetHighestValidBitPos( 199 | size_t HighestValidBitPos 200 | ) = 0; 201 | 202 | virtual 203 | void 204 | RebaseBuffer( 205 | const void *Data 206 | ) = 0; 207 | 208 | }; 209 | 210 | class BufferParser : public IBufferParser 211 | { 212 | 213 | public: 214 | 215 | enum BitOrderMode 216 | { 217 | BitOrderLowToHigh, 218 | BitOrderHighToLow 219 | }; 220 | 221 | BufferParser( 222 | const void *Data, 223 | size_t Length, 224 | BitOrderMode BitOrder = BitOrderLowToHigh 225 | ); 226 | 227 | ~BufferParser( ); 228 | 229 | virtual 230 | bool 231 | GetDataPtr( 232 | size_t FieldLength, 233 | const void **Field 234 | ); 235 | 236 | virtual 237 | bool 238 | GetData( 239 | size_t FieldLength, 240 | void *Field 241 | ); 242 | 243 | inline 244 | bool 245 | GetFieldBits( 246 | size_t NumBits, 247 | unsigned char &FieldBits 248 | ) 249 | { 250 | uint64_t Bits; 251 | 252 | if (NumBits > 8) 253 | return false; 254 | 255 | if (!GetFieldBits( NumBits, Bits )) 256 | return false; 257 | 258 | FieldBits = static_cast< unsigned char >( Bits ); 259 | 260 | return true; 261 | } 262 | 263 | inline 264 | bool 265 | GetFieldBits( 266 | size_t NumBits, 267 | unsigned short &FieldBits 268 | ) 269 | { 270 | uint64_t Bits; 271 | 272 | if (NumBits > 16) 273 | return false; 274 | 275 | if (!GetFieldBits( NumBits, Bits )) 276 | return false; 277 | 278 | FieldBits = static_cast< unsigned short >( Bits ); 279 | 280 | return true; 281 | } 282 | 283 | inline 284 | bool 285 | GetFieldBits( 286 | size_t NumBits, 287 | uint32_t &FieldBits 288 | ) 289 | { 290 | uint64_t Bits; 291 | 292 | if (NumBits > 32) 293 | return false; 294 | 295 | if (!GetFieldBits( NumBits, Bits )) 296 | return false; 297 | 298 | FieldBits = static_cast< uint32_t >( Bits ); 299 | 300 | return true; 301 | } 302 | 303 | virtual 304 | bool 305 | GetFieldBits( 306 | size_t NumBits, 307 | uint64_t &FieldBits 308 | ); 309 | 310 | virtual 311 | inline 312 | bool 313 | AtEndOfStream( 314 | ) const 315 | { 316 | // 317 | // If we are in byte mode, just check if we've got any bytes left. 318 | // 319 | 320 | if (m_BitPos == 8) 321 | return (m_DataPosRemaining == 0); 322 | 323 | // 324 | // DataPosRemaining should never be 0 as we have a byte that is 325 | // still being worked on by definition if we are in bit mode. 326 | // 327 | 328 | // 329 | // Otherwise we are in bit mode. We may have a byte left but have 330 | // zero valid bits left within it, so check that. 331 | // 332 | 333 | size_t BitsThisByte = ((m_DataPosRemaining > 1) ? 8 : m_HighestValidBitPos); 334 | size_t BitsRemaining = BitsThisByte - ((m_BitPos == 8) ? 0 : m_BitPos); 335 | 336 | return (BitsRemaining == 0); 337 | } 338 | 339 | virtual 340 | inline 341 | size_t 342 | GetBytePos( 343 | ) const 344 | { 345 | return m_DataPos - m_Data; 346 | } 347 | 348 | virtual 349 | inline 350 | const unsigned char * 351 | GetBaseDataPointer( 352 | ) const 353 | { 354 | return m_Data; 355 | } 356 | 357 | virtual 358 | inline 359 | size_t 360 | GetBitPos( 361 | ) const 362 | { 363 | return m_BitPos; 364 | } 365 | 366 | virtual 367 | inline 368 | size_t 369 | GetHighestValidBitPos( 370 | ) const 371 | { 372 | return m_HighestValidBitPos; 373 | } 374 | 375 | virtual 376 | inline 377 | size_t 378 | GetBytesRemaining( 379 | ) const 380 | { 381 | return (m_DataPosRemaining); 382 | } 383 | 384 | virtual 385 | bool 386 | SkipData( 387 | size_t FieldLength 388 | ); 389 | 390 | virtual 391 | bool 392 | SkipBits( 393 | size_t NumBits 394 | ); 395 | 396 | virtual 397 | void 398 | Reset( 399 | ); 400 | 401 | virtual 402 | void 403 | SetHighestValidBitPos( 404 | size_t HighestValidBitPos 405 | ); 406 | 407 | virtual 408 | void 409 | RebaseBuffer( 410 | const void *Data 411 | ); 412 | 413 | private: 414 | 415 | // 416 | // Initial values for parsing reset. 417 | // 418 | 419 | const unsigned char *m_Data; 420 | size_t m_DataLength; 421 | 422 | // 423 | // Current position and remaining data. 424 | // 425 | 426 | const unsigned char *m_DataPos; 427 | size_t m_DataPosRemaining; 428 | size_t m_BitPos; 429 | size_t m_HighestValidBitPos; 430 | BitOrderMode m_BitOrderMode; 431 | 432 | }; 433 | 434 | } 435 | 436 | #endif 437 | 438 | 439 | -------------------------------------------------------------------------------- /_NwnUtilLib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(nwnutillib 2 | BufferParser.cpp 3 | BufferParser.h 4 | easylogging++.cc 5 | easylogging++.h 6 | findfirst.cpp 7 | findfirst.h 8 | JSON.cpp 9 | JSON.h 10 | JSONValue.cpp 11 | JSONValue.h 12 | NWNUtilLib.h 13 | optionparser.h 14 | OsCompat.cpp 15 | OsCompat.h 16 | Precomp.h 17 | ProjGlobalDefs.h 18 | Ref.h 19 | spec.cpp 20 | spec.h 21 | version.cpp 22 | version.h 23 | VersionConstants.h 24 | ) -------------------------------------------------------------------------------- /_NwnUtilLib/JSON.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File JSON.cpp part of the SimpleJSON Library - http://mjpa.in/json 3 | * 4 | * Copyright (C) 2010 Mike Anchor 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "JSON.h" 26 | 27 | /** 28 | * Blocks off the public constructor 29 | * 30 | * @access private 31 | * 32 | */ 33 | JSON::JSON() 34 | { 35 | } 36 | 37 | /** 38 | * Parses a complete JSON encoded string 39 | * This is just a wrapper around the UNICODE Parse(). 40 | * 41 | * @access public 42 | * 43 | * @param char* data The JSON text 44 | * 45 | * @return JSONValue* Returns a JSON Value representing the root, or NULL on error 46 | */ 47 | JSONValue *JSON::Parse(const char *data) 48 | { 49 | size_t length = strlen(data) + 1; 50 | wchar_t *w_data = (wchar_t*)malloc(length * sizeof(wchar_t)); 51 | 52 | #if defined(WIN32) && !defined(__GNUC__) 53 | size_t ret_value = 0; 54 | if (mbstowcs_s(&ret_value, w_data, length, data, length) != 0) 55 | { 56 | free(w_data); 57 | return NULL; 58 | } 59 | #elif defined(ANDROID) 60 | // mbstowcs seems to misbehave on android 61 | for(size_t i = 0; iStringify(); 120 | else 121 | return L""; 122 | } 123 | 124 | /** 125 | * Skips over any whitespace characters (space, tab, \r or \n) defined by the JSON spec 126 | * 127 | * @access protected 128 | * 129 | * @param wchar_t** data Pointer to a wchar_t* that contains the JSON text 130 | * 131 | * @return bool Returns true if there is more data, or false if the end of the text was reached 132 | */ 133 | bool JSON::SkipWhitespace(const wchar_t **data) 134 | { 135 | while (**data != 0 && (**data == L' ' || **data == L'\t' || **data == L'\r' || **data == L'\n')) 136 | (*data)++; 137 | 138 | return **data != 0; 139 | } 140 | 141 | /** 142 | * Extracts a JSON String as defined by the spec - "" 143 | * Any escaped characters are swapped out for their unescaped values 144 | * 145 | * @access protected 146 | * 147 | * @param wchar_t** data Pointer to a wchar_t* that contains the JSON text 148 | * @param std::wstring& str Reference to a std::wstring to receive the extracted string 149 | * 150 | * @return bool Returns true on success, false on failure 151 | */ 152 | bool JSON::ExtractString(const wchar_t **data, std::wstring &str) 153 | { 154 | str = L""; 155 | 156 | while (**data != 0) 157 | { 158 | // Save the char so we can change it if need be 159 | wchar_t next_char = **data; 160 | 161 | // Escaping something? 162 | if (next_char == L'\\') 163 | { 164 | // Move over the escape char 165 | (*data)++; 166 | 167 | // Deal with the escaped char 168 | switch (**data) 169 | { 170 | case L'"': next_char = L'"'; break; 171 | case L'\\': next_char = L'\\'; break; 172 | case L'/': next_char = L'/'; break; 173 | case L'b': next_char = L'\b'; break; 174 | case L'f': next_char = L'\f'; break; 175 | case L'n': next_char = L'\n'; break; 176 | case L'r': next_char = L'\r'; break; 177 | case L't': next_char = L'\t'; break; 178 | case L'u': 179 | { 180 | // We need 5 chars (4 hex + the 'u') or its not valid 181 | if (!simplejson_wcsnlen(*data, 5)) 182 | return false; 183 | 184 | // Deal with the chars 185 | next_char = 0; 186 | for (int i = 0; i < 4; i++) 187 | { 188 | // Do it first to move off the 'u' and leave us on the 189 | // final hex digit as we move on by one later on 190 | (*data)++; 191 | 192 | next_char <<= 4; 193 | 194 | // Parse the hex digit 195 | if (**data >= '0' && **data <= '9') 196 | next_char |= (**data - '0'); 197 | else if (**data >= 'A' && **data <= 'F') 198 | next_char |= (10 + (**data - 'A')); 199 | else if (**data >= 'a' && **data <= 'f') 200 | next_char |= (10 + (**data - 'a')); 201 | else 202 | { 203 | // Invalid hex digit = invalid JSON 204 | return false; 205 | } 206 | } 207 | break; 208 | } 209 | 210 | // By the spec, only the above cases are allowed 211 | default: 212 | return false; 213 | } 214 | } 215 | 216 | // End of the string? 217 | else if (next_char == L'"') 218 | { 219 | (*data)++; 220 | str.reserve(); // Remove unused capacity 221 | return true; 222 | } 223 | 224 | // Disallowed char? 225 | else if (next_char < L' ' && next_char != L'\t') 226 | { 227 | // SPEC Violation: Allow tabs due to real world cases 228 | return false; 229 | } 230 | 231 | // Add the next char 232 | str += next_char; 233 | 234 | // Move on 235 | (*data)++; 236 | } 237 | 238 | // If we're here, the string ended incorrectly 239 | return false; 240 | } 241 | 242 | /** 243 | * Parses some text as though it is an integer 244 | * 245 | * @access protected 246 | * 247 | * @param wchar_t** data Pointer to a wchar_t* that contains the JSON text 248 | * 249 | * @return double Returns the double value of the number found 250 | */ 251 | double JSON::ParseInt(const wchar_t **data) 252 | { 253 | double integer = 0; 254 | while (**data != 0 && **data >= '0' && **data <= '9') 255 | integer = integer * 10 + (*(*data)++ - '0'); 256 | 257 | return integer; 258 | } 259 | 260 | /** 261 | * Parses some text as though it is a decimal 262 | * 263 | * @access protected 264 | * 265 | * @param wchar_t** data Pointer to a wchar_t* that contains the JSON text 266 | * 267 | * @return double Returns the double value of the decimal found 268 | */ 269 | double JSON::ParseDecimal(const wchar_t **data) 270 | { 271 | double decimal = 0.0; 272 | double factor = 0.1; 273 | while (**data != 0 && **data >= '0' && **data <= '9') 274 | { 275 | int digit = (*(*data)++ - '0'); 276 | decimal = decimal + digit * factor; 277 | factor *= 0.1; 278 | } 279 | return decimal; 280 | } 281 | -------------------------------------------------------------------------------- /_NwnUtilLib/JSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File JSON.h part of the SimpleJSON Library - http://mjpa.in/json 3 | * 4 | * Copyright (C) 2010 Mike Anchor 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _JSON_H_ 26 | #define _JSON_H_ 27 | 28 | // Win32 incompatibilities 29 | #if defined(WIN32) && !defined(__GNUC__) 30 | #define wcsncasecmp _wcsnicmp 31 | static inline bool isnan(double x) { return x != x; } 32 | static inline bool isinf(double x) { return !isnan(x) && isnan(x - x); } 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | // Linux compile fix - from quaker66 40 | #ifdef __GNUC__ 41 | #include 42 | #include 43 | #endif 44 | 45 | // Mac compile fixes - from quaker66, Lion fix by dabrahams 46 | #if defined(__APPLE__) && __DARWIN_C_LEVEL < 200809L || (defined(WIN32) && defined(__GNUC__)) || defined(ANDROID) 47 | #include 48 | #include 49 | 50 | static inline int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) 51 | { 52 | int lc1 = 0; 53 | int lc2 = 0; 54 | 55 | while (n--) 56 | { 57 | lc1 = towlower (*s1); 58 | lc2 = towlower (*s2); 59 | 60 | if (lc1 != lc2) 61 | return (lc1 - lc2); 62 | 63 | if (!lc1) 64 | return 0; 65 | 66 | ++s1; 67 | ++s2; 68 | } 69 | 70 | return 0; 71 | } 72 | #endif 73 | 74 | // Simple function to check a string 's' has at least 'n' characters 75 | static inline bool simplejson_wcsnlen(const wchar_t *s, size_t n) { 76 | if (s == 0) 77 | return false; 78 | 79 | const wchar_t *save = s; 80 | while (n-- > 0) 81 | { 82 | if (*(save++) == 0) return false; 83 | } 84 | 85 | return true; 86 | } 87 | 88 | // Custom types 89 | class JSONValue; 90 | typedef std::vector JSONArray; 91 | typedef std::map JSONObject; 92 | 93 | #include "JSONValue.h" 94 | 95 | class JSON 96 | { 97 | friend class JSONValue; 98 | 99 | public: 100 | static JSONValue* Parse(const char *data); 101 | static JSONValue* Parse(const wchar_t *data); 102 | static std::wstring Stringify(const JSONValue *value); 103 | protected: 104 | static bool SkipWhitespace(const wchar_t **data); 105 | static bool ExtractString(const wchar_t **data, std::wstring &str); 106 | static double ParseInt(const wchar_t **data); 107 | static double ParseDecimal(const wchar_t **data); 108 | private: 109 | JSON(); 110 | }; 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /_NwnUtilLib/JSONValue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File JSONValue.h part of the SimpleJSON Library - http://mjpa.in/json 3 | * 4 | * Copyright (C) 2010 Mike Anchor 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _JSONVALUE_H_ 26 | #define _JSONVALUE_H_ 27 | 28 | #include 29 | #include 30 | 31 | #include "JSON.h" 32 | 33 | class JSON; 34 | 35 | enum JSONType { JSONType_Null, JSONType_String, JSONType_Bool, JSONType_Number, JSONType_Array, JSONType_Object }; 36 | 37 | class JSONValue 38 | { 39 | friend class JSON; 40 | 41 | public: 42 | JSONValue(/*NULL*/); 43 | JSONValue(const wchar_t *m_char_value); 44 | JSONValue(const std::wstring &m_string_value); 45 | JSONValue(bool m_bool_value); 46 | JSONValue(double m_number_value); 47 | JSONValue(int m_integer_value); 48 | JSONValue(const JSONArray &m_array_value); 49 | JSONValue(const JSONObject &m_object_value); 50 | JSONValue(const JSONValue &m_source); 51 | ~JSONValue(); 52 | 53 | bool IsNull() const; 54 | bool IsString() const; 55 | bool IsBool() const; 56 | bool IsNumber() const; 57 | bool IsArray() const; 58 | bool IsObject() const; 59 | 60 | std::wstring AsString() const; 61 | bool AsBool() const; 62 | double AsNumber() const; 63 | const JSONArray &AsArray() const; 64 | const JSONObject &AsObject() const; 65 | 66 | std::size_t CountChildren() const; 67 | bool HasChild(std::size_t index) const; 68 | JSONValue *Child(std::size_t index); 69 | bool HasChild(const wchar_t* name) const; 70 | JSONValue *Child(const wchar_t* name); 71 | std::vector ObjectKeys() const; 72 | 73 | std::wstring Stringify(bool const prettyprint = false) const; 74 | protected: 75 | static JSONValue *Parse(const wchar_t **data); 76 | 77 | private: 78 | static std::wstring StringifyString(const std::wstring &str); 79 | std::wstring StringifyImpl(size_t const indentDepth) const; 80 | static std::wstring Indent(size_t depth); 81 | 82 | JSONType type; 83 | 84 | union 85 | { 86 | bool bool_value; 87 | double number_value; 88 | std::wstring *string_value; 89 | JSONArray *array_value; 90 | JSONObject *object_value; 91 | }; 92 | 93 | }; 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /_NwnUtilLib/NWNUtilLib.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kevin Sheehan on 2/11/18. 3 | // 4 | 5 | #ifndef NWN_TOOLS_NWNUTILLIB_H 6 | #define NWN_TOOLS_NWNUTILLIB_H 7 | 8 | #ifdef _MSC_VER 9 | #pragma once 10 | #endif 11 | 12 | #define BEGIN_NS_SWUTIL() namespace swutil { 13 | #define END_NS_SWUTIL() } 14 | 15 | //#include "findfirst.h" 16 | #include "OsCompat.h" 17 | #include "Ref.h" 18 | #include "BufferParser.h" 19 | 20 | 21 | #undef BEGIN_NS_SWUTIL 22 | #undef END_NS_SWUTIL 23 | 24 | #endif //NWN_TOOLS_NWNUTILLIB_H 25 | -------------------------------------------------------------------------------- /_NwnUtilLib/OsCompat.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kevin Sheehan on 2/10/18. 3 | // 4 | 5 | #include 6 | #include "Precomp.h" 7 | #include "OsCompat.h" 8 | #include "easylogging++.h" 9 | 10 | std::string 11 | OsCompat::getFileExt(const std::string& s) { 12 | 13 | size_t i = s.rfind('.', s.length()); 14 | if (i != std::string::npos) { 15 | return(s.substr(i+1, s.length() - i)); 16 | } 17 | 18 | return(""); 19 | } 20 | 21 | char * OsCompat::filename(const char *str) { 22 | char *result; 23 | char *last; 24 | char *tmpStr = const_cast(str); 25 | if ((last = strrchr(tmpStr, '.')) != nullptr ) { 26 | if ((*last == '.') && (last == tmpStr)) { 27 | return tmpStr; 28 | } else { 29 | result = (char*) malloc(_MAX_FNAME); 30 | char *fname = strtok(tmpStr,"."); 31 | strncpy(result,fname,_MAX_FNAME); 32 | return result; 33 | } 34 | } else { 35 | return tmpStr; 36 | } 37 | } 38 | 39 | char * OsCompat::extname(const char *str) { 40 | char *result; 41 | char *last; 42 | char *tmpStr = const_cast(str); 43 | 44 | if ((last = strrchr(tmpStr, '.')) != nullptr) { 45 | if ((*last == '.') && (last == tmpStr)) 46 | return ""; 47 | else { 48 | result = (char*) malloc(_MAX_EXT); 49 | snprintf(result, _MAX_EXT, "%s", last + 1); 50 | return result; 51 | } 52 | } else { 53 | return ""; // Empty/nullptr string 54 | } 55 | } 56 | 57 | std::string OsCompat::ReplaceAll(std::string str, const std::string& from, const std::string& to) { 58 | size_t start_pos = 0; 59 | while((start_pos = str.find(from, start_pos)) != std::string::npos) { 60 | str.replace(start_pos, from.length(), to); 61 | start_pos += to.length(); // Handles case where 'to' is a substring of 'from' 62 | } 63 | return str; 64 | } 65 | 66 | int OsCompat::dirExists(const char *path) 67 | { 68 | struct stat info; 69 | 70 | if(stat( path, &info ) != 0) { 71 | LOG(DEBUG) << "Bad Path"; 72 | return 0; 73 | } 74 | else if(info.st_mode & S_IFDIR) { 75 | LOG(DEBUG) << "Is a dir"; 76 | return 1; 77 | } 78 | else { 79 | LOG(DEBUG) << "Is not a dir"; 80 | return 0; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /_NwnUtilLib/OsCompat.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kevin Sheehan on 2/10/18. 3 | // 4 | 5 | #ifndef NWN_TOOLS_OSCOMPAT_H 6 | #define NWN_TOOLS_OSCOMPAT_H 7 | 8 | #include 9 | #include 10 | 11 | #if !defined(_WIN32) && !defined(_WIN64) 12 | typedef int8_t CHAR; 13 | typedef uint8_t UCHAR; 14 | typedef uint16_t USHORT; 15 | typedef uint16_t WORD; 16 | typedef int16_t BOOL; 17 | 18 | 19 | typedef uint32_t DWORD; 20 | typedef int32_t LONG; 21 | typedef uint8_t BYTE; 22 | typedef uint64_t ULONG64; 23 | typedef uint32_t ULONG; 24 | 25 | //typedef ULONG64 FileHandle; 26 | //typedef ULONG64 FileId; 27 | //static const FileHandle INVALID_FILE = 0; 28 | 29 | #if defined(_WIN64) 30 | typedef __int64 LONG_PTR; 31 | #else 32 | typedef int32_t LONG_PTR; 33 | #endif 34 | 35 | #if defined(_WIN64) 36 | typedef unsigned __int64 ULONG_PTR; 37 | #else 38 | typedef uint32_t ULONG_PTR; 39 | #endif 40 | 41 | #if !defined(_M_IX86) 42 | typedef uint64_t ULONGLONG; 43 | #else 44 | typedef double ULONGLONG; 45 | #endif 46 | 47 | #if !defined(_M_IX86) 48 | typedef int64_t LONGLONG; 49 | #else 50 | typedef double LONGLONG; 51 | #endif 52 | 53 | typedef void *PVOID; 54 | typedef FILE *HANDLE; 55 | typedef HANDLE HKEY; 56 | 57 | typedef struct _GUID { 58 | DWORD Data1; 59 | WORD Data2; 60 | WORD Data3; 61 | BYTE Data4[8]; 62 | } GUID; 63 | 64 | typedef union _LARGE_INTEGER { 65 | struct { 66 | DWORD LowPart; 67 | LONG HighPart; 68 | }; 69 | struct { 70 | DWORD LowPart; 71 | LONG HighPart; 72 | } u; 73 | LONGLONG QuadPart; 74 | } LARGE_INTEGER, *PLARGE_INTEGER; 75 | 76 | 77 | //#define INVALID_HANDLE_VALUE (0xFFFFFFFF) 78 | #define INVALID_SET_FILE_POINTER ((DWORD)-1) 79 | 80 | 81 | /* compatibility macros */ 82 | #define FillMemory RtlFillMemory 83 | #define MoveMemory RtlMoveMemory 84 | #define ZeroMemory RtlZeroMemory 85 | #define CopyMemory RtlCopyMemory 86 | 87 | #define RtlEqualMemory(Destination, Source, Length) (!memcmp((Destination),(Source),(Length))) 88 | #define RtlMoveMemory(Destination, Source, Length) memmove((Destination),(Source),(Length)) 89 | #define RtlCopyMemory(Destination, Source, Length) memcpy((Destination),(Source),(Length)) 90 | #define RtlFillMemory(Destination, Length, Fill) memset((Destination),(Fill),(Length)) 91 | #define RtlZeroMemory(Destination, Length) memset((Destination),0,(Length)) 92 | 93 | #define vsmin(a, b) (((a) < (b)) ? (a) : (b)) 94 | 95 | #define _MAX_DRIVE 3 96 | #define _MAX_DIR 256 97 | #define _MAX_FNAME 256 98 | #define _MAX_EXT 256 99 | #define _MAX_PATH 1024 100 | 101 | #endif 102 | 103 | #ifdef _WINDOWS 104 | 105 | #include 106 | #define bswap_16(x) _byteswap_ushort(x) 107 | #define bswap_32(x) _byteswap_ulong(x) 108 | #define bswap_64(x) _byteswap_uint64(x) 109 | #define access _access 110 | #define vsmin std::min 111 | 112 | #elif defined(__APPLE__) 113 | 114 | // Mac OS X / Darwin features 115 | #include 116 | #define bswap_16(x) OSSwapInt16(x) 117 | #define bswap_32(x) OSSwapInt32(x) 118 | #define bswap_64(x) OSSwapInt64(x) 119 | 120 | #include 121 | 122 | #elif defined(__sun) || defined(sun) 123 | 124 | #include 125 | #define bswap_16(x) BSWAP_16(x) 126 | #define bswap_32(x) BSWAP_32(x) 127 | #define bswap_64(x) BSWAP_64(x) 128 | 129 | #elif defined(__FreeBSD__) 130 | 131 | #include 132 | #define bswap_16(x) bswap16(x) 133 | #define bswap_32(x) bswap32(x) 134 | #define bswap_64(x) bswap64(x) 135 | 136 | #elif defined(__OpenBSD__) 137 | 138 | #include 139 | #define bswap_16(x) swap16(x) 140 | #define bswap_32(x) swap32(x) 141 | #define bswap_64(x) swap64(x) 142 | 143 | #elif defined(__NetBSD__) 144 | 145 | #include 146 | #include 147 | #if defined(__BSWAP_RENAME) && !defined(__bswap_32) 148 | #define bswap_16(x) bswap16(x) 149 | #define bswap_32(x) bswap32(x) 150 | #define bswap_64(x) bswap64(x) 151 | #endif 152 | 153 | #else 154 | 155 | #include 156 | 157 | #endif 158 | 159 | class OsCompat { 160 | public: 161 | 162 | static std::string getFileExt(const std::string &s); 163 | static char *filename(const char *str); 164 | char * extname(const char *str); 165 | static std::string ReplaceAll(std::string str, const std::string& from, const std::string& to); 166 | static int dirExists(const char *path); 167 | }; 168 | 169 | #endif //NWN_TOOLS_OSCOMPAT_H 170 | -------------------------------------------------------------------------------- /_NwnUtilLib/Precomp.h: -------------------------------------------------------------------------------- 1 | #ifndef _SOURCE_PROGRAMS_SKYWINGUTILS_PRECOMP_H 2 | #define _SOURCE_PROGRAMS_SKYWINGUTILS_PRECOMP_H 3 | 4 | #ifdef _MSC_VER 5 | #pragma once 6 | 7 | // 8 | // Turn off warnings about deprecated API usage in ATL. 9 | // 10 | 11 | #pragma warning(push) 12 | #pragma warning(disable:4995) // warning C4995: 'wcscpy': name was marked as #pragma deprecated 13 | 14 | #endif 15 | 16 | #if defined(_WINDOWS) 17 | 18 | //#include 19 | //#include 20 | //#include 21 | #include 22 | #ifndef SKIP_ATLENC 23 | #include 24 | #endif 25 | #include 26 | #include 27 | #include 28 | 29 | #endif 30 | 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #ifdef _MSC_VER 42 | #pragma warning(pop) 43 | #pragma warning(disable:4512) // warning C4512: 'swutil::ScopedLock' : assignment operator could not be generated 44 | #endif 45 | 46 | #endif 47 | 48 | 49 | -------------------------------------------------------------------------------- /_NwnUtilLib/ProjGlobalDefs.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | ProjGlobalDefs.h 8 | 9 | Abstract: 10 | 11 | This module defines common values and macros that are used across all 12 | NWN2Dev projects. 13 | 14 | --*/ 15 | 16 | #ifndef _PROGRAMS_PROJECTGLOBAL_PROJGLOBALDEFS_H 17 | #define _PROGRAMS_PROJECTGLOBAL_PROJGLOBALDEFS_H 18 | 19 | #ifdef _MSC_VER 20 | #pragma once 21 | #endif 22 | 23 | #ifdef __cplusplus 24 | extern "C" 25 | { 26 | #endif 27 | 28 | // 29 | // Test if an argument is present (i.e. non-NULL) or not. 30 | // 31 | 32 | #define ARGUMENT_PRESENT( x ) ( (x) ) 33 | 34 | // 35 | // Standard assertion. 36 | // 37 | 38 | #define ASSERT( x ) assert( (x) ) 39 | 40 | // 41 | // NT_ASSERT-like assertion (annotation embedded in symbols, compact raise 42 | // assertion instrumentation). 43 | // 44 | 45 | #define NWN_ASSERT( _exp ) \ 46 | ((!(_exp)) ? \ 47 | (__annotation( L"Debug", L"AssertFail", L#_exp ), \ 48 | DbgRaiseAssertionFailure( ), FALSE) : \ 49 | TRUE) 50 | 51 | #ifdef _MSC_VER 52 | #if defined(_X86_) || defined(_AMD64_) 53 | 54 | unsigned __int64 55 | __rdtsc( 56 | ); 57 | #pragma intrinsic(__rdtsc) 58 | 59 | #define _ReadTimeStampCounter() __rdtsc() 60 | 61 | #elif defined(_IA64_) 62 | 63 | unsigned __int64 64 | __getReg( 65 | __in int Number 66 | ); 67 | #pragma intrinsic(__getReg) 68 | 69 | #define _ReadTimeStampCounter() __getReg(3116) /* CV_IA64_ApITC */ 70 | 71 | #else 72 | 73 | #define _ReadTimeStampCounter() GetTickCount() 74 | 75 | #endif // arch 76 | #else // _MSC_VER 77 | #define _ReadTimeStampCounter() GetTickCount() 78 | #endif 79 | 80 | #define PI 3.14159265f 81 | #define DEGREES_TO_RADIANS 0.0174532925f 82 | 83 | #if defined(_M_IX86) 84 | #define BUILD_ARCHITECTURE_STRING "i386" 85 | #elif defined(_AMD64_) 86 | #define BUILD_ARCHITECTURE_STRING "amd64" 87 | #elif defined(_IA64_) 88 | #define BUILD_ARCHITECTURE_STRING "ia64" 89 | #else 90 | #define BUILD_ARCHITECTURE_STRING "" 91 | #endif 92 | 93 | // 94 | // Ensure standard macros actually have definitions. 95 | // 96 | 97 | #ifndef __DATE__ 98 | #define __DATE__ "" 99 | #endif 100 | 101 | #ifndef __TIME__ 102 | #define __TIME__ "" 103 | #endif 104 | 105 | #ifdef __cplusplus 106 | } 107 | #endif 108 | 109 | #endif 110 | 111 | -------------------------------------------------------------------------------- /_NwnUtilLib/VersionConstants.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Ken Johnson (Skywing). All rights reserved. 4 | 5 | Module Name: 6 | 7 | VersionConstants.h 8 | 9 | Abstract: 10 | 11 | The module houses SKU-definition constants. 12 | 13 | --*/ 14 | 15 | #ifndef _PROGRAMS_PROJECTGLOBAL_VERSIONCONSTANTS_H 16 | #define _PROGRAMS_PROJECTGLOBAL_VERSIONCONSTANTS_H 17 | 18 | #ifdef _MSC_VER 19 | #pragma once 20 | #endif 21 | 22 | #define NWN2MAIN_VERSION 0x01231765 23 | 24 | // 25 | // Extract the build number (e.g. 1765) from the low order word as a BCD-hex 26 | // value, e.g. 0x1765 -> 1765. 27 | // 28 | 29 | #ifdef RC_INVOKED 30 | 31 | #if 0 32 | // 33 | // rc.exe doesn't support operator >> so do it with div. 34 | // 35 | 36 | #define NWN2_BUILD \ 37 | (((NWN2MAIN_VERSION & 0x000F) * (0x0001)) * 1) + \ 38 | (((NWN2MAIN_VERSION & 0x00F0) * (0x0010)) * 10) + \ 39 | (((NWN2MAIN_VERSION & 0x0F00) * (0x0100)) * 100) + \ 40 | (((NWN2MAIN_VERSION & 0xF000) * (0x1000)) * 1000) 41 | #endif 42 | 43 | #else // RC_INVOKED 44 | 45 | #define NWN2_BUILD \ 46 | (((NWN2MAIN_VERSION >> 0) & 0xF) * 1) + \ 47 | (((NWN2MAIN_VERSION >> 4) & 0xF) * 10) + \ 48 | (((NWN2MAIN_VERSION >> 8) & 0xF) * 100) + \ 49 | (((NWN2MAIN_VERSION >> 12) & 0xF) * 1000) 50 | 51 | #endif // RC_INVOKED 52 | 53 | #define NWN2_BUILD_STR__( x ) #x 54 | #define NWN2_BUILD_STR_( x ) NWN2_BUILD_STR__( x ) 55 | #define NWN2_BUILD_STRL__( x ) L#x 56 | #define NWN2_BUILD_STRL_( x ) NWN2_BUILD_STRL__( x ) 57 | #define NWN2_BUILD_STR NWN2_BUILD_STR_( NWN2MAIN_VERSION ) 58 | 59 | #define NWN2DEV_COPYRIGHT_STR "Copyright (C) 2008-2015 Skywing" 60 | #define __NWN2DEV_COPYRIGHT_STR_MAKE_L(STOKEN) L ## STOKEN 61 | #define __NWN2DEV_COPYRIGHT_STR_MAKE_L_(STOKEN) __NWN2DEV_COPYRIGHT_STR_MAKE_L(STOKEN) 62 | #define NWN2DEV_COPYRIGHT_STR_L __NWN2DEV_COPYRIGHT_STR_MAKE_L_(NWN2DEV_COPYRIGHT_STR) 63 | 64 | #define CLIEXTVER_MAJORMAJOR 1 65 | #define CLIEXTVER_MAJORMINOR 0 66 | #define CLIEXTVER_MINORMAJOR 0 67 | #define CLIEXTVER_MINORMINOR 29 68 | 69 | #define CLIEXT_VER CLIEXTVER_MAJORMAJOR, \ 70 | CLIEXTVER_MAJORMINOR, \ 71 | CLIEXTVER_MINORMAJOR, \ 72 | CLIEXTVER_MINORMINOR 73 | 74 | #define CLIEXTVER_STR NWN2_BUILD_STR_( CLIEXTVER_MAJORMAJOR ) "." \ 75 | NWN2_BUILD_STR_( CLIEXTVER_MAJORMINOR ) "." \ 76 | NWN2_BUILD_STR_( CLIEXTVER_MINORMAJOR ) "." \ 77 | NWN2_BUILD_STR_( CLIEXTVER_MINORMINOR ) 78 | 79 | 80 | #define CLIEXTVER_STRW NWN2_BUILD_STRL_( CLIEXTVER_MAJORMAJOR ) L"." \ 81 | NWN2_BUILD_STRL_( CLIEXTVER_MAJORMINOR ) L"." \ 82 | NWN2_BUILD_STRL_( CLIEXTVER_MINORMAJOR ) L"." \ 83 | NWN2_BUILD_STRL_( CLIEXTVER_MINORMINOR ) 84 | 85 | #define CLIEXT_VER_PACKED ((CLIEXTVER_MAJORMAJOR << 24) | \ 86 | (CLIEXTVER_MAJORMINOR << 16) | \ 87 | (CLIEXTVER_MINORMAJOR << 8) | \ 88 | (CLIEXTVER_MINORMINOR << 0) ) \ 89 | 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /_NwnUtilLib/findfirst.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kevin Sheehan on 2/10/18. 3 | // 4 | 5 | /* 6 | * Copyright (C) 2011 Mathieu Turcotte (mathieuturcotte.ca) 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see http://www.gnu.org/licenses/. 20 | */ 21 | 22 | #if !defined(_WIN32) && !defined(_WIN64) 23 | 24 | #ifdef __linux__ 25 | #define _XOPEN_SOURCE 700 /* SUSv4 */ 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #ifdef __linux__ 41 | #include 42 | #endif 43 | 44 | #include "findfirst.h" 45 | #include "spec.h" 46 | 47 | #define DOTDOT_HANDLE 0L 48 | #define INVALID_HANDLE -1L 49 | 50 | typedef struct fhandle_t { 51 | DIR* dstream; 52 | short dironly; 53 | char* spec; 54 | } fhandle_t; 55 | 56 | static void fill_finddata(struct stat* st, const char* name, 57 | struct _finddata_t* fileinfo); 58 | 59 | static intptr_t findfirst_dotdot(const char* filespec, 60 | struct _finddata_t* fileinfo); 61 | 62 | static intptr_t findfirst_in_directory(const char* dirpath, 63 | const char* spec, struct _finddata_t* fileinfo); 64 | 65 | static void findfirst_set_errno(); 66 | 67 | intptr_t _findfirst(const char* filespec, struct _finddata_t* fileinfo) { 68 | const char* rmslash; /* Rightmost forward slash in filespec. */ 69 | const char* spec; /* Specification string. */ 70 | 71 | if (!fileinfo || !filespec) { 72 | errno = EINVAL; 73 | return INVALID_HANDLE; 74 | } 75 | 76 | if (filespec[0] == '\0') { 77 | errno = ENOENT; 78 | return INVALID_HANDLE; 79 | } 80 | 81 | rmslash = strrchr(filespec, '/'); 82 | 83 | if (rmslash != NULL) { 84 | /* 85 | * At least one forward slash was found in the filespec 86 | * string, and rmslash points to the rightmost one. The 87 | * specification part, if any, begins right after it. 88 | */ 89 | spec = rmslash + 1; 90 | } else { 91 | /* 92 | * Since no slash was found in the filespec string, its 93 | * entire content can be used as our spec string. 94 | */ 95 | spec = filespec; 96 | } 97 | 98 | if (strcmp(spec, ".") == 0 || strcmp(spec, "..") == 0) { 99 | /* On Windows, . and .. must return canonicalized names. */ 100 | return findfirst_dotdot(filespec, fileinfo); 101 | } else if (rmslash == filespec) { 102 | /* 103 | * Since the rightmost slash is the first character, we're 104 | * looking for something located at the file system's root. 105 | */ 106 | return findfirst_in_directory("/", spec, fileinfo); 107 | } else if (rmslash != NULL) { 108 | /* 109 | * Since the rightmost slash isn't the first one, we're 110 | * looking for something located in a specific folder. In 111 | * order to open this folder, we split the folder path from 112 | * the specification part by overwriting the rightmost 113 | * forward slash. 114 | */ 115 | size_t pathlen = strlen(filespec) +1; 116 | char* dirpath = new char[pathlen]; 117 | memcpy(dirpath, filespec, pathlen); 118 | dirpath[rmslash - filespec] = '\0'; 119 | return findfirst_in_directory(dirpath, spec, fileinfo); 120 | } else { 121 | /* 122 | * Since the filespec doesn't contain any forward slash, 123 | * we're looking for something located in the current 124 | * directory. 125 | */ 126 | return findfirst_in_directory(".", spec, fileinfo); 127 | } 128 | } 129 | 130 | /* Perfom a scan in the directory identified by dirpath. */ 131 | static intptr_t findfirst_in_directory(const char* dirpath, 132 | const char* spec, struct _finddata_t* fileinfo) { 133 | DIR* dstream; 134 | fhandle_t* ffhandle; 135 | 136 | if (spec[0] == '\0') { 137 | errno = ENOENT; 138 | return INVALID_HANDLE; 139 | } 140 | 141 | if ((dstream = opendir(dirpath)) == NULL) { 142 | findfirst_set_errno(); 143 | return INVALID_HANDLE; 144 | } 145 | 146 | if ((ffhandle = static_cast(malloc(sizeof(fhandle_t)))) == NULL) { 147 | closedir(dstream); 148 | errno = ENOMEM; 149 | return INVALID_HANDLE; 150 | } 151 | 152 | /* On Windows, *. returns only directories. */ 153 | ffhandle->dironly = strcmp(spec, "*.") == 0 ? 1 : 0; 154 | ffhandle->dstream = dstream; 155 | ffhandle->spec = strdup(spec); 156 | 157 | if (_findnext((intptr_t) ffhandle, fileinfo) != 0) { 158 | _findclose((intptr_t) ffhandle); 159 | errno = ENOENT; 160 | return INVALID_HANDLE; 161 | } 162 | 163 | return (intptr_t) ffhandle; 164 | } 165 | 166 | /* On Windows, . and .. return canonicalized directory names. */ 167 | static intptr_t findfirst_dotdot(const char* filespec, 168 | struct _finddata_t* fileinfo) { 169 | char* dirname; 170 | char* canonicalized; 171 | struct stat st; 172 | 173 | if (stat(filespec, &st) != 0) { 174 | findfirst_set_errno(); 175 | return INVALID_HANDLE; 176 | } 177 | 178 | /* Resolve filespec to an absolute path. */ 179 | if ((canonicalized = realpath(filespec, NULL)) == NULL) { 180 | findfirst_set_errno(); 181 | return INVALID_HANDLE; 182 | } 183 | 184 | /* Retrieve the basename from it. */ 185 | dirname = basename(canonicalized); 186 | 187 | /* Make sure that we actually have a basename. */ 188 | if (dirname[0] == '\0') { 189 | free(canonicalized); 190 | errno = ENOENT; 191 | return INVALID_HANDLE; 192 | } 193 | 194 | /* Make sure that we won't overflow finddata_t::name. */ 195 | if (strlen(dirname) > 259) { 196 | free(canonicalized); 197 | errno = ENOMEM; 198 | return INVALID_HANDLE; 199 | } 200 | 201 | fill_finddata(&st, dirname, fileinfo); 202 | 203 | free(canonicalized); 204 | 205 | /* 206 | * Return a special handle since we can't return 207 | * NULL. The findnext and findclose functions know 208 | * about this custom handle. 209 | */ 210 | return DOTDOT_HANDLE; 211 | } 212 | 213 | /* 214 | * Windows implementation of _findfirst either returns EINVAL, 215 | * ENOENT or ENOMEM. This function makes sure that the above 216 | * implementation doesn't return anything else when an error 217 | * condition is encountered. 218 | */ 219 | static void findfirst_set_errno() { 220 | if (errno != ENOENT && 221 | errno != ENOMEM && 222 | errno != EINVAL) { 223 | errno = EINVAL; 224 | } 225 | } 226 | 227 | static void fill_finddata(struct stat* st, const char* name, 228 | struct _finddata_t* fileinfo) { 229 | fileinfo->attrib = S_ISDIR(st->st_mode) ? _A_SUBDIR : _A_NORMAL; 230 | fileinfo->size = st->st_size; 231 | fileinfo->time_create = st->st_ctime; 232 | fileinfo->time_access = st->st_atime; 233 | fileinfo->time_write = st->st_mtime; 234 | strcpy(fileinfo->name, name); 235 | } 236 | 237 | int _findnext(intptr_t fhandle, struct _finddata_t* fileinfo) { 238 | struct dirent entry, *result; 239 | struct fhandle_t* handle; 240 | struct stat st; 241 | 242 | if (fhandle == DOTDOT_HANDLE) { 243 | errno = ENOENT; 244 | return -1; 245 | } 246 | 247 | if (fhandle == INVALID_HANDLE || !fileinfo) { 248 | errno = EINVAL; 249 | return -1; 250 | } 251 | 252 | handle = (struct fhandle_t*) fhandle; 253 | 254 | while (readdir_r(handle->dstream, &entry, &result) == 0 && result != NULL) { 255 | if (!handle->dironly && !match_spec(handle->spec, entry.d_name)) { 256 | continue; 257 | } 258 | 259 | if (fstatat(dirfd(handle->dstream), entry.d_name, &st, 0) == -1) { 260 | return -1; 261 | } 262 | 263 | if (handle->dironly && !S_ISDIR(st.st_mode)) { 264 | continue; 265 | } 266 | 267 | fill_finddata(&st, entry.d_name, fileinfo); 268 | 269 | return 0; 270 | } 271 | 272 | errno = ENOENT; 273 | return -1; 274 | } 275 | 276 | int _findclose(intptr_t fhandle) { 277 | struct fhandle_t* handle; 278 | 279 | if (fhandle == DOTDOT_HANDLE) { 280 | return 0; 281 | } 282 | 283 | if (fhandle == INVALID_HANDLE) { 284 | errno = ENOENT; 285 | return -1; 286 | } 287 | 288 | handle = (struct fhandle_t*) fhandle; 289 | 290 | closedir(handle->dstream); 291 | free(handle->spec); 292 | free(handle); 293 | 294 | return 0; 295 | } 296 | 297 | #endif -------------------------------------------------------------------------------- /_NwnUtilLib/findfirst.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kevin Sheehan on 2/10/18. 3 | // 4 | 5 | #ifndef NWN_TOOLS_FINDFIRST_H 6 | #define NWN_TOOLS_FINDFIRST_H 7 | 8 | #if !defined(_WIN32) && !defined(_WIN64) 9 | 10 | /* 11 | * Copyright (C) 2011 Mathieu Turcotte (mathieuturcotte.ca) 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see http://www.gnu.org/licenses/. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | /* http://en.wikipedia.org/wiki/Attrib */ 32 | #define _A_NORMAL 0x00 /* Normal file. */ 33 | #define _A_RDONLY 0x01 /* Read only file. */ 34 | #define _A_HIDDEN 0x02 /* Hidden file. */ 35 | #define _A_SYSTEM 0x04 /* System file. */ 36 | #define _A_SUBDIR 0x10 /* Subdirectory. */ 37 | #define _A_ARCH 0x20 /* Archive file. */ 38 | 39 | struct _finddata_t { 40 | unsigned attrib; 41 | time_t time_create; 42 | time_t time_access; 43 | time_t time_write; 44 | off_t size; 45 | char name[260]; 46 | }; 47 | 48 | /* 49 | * Returns a unique search handle identifying the file or group of 50 | * files matching the filespec specification, which can be used in 51 | * a subsequent call to findnext or to findclose. Otherwise, findfirst 52 | * returns NULL and sets errno to EINVAL if filespec or fileinfo 53 | * was NULL or if the operating system returned an unexpected error 54 | * and ENOENT if the file specification could not be matched. 55 | */ 56 | intptr_t _findfirst(const char* filespec, struct _finddata_t* fileinfo); 57 | 58 | /* 59 | * Find the next entry, if any, that matches the filespec argument 60 | * of a previous call to findfirst, and then alter the fileinfo 61 | * structure contents accordingly. If successful, returns 0. Otherwise, 62 | * returns -1 and sets errno to EINVAL if handle or fileinfo was NULL 63 | * or if the operating system returned an unexpected error and ENOENT 64 | * if no more matching files could be found. 65 | */ 66 | int _findnext(intptr_t handle, struct _finddata_t* fileinfo); 67 | 68 | /* 69 | * Closes the specified search handle and releases associated 70 | * resources. If successful, findclose returns 0. Otherwise, it 71 | * returns -1 and sets errno to ENOENT, indicating that no more 72 | * matching files could be found. 73 | */ 74 | int _findclose(intptr_t handle); 75 | 76 | #endif 77 | 78 | #endif //NWN_TOOLS_FINDFIRST_H 79 | -------------------------------------------------------------------------------- /_NwnUtilLib/spec.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kevin Sheehan on 2/11/18. 3 | // 4 | 5 | /* 6 | * Copyright (C) 2011 Mathieu Turcotte (mathieuturcotte.ca) 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see http://www.gnu.org/licenses/. 20 | */ 21 | 22 | #include 23 | 24 | #include "spec.h" 25 | 26 | int _match_spec(const char* spec, const char* text) { 27 | /* 28 | * If the whole specification string was consumed and 29 | * the input text is also exhausted: it's a match. 30 | */ 31 | if (spec[0] == '\0' && text[0] == '\0') { 32 | return 1; 33 | } 34 | 35 | /* A star matches 0 or more characters. */ 36 | if (spec[0] == '*') { 37 | /* 38 | * Skip the star and try to find a match after it 39 | * by successively incrementing the text pointer. 40 | */ 41 | do { 42 | if (_match_spec(spec + 1, text)) { 43 | return 1; 44 | } 45 | } while (*text++ != '\0'); 46 | } 47 | 48 | /* 49 | * An interrogation mark matches any character. Other 50 | * characters match themself. Also, if the input text 51 | * is exhausted but the specification isn't, there is 52 | * no match. 53 | */ 54 | if (text[0] != '\0' && (spec[0] == '?' || spec[0] == text[0])) { 55 | return _match_spec(spec + 1, text + 1); 56 | } 57 | 58 | return 0; 59 | } 60 | 61 | int match_spec(const char* spec, const char* text) { 62 | /* On Windows, *.* matches everything. */ 63 | if (strcmp(spec, "*.*") == 0) { 64 | return 1; 65 | } 66 | 67 | return _match_spec(spec, text); 68 | } -------------------------------------------------------------------------------- /_NwnUtilLib/spec.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kevin Sheehan on 2/11/18. 3 | // 4 | 5 | #ifndef NWN_TOOLS_SPEC_H 6 | #define NWN_TOOLS_SPEC_H 7 | 8 | /* 9 | * Copyright (C) 2011 Mathieu Turcotte (mathieuturcotte.ca) 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see http://www.gnu.org/licenses/. 23 | */ 24 | 25 | #ifndef SPEC_H_ 26 | #define SPEC_H_ 27 | 28 | /* 29 | * Matches the regular language accepted by findfirst/findnext. More 30 | * precisely, * matches zero or more characters and ? matches any 31 | * characters, but only one. Every other characters match themself. 32 | * To respect the Windows behavior, *.* matches everything. 33 | */ 34 | int match_spec(const char* spec, const char* text); 35 | 36 | #endif /* SPEC_H_ */ 37 | 38 | #endif //NWN_TOOLS_SPEC_H 39 | -------------------------------------------------------------------------------- /_NwnUtilLib/version.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Kevin Sheehan on 2/19/18. 3 | // 4 | 5 | #ifndef NWN_TOOLS_VERSION_H 6 | #define NWN_TOOLS_VERSION_H 7 | 8 | #include 9 | 10 | extern const std::string gGIT_VERSION; 11 | extern const std::string gGIT_VERSION_SHORT; 12 | 13 | #endif //NWN_TOOLS_VERSION_H 14 | -------------------------------------------------------------------------------- /cmake/modules/GetGitRevisionDescription.cmake: -------------------------------------------------------------------------------- 1 | # - Returns a version string from Git 2 | # 3 | # These functions force a re-configure on each git commit so that you can 4 | # trust the values of the variables in your build system. 5 | # 6 | # get_git_head_revision( [ ...]) 7 | # 8 | # Returns the refspec and sha hash of the current head revision 9 | # 10 | # git_describe( [ ...]) 11 | # 12 | # Returns the results of git describe on the source tree, and adjusting 13 | # the output so that it tests false if an error occurs. 14 | # 15 | # git_get_exact_tag( [ ...]) 16 | # 17 | # Returns the results of git describe --exact-match on the source tree, 18 | # and adjusting the output so that it tests false if there was no exact 19 | # matching tag. 20 | # 21 | # git_local_changes() 22 | # 23 | # Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. 24 | # Uses the return code of "git diff-index --quiet HEAD --". 25 | # Does not regard untracked files. 26 | # 27 | # Requires CMake 2.6 or newer (uses the 'function' command) 28 | # 29 | # Original Author: 30 | # 2009-2010 Ryan Pavlik 31 | # http://academic.cleardefinition.com 32 | # Iowa State University HCI Graduate Program/VRAC 33 | # 34 | # Copyright Iowa State University 2009-2010. 35 | # Distributed under the Boost Software License, Version 1.0. 36 | # (See accompanying file LICENSE_1_0.txt or copy at 37 | # http://www.boost.org/LICENSE_1_0.txt) 38 | 39 | if(__get_git_revision_description) 40 | return() 41 | endif() 42 | set(__get_git_revision_description YES) 43 | 44 | # We must run the following at "include" time, not at function call time, 45 | # to find the path to this module rather than the path to a calling list file 46 | get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) 47 | 48 | function(get_git_head_revision _refspecvar _hashvar) 49 | set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 50 | set(GIT_DIR "${GIT_PARENT_DIR}/.git") 51 | while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories 52 | set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") 53 | get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) 54 | if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) 55 | # We have reached the root directory, we are not in git 56 | set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) 57 | set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) 58 | return() 59 | endif() 60 | set(GIT_DIR "${GIT_PARENT_DIR}/.git") 61 | endwhile() 62 | # check if this is a submodule 63 | if(NOT IS_DIRECTORY ${GIT_DIR}) 64 | file(READ ${GIT_DIR} submodule) 65 | string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) 66 | get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) 67 | get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) 68 | endif() 69 | set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") 70 | if(NOT EXISTS "${GIT_DATA}") 71 | file(MAKE_DIRECTORY "${GIT_DATA}") 72 | endif() 73 | 74 | if(NOT EXISTS "${GIT_DIR}/HEAD") 75 | return() 76 | endif() 77 | set(HEAD_FILE "${GIT_DATA}/HEAD") 78 | configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) 79 | 80 | configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" 81 | "${GIT_DATA}/grabRef.cmake" 82 | @ONLY) 83 | include("${GIT_DATA}/grabRef.cmake") 84 | 85 | set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) 86 | set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) 87 | endfunction() 88 | 89 | function(git_describe _var) 90 | if(NOT GIT_FOUND) 91 | find_package(Git QUIET) 92 | endif() 93 | get_git_head_revision(refspec hash) 94 | if(NOT GIT_FOUND) 95 | set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) 96 | return() 97 | endif() 98 | if(NOT hash) 99 | set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) 100 | return() 101 | endif() 102 | 103 | # TODO sanitize 104 | #if((${ARGN}" MATCHES "&&") OR 105 | # (ARGN MATCHES "||") OR 106 | # (ARGN MATCHES "\\;")) 107 | # message("Please report the following error to the project!") 108 | # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") 109 | #endif() 110 | 111 | #message(STATUS "Arguments to execute_process: ${ARGN}") 112 | 113 | execute_process(COMMAND 114 | "${GIT_EXECUTABLE}" 115 | describe 116 | ${ARGN} 117 | WORKING_DIRECTORY 118 | "${CMAKE_CURRENT_SOURCE_DIR}" 119 | RESULT_VARIABLE 120 | res 121 | OUTPUT_VARIABLE 122 | out 123 | ERROR_QUIET 124 | OUTPUT_STRIP_TRAILING_WHITESPACE) 125 | if(NOT res EQUAL 0) 126 | set(out "${out}-${res}-NOTFOUND") 127 | endif() 128 | 129 | set(${_var} "${out}" PARENT_SCOPE) 130 | endfunction() 131 | 132 | function(git_get_exact_tag _var) 133 | git_describe(out --exact-match ${ARGN}) 134 | set(${_var} "${out}" PARENT_SCOPE) 135 | endfunction() 136 | 137 | function(git_local_changes _var) 138 | if(NOT GIT_FOUND) 139 | find_package(Git QUIET) 140 | endif() 141 | get_git_head_revision(refspec hash) 142 | if(NOT GIT_FOUND) 143 | set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) 144 | return() 145 | endif() 146 | if(NOT hash) 147 | set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) 148 | return() 149 | endif() 150 | 151 | execute_process(COMMAND 152 | "${GIT_EXECUTABLE}" 153 | diff-index --quiet HEAD -- 154 | WORKING_DIRECTORY 155 | "${CMAKE_CURRENT_SOURCE_DIR}" 156 | RESULT_VARIABLE 157 | res 158 | OUTPUT_VARIABLE 159 | out 160 | ERROR_QUIET 161 | OUTPUT_STRIP_TRAILING_WHITESPACE) 162 | if(res EQUAL 0) 163 | set(${_var} "CLEAN" PARENT_SCOPE) 164 | else() 165 | set(${_var} "DIRTY" PARENT_SCOPE) 166 | endif() 167 | endfunction() 168 | -------------------------------------------------------------------------------- /cmake/modules/GetGitRevisionDescription.cmake.in: -------------------------------------------------------------------------------- 1 | # 2 | # Internal file for GetGitRevisionDescription.cmake 3 | # 4 | # Requires CMake 2.6 or newer (uses the 'function' command) 5 | # 6 | # Original Author: 7 | # 2009-2010 Ryan Pavlik 8 | # http://academic.cleardefinition.com 9 | # Iowa State University HCI Graduate Program/VRAC 10 | # 11 | # Copyright Iowa State University 2009-2010. 12 | # Distributed under the Boost Software License, Version 1.0. 13 | # (See accompanying file LICENSE_1_0.txt or copy at 14 | # http://www.boost.org/LICENSE_1_0.txt) 15 | 16 | set(HEAD_HASH) 17 | 18 | file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) 19 | 20 | string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) 21 | if(HEAD_CONTENTS MATCHES "ref") 22 | # named branch 23 | string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") 24 | if(EXISTS "@GIT_DIR@/${HEAD_REF}") 25 | configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) 26 | else() 27 | configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) 28 | file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) 29 | if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") 30 | set(HEAD_HASH "${CMAKE_MATCH_1}") 31 | endif() 32 | endif() 33 | else() 34 | # detached HEAD 35 | configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) 36 | endif() 37 | 38 | if(NOT HEAD_HASH) 39 | file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) 40 | string(STRIP "${HEAD_HASH}" HEAD_HASH) 41 | endif() -------------------------------------------------------------------------------- /cmake/modules/version.cpp.in: -------------------------------------------------------------------------------- 1 | #include "version.h" 2 | 3 | const std::string gGIT_VERSION = "@VERSION@"; 4 | const std::string gGIT_VERSION_SHORT = "@VERSION_SHORT@"; -------------------------------------------------------------------------------- /extras/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Sample Makefile for use with nwnsc 3 | # 4 | # Notes for Windows users 5 | # make is not installed by default on Windows, you'll need to download it. 6 | # The easiest option is: 7 | # http://www.equation.com/servlet/equation.cmd?fa=make 8 | # as that comes without any dependencies. Other options are Cygwin and MinGW. 9 | 10 | # 11 | # Examples of commands to run: 12 | # make batch - Compile everything in a single batch call 13 | # make -j8 - Compile everything, one call per file, on 8 threads 14 | # make clean - Remove all .ncs and .d files 15 | # make VERBOSE=1 - Compile everything, one call per file, extra verbose output 16 | # make 17 | 18 | # 19 | # Set up your paths. These values can also be set as environment variables, and 20 | # they will overwrite what is specified here. 21 | # 22 | # You can also override them from the command line, like: 23 | # make NWNDIR=path/to/nwn NWNHOMEDIR=path/to/home 24 | 25 | # Path to nwnsc compiler 26 | NWNSC ?= ../nwnsc/nwnsc 27 | # Path to the NWN:EE home directory 28 | NWNHOMEDIR ?= "~/.local/share/Neverwinter Nights" 29 | # Install directory for NWN:EE 30 | NWNDIR ?= "~/Beamdog Library/00829" 31 | # Path to folder with scripts to be compiled 32 | SCRIPTS ?= . 33 | # Where the compiled NCS files are to be stored 34 | OUTPUTDIR ?= $(SCRIPTS) 35 | # Any additional dirs to look into when including files 36 | INCLUDE_DIRS ?= 37 | # Whether to print verbose info while compiling 38 | VERBOSE ?= 39 | 40 | # NSS is a list of all scripts to compile 41 | NSS := $(wildcard $(SCRIPTS)/*.nss) 42 | # NCS is a list of all final compiled scripts 43 | NCS := $(addprefix $(OUTPUTDIR)/,$(notdir $(NSS:.nss=.ncs))) 44 | 45 | # Additional flags to pass to the compiler 46 | NSCFLAGS ?= -ole 47 | 48 | # Add scripts dir to includes includes if not current dir 49 | ifneq ("$(SCRIPTS)",".") 50 | INCLUDE_DIRS += $(SCRIPTS) 51 | endif 52 | 53 | ifneq ("$(INCLUDE_DIRS)","") 54 | INCLUDE_DIRS := $(addprefix -i ,$(INCLUDE_DIRS)) 55 | endif 56 | 57 | ifeq ("$(VERBOSE)","") 58 | Q = @ 59 | NSCFLAGS += -q 60 | else 61 | Q = 62 | endif 63 | 64 | build:: $(NCS) 65 | 66 | $(OUTPUTDIR)/%.ncs: $(SCRIPTS)/%.nss 67 | $(Q)echo [nwnsc] $@ 68 | $(Q)$(NWNSC) $(NSCFLAGS) -n $(NWNDIR) -i "$(NWNDIR)/ovr" $(INCLUDE_DIRS) -i $(SCRIPTS) -M -r $@ $< 69 | 70 | batch: 71 | $(Q)echo [nwnsc] $(NCS) 72 | $(Q)$(NWNSC) $(NSCFLAGS) -n $(NWNDIR) -i "$(NWNDIR)/ovr" $(INCLUDE_DIRS) -i $(SCRIPTS) -M $(NSS) 73 | 74 | .PHONY: clean batch 75 | clean: 76 | -$(Q)rm -f $(NCS) $(NCS:.ncs=.d) 77 | 78 | -include $(OUTPUTDIR)/*.d 79 | -------------------------------------------------------------------------------- /hooks/post_push: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SHORT_COMMIT_HASH=${SOURCE_COMMIT:0:7} 3 | docker tag $IMAGE_NAME $DOCKER_REPO:$SHORT_COMMIT_HASH 4 | docker push $DOCKER_REPO:$SHORT_COMMIT_HASH 5 | -------------------------------------------------------------------------------- /nwnsc/.gitignore: -------------------------------------------------------------------------------- 1 | nwnsc -------------------------------------------------------------------------------- /nwnsc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | add_executable(nwnsc nwnsc.cpp) 4 | target_link_libraries(nwnsc nsclib nwndatalib nwnbaselib nwnutillib) -------------------------------------------------------------------------------- /scripts/buildnwnsc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . /hbb_exe/activate 4 | 5 | usage() { echo "$0 usage:" && grep " .)\ #" $0; exit 0; } 6 | 7 | CLEAN=1 8 | BUILD_TYPE="RelWithDebInfo" 9 | SANITIZE="" 10 | 11 | while getopts "hcj:ds" o; do 12 | case "${o}" in 13 | c) # Clean build - remove Binaries and re-execute cmake 14 | CLEAN=0 15 | ;; 16 | h | *) # Display help 17 | usage 18 | exit 0 19 | ;; 20 | esac 21 | done 22 | shift $((OPTIND-1)) 23 | 24 | CC="gcc -m32" 25 | CXX="g++ -m32" 26 | 27 | if [ ${CLEAN} == 0 ]; then 28 | make clean 29 | if [ -d ./CMakeFiles ]; then 30 | echo "Removing CMakeFiles" 31 | rm -rf ./CMakeFiles; 32 | fi 33 | 34 | if [ -e ./CMakeCache.txt ]; then 35 | echo "Removing CMakeCache.txt" 36 | rm ./CMakeCache.txt; 37 | fi 38 | fi 39 | 40 | cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE . 41 | 42 | make all 43 | -------------------------------------------------------------------------------- /scripts/run-linux-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage() { echo "$0 usage:" && grep " .)\ #" $0; exit 0; } 4 | 5 | CLEAN= 6 | 7 | while getopts ":hcj:" o; do 8 | case "${o}" in 9 | c) # Clean build - remove Binaries and re-execute cmake 10 | CLEAN=-c 11 | ;; 12 | h | *) # Display help 13 | usage 14 | exit 0 15 | ;; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | docker run --rm -w /src --entrypoint "/bin/bash" -v $(pwd):/src glorwinger/holy-build-box-32:1.0.0 ./scripts/buildnwnsc.sh ${CLEAN} 21 | --------------------------------------------------------------------------------