mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
Compare commits
1 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21f4d1486c |
@@ -5,7 +5,6 @@ packages:
|
||||
- freetype-dev
|
||||
- fontconfig-dev
|
||||
- opus-dev
|
||||
- bzip2-dev
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
|
||||
@@ -7,7 +7,6 @@ packages:
|
||||
- libfreetype-dev
|
||||
- libfontconfig-dev
|
||||
- libopus-dev
|
||||
- libbz2-dev
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
|
||||
@@ -6,7 +6,6 @@ packages:
|
||||
- libfreetype-dev
|
||||
- libfontconfig-dev
|
||||
- libopus-dev
|
||||
- libbz2-dev
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
|
||||
@@ -6,7 +6,6 @@ packages:
|
||||
- print/freetype2
|
||||
- x11-fonts/fontconfig
|
||||
- audio/opus
|
||||
- archivers/bzip2
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
|
||||
@@ -6,7 +6,6 @@ packages:
|
||||
- fontconfig
|
||||
- libopus
|
||||
- pkgconf
|
||||
- bzip2
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
|
||||
@@ -3,7 +3,6 @@ packages:
|
||||
- python3
|
||||
- sdl2
|
||||
- opus
|
||||
- bzip2
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
|
||||
25
.github/workflows/c-cpp.yml
vendored
25
.github/workflows/c-cpp.yml
vendored
@@ -21,22 +21,6 @@ jobs:
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: i386
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: arm64
|
||||
cross: true
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: armhf
|
||||
cross: true
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: riscv64
|
||||
cross: true
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: ppc64el
|
||||
cross: true
|
||||
# - os: ubuntu-aarch64-20.04
|
||||
# targetos: linux
|
||||
# targetarch: aarch64
|
||||
@@ -59,16 +43,15 @@ jobs:
|
||||
- os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
|
||||
targetos: win32
|
||||
targetarch: i386
|
||||
- os: macos-14 # arm64 as per github documentation
|
||||
- os: macos-14 # in GitHub documentation, it's an ARM64 machine
|
||||
targetos: apple
|
||||
targetarch: arm64
|
||||
- os: macos-13 # x86 as per github documentation (will they fix it before they deprecate this version?..)
|
||||
- os: macos-12 # in GitHub documentation, it's an x86 machine
|
||||
targetos: apple
|
||||
targetarch: amd64
|
||||
env:
|
||||
SDL_VERSION: 2.30.9
|
||||
SDL_VERSION: 2.30.3
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
GH_CROSSCOMPILING: ${{ matrix.cross }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -92,7 +75,7 @@ jobs:
|
||||
include:
|
||||
- app: su.xash.Engine.Compat.i386
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:freedesktop-24.08
|
||||
image: bilelmoussaoui/flatpak-github-actions:freedesktop-23.08
|
||||
options: --privileged
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -342,6 +342,3 @@ enc_temp_folder/
|
||||
|
||||
# KDevelop4
|
||||
*.kdev4
|
||||
|
||||
# ccls langauge server
|
||||
.ccls-*
|
||||
|
||||
12
.gitmodules
vendored
12
.gitmodules
vendored
@@ -22,15 +22,3 @@
|
||||
[submodule "3rdparty/bzip2/bzip2"]
|
||||
path = 3rdparty/bzip2/bzip2
|
||||
url = https://gitlab.com/bzip2/bzip2
|
||||
[submodule "3rdparty/MultiEmulator"]
|
||||
path = 3rdparty/MultiEmulator
|
||||
url = https://github.com/FWGS/MultiEmulator
|
||||
[submodule "3rdparty/libogg/libogg"]
|
||||
path = 3rdparty/libogg/libogg
|
||||
url = https://gitlab.xiph.org/xiph/ogg.git
|
||||
[submodule "3rdparty/vorbis/vorbis-src"]
|
||||
path = 3rdparty/vorbis/vorbis-src
|
||||
url = https://gitlab.xiph.org/xiph/vorbis.git
|
||||
[submodule "3rdparty/opusfile/opusfile"]
|
||||
path = 3rdparty/opusfile/opusfile
|
||||
url = https://gitlab.xiph.org/xiph/opusfile.git
|
||||
|
||||
1
3rdparty/MultiEmulator
vendored
1
3rdparty/MultiEmulator
vendored
Submodule 3rdparty/MultiEmulator deleted from 7e989e670e
21
3rdparty/MultiEmulator/LICENSE
vendored
Normal file
21
3rdparty/MultiEmulator/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2018 Alexander Belkin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
25
3rdparty/MultiEmulator/README.md
vendored
Normal file
25
3rdparty/MultiEmulator/README.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# MultiEmulator
|
||||
|
||||
**MultiEmulator** - project for GoldSource Engine, which provides ability to generate tickets with a specific SteamID key, using all available emulators for this engine.
|
||||
|
||||
Ticket is processed by the game server of Half-Life 1 and modifications using **DProto** or **ReUnion** modules. If the server does not have these modules, then MultiEmulator won't work.
|
||||
|
||||
# Ticket generators
|
||||
|
||||
Currently available ticket generators:
|
||||
* OldRevEmu
|
||||
* AVSMP
|
||||
* Setti
|
||||
* SteamEmu
|
||||
* RevEmu
|
||||
* SC2009
|
||||
* RevEmu2013
|
||||
|
||||
Currently under development generators:
|
||||
* SmartSteamEmu (SSE3)
|
||||
|
||||
# How to use?
|
||||
Each file in the **MultiEmulator\Source\Emulators** folder contains a **Generate** function that writes a ticket to the **pDest** argument for the emulator of the same name as a header file. As a result of the function, the size of the written ticket is returned. If the generator can set an arbitrary SteamID, the function will have the **nSteamID** argument, in which the required SteamID is specified.
|
||||
|
||||
# Examples
|
||||
As an example, the DLL was developed that searches InitiateGameConnection method in ISteamUser interface, which generates Steam ticket, and inserts in its place own generator, which creates RevEmu2013 ticket with SteamID equal to 3333333. You can find this project in **Example** folder, you just need to compile it and perform DLL injection in hl.exe process with any known injection method.
|
||||
37
3rdparty/MultiEmulator/include/multi_emulator.h
vendored
Normal file
37
3rdparty/MultiEmulator/include/multi_emulator.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef MULTI_EMULATOR_H
|
||||
#define MULTI_EMULATOR_H
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
#if defined( __i386__ )
|
||||
#define ME_EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
|
||||
#else
|
||||
#define ME_EXPORT __attribute__(( visibility ( "default" )))
|
||||
#endif
|
||||
#else
|
||||
#if defined( _MSC_VER )
|
||||
#define ME_EXPORT __declspec( dllexport )
|
||||
#else
|
||||
#define ME_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int ME_EXPORT GenerateRevEmu2013( void *pDest, int nSteamID );
|
||||
int ME_EXPORT GenerateSC2009( void *pDest, int nSteamID );
|
||||
int ME_EXPORT GenerateOldRevEmu( void *pDest, int nSteamID );
|
||||
int ME_EXPORT GenerateSteamEmu( void *pDest, int nSteamID );
|
||||
int ME_EXPORT GenerateRevEmu( void *pDest, int nSteamID );
|
||||
int ME_EXPORT GenerateSetti( void *pDest );
|
||||
int ME_EXPORT GenerateAVSMP( void *pDest, int nSteamID, int bUniverse );
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MULTI_EMULATOR_H
|
||||
13
3rdparty/MultiEmulator/src/AVSMP.cpp
vendored
Normal file
13
3rdparty/MultiEmulator/src/AVSMP.cpp
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "multi_emulator.h"
|
||||
|
||||
/* bUniverse param is "y" value in "STEAM_x:y:z" */
|
||||
int GenerateAVSMP(void *pDest, int nSteamID, int bUniverse)
|
||||
{
|
||||
auto pTicket = (int *)pDest;
|
||||
|
||||
pTicket[0] = 0x14; // +0, header
|
||||
pTicket[3] = (nSteamID << 1) | (bUniverse ? 1 : 0); // +12, SteamId, Low part
|
||||
pTicket[4] = 0x01100001; // +16, SteamId, High part
|
||||
|
||||
return 28;
|
||||
}
|
||||
1376
3rdparty/MultiEmulator/src/CRijndael.cpp
vendored
Normal file
1376
3rdparty/MultiEmulator/src/CRijndael.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
187
3rdparty/MultiEmulator/src/CRijndael.h
vendored
Normal file
187
3rdparty/MultiEmulator/src/CRijndael.h
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
#ifndef __RIJNDAEL_H__
|
||||
#define __RIJNDAEL_H__
|
||||
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//Rijndael (pronounced Reindaal) is a block cipher, designed by Joan Daemen and Vincent Rijmen as a candidate algorithm for the AES.
|
||||
//The cipher has a variable block length and key length. The authors currently specify how to use keys with a length
|
||||
//of 128, 192, or 256 bits to encrypt blocks with al length of 128, 192 or 256 bits (all nine combinations of
|
||||
//key length and block length are possible). Both block length and key length can be extended very easily to
|
||||
// multiples of 32 bits.
|
||||
//Rijndael can be implemented very efficiently on a wide range of processors and in hardware.
|
||||
//This implementation is based on the Java Implementation used with the Cryptix toolkit found at:
|
||||
//http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael.zip
|
||||
//Java code authors: Raif S. Naffah, Paulo S. L. M. Barreto
|
||||
//This Implementation was tested against KAT test published by the authors of the method and the
|
||||
//results were identical.
|
||||
class CRijndael
|
||||
{
|
||||
public:
|
||||
//Operation Modes
|
||||
//The Electronic Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB) modes
|
||||
//are implemented.
|
||||
//In ECB mode if the same block is encrypted twice with the same key, the resulting
|
||||
//ciphertext blocks are the same.
|
||||
//In CBC Mode a ciphertext block is obtained by first xoring the
|
||||
//plaintext block with the previous ciphertext block, and encrypting the resulting value.
|
||||
//In CFB mode a ciphertext block is obtained by encrypting the previous ciphertext block
|
||||
//and xoring the resulting value with the plaintext.
|
||||
enum { ECB = 0, CBC = 1, CFB = 2 };
|
||||
|
||||
private:
|
||||
enum { DEFAULT_BLOCK_SIZE = 16 };
|
||||
enum { MAX_BLOCK_SIZE = 32, MAX_ROUNDS = 14, MAX_KC = 8, MAX_BC = 8 };
|
||||
|
||||
//Auxiliary Functions
|
||||
//Multiply two elements of GF(2^m)
|
||||
static int Mul(int a, int b)
|
||||
{
|
||||
return (a != 0 && b != 0) ? sm_alog[(sm_log[a & 0xFF] + sm_log[b & 0xFF]) % 255] : 0;
|
||||
}
|
||||
|
||||
//Convenience method used in generating Transposition Boxes
|
||||
static int Mul4(int a, char b[])
|
||||
{
|
||||
if (a == 0)
|
||||
return 0;
|
||||
a = sm_log[a & 0xFF];
|
||||
int a0 = (b[0] != 0) ? sm_alog[(a + sm_log[b[0] & 0xFF]) % 255] & 0xFF : 0;
|
||||
int a1 = (b[1] != 0) ? sm_alog[(a + sm_log[b[1] & 0xFF]) % 255] & 0xFF : 0;
|
||||
int a2 = (b[2] != 0) ? sm_alog[(a + sm_log[b[2] & 0xFF]) % 255] & 0xFF : 0;
|
||||
int a3 = (b[3] != 0) ? sm_alog[(a + sm_log[b[3] & 0xFF]) % 255] & 0xFF : 0;
|
||||
return a0 << 24 | a1 << 16 | a2 << 8 | a3;
|
||||
}
|
||||
|
||||
public:
|
||||
//CONSTRUCTOR
|
||||
CRijndael();
|
||||
|
||||
//DESTRUCTOR
|
||||
virtual ~CRijndael();
|
||||
|
||||
//Expand a user-supplied key material into a session key.
|
||||
// key - The 128/192/256-bit user-key to use.
|
||||
// chain - initial chain block for CBC and CFB modes.
|
||||
// keylength - 16, 24 or 32 bytes
|
||||
// blockSize - The block size in bytes of this Rijndael (16, 24 or 32 bytes).
|
||||
void MakeKey(char const* key, char const* chain, int keylength = DEFAULT_BLOCK_SIZE, int blockSize = DEFAULT_BLOCK_SIZE);
|
||||
|
||||
private:
|
||||
//Auxiliary Function
|
||||
void Xor(char* buff, char const* chain)
|
||||
{
|
||||
if (false == m_bKeyInit)
|
||||
throw runtime_error(sm_szErrorMsg1);
|
||||
for (int i = 0; i<m_blockSize; i++)
|
||||
*(buff++) ^= *(chain++);
|
||||
}
|
||||
|
||||
//Convenience method to encrypt exactly one block of plaintext, assuming
|
||||
//Rijndael's default block size (128-bit).
|
||||
// in - The plaintext
|
||||
// result - The ciphertext generated from a plaintext using the key
|
||||
void DefEncryptBlock(char const* in, char* result);
|
||||
|
||||
//Convenience method to decrypt exactly one block of plaintext, assuming
|
||||
//Rijndael's default block size (128-bit).
|
||||
// in - The ciphertext.
|
||||
// result - The plaintext generated from a ciphertext using the session key.
|
||||
void DefDecryptBlock(char const* in, char* result);
|
||||
|
||||
public:
|
||||
//Encrypt exactly one block of plaintext.
|
||||
// in - The plaintext.
|
||||
// result - The ciphertext generated from a plaintext using the key.
|
||||
void EncryptBlock(char const* in, char* result);
|
||||
|
||||
//Decrypt exactly one block of ciphertext.
|
||||
// in - The ciphertext.
|
||||
// result - The plaintext generated from a ciphertext using the session key.
|
||||
void DecryptBlock(char const* in, char* result);
|
||||
|
||||
void Encrypt(char const* in, char* result, size_t n, int iMode = ECB);
|
||||
|
||||
void Decrypt(char const* in, char* result, size_t n, int iMode = ECB);
|
||||
|
||||
//Get Key Length
|
||||
int GetKeyLength()
|
||||
{
|
||||
if (false == m_bKeyInit)
|
||||
throw runtime_error(sm_szErrorMsg1);
|
||||
return m_keylength;
|
||||
}
|
||||
|
||||
//Block Size
|
||||
int GetBlockSize()
|
||||
{
|
||||
if (false == m_bKeyInit)
|
||||
throw runtime_error(sm_szErrorMsg1);
|
||||
return m_blockSize;
|
||||
}
|
||||
|
||||
//Number of Rounds
|
||||
int GetRounds()
|
||||
{
|
||||
if (false == m_bKeyInit)
|
||||
throw runtime_error(sm_szErrorMsg1);
|
||||
return m_iROUNDS;
|
||||
}
|
||||
|
||||
void ResetChain()
|
||||
{
|
||||
memcpy(m_chain, m_chain0, m_blockSize);
|
||||
}
|
||||
|
||||
public:
|
||||
//Null chain
|
||||
static char const* sm_chain0;
|
||||
|
||||
private:
|
||||
static const int sm_alog[256];
|
||||
static const int sm_log[256];
|
||||
static const char sm_S[256];
|
||||
static const char sm_Si[256];
|
||||
static const int sm_T1[256];
|
||||
static const int sm_T2[256];
|
||||
static const int sm_T3[256];
|
||||
static const int sm_T4[256];
|
||||
static const int sm_T5[256];
|
||||
static const int sm_T6[256];
|
||||
static const int sm_T7[256];
|
||||
static const int sm_T8[256];
|
||||
static const int sm_U1[256];
|
||||
static const int sm_U2[256];
|
||||
static const int sm_U3[256];
|
||||
static const int sm_U4[256];
|
||||
static const char sm_rcon[30];
|
||||
static const int sm_shifts[3][4][2];
|
||||
//Error Messages
|
||||
static char const* sm_szErrorMsg1;
|
||||
static char const* sm_szErrorMsg2;
|
||||
//Key Initialization Flag
|
||||
bool m_bKeyInit;
|
||||
//Encryption (m_Ke) round key
|
||||
int m_Ke[MAX_ROUNDS + 1][MAX_BC];
|
||||
//Decryption (m_Kd) round key
|
||||
int m_Kd[MAX_ROUNDS + 1][MAX_BC];
|
||||
//Key Length
|
||||
int m_keylength;
|
||||
//Block Size
|
||||
int m_blockSize;
|
||||
//Number of Rounds
|
||||
int m_iROUNDS;
|
||||
//Chain Block
|
||||
char m_chain0[MAX_BLOCK_SIZE];
|
||||
char m_chain[MAX_BLOCK_SIZE];
|
||||
//Auxiliary private use buffers
|
||||
int tk[MAX_KC];
|
||||
int a[MAX_BC];
|
||||
int t[MAX_BC];
|
||||
};
|
||||
|
||||
#endif // __RIJNDAEL_H__
|
||||
128
3rdparty/MultiEmulator/src/DoubleBuffering.cpp
vendored
Normal file
128
3rdparty/MultiEmulator/src/DoubleBuffering.cpp
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
//DoubleBuffering.cpp Source File
|
||||
|
||||
#include "DoubleBuffering.h"
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
#include <string.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
CDoubleBuffering::CDoubleBuffering(ifstream& in, char* pcBuff, int iSize, int iDataLen) : m_rin(in),
|
||||
m_iDataLen(iDataLen), m_bEOF(false), m_iSize(iSize), m_iSize2(iSize >> 1), m_pcBuff(pcBuff)
|
||||
{
|
||||
//m_iSize should be even
|
||||
if(m_iSize%2 != 0)
|
||||
throw runtime_error("CDoubleBuffering: m_iSize should be Even Number!");
|
||||
//Check file
|
||||
if(!in.is_open() || in.bad())
|
||||
throw runtime_error("CDoubleBuffering: Referenced File not Opened or in Bad State!");
|
||||
//Check construction data
|
||||
if(m_iDataLen<1 || m_iSize2<m_iDataLen)
|
||||
throw runtime_error("CDoubleBuffering: Illegal Construction Data!");
|
||||
in.read(m_pcBuff, m_iSize2);
|
||||
m_iEnd = m_rin.gcount();
|
||||
m_iCurPos = 0;
|
||||
m_iBuf = 0;
|
||||
}
|
||||
|
||||
int CDoubleBuffering::GetData(char* pszDataBuf, int iDataLen)
|
||||
{
|
||||
if(-1 == iDataLen)
|
||||
iDataLen = m_iDataLen;
|
||||
if(iDataLen<1 || m_iSize2<iDataLen)
|
||||
throw runtime_error("CDoubleBuffering::GetData(): Illegal iDataLen!");
|
||||
if(true == m_bEOF)
|
||||
return 0;
|
||||
//Estimate the next position
|
||||
int iCurPos = m_iCurPos + iDataLen;
|
||||
if(0 == m_iBuf) //First Buffer
|
||||
{
|
||||
if(iCurPos >= m_iEnd)
|
||||
{
|
||||
//Read the next buffer
|
||||
if(m_rin.eof())
|
||||
{
|
||||
m_bEOF = true;
|
||||
//Take everything remained
|
||||
int iRead = m_iEnd-m_iCurPos;
|
||||
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
|
||||
return iRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rin.read(m_pcBuff+m_iEnd, m_iSize2);
|
||||
m_iEnd += m_rin.gcount();
|
||||
if(iCurPos > m_iEnd) //Still greater, then EOF attained
|
||||
{
|
||||
assert(m_rin.eof());
|
||||
m_bEOF = true;
|
||||
//Take everything remained
|
||||
int iRead = m_iEnd-m_iCurPos;
|
||||
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
|
||||
return iRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
|
||||
m_iCurPos = iCurPos;
|
||||
assert(m_iCurPos >= m_iSize2);
|
||||
m_iBuf = 1;
|
||||
return iDataLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
|
||||
m_iCurPos = iCurPos;
|
||||
return iDataLen;
|
||||
}
|
||||
}
|
||||
else //1 == m_iBuf, Second Buffer
|
||||
{
|
||||
if(iCurPos >= m_iEnd)
|
||||
{
|
||||
//Read the next buffer
|
||||
if(m_rin.eof())
|
||||
{
|
||||
m_bEOF = true;
|
||||
//Take everything remained
|
||||
int iRead = m_iEnd-m_iCurPos;
|
||||
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
|
||||
return iRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rin.read(m_pcBuff, m_iSize2);
|
||||
m_iEnd = m_rin.gcount();
|
||||
iCurPos %= m_iSize;
|
||||
if(iCurPos > m_iEnd) //Still greater, then EOF attained
|
||||
{
|
||||
assert(m_rin.eof());
|
||||
m_bEOF = true;
|
||||
//Take everything remained
|
||||
int iRead = m_iSize-m_iCurPos;
|
||||
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
|
||||
memcpy(pszDataBuf+iRead, m_pcBuff, m_iEnd);
|
||||
return iRead + m_iEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iRead = m_iSize-m_iCurPos;
|
||||
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
|
||||
memcpy(pszDataBuf+iRead, m_pcBuff, iDataLen-iRead);
|
||||
m_iCurPos = iCurPos;
|
||||
assert(m_iCurPos < m_iSize2);
|
||||
m_iBuf = 0;
|
||||
return iDataLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
|
||||
m_iCurPos = iCurPos;
|
||||
return iDataLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
3rdparty/MultiEmulator/src/DoubleBuffering.h
vendored
Normal file
40
3rdparty/MultiEmulator/src/DoubleBuffering.h
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
//DoubleBuffering.h Header File
|
||||
|
||||
#ifndef __DOUBLEBUFFERING_H__
|
||||
#define __DOUBLEBUFFERING_H__
|
||||
|
||||
//Typical DISCLAIMER:
|
||||
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
|
||||
//use and distribute the code in any way you see fit as long as this paragraph is included
|
||||
//with the distribution. No warranties or claims are made as to the validity of the
|
||||
//information and code contained herein, so use it at your own risk.
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class CDoubleBuffering
|
||||
{
|
||||
public:
|
||||
//Constructor
|
||||
CDoubleBuffering(ifstream& in, char* pcBuff, int iSize, int iDataLen);
|
||||
//Get Next Data Buffer
|
||||
int GetData(char* pszDataBuf, int iDataLen=-1);
|
||||
|
||||
private:
|
||||
ifstream& m_rin;
|
||||
int m_iSize;
|
||||
int m_iSize2; //m_iSize/2
|
||||
int m_iDataLen;
|
||||
//Current Position
|
||||
int m_iCurPos;
|
||||
//End Position
|
||||
int m_iEnd;
|
||||
//Which Buffer
|
||||
int m_iBuf;
|
||||
char* m_pcBuff;
|
||||
//EOF attained
|
||||
bool m_bEOF;
|
||||
};
|
||||
|
||||
#endif //__DOUBLEBUFFERING_H__
|
||||
38
3rdparty/MultiEmulator/src/MessageDigest.cpp
vendored
Normal file
38
3rdparty/MultiEmulator/src/MessageDigest.cpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
//MessageDigest.cpp
|
||||
|
||||
#include "MessageDigest.h"
|
||||
#include "DoubleBuffering.h"
|
||||
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <strstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//Digesting a Full File
|
||||
void IMessageDigest::DigestFile(string const& rostrFileIn, char* pcDigest)
|
||||
{
|
||||
//Is the User's responsability to ensure that pcDigest is appropriately allocated
|
||||
//Open Input File
|
||||
ifstream in(rostrFileIn.c_str(), ios::binary);
|
||||
if(!in)
|
||||
{
|
||||
ostrstream ostr;
|
||||
ostr << "FileDigest ERROR: in IMessageDigest::DigestFile(): Cannot open File " << rostrFileIn << "!" << ends;
|
||||
string ostrMsg = ostr.str();
|
||||
ostr.freeze(false);
|
||||
throw runtime_error(ostrMsg);
|
||||
}
|
||||
//Resetting first
|
||||
Reset();
|
||||
//Reading from file
|
||||
char szLargeBuff[BUFF_LEN+1] = {0};
|
||||
char szBuff[DATA_LEN+1] = {0};
|
||||
CDoubleBuffering oDoubleBuffering(in, szLargeBuff, BUFF_LEN, DATA_LEN);
|
||||
int iRead;
|
||||
while((iRead=oDoubleBuffering.GetData(szBuff)) > 0)
|
||||
AddData(szBuff, iRead);
|
||||
in.close();
|
||||
//Final Step
|
||||
FinalDigest(pcDigest);
|
||||
}
|
||||
47
3rdparty/MultiEmulator/src/MessageDigest.h
vendored
Normal file
47
3rdparty/MultiEmulator/src/MessageDigest.h
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
//MessageDigest.h
|
||||
|
||||
#ifndef __MESSAGEDIGEST_H__
|
||||
#define __MESSAGEDIGEST_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//Typical DISCLAIMER:
|
||||
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
|
||||
//use and distribute the code in any way you see fit as long as this paragraph is included
|
||||
//with the distribution. No warranties or claims are made as to the validity of the
|
||||
//information and code contained herein, so use it at your own risk.
|
||||
|
||||
//General Message Digest Interface
|
||||
class IMessageDigest
|
||||
{
|
||||
public:
|
||||
//CONSTRUCTOR
|
||||
IMessageDigest() : m_bAddData(false) {}
|
||||
//DESTRUCTOR
|
||||
virtual ~IMessageDigest() {}
|
||||
//Update context to reflect the concatenation of another buffer of bytes
|
||||
virtual void AddData(char const* pcData, int iDataLength) = 0;
|
||||
//Final wrapup - pad to BLOCKSIZE-byte boundary with the bit pattern
|
||||
//10000...(64-bit count of bits processed, MSB-first)
|
||||
virtual void FinalDigest(char* pcDigest) = 0;
|
||||
//Reset current operation in order to prepare for a new one
|
||||
virtual void Reset() = 0;
|
||||
//Digesting a Full File
|
||||
void DigestFile(string const& rostrFileIn, char* pcDigest);
|
||||
|
||||
protected:
|
||||
enum { BLOCKSIZE=64 };
|
||||
//Control Flag
|
||||
bool m_bAddData;
|
||||
//The core of the MessageDigest algorithm, this alters an existing MessageDigest hash to
|
||||
//reflect the addition of 64 bytes of new data
|
||||
virtual void Transform() = 0;
|
||||
|
||||
private:
|
||||
enum { DATA_LEN=384, BUFF_LEN=1024 };
|
||||
};
|
||||
|
||||
#endif // __MESSAGEDIGEST_H__
|
||||
|
||||
13
3rdparty/MultiEmulator/src/OldRevEmu.cpp
vendored
Normal file
13
3rdparty/MultiEmulator/src/OldRevEmu.cpp
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "multi_emulator.h"
|
||||
|
||||
int GenerateOldRevEmu(void* pDest, int nSteamID)
|
||||
{
|
||||
auto pTicket = (int*)pDest;
|
||||
auto pbTicket = (unsigned char*)pDest;
|
||||
|
||||
pTicket[0] = 0xFFFF; // +0, header
|
||||
pTicket[1] = (nSteamID ^ 0xC9710266) << 1; // +4, SteamId
|
||||
*(short *)&pbTicket[8] = 0; // +8, unknown, in original emulator must be 0
|
||||
|
||||
return 10;
|
||||
}
|
||||
27
3rdparty/MultiEmulator/src/RevEmu.cpp
vendored
Normal file
27
3rdparty/MultiEmulator/src/RevEmu.cpp
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "multi_emulator.h"
|
||||
#include "StrUtils.h"
|
||||
#include "RevSpoofer.h"
|
||||
|
||||
int GenerateRevEmu(void *pDest, int nSteamID)
|
||||
{
|
||||
char szhwid[64];
|
||||
|
||||
CreateRandomString(szhwid, 16);
|
||||
if (!RevSpoofer::Spoof(szhwid, nSteamID))
|
||||
return 0;
|
||||
|
||||
auto pTicket = (int *)pDest;
|
||||
auto revHash = RevSpoofer::Hash(szhwid);
|
||||
|
||||
pTicket[0] = 'J'; // +0, header
|
||||
pTicket[1] = revHash; // +4, hash of string at +24 offset
|
||||
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';// +8, magic number
|
||||
pTicket[3] = 0; // +12, unknown number, must always be 0
|
||||
|
||||
pTicket[4] = revHash << 1; // +16, SteamId, Low part
|
||||
pTicket[5] = 0x01100001; // +20, SteamId, High part
|
||||
|
||||
strcpy((char *)&pTicket[6], szhwid); // +24, string for hash
|
||||
|
||||
return 152;
|
||||
}
|
||||
55
3rdparty/MultiEmulator/src/RevEmu2013.cpp
vendored
Normal file
55
3rdparty/MultiEmulator/src/RevEmu2013.cpp
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "multi_emulator.h"
|
||||
#include "StrUtils.h"
|
||||
#include "RevSpoofer.h"
|
||||
#include "CRijndael.h"
|
||||
#include "SHA.h"
|
||||
#include <time.h>
|
||||
|
||||
int GenerateRevEmu2013(void *pDest, int nSteamID)
|
||||
{
|
||||
char szhwid[64];
|
||||
|
||||
CreateRandomString(szhwid, 32);
|
||||
if (!RevSpoofer::Spoof(szhwid, nSteamID))
|
||||
return 0;
|
||||
|
||||
auto pTicket = (int *)pDest;
|
||||
auto pbTicket = (unsigned char *)pDest;
|
||||
|
||||
auto revHash = RevSpoofer::Hash(szhwid);
|
||||
|
||||
pTicket[0] = 'S'; // +0
|
||||
pTicket[1] = revHash; // +4
|
||||
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';;// +8
|
||||
pTicket[3] = 0; // +12
|
||||
pTicket[4] = revHash << 1; // +16
|
||||
pTicket[5] = 0x01100001; // +20
|
||||
pTicket[6] = (int)time(0) + 90123; // +24
|
||||
pbTicket[27] = ~(pbTicket[27] + pbTicket[24]);
|
||||
pTicket[7] = ~(int)time(0); // +28
|
||||
pTicket[8] = revHash * 2 >> 3; // +32
|
||||
pTicket[9] = 0; // +36
|
||||
|
||||
static const char c_szAESKeyRand[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
|
||||
|
||||
char szAESHashRand[32];
|
||||
auto AESRand = CRijndael();
|
||||
AESRand.MakeKey(c_szAESKeyRand, CRijndael::sm_chain0, 32, 32);
|
||||
AESRand.EncryptBlock(szhwid, szAESHashRand);
|
||||
memcpy(&pbTicket[40], szAESHashRand, 32);
|
||||
|
||||
static const char c_szAESKeyRev[] = "_YOU_SERIOUSLY_NEED_TO_GET_LAID_";
|
||||
char AESHashRev[32];
|
||||
auto AESRev = CRijndael();
|
||||
AESRev.MakeKey(c_szAESKeyRev, CRijndael::sm_chain0, 32, 32);
|
||||
AESRev.EncryptBlock(c_szAESKeyRand, AESHashRev);
|
||||
memcpy(&pbTicket[72], AESHashRev, 32);
|
||||
|
||||
char szSHAHash[32];
|
||||
auto sha = CSHA(CSHA::SHA256);
|
||||
sha.AddData(szhwid, 32);
|
||||
sha.FinalDigest(szSHAHash);
|
||||
memcpy(&pbTicket[104], szSHAHash, 32);
|
||||
|
||||
return 194;
|
||||
}
|
||||
96
3rdparty/MultiEmulator/src/RevSpoofer.cpp
vendored
Normal file
96
3rdparty/MultiEmulator/src/RevSpoofer.cpp
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "RevSpoofer.h"
|
||||
#include <string.h>
|
||||
|
||||
#define astrlen(x) sizeof(x) - 1
|
||||
|
||||
static char s_szDictionary[] = { "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" };
|
||||
|
||||
static int iInputLen;
|
||||
static unsigned int uTreasure;
|
||||
|
||||
bool ScanLast3(char *pszInput, unsigned int uPrevHash)
|
||||
{
|
||||
unsigned int h1, h2, h3, hh;
|
||||
for (int i1 = 0; i1 < astrlen(s_szDictionary); i1++)
|
||||
{
|
||||
h1 = uPrevHash ^ ((uPrevHash >> 2) + (uPrevHash << 5) + s_szDictionary[i1]);
|
||||
hh = h1 ^ ((h1 >> 2) + (h1 << 5));
|
||||
hh = hh ^ ((hh >> 2) + (hh << 5));
|
||||
|
||||
if ((hh ^ uTreasure) >> (8 + 5 + 3))
|
||||
continue;
|
||||
|
||||
for (int i2 = 0; i2 < astrlen(s_szDictionary); i2++)
|
||||
{
|
||||
h2 = h1 ^ ((h1 >> 2) + (h1 << 5) + s_szDictionary[i2]);
|
||||
hh = h2 ^ ((h2 >> 2) + (h2 << 5));
|
||||
if ((hh ^ uTreasure) >> (8 + 3))
|
||||
continue;
|
||||
|
||||
for (int i3 = 0; i3 < astrlen(s_szDictionary); i3++)
|
||||
{
|
||||
h3 = h2 ^ ((h2 >> 2) + (h2 << 5) + s_szDictionary[i3]);
|
||||
if (h3 == uTreasure)
|
||||
{
|
||||
pszInput[iInputLen - 3] = s_szDictionary[i1];
|
||||
pszInput[iInputLen - 2] = s_szDictionary[i2];
|
||||
pszInput[iInputLen - 1] = s_szDictionary[i3];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScanNext(char* pszInput, int uIndex, unsigned int uPrevHash)
|
||||
{
|
||||
bool res;
|
||||
|
||||
for (int i = 0; i < astrlen(s_szDictionary); i++)
|
||||
{
|
||||
auto h = uPrevHash ^ ((uPrevHash >> 2) + (uPrevHash << 5) + s_szDictionary[i]);
|
||||
|
||||
if (uIndex + 1 < iInputLen - 3)
|
||||
res = ScanNext(pszInput, uIndex + 1, h);
|
||||
else
|
||||
res = ScanLast3(pszInput, h);
|
||||
|
||||
if (res)
|
||||
{
|
||||
pszInput[uIndex] = s_szDictionary[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace RevSpoofer
|
||||
{
|
||||
bool Spoof(char *pszDest, int uSID)
|
||||
{
|
||||
uTreasure = uSID;
|
||||
iInputLen = strlen(pszDest);
|
||||
|
||||
auto i = iInputLen - 7;
|
||||
i = (i < 0) ? 0 : i;
|
||||
pszDest[i] = '\0';
|
||||
auto h = Hash(pszDest);
|
||||
return ScanNext(pszDest, i, h);
|
||||
}
|
||||
|
||||
unsigned int Hash(char *pszString)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int nHash = 0x4E67C6A7;
|
||||
int c = pszString[i++];
|
||||
|
||||
while (c)
|
||||
{
|
||||
nHash = nHash ^ ((nHash >> 2) + (nHash << 5) + c);
|
||||
c = pszString[i++];
|
||||
}
|
||||
|
||||
return nHash;
|
||||
}
|
||||
}
|
||||
7
3rdparty/MultiEmulator/src/RevSpoofer.h
vendored
Normal file
7
3rdparty/MultiEmulator/src/RevSpoofer.h
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace RevSpoofer
|
||||
{
|
||||
bool Spoof(char *pszDest, int uSID);
|
||||
unsigned int Hash(char *pszString);
|
||||
}
|
||||
52
3rdparty/MultiEmulator/src/SC2009.cpp
vendored
Normal file
52
3rdparty/MultiEmulator/src/SC2009.cpp
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "multi_emulator.h"
|
||||
#include "StrUtils.h"
|
||||
#include "RevSpoofer.h"
|
||||
#include "CRijndael.h"
|
||||
#include "SHA.h"
|
||||
|
||||
int GenerateSC2009(void* pDest, int nSteamID)
|
||||
{
|
||||
char hwid[64];
|
||||
|
||||
CreateRandomString(hwid, 32);
|
||||
if (!RevSpoofer::Spoof(hwid, nSteamID))
|
||||
return 0;
|
||||
|
||||
auto pTicket = (int*)pDest;
|
||||
auto pbTicket = (unsigned char*)pDest;
|
||||
|
||||
auto revHash = RevSpoofer::Hash(hwid);
|
||||
|
||||
pTicket[0] = 'S'; // +0
|
||||
pTicket[1] = revHash; // +4
|
||||
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';;// +8
|
||||
pTicket[3] = 0; // +12
|
||||
pTicket[4] = revHash << 1; // +16
|
||||
pTicket[5] = 0x01100001; // +20
|
||||
|
||||
/* Encrypt HWID with AESKeyRand key and save it in the ticket. */
|
||||
static const char AESKeyRand[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
|
||||
char AESHashRand[32];
|
||||
auto AESRand = CRijndael();
|
||||
AESRand.MakeKey(AESKeyRand, CRijndael::sm_chain0, 32, 32);
|
||||
AESRand.EncryptBlock(hwid, AESHashRand);
|
||||
memcpy(&pbTicket[24], AESHashRand, 32);
|
||||
|
||||
/* Encrypt AESKeyRand with AESKeyRev key and save it in the ticket.
|
||||
* AESKeyRev key is identical to the key in dproto/reunion. */
|
||||
static const char AESKeyRev[] = "_YOU_SERIOUSLY_NEED_TO_GET_LAID_";
|
||||
char AESHashRev[32];
|
||||
auto AESRev = CRijndael();
|
||||
AESRev.MakeKey(AESKeyRev, CRijndael::sm_chain0, 32, 32);
|
||||
AESRev.EncryptBlock(AESKeyRand, AESHashRev);
|
||||
memcpy(&pbTicket[56], AESHashRev, 32);
|
||||
|
||||
/* Perform HWID hashing and save hash to the ticket. */
|
||||
char SHAHash[32];
|
||||
auto sha = CSHA(CSHA::SHA256);
|
||||
sha.AddData(hwid, 32);
|
||||
sha.FinalDigest(SHAHash);
|
||||
memcpy(&pbTicket[88], SHAHash, 32);
|
||||
|
||||
return 178;
|
||||
}
|
||||
734
3rdparty/MultiEmulator/src/SHA.cpp
vendored
Normal file
734
3rdparty/MultiEmulator/src/SHA.cpp
vendored
Normal file
@@ -0,0 +1,734 @@
|
||||
//SHA.cpp
|
||||
#include "SHA.h"
|
||||
#include <exception>
|
||||
#include <strstream>
|
||||
#include <string.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const unsigned int CSHA::sm_K160[4] =
|
||||
{
|
||||
0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
|
||||
};
|
||||
|
||||
const unsigned int CSHA::sm_H160[SHA160LENGTH] =
|
||||
{
|
||||
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
|
||||
};
|
||||
|
||||
const unsigned int CSHA::sm_K256[64] =
|
||||
{
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
const unsigned int CSHA::sm_H256[SHA256LENGTH] =
|
||||
{
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
};
|
||||
|
||||
const SUI64 CSHA::sm_H384[SHA512LENGTH] =
|
||||
{
|
||||
{0xcbbb9d5d, 0xc1059ed8},
|
||||
{0x629a292a, 0x367cd507},
|
||||
{0x9159015a, 0x3070dd17},
|
||||
{0x152fecd8, 0xf70e5939},
|
||||
{0x67332667, 0xffc00b31},
|
||||
{0x8eb44a87, 0x68581511},
|
||||
{0xdb0c2e0d, 0x64f98fa7},
|
||||
{0x47b5481d, 0xbefa4fa4}
|
||||
};
|
||||
|
||||
const SUI64 CSHA::sm_K512[80] =
|
||||
{
|
||||
{0x428a2f98, 0xd728ae22}, {0x71374491, 0x23ef65cd},
|
||||
{0xb5c0fbcf, 0xec4d3b2f}, {0xe9b5dba5, 0x8189dbbc},
|
||||
{0x3956c25b, 0xf348b538}, {0x59f111f1, 0xb605d019},
|
||||
{0x923f82a4, 0xaf194f9b}, {0xab1c5ed5, 0xda6d8118},
|
||||
{0xd807aa98, 0xa3030242}, {0x12835b01, 0x45706fbe},
|
||||
{0x243185be, 0x4ee4b28c}, {0x550c7dc3, 0xd5ffb4e2},
|
||||
{0x72be5d74, 0xf27b896f}, {0x80deb1fe, 0x3b1696b1},
|
||||
{0x9bdc06a7, 0x25c71235}, {0xc19bf174, 0xcf692694},
|
||||
{0xe49b69c1, 0x9ef14ad2}, {0xefbe4786, 0x384f25e3},
|
||||
{0x0fc19dc6, 0x8b8cd5b5}, {0x240ca1cc, 0x77ac9c65},
|
||||
{0x2de92c6f, 0x592b0275}, {0x4a7484aa, 0x6ea6e483},
|
||||
{0x5cb0a9dc, 0xbd41fbd4}, {0x76f988da, 0x831153b5},
|
||||
{0x983e5152, 0xee66dfab}, {0xa831c66d, 0x2db43210},
|
||||
{0xb00327c8, 0x98fb213f}, {0xbf597fc7, 0xbeef0ee4},
|
||||
{0xc6e00bf3, 0x3da88fc2}, {0xd5a79147, 0x930aa725},
|
||||
{0x06ca6351, 0xe003826f}, {0x14292967, 0x0a0e6e70},
|
||||
{0x27b70a85, 0x46d22ffc}, {0x2e1b2138, 0x5c26c926},
|
||||
{0x4d2c6dfc, 0x5ac42aed}, {0x53380d13, 0x9d95b3df},
|
||||
{0x650a7354, 0x8baf63de}, {0x766a0abb, 0x3c77b2a8},
|
||||
{0x81c2c92e, 0x47edaee6}, {0x92722c85, 0x1482353b},
|
||||
{0xa2bfe8a1, 0x4cf10364}, {0xa81a664b, 0xbc423001},
|
||||
{0xc24b8b70, 0xd0f89791}, {0xc76c51a3, 0x0654be30},
|
||||
{0xd192e819, 0xd6ef5218}, {0xd6990624, 0x5565a910},
|
||||
{0xf40e3585, 0x5771202a}, {0x106aa070, 0x32bbd1b8},
|
||||
{0x19a4c116, 0xb8d2d0c8}, {0x1e376c08, 0x5141ab53},
|
||||
{0x2748774c, 0xdf8eeb99}, {0x34b0bcb5, 0xe19b48a8},
|
||||
{0x391c0cb3, 0xc5c95a63}, {0x4ed8aa4a, 0xe3418acb},
|
||||
{0x5b9cca4f, 0x7763e373}, {0x682e6ff3, 0xd6b2b8a3},
|
||||
{0x748f82ee, 0x5defb2fc}, {0x78a5636f, 0x43172f60},
|
||||
{0x84c87814, 0xa1f0ab72}, {0x8cc70208, 0x1a6439ec},
|
||||
{0x90befffa, 0x23631e28}, {0xa4506ceb, 0xde82bde9},
|
||||
{0xbef9a3f7, 0xb2c67915}, {0xc67178f2, 0xe372532b},
|
||||
{0xca273ece, 0xea26619c}, {0xd186b8c7, 0x21c0c207},
|
||||
{0xeada7dd6, 0xcde0eb1e}, {0xf57d4f7f, 0xee6ed178},
|
||||
{0x06f067aa, 0x72176fba}, {0x0a637dc5, 0xa2c898a6},
|
||||
{0x113f9804, 0xbef90dae}, {0x1b710b35, 0x131c471b},
|
||||
{0x28db77f5, 0x23047d84}, {0x32caab7b, 0x40c72493},
|
||||
{0x3c9ebe0a, 0x15c9bebc}, {0x431d67c4, 0x9c100d4c},
|
||||
{0x4cc5d4be, 0xcb3e42b6}, {0x597f299c, 0xfc657e2a},
|
||||
{0x5fcb6fab, 0x3ad6faec}, {0x6c44198c, 0x4a475817}
|
||||
};
|
||||
|
||||
const SUI64 CSHA::sm_H512[SHA512LENGTH] =
|
||||
{
|
||||
{0x6a09e667, 0xf3bcc908},
|
||||
{0xbb67ae85, 0x84caa73b},
|
||||
{0x3c6ef372, 0xfe94f82b},
|
||||
{0xa54ff53a, 0x5f1d36f1},
|
||||
{0x510e527f, 0xade682d1},
|
||||
{0x9b05688c, 0x2b3e6c1f},
|
||||
{0x1f83d9ab, 0xfb41bd6b},
|
||||
{0x5be0cd19, 0x137e2179}
|
||||
};
|
||||
|
||||
//CONSTRUCTOR
|
||||
CSHA::CSHA(int iMethod)
|
||||
{
|
||||
//Check the method
|
||||
switch(iMethod)
|
||||
{
|
||||
case SHA160:
|
||||
{
|
||||
for(int i=0; i<SHA160LENGTH; i++)
|
||||
m_auiBuf[i] = sm_H160[i];
|
||||
m_auiBits[0] = 0;
|
||||
m_auiBits[1] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA256:
|
||||
{
|
||||
for(int i=0; i<SHA256LENGTH; i++)
|
||||
m_auiBuf[i] = sm_H256[i];
|
||||
m_auiBits[0] = 0;
|
||||
m_auiBits[1] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA384:
|
||||
{
|
||||
for(int i=0; i<SHA512LENGTH; i++)
|
||||
m_aoui64Buf[i] = sm_H384[i];
|
||||
m_aoui64Bits[0].m_uiLeft = 0;
|
||||
m_aoui64Bits[0].m_uiRight = 0;
|
||||
m_aoui64Bits[1].m_uiLeft = 0;
|
||||
m_aoui64Bits[1].m_uiRight = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA512:
|
||||
{
|
||||
for(int i=0; i<SHA512LENGTH; i++)
|
||||
m_aoui64Buf[i] = sm_H512[i];
|
||||
m_aoui64Bits[0].m_uiLeft = 0;
|
||||
m_aoui64Bits[0].m_uiRight = 0;
|
||||
m_aoui64Bits[1].m_uiLeft = 0;
|
||||
m_aoui64Bits[1].m_uiRight = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
ostrstream ostr;
|
||||
ostr << "FileDigest ERROR: in CSHA() Constructor, Illegal Method " << iMethod << "!" << ends;
|
||||
string ostrMsg = ostr.str();
|
||||
ostr.freeze(false);
|
||||
throw runtime_error(ostrMsg);
|
||||
}
|
||||
}
|
||||
m_iMethod = iMethod;
|
||||
}
|
||||
|
||||
//Update context to reflect the concatenation of another buffer of bytes.
|
||||
void CSHA::AddData(char const* pcData, int iDataLength)
|
||||
{
|
||||
if(iDataLength < 0)
|
||||
throw runtime_error(string("FileDigest ERROR: in CSHA::AddData(), Data Length should be >= 0!"));
|
||||
unsigned int uiT;
|
||||
switch(m_iMethod)
|
||||
{
|
||||
case SHA160:
|
||||
case SHA256:
|
||||
{
|
||||
//Update bitcount
|
||||
uiT = m_auiBits[0];
|
||||
if((m_auiBits[0] = uiT + ((unsigned int)iDataLength << 3)) < uiT)
|
||||
m_auiBits[1]++; //Carry from low to high
|
||||
m_auiBits[1] += iDataLength >> 29;
|
||||
uiT = (uiT >> 3) & (BLOCKSIZE-1); //Bytes already
|
||||
//Handle any leading odd-sized chunks
|
||||
if(uiT != 0)
|
||||
{
|
||||
unsigned char* puc = (unsigned char*)m_aucIn + uiT;
|
||||
uiT = BLOCKSIZE - uiT;
|
||||
if(iDataLength < uiT)
|
||||
{
|
||||
memcpy(puc, pcData, iDataLength);
|
||||
return;
|
||||
}
|
||||
memcpy(puc, pcData, uiT);
|
||||
Transform();
|
||||
pcData += uiT;
|
||||
iDataLength -= uiT;
|
||||
}
|
||||
//Process data in 64-byte chunks
|
||||
while(iDataLength >= BLOCKSIZE)
|
||||
{
|
||||
memcpy(m_aucIn, pcData, BLOCKSIZE);
|
||||
Transform();
|
||||
pcData += BLOCKSIZE;
|
||||
iDataLength -= BLOCKSIZE;
|
||||
}
|
||||
//Handle any remaining bytes of data
|
||||
memcpy(m_aucIn, pcData, iDataLength);
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA384:
|
||||
case SHA512:
|
||||
{
|
||||
uiT = m_aoui64Bits[0].m_uiRight;
|
||||
unsigned int uiU = m_aoui64Bits[0].m_uiLeft;
|
||||
if((m_aoui64Bits[0].m_uiRight = uiT + ((unsigned int)iDataLength << 3)) < uiT)
|
||||
m_aoui64Bits[0].m_uiLeft++; //Carry from low to high
|
||||
unsigned int uiV = m_aoui64Bits[1].m_uiRight;
|
||||
if((m_aoui64Bits[0].m_uiLeft += iDataLength >> 29) < uiU)
|
||||
m_aoui64Bits[1].m_uiRight++;
|
||||
if(m_aoui64Bits[1].m_uiRight < uiV)
|
||||
m_aoui64Bits[1].m_uiLeft++;
|
||||
uiT = (uiT >> 3) & (BLOCKSIZE2-1); //Bytes already
|
||||
//Handle any leading odd-sized chunks
|
||||
if(uiT != 0)
|
||||
{
|
||||
unsigned char* puc = (unsigned char*)m_aucIn + uiT;
|
||||
uiT = BLOCKSIZE2 - uiT;
|
||||
if(iDataLength < uiT)
|
||||
{
|
||||
memcpy(puc, pcData, iDataLength);
|
||||
return;
|
||||
}
|
||||
memcpy(puc, pcData, uiT);
|
||||
Transform();
|
||||
pcData += uiT;
|
||||
iDataLength -= uiT;
|
||||
}
|
||||
//Process data in 64-byte chunks
|
||||
while(iDataLength >= BLOCKSIZE2)
|
||||
{
|
||||
memcpy(m_aucIn, pcData, BLOCKSIZE2);
|
||||
Transform();
|
||||
pcData += BLOCKSIZE2;
|
||||
iDataLength -= BLOCKSIZE2;
|
||||
}
|
||||
//Handle any remaining bytes of data
|
||||
memcpy(m_aucIn, pcData, iDataLength);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//Set the flag
|
||||
m_bAddData = true;
|
||||
}
|
||||
|
||||
//Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
//1 0*(64-bit count of bits processed, MSB-first)
|
||||
void CSHA::FinalDigest(char* pcDigest)
|
||||
{
|
||||
//Is the User's responsability to ensure that pcDigest is properly allocated 20, 32,
|
||||
//48 or 64 bytes, depending on the method
|
||||
if(false == m_bAddData)
|
||||
throw runtime_error(string("FileDigest ERROR: in CSHA::FinalDigest(), No data Added before call!"));
|
||||
switch(m_iMethod)
|
||||
{
|
||||
case SHA160:
|
||||
case SHA256:
|
||||
{
|
||||
unsigned int uiCount;
|
||||
unsigned char *puc;
|
||||
//Compute number of bytes mod 64
|
||||
uiCount = (m_auiBits[0] >> 3) & (BLOCKSIZE-1);
|
||||
//Set the first char of padding to 0x80. This is safe since there is
|
||||
//always at least one byte free
|
||||
puc = m_aucIn + uiCount;
|
||||
*puc++ = 0x80;
|
||||
//Bytes of padding needed to make 64 bytes
|
||||
uiCount = BLOCKSIZE - uiCount - 1;
|
||||
//Pad out to 56 mod 64
|
||||
if(uiCount < 8)
|
||||
{
|
||||
//Two lots of padding: Pad the first block to 64 bytes
|
||||
memset(puc, 0, uiCount);
|
||||
Transform();
|
||||
//Now fill the next block with 56 bytes
|
||||
memset(m_aucIn, 0, BLOCKSIZE-8);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Pad block to 56 bytes
|
||||
memset(puc, 0, uiCount - 8);
|
||||
}
|
||||
//Append length in bits and transform
|
||||
Word2Bytes(m_auiBits[1], &m_aucIn[BLOCKSIZE-8]);
|
||||
Word2Bytes(m_auiBits[0], &m_aucIn[BLOCKSIZE-4]);
|
||||
Transform();
|
||||
switch(m_iMethod)
|
||||
{
|
||||
case SHA160:
|
||||
{
|
||||
for(int i=0; i<SHA160LENGTH; i++,pcDigest+=4)
|
||||
Word2Bytes(m_auiBuf[i], reinterpret_cast<unsigned char*>(pcDigest));
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA256:
|
||||
{
|
||||
for(int i=0; i<SHA256LENGTH; i++,pcDigest+=4)
|
||||
Word2Bytes(m_auiBuf[i], reinterpret_cast<unsigned char*>(pcDigest));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA384:
|
||||
case SHA512:
|
||||
{
|
||||
unsigned char *puc;
|
||||
//Compute number of bytes mod 128
|
||||
unsigned int uiCount = (m_aoui64Bits[0].m_uiRight >> 3) & (BLOCKSIZE2-1);
|
||||
//Set the first char of padding to 0x80. This is safe since there is
|
||||
//always at least one byte free
|
||||
puc = m_aucIn + uiCount;
|
||||
*puc++ = 0x80;
|
||||
//Bytes of padding needed to make 128 bytes
|
||||
uiCount = BLOCKSIZE2 - uiCount - 1;
|
||||
//Pad out to 112 mod 128
|
||||
if(uiCount < 16)
|
||||
{
|
||||
//Two lots of padding: Pad the first block to 128 bytes
|
||||
memset(puc, 0, uiCount);
|
||||
Transform();
|
||||
//Now fill the next block with 112 bytes
|
||||
memset(m_aucIn, 0, BLOCKSIZE2-16);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Pad block to 112 bytes
|
||||
memset(puc, 0, uiCount - 16);
|
||||
}
|
||||
//Append length in bits and transform
|
||||
Word2Bytes(m_aoui64Bits[1], &m_aucIn[BLOCKSIZE2-16]);
|
||||
Word2Bytes(m_aoui64Bits[0], &m_aucIn[BLOCKSIZE2-8]);
|
||||
Transform();
|
||||
switch(m_iMethod)
|
||||
{
|
||||
case SHA384:
|
||||
{
|
||||
for(int i=0; i<SHA384LENGTH; i++,pcDigest+=8)
|
||||
Word2Bytes(m_aoui64Buf[i], reinterpret_cast<unsigned char*>(pcDigest));
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA512:
|
||||
{
|
||||
for(int i=0; i<SHA512LENGTH; i++,pcDigest+=8)
|
||||
Word2Bytes(m_aoui64Buf[i], reinterpret_cast<unsigned char*>(pcDigest));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//Reinitialize
|
||||
Reset();
|
||||
}
|
||||
|
||||
//Reset current operation in order to prepare a new one
|
||||
void CSHA::Reset()
|
||||
{
|
||||
//Reinitialize
|
||||
switch(m_iMethod)
|
||||
{
|
||||
case SHA160:
|
||||
{
|
||||
for(int i=0; i<SHA160LENGTH; i++)
|
||||
m_auiBuf[i] = sm_H160[i];
|
||||
m_auiBits[0] = 0;
|
||||
m_auiBits[1] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA256:
|
||||
{
|
||||
for(int i=0; i<SHA256LENGTH; i++)
|
||||
m_auiBuf[i] = sm_H256[i];
|
||||
m_auiBits[0] = 0;
|
||||
m_auiBits[1] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA384:
|
||||
{
|
||||
for(int i=0; i<SHA512LENGTH; i++)
|
||||
m_aoui64Buf[i] = sm_H384[i];
|
||||
m_aoui64Bits[0].m_uiLeft = 0;
|
||||
m_aoui64Bits[0].m_uiRight = 0;
|
||||
m_aoui64Bits[1].m_uiLeft = 0;
|
||||
m_aoui64Bits[1].m_uiRight = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA512:
|
||||
{
|
||||
for(int i=0; i<SHA512LENGTH; i++)
|
||||
m_aoui64Buf[i] = sm_H512[i];
|
||||
m_aoui64Bits[0].m_uiLeft = 0;
|
||||
m_aoui64Bits[0].m_uiRight = 0;
|
||||
m_aoui64Bits[1].m_uiLeft = 0;
|
||||
m_aoui64Bits[1].m_uiRight = 0;
|
||||
}
|
||||
}
|
||||
//Reset the flag
|
||||
m_bAddData = false;
|
||||
}
|
||||
|
||||
//The core of the SHA algorithm, this alters an existing SHA hash to
|
||||
//reflect the addition of 16 longwords of new data.
|
||||
void CSHA::Transform()
|
||||
{
|
||||
switch(m_iMethod)
|
||||
{
|
||||
case SHA160:
|
||||
{
|
||||
//Expansion of m_aucIn
|
||||
unsigned char* pucIn = m_aucIn;
|
||||
unsigned int auiW[80];
|
||||
int i;
|
||||
for(i=0; i<16; i++,pucIn+=4)
|
||||
Bytes2Word(pucIn, auiW[i]);
|
||||
for(i=16; i<80; i++)
|
||||
auiW[i] = CircularShift(1, auiW[i-3]^auiW[i-8]^auiW[i-14]^auiW[i-16]);
|
||||
unsigned int temp;
|
||||
unsigned int A, B, C, D, E;
|
||||
A = m_auiBuf[0];
|
||||
B = m_auiBuf[1];
|
||||
C = m_auiBuf[2];
|
||||
D = m_auiBuf[3];
|
||||
E = m_auiBuf[4];
|
||||
for(i=0; i<20; i++)
|
||||
{
|
||||
temp = CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + auiW[i] + sm_K160[0];
|
||||
E = D;
|
||||
D = C;
|
||||
C = CircularShift(30, B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
for(i=20; i<40; i++)
|
||||
{
|
||||
temp = CircularShift(5, A) + (B ^ C ^ D) + E + auiW[i] + sm_K160[1];
|
||||
E = D;
|
||||
D = C;
|
||||
C = CircularShift(30, B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
for(i=40; i<60; i++)
|
||||
{
|
||||
temp = CircularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + auiW[i] + sm_K160[2];
|
||||
E = D;
|
||||
D = C;
|
||||
C = CircularShift(30, B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
for(i=60; i<80; i++)
|
||||
{
|
||||
temp = CircularShift(5, A) + (B ^ C ^ D) + E + auiW[i] + sm_K160[3];
|
||||
E = D;
|
||||
D = C;
|
||||
C = CircularShift(30, B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
m_auiBuf[0] += A;
|
||||
m_auiBuf[1] += B;
|
||||
m_auiBuf[2] += C;
|
||||
m_auiBuf[3] += D;
|
||||
m_auiBuf[4] += E;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA256:
|
||||
{
|
||||
//Expansion of m_aucIn
|
||||
unsigned char* pucIn = m_aucIn;
|
||||
unsigned int auiW[64];
|
||||
int i;
|
||||
for(i=0; i<16; i++,pucIn+=4)
|
||||
Bytes2Word(pucIn, auiW[i]);
|
||||
for(i=16; i<64; i++)
|
||||
auiW[i] = sig1(auiW[i-2]) + auiW[i-7] + sig0(auiW[i-15]) + auiW[i-16];
|
||||
//OR
|
||||
//for(i=0; i<48; i++)
|
||||
// auiW[i+16] = sig1(auiW[i+14]) + auiW[i+9] + sig0(auiW[i+1]) + auiW[i];
|
||||
unsigned int a, b, c, d, e, f, g, h, t;
|
||||
a = m_auiBuf[0];
|
||||
b = m_auiBuf[1];
|
||||
c = m_auiBuf[2];
|
||||
d = m_auiBuf[3];
|
||||
e = m_auiBuf[4];
|
||||
f = m_auiBuf[5];
|
||||
g = m_auiBuf[6];
|
||||
h = m_auiBuf[7];
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K256[0] + auiW[0]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K256[1] + auiW[1]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K256[2] + auiW[2]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K256[3] + auiW[3]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K256[4] + auiW[4]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K256[5] + auiW[5]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K256[6] + auiW[6]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K256[7] + auiW[7]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K256[8] + auiW[8]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K256[9] + auiW[9]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K256[10] + auiW[10]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K256[11] + auiW[11]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K256[12] + auiW[12]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K256[13] + auiW[13]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K256[14] + auiW[14]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K256[15] + auiW[15]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K256[16] + auiW[16]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K256[17] + auiW[17]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K256[18] + auiW[18]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K256[19] + auiW[19]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K256[20] + auiW[20]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K256[21] + auiW[21]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K256[22] + auiW[22]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K256[23] + auiW[23]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K256[24] + auiW[24]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K256[25] + auiW[25]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K256[26] + auiW[26]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K256[27] + auiW[27]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K256[28] + auiW[28]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K256[29] + auiW[29]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K256[30] + auiW[30]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K256[31] + auiW[31]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K256[32] + auiW[32]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K256[33] + auiW[33]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K256[34] + auiW[34]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K256[35] + auiW[35]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K256[36] + auiW[36]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K256[37] + auiW[37]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K256[38] + auiW[38]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K256[39] + auiW[39]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K256[40] + auiW[40]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K256[41] + auiW[41]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K256[42] + auiW[42]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K256[43] + auiW[43]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K256[44] + auiW[44]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K256[45] + auiW[45]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K256[46] + auiW[46]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K256[47] + auiW[47]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K256[48] + auiW[48]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K256[49] + auiW[49]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K256[50] + auiW[50]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K256[51] + auiW[51]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K256[52] + auiW[52]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K256[53] + auiW[53]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K256[54] + auiW[54]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K256[55] + auiW[55]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K256[56] + auiW[56]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K256[57] + auiW[57]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K256[58] + auiW[58]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K256[59] + auiW[59]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K256[60] + auiW[60]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K256[61] + auiW[61]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K256[62] + auiW[62]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K256[63] + auiW[63]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
//OR
|
||||
/*
|
||||
unsigned int a, b, c, d, e, f, g, h, t1, t2;
|
||||
a = m_auiBuf[0];
|
||||
b = m_auiBuf[1];
|
||||
c = m_auiBuf[2];
|
||||
d = m_auiBuf[3];
|
||||
e = m_auiBuf[4];
|
||||
f = m_auiBuf[5];
|
||||
g = m_auiBuf[6];
|
||||
h = m_auiBuf[7];
|
||||
//
|
||||
for(i=0; i<64; i++)
|
||||
{
|
||||
t1 = h + SIG1(e) + CH(e, f, g) + sm_K256[i] + auiW[i];
|
||||
t2 = SIG0(a) + MAJ(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d+t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
*/
|
||||
m_auiBuf[0] += a;
|
||||
m_auiBuf[1] += b;
|
||||
m_auiBuf[2] += c;
|
||||
m_auiBuf[3] += d;
|
||||
m_auiBuf[4] += e;
|
||||
m_auiBuf[5] += f;
|
||||
m_auiBuf[6] += g;
|
||||
m_auiBuf[7] += h;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHA384:
|
||||
case SHA512:
|
||||
{
|
||||
//Expansion of m_aucIn
|
||||
unsigned char* pucIn = m_aucIn;
|
||||
SUI64 aoui64W[80];
|
||||
int i;
|
||||
for(i=0; i<16; i++,pucIn+=8)
|
||||
Bytes2Word(pucIn, aoui64W[i]);
|
||||
for(i=16; i<80; i++)
|
||||
aoui64W[i] = sig1(aoui64W[i-2]) + aoui64W[i-7] + sig0(aoui64W[i-15]) + aoui64W[i-16];
|
||||
SUI64 a, b, c, d, e, f, g, h, t;
|
||||
a = m_aoui64Buf[0];
|
||||
b = m_aoui64Buf[1];
|
||||
c = m_aoui64Buf[2];
|
||||
d = m_aoui64Buf[3];
|
||||
e = m_aoui64Buf[4];
|
||||
f = m_aoui64Buf[5];
|
||||
g = m_aoui64Buf[6];
|
||||
h = m_aoui64Buf[7];
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[0] + aoui64W[0]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[1] + aoui64W[1]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[2] + aoui64W[2]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[3] + aoui64W[3]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[4] + aoui64W[4]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[5] + aoui64W[5]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[6] + aoui64W[6]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[7] + aoui64W[7]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[8] + aoui64W[8]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[9] + aoui64W[9]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[10] + aoui64W[10]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[11] + aoui64W[11]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[12] + aoui64W[12]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[13] + aoui64W[13]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[14] + aoui64W[14]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[15] + aoui64W[15]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[16] + aoui64W[16]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[17] + aoui64W[17]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[18] + aoui64W[18]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[19] + aoui64W[19]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[20] + aoui64W[20]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[21] + aoui64W[21]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[22] + aoui64W[22]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[23] + aoui64W[23]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[24] + aoui64W[24]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[25] + aoui64W[25]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[26] + aoui64W[26]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[27] + aoui64W[27]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[28] + aoui64W[28]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[29] + aoui64W[29]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[30] + aoui64W[30]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[31] + aoui64W[31]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[32] + aoui64W[32]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[33] + aoui64W[33]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[34] + aoui64W[34]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[35] + aoui64W[35]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[36] + aoui64W[36]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[37] + aoui64W[37]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[38] + aoui64W[38]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[39] + aoui64W[39]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[40] + aoui64W[40]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[41] + aoui64W[41]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[42] + aoui64W[42]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[43] + aoui64W[43]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[44] + aoui64W[44]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[45] + aoui64W[45]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[46] + aoui64W[46]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[47] + aoui64W[47]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[48] + aoui64W[48]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[49] + aoui64W[49]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[50] + aoui64W[50]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[51] + aoui64W[51]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[52] + aoui64W[52]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[53] + aoui64W[53]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[54] + aoui64W[54]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[55] + aoui64W[55]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[56] + aoui64W[56]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[57] + aoui64W[57]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[58] + aoui64W[58]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[59] + aoui64W[59]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[60] + aoui64W[60]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[61] + aoui64W[61]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[62] + aoui64W[62]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[63] + aoui64W[63]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[64] + aoui64W[64]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[65] + aoui64W[65]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[66] + aoui64W[66]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[67] + aoui64W[67]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[68] + aoui64W[68]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[69] + aoui64W[69]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[70] + aoui64W[70]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[71] + aoui64W[71]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
t = h + SIG1(e) + CH(e, f, g) + sm_K512[72] + aoui64W[72]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
|
||||
t = g + SIG1(d) + CH(d, e, f) + sm_K512[73] + aoui64W[73]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
|
||||
t = f + SIG1(c) + CH(c, d, e) + sm_K512[74] + aoui64W[74]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
|
||||
t = e + SIG1(b) + CH(b, c, d) + sm_K512[75] + aoui64W[75]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
|
||||
t = d + SIG1(a) + CH(a, b, c) + sm_K512[76] + aoui64W[76]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
|
||||
t = c + SIG1(h) + CH(h, a, b) + sm_K512[77] + aoui64W[77]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
|
||||
t = b + SIG1(g) + CH(g, h, a) + sm_K512[78] + aoui64W[78]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
|
||||
t = a + SIG1(f) + CH(f, g, h) + sm_K512[79] + aoui64W[79]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
|
||||
//
|
||||
m_aoui64Buf[0] += a;
|
||||
m_aoui64Buf[1] += b;
|
||||
m_aoui64Buf[2] += c;
|
||||
m_aoui64Buf[3] += d;
|
||||
m_aoui64Buf[4] += e;
|
||||
m_aoui64Buf[5] += f;
|
||||
m_aoui64Buf[6] += g;
|
||||
m_aoui64Buf[7] += h;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
379
3rdparty/MultiEmulator/src/SHA.h
vendored
Normal file
379
3rdparty/MultiEmulator/src/SHA.h
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
//SHA.h
|
||||
|
||||
#ifndef __SHA_H__
|
||||
#define __SHA_H__
|
||||
|
||||
#include "MessageDigest.h"
|
||||
|
||||
//Typical DISCLAIMER:
|
||||
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
|
||||
//use and distribute the code in any way you see fit as long as this paragraph is included
|
||||
//with the distribution. No warranties or claims are made as to the validity of the
|
||||
//information and code contained herein, so use it at your own risk.
|
||||
|
||||
//Structure for representing an Unsigned Integer on 64 bits
|
||||
struct SUI64
|
||||
{
|
||||
//Data
|
||||
unsigned int m_uiLeft;
|
||||
unsigned int m_uiRight;
|
||||
|
||||
//Operators
|
||||
SUI64& operator++()
|
||||
{
|
||||
unsigned int uiTemp = m_uiRight;
|
||||
m_uiRight++;
|
||||
if(m_uiRight < uiTemp)
|
||||
m_uiLeft++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SUI64& operator--()
|
||||
{
|
||||
unsigned int uiTemp = m_uiRight;
|
||||
m_uiRight--;
|
||||
if(m_uiRight > uiTemp)
|
||||
m_uiLeft--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SUI64& operator+=(SUI64 const& roUI64)
|
||||
{
|
||||
m_uiRight += roUI64.m_uiRight;
|
||||
if(m_uiRight < roUI64.m_uiRight)
|
||||
m_uiLeft++;
|
||||
m_uiLeft += roUI64.m_uiLeft;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SUI64& operator|=(SUI64 const& roUI64)
|
||||
{
|
||||
m_uiRight |= roUI64.m_uiRight;
|
||||
m_uiLeft |= roUI64.m_uiLeft;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SUI64& operator&=(SUI64 const& roUI64)
|
||||
{
|
||||
m_uiRight &= roUI64.m_uiRight;
|
||||
m_uiLeft &= roUI64.m_uiLeft;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SUI64& operator^=(SUI64 const& roUI64)
|
||||
{
|
||||
m_uiRight ^= roUI64.m_uiRight;
|
||||
m_uiLeft ^= roUI64.m_uiLeft;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SUI64& operator<<=(unsigned int uiBits)
|
||||
{
|
||||
if(uiBits < 32)
|
||||
{
|
||||
(m_uiLeft <<= uiBits) |= (m_uiRight >> (32-uiBits));
|
||||
m_uiRight <<= uiBits;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uiLeft = m_uiRight << (uiBits-32);
|
||||
m_uiRight = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SUI64& operator>>=(unsigned int uiBits)
|
||||
{
|
||||
if(uiBits < 32)
|
||||
{
|
||||
(m_uiRight >>= uiBits) |= (m_uiLeft << (32-uiBits));
|
||||
m_uiLeft >>= uiBits;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uiRight = m_uiLeft >> (uiBits-32);
|
||||
m_uiLeft = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator>(SUI64 const& roUI64) const
|
||||
{
|
||||
if(m_uiLeft == roUI64.m_uiLeft)
|
||||
return m_uiRight > roUI64.m_uiRight;
|
||||
else
|
||||
return m_uiLeft > roUI64.m_uiLeft;
|
||||
}
|
||||
|
||||
bool operator<(SUI64 const& roUI64) const
|
||||
{
|
||||
if(m_uiLeft == roUI64.m_uiLeft)
|
||||
return m_uiRight < roUI64.m_uiRight;
|
||||
else
|
||||
return m_uiLeft < roUI64.m_uiLeft;
|
||||
}
|
||||
};
|
||||
|
||||
inline SUI64 operator+(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
|
||||
{
|
||||
SUI64 temp = roUI64_1;
|
||||
temp += roUI64_2;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline SUI64 operator|(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
|
||||
{
|
||||
SUI64 temp = roUI64_1;
|
||||
temp |= roUI64_2;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline SUI64 operator&(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
|
||||
{
|
||||
SUI64 temp = roUI64_1;
|
||||
temp &= roUI64_2;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline SUI64 operator^(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
|
||||
{
|
||||
SUI64 temp = roUI64_1;
|
||||
temp ^= roUI64_2;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline SUI64 operator<<(SUI64 const& roUI64, unsigned int uiBits)
|
||||
{
|
||||
SUI64 temp = roUI64;
|
||||
temp <<= uiBits;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline SUI64 operator>>(SUI64 const& roUI64, unsigned int uiBits)
|
||||
{
|
||||
SUI64 temp = roUI64;
|
||||
temp >>= uiBits;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline bool operator>(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
|
||||
{
|
||||
return roUI64_1.operator>(roUI64_2);
|
||||
}
|
||||
|
||||
inline bool operator<(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
|
||||
{
|
||||
return roUI64_1.operator<(roUI64_2);
|
||||
}
|
||||
|
||||
//SHA Message Digest algorithm
|
||||
//SHA160 TEST VALUES:
|
||||
//1)"abc"
|
||||
//"A9993E364706816ABA3E25717850C26C9CD0D89D"
|
||||
//
|
||||
//2)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
//"84983E441C3BD26EBAAE4AA1F95129E5E54670F1"
|
||||
//
|
||||
//3)1,000,000 repetitions of "a".
|
||||
//"34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"
|
||||
//
|
||||
//SHA256 TEST VALUES:
|
||||
//1)One-Block Message "abc"
|
||||
//"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
|
||||
//
|
||||
//2)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
//"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
|
||||
//
|
||||
//3)Multi-Block Message "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
|
||||
//"CF5B16A778AF8380036CE59E7B0492370B249B11E8F07A51AFAC45037AFEE9D1"
|
||||
//
|
||||
//4)Long Message "a" 1,000,000 times
|
||||
//"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
|
||||
//
|
||||
//SHA384 TEST VALUES:
|
||||
//1)One-Block Message "abc"
|
||||
//"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"
|
||||
//
|
||||
//2)Multi-Block Message "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
|
||||
//"09330C33F71147E83D192FC782CD1B4753111B173B3B05D22FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039"
|
||||
//
|
||||
//3)Long Message "a" 1,000,000 times
|
||||
//"9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"
|
||||
//
|
||||
//SHA512 TEST VALUES:
|
||||
//1)One-Block Message "abc"
|
||||
//"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a8
|
||||
//36ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
||||
//
|
||||
//2)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
|
||||
//"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4
|
||||
//331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
|
||||
//
|
||||
//3)""
|
||||
//"CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE47D0D13C5D85F2B0
|
||||
//FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E"
|
||||
//
|
||||
//4)Long Message "a" 1,000,000 times
|
||||
//"E718483D0CE769644E2E42C7BC15B4638E1F98B13B2044285632A803AFA973EBDE0FF244877EA60A
|
||||
//4CB0432CE577C31BEB009C5C2C49AA2E4EADB217AD8CC09B"
|
||||
|
||||
class CSHA : public IMessageDigest
|
||||
{
|
||||
public:
|
||||
enum { SHA160=0, SHA256=1, SHA384=2, SHA512=3 };
|
||||
//CONSTRUCTOR
|
||||
CSHA(int iMethod=SHA160);
|
||||
//Update context to reflect the concatenation of another buffer of bytes.
|
||||
void AddData(char const* pcData, int iDataLength);
|
||||
//Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
//1 0*(64-bit count of bits processed, MSB-first)
|
||||
void FinalDigest(char* pcDigest);
|
||||
//Reset current operation in order to prepare a new one
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
//Transformation Function
|
||||
void Transform();
|
||||
//The Method
|
||||
int m_iMethod;
|
||||
enum { BLOCKSIZE2 = BLOCKSIZE<<1 };
|
||||
//For 32 bits Integers
|
||||
enum { SHA160LENGTH=5, SHA256LENGTH=8 };
|
||||
//Context Variables
|
||||
unsigned int m_auiBuf[SHA256LENGTH]; //Maximum for SHA256
|
||||
unsigned int m_auiBits[2];
|
||||
unsigned char m_aucIn[BLOCKSIZE2]; //128 bytes for SHA384, SHA512
|
||||
//Internal auxiliary static functions
|
||||
static unsigned int CircularShift(unsigned int uiBits, unsigned int uiWord);
|
||||
static unsigned int CH(unsigned int x, unsigned int y, unsigned int z);
|
||||
static unsigned int MAJ(unsigned int x, unsigned int y, unsigned int z);
|
||||
static unsigned int SIG0(unsigned int x);
|
||||
static unsigned int SIG1(unsigned int x);
|
||||
static unsigned int sig0(unsigned int x);
|
||||
static unsigned int sig1(unsigned int x);
|
||||
static void Bytes2Word(unsigned char const* pcBytes, unsigned int& ruiWord);
|
||||
static void Word2Bytes(unsigned int const& ruiWord, unsigned char* pcBytes);
|
||||
static const unsigned int sm_K160[4];
|
||||
static const unsigned int sm_H160[SHA160LENGTH];
|
||||
static const unsigned int sm_K256[64];
|
||||
static const unsigned int sm_H256[SHA256LENGTH];
|
||||
|
||||
//For 64 bits Integers
|
||||
enum { SHA384LENGTH=6, SHA512LENGTH=8 };
|
||||
//Context Variables
|
||||
SUI64 m_aoui64Buf[SHA512LENGTH]; //Maximum for SHA512
|
||||
SUI64 m_aoui64Bits[2];
|
||||
//Internal auxiliary static functions
|
||||
static SUI64 CircularShift(unsigned int uiBits, SUI64 const& roui64Word);
|
||||
static SUI64 CH(SUI64 const& x, SUI64 const& y, SUI64 const& z);
|
||||
static SUI64 MAJ(SUI64 const& x, SUI64 const& y, SUI64 const& z);
|
||||
static SUI64 SIG0(SUI64 const& x);
|
||||
static SUI64 SIG1(SUI64 const& x);
|
||||
static SUI64 sig0(SUI64 const& x);
|
||||
static SUI64 sig1(SUI64 const& x);
|
||||
static void Bytes2Word(unsigned char const* pcBytes, SUI64& ruiWord);
|
||||
static void Word2Bytes(SUI64 const& ruiWord, unsigned char* pcBytes);
|
||||
static const SUI64 sm_H384[SHA512LENGTH]; //Dim is as 512
|
||||
static const SUI64 sm_K512[80];
|
||||
static const SUI64 sm_H512[SHA512LENGTH];
|
||||
};
|
||||
|
||||
inline unsigned int CSHA::CircularShift(unsigned int uiBits, unsigned int uiWord)
|
||||
{
|
||||
return (uiWord << uiBits) | (uiWord >> (32-uiBits));
|
||||
}
|
||||
|
||||
inline unsigned int CSHA::CH(unsigned int x, unsigned int y, unsigned int z)
|
||||
{
|
||||
return ((x&(y^z))^z);
|
||||
}
|
||||
|
||||
inline unsigned int CSHA::MAJ(unsigned int x, unsigned int y, unsigned int z)
|
||||
{
|
||||
return (((x|y)&z)|(x&y));
|
||||
}
|
||||
|
||||
inline unsigned int CSHA::SIG0(unsigned int x)
|
||||
{
|
||||
return ((x >> 2)|(x << 30)) ^ ((x >> 13)|(x << 19)) ^ ((x >> 22)|(x << 10));
|
||||
}
|
||||
|
||||
inline unsigned int CSHA::SIG1(unsigned int x)
|
||||
{
|
||||
return ((x >> 6)|(x << 26)) ^ ((x >> 11)|(x << 21)) ^ ((x >> 25)|(x << 7));
|
||||
}
|
||||
|
||||
inline unsigned int CSHA::sig0(unsigned int x)
|
||||
{
|
||||
return ((x >> 7)|(x << 25)) ^ ((x >> 18)|(x << 14)) ^ (x >> 3);
|
||||
}
|
||||
|
||||
inline unsigned int CSHA::sig1(unsigned int x)
|
||||
{
|
||||
return ((x >> 17)|(x << 15)) ^ ((x >> 19)|(x << 13)) ^ (x >> 10);
|
||||
}
|
||||
|
||||
inline void CSHA::Bytes2Word(unsigned char const* pcBytes, unsigned int& ruiWord)
|
||||
{
|
||||
ruiWord = (unsigned int)*(pcBytes+3) | (unsigned int)(*(pcBytes+2)<<8) |
|
||||
(unsigned int)(*(pcBytes+1)<<16) | (unsigned int)(*pcBytes<<24);
|
||||
}
|
||||
|
||||
inline void CSHA::Word2Bytes(unsigned int const& ruiWord, unsigned char* pcBytes)
|
||||
{
|
||||
pcBytes += 3;
|
||||
*pcBytes = ruiWord & 0xff;
|
||||
*--pcBytes = (ruiWord>>8) & 0xff;
|
||||
*--pcBytes = (ruiWord>>16) & 0xff;
|
||||
*--pcBytes = (ruiWord>>24) & 0xff;
|
||||
}
|
||||
|
||||
inline SUI64 CSHA::CircularShift(unsigned int uiBits, SUI64 const& roui64Word)
|
||||
{
|
||||
return (roui64Word << uiBits) | (roui64Word >> (64-uiBits));
|
||||
}
|
||||
|
||||
inline SUI64 CSHA::CH(SUI64 const& x, SUI64 const& y, SUI64 const& z)
|
||||
{
|
||||
return ((x&(y^z))^z);
|
||||
}
|
||||
|
||||
inline SUI64 CSHA::MAJ(SUI64 const& x, SUI64 const& y, SUI64 const& z)
|
||||
{
|
||||
return (((x|y)&z)|(x&y));
|
||||
}
|
||||
|
||||
inline SUI64 CSHA::SIG0(SUI64 const& x)
|
||||
{
|
||||
return ((x >> 28)|(x << 36)) ^ ((x >> 34)|(x << 30)) ^ ((x >> 39)|(x << 25));
|
||||
}
|
||||
|
||||
inline SUI64 CSHA::SIG1(SUI64 const& x)
|
||||
{
|
||||
return ((x >> 14)|(x << 50)) ^ ((x >> 18)|(x << 46)) ^ ((x >> 41)|(x << 23));
|
||||
}
|
||||
|
||||
inline SUI64 CSHA::sig0(SUI64 const& x)
|
||||
{
|
||||
return ((x >> 1)|(x << 63)) ^ ((x >> 8)|(x << 56)) ^ (x >> 7);
|
||||
}
|
||||
|
||||
inline SUI64 CSHA::sig1(SUI64 const& x)
|
||||
{
|
||||
return ((x >> 19)|(x << 45)) ^ ((x >> 61)|(x << 3)) ^ (x >> 6);
|
||||
}
|
||||
|
||||
inline void CSHA::Bytes2Word(unsigned char const* pcBytes, SUI64& ruiWord)
|
||||
{
|
||||
Bytes2Word(pcBytes+4, ruiWord.m_uiRight);
|
||||
Bytes2Word(pcBytes, ruiWord.m_uiLeft);
|
||||
}
|
||||
|
||||
inline void CSHA::Word2Bytes(SUI64 const& ruiWord, unsigned char* pcBytes)
|
||||
{
|
||||
Word2Bytes(ruiWord.m_uiRight, pcBytes+4);
|
||||
Word2Bytes(ruiWord.m_uiLeft, pcBytes);
|
||||
}
|
||||
|
||||
#endif // __SHA_H__
|
||||
13
3rdparty/MultiEmulator/src/Setti.cpp
vendored
Normal file
13
3rdparty/MultiEmulator/src/Setti.cpp
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "multi_emulator.h"
|
||||
|
||||
int GenerateSetti(void *pDest)
|
||||
{
|
||||
auto pTicket = (int *)pDest;
|
||||
|
||||
pTicket[0] = 0xD4CA7F7B;
|
||||
pTicket[1] = 0xC7DB6023;
|
||||
pTicket[2] = 0x6D6A2E1F;
|
||||
pTicket[5] = 0xB4C43105;
|
||||
|
||||
return 768;
|
||||
}
|
||||
18
3rdparty/MultiEmulator/src/SteamEmu.cpp
vendored
Normal file
18
3rdparty/MultiEmulator/src/SteamEmu.cpp
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "multi_emulator.h"
|
||||
int GenerateSteamEmu(void *pDest, int nSteamID)
|
||||
{
|
||||
auto pTicket = (int *)pDest;
|
||||
|
||||
pTicket[20] = -1; // +80, dproto/reunion wants this value to be -1, but if this value
|
||||
// does not match -1, then instead of SteamID in [21] cell
|
||||
// client IP address that xored with 0x25730981 number should
|
||||
// be used. But dproto/reunion will just skip ticket validation
|
||||
// in that case.
|
||||
|
||||
pTicket[21] = nSteamID; // +84, SteamId, low part. Actually, this is just system volume serial
|
||||
// number, which comes from GetVolumeInformationA() function. If
|
||||
// function failed (returned 0), then instead of volume serial number
|
||||
// 777 number will be written to the ticket.
|
||||
|
||||
return 768;
|
||||
}
|
||||
12
3rdparty/MultiEmulator/src/StrUtils.cpp
vendored
Normal file
12
3rdparty/MultiEmulator/src/StrUtils.cpp
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "StrUtils.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void CreateRandomString(char *pszDest, int nLength)
|
||||
{
|
||||
static const char c_szAlphaNum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
for (int i = 0; i < nLength; ++i)
|
||||
pszDest[i] = c_szAlphaNum[rand() % (sizeof(c_szAlphaNum) - 1)];
|
||||
|
||||
pszDest[nLength] = '\0';
|
||||
}
|
||||
3
3rdparty/MultiEmulator/src/StrUtils.h
vendored
Normal file
3
3rdparty/MultiEmulator/src/StrUtils.h
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void CreateRandomString(char *pszDest, int nLength);
|
||||
24
3rdparty/MultiEmulator/wscript
vendored
Normal file
24
3rdparty/MultiEmulator/wscript
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# mittorn, 2018
|
||||
|
||||
from waflib import Logs
|
||||
import os
|
||||
|
||||
top = '.'
|
||||
|
||||
def options(opt):
|
||||
return
|
||||
|
||||
def configure(conf):
|
||||
return
|
||||
|
||||
def build(bld):
|
||||
bld.stlib(
|
||||
source = bld.path.ant_glob(['src/*.cpp']),
|
||||
target = 'MultiEmulator',
|
||||
features = 'cxx',
|
||||
includes = ['include/', 'src/'],
|
||||
export_includes = ['include/'],
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM
|
||||
)
|
||||
1
3rdparty/bzip2/bz_version.h
vendored
Normal file
1
3rdparty/bzip2/bz_version.h
vendored
Normal file
@@ -0,0 +1 @@
|
||||
#define BZ_VERSION "1.1.0-fwgs"
|
||||
15
3rdparty/bzip2/wscript
vendored
15
3rdparty/bzip2/wscript
vendored
@@ -14,14 +14,21 @@ def configure(conf):
|
||||
conf.define('BZ_UNIX', 1)
|
||||
|
||||
def build(bld):
|
||||
bld(features = 'subst', source = 'bzip2/bz_version.h.in', target = 'bzip2/bz_version.h', BZ_VERSION='1.1.0-fwgs', name = 'bz_version')
|
||||
# bld(
|
||||
# features = 'subst',
|
||||
# source = 'bzip2/bz_version.h.in',
|
||||
# target = 'bz_version.h',
|
||||
# BZ_VERSION='1.1.0-fwgs'
|
||||
# )
|
||||
|
||||
bz_sources = ['bzip2/blocksort.c', 'bzip2/huffman.c', 'bzip2/crctable.c', 'bzip2/randtable.c', 'bzip2/compress.c', 'bzip2/decompress.c', 'bzip2/bzlib.c']
|
||||
|
||||
bld.stlib(
|
||||
source = bz_sources,
|
||||
target = 'bzip2',
|
||||
use = 'bz_version',
|
||||
includes = 'bzip2/',
|
||||
export_includes = 'bzip2/'
|
||||
# use = 'bz_version.h',
|
||||
features = 'c',
|
||||
includes = ['.', 'bzip2/'],
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
||||
export_includes = ['bzip2/']
|
||||
)
|
||||
|
||||
2
3rdparty/extras/xash-extras
vendored
2
3rdparty/extras/xash-extras
vendored
Submodule 3rdparty/extras/xash-extras updated: 1bdeab2d8f...f4ff263d42
2
3rdparty/gl-wes-v2
vendored
2
3rdparty/gl-wes-v2
vendored
Submodule 3rdparty/gl-wes-v2 updated: 6b392aecbb...2d9b5afe10
2
3rdparty/gl4es/wscript
vendored
2
3rdparty/gl4es/wscript
vendored
@@ -16,7 +16,9 @@ def build(bld):
|
||||
|
||||
bld.stlib(source = gl4es_srcdir.ant_glob(['gl/*.c', 'gl/*/*.c', 'glx/hardext.c']),
|
||||
target = 'gl4es',
|
||||
features = 'c',
|
||||
includes = ['gl4es/src', 'gl4es/src/gl', 'gl4es/src/glx', 'gl4es/include'],
|
||||
defines = ['NOX11', 'NO_GBM', 'NO_INIT_CONSTRUCTOR', 'DEFAULT_ES=2', 'NOEGL', 'NO_LOADER', 'STATICLIB'],
|
||||
cflags = ['-w', '-fvisibility=hidden', '-std=gnu99'],
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
||||
export_includes = '.')
|
||||
|
||||
1
3rdparty/libogg/libogg
vendored
1
3rdparty/libogg/libogg
vendored
Submodule 3rdparty/libogg/libogg deleted from 7cf42ea17a
50
3rdparty/libogg/wscript
vendored
50
3rdparty/libogg/wscript
vendored
@@ -1,50 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
if not conf.path.find_dir('libogg') or not conf.path.find_dir('libogg/src'):
|
||||
conf.fatal('Can\'t find libogg submodule. Run `git submodule update --init --recursive`.')
|
||||
return
|
||||
|
||||
conf.env.INCLUDE_INTTYPES_H = 0
|
||||
conf.env.INCLUDE_SYS_TYPES_H = 0
|
||||
conf.env.INCLUDE_STDINT_H = 0
|
||||
|
||||
if conf.check_cc(header_name='inttypes.h', mandatory = False):
|
||||
conf.env.INCLUDE_INTTYPES_H = 1
|
||||
elif conf.check_cc(header_name='sys/types.h', mandatory = False):
|
||||
conf.env.INCLUDE_SYS_TYPES_H = 1
|
||||
elif conf.check_cc(header_name='stdint.h', mandatory = False):
|
||||
conf.env.INCLUDE_STDINT_H = 1
|
||||
|
||||
def build(bld):
|
||||
sources = bld.path.ant_glob([
|
||||
'libogg/src/*.c'
|
||||
])
|
||||
|
||||
bld(
|
||||
features = 'subst',
|
||||
name = 'libogg_config_types',
|
||||
source = 'libogg/include/ogg/config_types.h.in',
|
||||
target = 'libogg/include/ogg/config_types.h',
|
||||
INCLUDE_INTTYPES_H = bld.env.INCLUDE_INTTYPES_H,
|
||||
INCLUDE_SYS_TYPES_H = bld.env.INCLUDE_SYS_TYPES_H,
|
||||
INCLUDE_STDINT_H = bld.env.INCLUDE_STDINT_H,
|
||||
SIZE16 = 'int16_t',
|
||||
USIZE16 = 'uint16_t',
|
||||
SIZE32 = 'int32_t',
|
||||
USIZE32 = 'uint32_t',
|
||||
SIZE64 = 'int64_t',
|
||||
USIZE64 = 'uint64_t'
|
||||
)
|
||||
|
||||
bld.stlib(
|
||||
source = sources,
|
||||
target = 'ogg',
|
||||
use = 'libogg_config_types',
|
||||
includes = 'libogg/include/',
|
||||
export_includes = 'libogg/include/'
|
||||
)
|
||||
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: c92a06e979...b7edbaf2de
2
3rdparty/nanogl
vendored
2
3rdparty/nanogl
vendored
Submodule 3rdparty/nanogl updated: dbfe2e75b3...e75792de03
2
3rdparty/opus/opus
vendored
2
3rdparty/opus/opus
vendored
Submodule 3rdparty/opus/opus updated: 82ac57d9f1...8cf872a186
32
3rdparty/opus/wscript
vendored
32
3rdparty/opus/wscript
vendored
@@ -3,26 +3,6 @@
|
||||
|
||||
import os
|
||||
|
||||
FRAGMENT_VLA='''int main (int argc, char **argv) {
|
||||
char a[argc];
|
||||
a[sizeof( a ) - 1] = 0;
|
||||
int N;
|
||||
return a[0];
|
||||
}'''
|
||||
|
||||
FRAGMENT_ALLOCA_H='''#include <alloca.h>
|
||||
int main (void) {
|
||||
int foo=10;
|
||||
int * array = alloca(foo);
|
||||
}'''
|
||||
|
||||
FRAGMENT_STDLIB_H='''#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
int main (void) {
|
||||
int foo=10;
|
||||
int * array = alloca(foo);
|
||||
}'''
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
@@ -31,15 +11,6 @@ def configure(conf):
|
||||
conf.fatal('Can\'t find opus submodule. Run `git submodule update --init --recursive`.')
|
||||
return
|
||||
|
||||
# Check for C99 variable-size arrays, or alloca() as fallback
|
||||
if conf.check_cc(fragment=FRAGMENT_VLA, msg = 'Checking for C99 VLA support', mandatory = False):
|
||||
conf.define('VAR_ARRAYS', 1)
|
||||
elif conf.check_cc(fragment=FRAGMENT_ALLOCA_H, msg = 'Checking for alloca in alloca.h header', mandatory = False):
|
||||
conf.define('USE_ALLOCA', 1)
|
||||
conf.define('HAVE_ALLOCA_H', 1)
|
||||
elif conf.check_cc(fragmenmt=FRAGMENT_STDLIB_H, msg = 'Checking for alloca.h in stdlib.h', mandatory = False):
|
||||
conf.define('USE_ALLOCA', 1)
|
||||
|
||||
# TODO: ARM/x86 intrinsics detection
|
||||
# TODO: maybe call autotools/cmake/meson instead?
|
||||
|
||||
@@ -56,7 +27,7 @@ def build(bld):
|
||||
'opus/celt/opus_custom_demo.c'
|
||||
])
|
||||
includes = ['opus/include/', 'opus/celt/', 'opus/silk/', 'opus/silk/float/']
|
||||
defines = ['OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.4.0"', 'CUSTOM_MODES']
|
||||
defines = ['USE_ALLOCA', 'OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.3.1"', 'CUSTOM_MODES']
|
||||
|
||||
bld.stlib(
|
||||
source = sources,
|
||||
@@ -64,5 +35,6 @@ def build(bld):
|
||||
features = 'c',
|
||||
includes = includes,
|
||||
defines = defines,
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
||||
export_includes = ['opus/include/']
|
||||
)
|
||||
|
||||
1
3rdparty/opusfile/opusfile
vendored
1
3rdparty/opusfile/opusfile
vendored
Submodule 3rdparty/opusfile/opusfile deleted from 3ecc22aa0a
37
3rdparty/opusfile/wscript
vendored
37
3rdparty/opusfile/wscript
vendored
@@ -1,37 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
if not conf.path.find_dir('opusfile') or not conf.path.find_dir('opusfile/src'):
|
||||
conf.fatal('Can\'t find opusfile submodule. Run `git submodule update --init --recursive`.')
|
||||
return
|
||||
|
||||
if conf.env.COMPILER_CC == 'msvc':
|
||||
conf.define('_CRT_SECURE_NO_WARNINGS', 1)
|
||||
conf.define('_CRT_SECURE_NO_DEPRECATE', 1)
|
||||
conf.define('_CRT_NONSTDC_NO_DEPRECATE', 1)
|
||||
|
||||
if conf.env.DEST_OS == 'android':
|
||||
# HACKHACK: set it to 32 here because opusfile can't be built on Android SDK < 24
|
||||
# with _FILE_OFFSET_BITS 64 (which it sets automatically in src/internal.h)
|
||||
# we are not (????) relying on this part of the API, so it should be harmless
|
||||
conf.define('_FILE_OFFSET_BITS', 32)
|
||||
|
||||
def build(bld):
|
||||
sources = [
|
||||
'opusfile/src/info.c',
|
||||
'opusfile/src/internal.c',
|
||||
'opusfile/src/opusfile.c',
|
||||
'opusfile/src/stream.c'
|
||||
]
|
||||
|
||||
bld.stlib(
|
||||
source = sources,
|
||||
target = 'opusfile',
|
||||
includes = 'opusfile/include/',
|
||||
use = 'ogg opus',
|
||||
export_includes = 'opusfile/include/'
|
||||
)
|
||||
2
3rdparty/vgui_support
vendored
2
3rdparty/vgui_support
vendored
Submodule 3rdparty/vgui_support updated: d585ab86da...7276993f3f
1
3rdparty/vorbis/vorbis-src
vendored
1
3rdparty/vorbis/vorbis-src
vendored
Submodule 3rdparty/vorbis/vorbis-src deleted from bb4047de4c
71
3rdparty/vorbis/wscript
vendored
71
3rdparty/vorbis/wscript
vendored
@@ -1,71 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
FRAGMENT_MEMORY_H='''#include <memory.h>
|
||||
int main (void) {
|
||||
return 0;
|
||||
}'''
|
||||
|
||||
FRAGMENT_ALLOCA_H='''#include <alloca.h>
|
||||
int main (void) {
|
||||
int foo=10;
|
||||
int * array = alloca(foo);
|
||||
}'''
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
if not conf.path.find_dir('vorbis-src') or not conf.path.find_dir('vorbis-src/lib'):
|
||||
conf.fatal('Can\'t find Vorbis submodule. Run `git submodule update --init --recursive`.')
|
||||
return
|
||||
|
||||
if conf.check_cc(fragment=FRAGMENT_MEMORY_H, msg = 'Checking for memory.h header', mandatory = False):
|
||||
conf.define('USE_MEMORY_H', 1)
|
||||
|
||||
conf.check_cc(fragment=FRAGMENT_ALLOCA_H, msg = 'Checking for alloca in alloca.h header', mandatory = False)
|
||||
|
||||
if conf.env.COMPILER_CC == 'msvc':
|
||||
conf.define('_CRT_SECURE_NO_WARNINGS', 1)
|
||||
conf.define('_CRT_SECURE_NO_DEPRECATE', 1)
|
||||
conf.define('_CRT_NONSTDC_NO_DEPRECATE', 1)
|
||||
|
||||
def build(bld):
|
||||
libvorbis_sources = [
|
||||
'vorbis-src/lib/mdct.c',
|
||||
'vorbis-src/lib/smallft.c',
|
||||
'vorbis-src/lib/block.c',
|
||||
'vorbis-src/lib/envelope.c',
|
||||
'vorbis-src/lib/window.c',
|
||||
'vorbis-src/lib/lsp.c',
|
||||
'vorbis-src/lib/lpc.c',
|
||||
'vorbis-src/lib/analysis.c',
|
||||
'vorbis-src/lib/synthesis.c',
|
||||
'vorbis-src/lib/psy.c',
|
||||
'vorbis-src/lib/info.c',
|
||||
'vorbis-src/lib/floor1.c',
|
||||
'vorbis-src/lib/floor0.c',
|
||||
'vorbis-src/lib/res0.c',
|
||||
'vorbis-src/lib/mapping0.c',
|
||||
'vorbis-src/lib/registry.c',
|
||||
'vorbis-src/lib/codebook.c',
|
||||
'vorbis-src/lib/sharedbook.c',
|
||||
'vorbis-src/lib/lookup.c',
|
||||
'vorbis-src/lib/bitrate.c'
|
||||
]
|
||||
|
||||
bld.stlib(
|
||||
source = libvorbis_sources,
|
||||
target = 'vorbis',
|
||||
includes = 'vorbis-src/include/',
|
||||
use = 'ogg',
|
||||
export_includes = 'vorbis-src/include/'
|
||||
)
|
||||
|
||||
bld.stlib(
|
||||
source = 'vorbis-src/lib/vorbisfile.c',
|
||||
target = 'vorbisfile',
|
||||
includes = 'vorbis-src/include/',
|
||||
use = 'vorbis',
|
||||
export_includes = 'vorbis-src/include/'
|
||||
)
|
||||
@@ -13,6 +13,5 @@ When `-bugcomp` is specified with argument, it interpreted as flags separated wi
|
||||
| Flag | Description | Games that require this flag |
|
||||
| ------- | ----------- | ---------------------------- |
|
||||
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
|
||||
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol.<br>Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
|
||||
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol. Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
|
||||
| `sp_attn_none` | Makes sounds with attenuation zero spatialized, i.e. have a stereo effect. | Possibly, every game that was made for GoldSrc. |
|
||||
| `get_game_dir_full` | Makes server return full path in server's `pfnGetGameDir` API function | Mods targetting engine before HL 1.1.1.1, according to MetaMod [documentation](http://metamod.org/engine_notes.html#GetGameDir) |
|
||||
|
||||
150
Documentation/entity-tools.md
Normal file
150
Documentation/entity-tools.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# There are few new commands availiable in xash3d fork:
|
||||
|
||||
## Commands:
|
||||
### ent_create
|
||||
Create entity with specified classname and key/values
|
||||
|
||||
`ent_create <classname> <key> <value> <key> <value> ...`
|
||||
|
||||
for example:
|
||||
|
||||
`ent_create monster_zombie targetname zomb1`
|
||||
|
||||
after creating entity, ent_last_xxx cvars are set to new entity and ent_last_cb called, look at ent_getvars description
|
||||
|
||||
### ent_fire
|
||||
|
||||
Make some actions on entity
|
||||
|
||||
`ent_fire <pattern> <command> <args>`
|
||||
Availiavle commands:
|
||||
* Set fields (Only set entity field, does not call any functions):
|
||||
* health
|
||||
* gravity
|
||||
* movetype
|
||||
* solid
|
||||
* rendermode
|
||||
* rendercolor (vector)
|
||||
* renderfx
|
||||
* renderamt
|
||||
* hullmin (vector)
|
||||
* hullmax (vector)
|
||||
* Actions
|
||||
* rename: set entity targetname
|
||||
* settarget: set entity target (only targetnames)
|
||||
* setmodel: set entity model (does not update)
|
||||
* set: set key/value by server library
|
||||
* See game FGD to get list.
|
||||
* command takes two arguments
|
||||
* touch: touch entity by current player.
|
||||
* use: use entity by current player.
|
||||
* movehere: place entity in player fov.
|
||||
* drop2floor: place entity to nearest floor surface
|
||||
* moveup: move entity to 25 units up
|
||||
* moveup (value): move by y axis relatively to specified value
|
||||
* Flags (Set/clear specified flag bit, arg is bit number):
|
||||
* setflag
|
||||
* clearflag
|
||||
* setspawnflag
|
||||
* clearspawnflag
|
||||
|
||||
### ent_info
|
||||
Print information about entity by identificator
|
||||
|
||||
`ent_info <identificator>`
|
||||
|
||||
### ent_getvars
|
||||
Set client cvars containing entity information (useful for [[Scripting]]) and call ent_last_cb
|
||||
|
||||
`ent_getvars <identificator>`
|
||||
|
||||
These cvars are set:
|
||||
```
|
||||
ent_last_name
|
||||
ent_last_num
|
||||
ent_last_inst
|
||||
ent_last_origin
|
||||
ent_last_class
|
||||
```
|
||||
|
||||
### ent_list
|
||||
Print short information about antities, filtered by pattern
|
||||
|
||||
`ent_list <pattern>`
|
||||
|
||||
## Syntax description
|
||||
|
||||
### \<identificator\>
|
||||
|
||||
* !cross: entity under aim
|
||||
* Instance code: !\<number\>_\<seria\l>
|
||||
* set by ent_getvars command
|
||||
* Entity index
|
||||
* targetname pattern
|
||||
|
||||
### \<pattern\>
|
||||
|
||||
Pattern is like identificator, but may filter many entities by classname
|
||||
|
||||
### (vector)
|
||||
|
||||
used by ent_fire command. vector means three float values, entered without quotes
|
||||
|
||||
### key/value
|
||||
|
||||
All entities parameters may be set by specifiing key and value strings.
|
||||
|
||||
Originally, this mechanizm is used in map/bsp format, but it can be used in enttools too.
|
||||
|
||||
Keys and values are passed to server library and processed by entity keyvalue function, setting edict and entity owns parameters.
|
||||
|
||||
If value contains spaces, it must be put in quotes:
|
||||
|
||||
`ent_fire !cross set origin "0 0 0"`
|
||||
|
||||
## Using with scripting
|
||||
|
||||
ent_create and ent_getvars commands are setting cvars on client
|
||||
|
||||
It can be used with ent_last_cb alias that is executed after setting cvars.
|
||||
|
||||
Simple example:
|
||||
|
||||
```
|
||||
ent_create weapon_c4
|
||||
alias ent_last_cb "ent_fire \$ent_last_inst use"
|
||||
```
|
||||
|
||||
Use weapon_c4 after creating it.
|
||||
|
||||
Note that you cannot use many dfferent callbacks at the same time.
|
||||
|
||||
You can set entity name by by pattern and create special script, contatning all callbacks.
|
||||
|
||||
Example:
|
||||
|
||||
example.cfg
|
||||
```
|
||||
alias ent_last_cb exec entity_cb.cfg
|
||||
ent create \<class\> targetname my_ent1_$name
|
||||
ent_create \<class\> targetname my_ent2_$name
|
||||
```
|
||||
entity_cb.cfg
|
||||
```
|
||||
if $ent_last_name == my_ent1_$name
|
||||
:(ent1 actions)
|
||||
if $ent_last_name == my_ent2_$name
|
||||
:(ent2 actions)
|
||||
```
|
||||
Note that scripting cannot be blocking. You cannot wait for server answer and continue. But you can use small scripts, connected with ent_last_cb command. The best usage is user interaction. You can add touch buttons to screen or call user command menu actions by callbacks.
|
||||
## Server side
|
||||
|
||||
To enable entity tools on server, set sv_enttools_enable to 1
|
||||
|
||||
To change maximum number of entities, touched by ent_fire, change sv_enttools_maxfire to required number.
|
||||
|
||||
To enable actions on players, set sv_enttools_players to 1.
|
||||
|
||||
To enable entity tools for player by nickname, set sv_enttools_godplayer to nickname. Useful to temporary enable from rcon.
|
||||
|
||||
To prevent crash on some actions, set host_mapdesign_fatal to 0
|
||||
@@ -1,152 +0,0 @@
|
||||
# Entity tools
|
||||
|
||||
For some features described below, you need to enable [console scripting](https://github.com/FWGS/xash3d-fwgs/blob/master/Documentation/extensions/console-scripting.md) with command `cmd_scripting 1` in console.
|
||||
To get more information about it, check another according page related to console scripting.
|
||||
|
||||
## Commands description
|
||||
|
||||
### ent_create
|
||||
Create entity with specified classname and key/values.
|
||||
|
||||
`ent_create <classname> <key> <value> <key> <value> ...`
|
||||
|
||||
For example:
|
||||
|
||||
`ent_create monster_zombie targetname zomb1`
|
||||
|
||||
After creating entity, ent_last_xxx cvars are set to new entity and ent_last_cb called, look at ent_getvars description.
|
||||
|
||||
### ent_fire
|
||||
|
||||
Makes some actions on entity.
|
||||
|
||||
`ent_fire <pattern> <command> <args>`
|
||||
|
||||
#### Available commands:
|
||||
|
||||
Set fields (only set entity field, does not call any functions)
|
||||
* health
|
||||
* gravity
|
||||
* movetype
|
||||
* solid
|
||||
* rendermode
|
||||
* rendercolor (vector)
|
||||
* renderfx
|
||||
* renderamt
|
||||
* hullmin (vector)
|
||||
* hullmax (vector)
|
||||
|
||||
Actions
|
||||
* rename: set entity targetname
|
||||
* settarget: set entity target (only targetnames)
|
||||
* setmodel: set entity model (does not update)
|
||||
* set: set key/value by server library
|
||||
* See game FGD to get list.
|
||||
* command takes two arguments
|
||||
* touch: touch entity by current player.
|
||||
* use: use entity by current player.
|
||||
* movehere: place entity in player fov.
|
||||
* drop2floor: place entity to nearest floor surface
|
||||
* moveup: move entity to 25 units up
|
||||
* moveup (value): move by y axis relatively to specified value
|
||||
|
||||
Flags (set/clear specified flag bit, arg is bit number):
|
||||
* setflag
|
||||
* clearflag
|
||||
* setspawnflag
|
||||
* clearspawnflag
|
||||
|
||||
### ent_info
|
||||
Print information about entity by identificator.
|
||||
|
||||
`ent_info <identificator>`
|
||||
|
||||
### ent_getvars
|
||||
Set client cvars containing entity information (useful for [scripting](extensions/console-scripting.md)) and then calls ent_last_cb.
|
||||
|
||||
`ent_getvars <identificator>`
|
||||
|
||||
These cvars are set:
|
||||
```
|
||||
ent_last_name
|
||||
ent_last_num
|
||||
ent_last_inst
|
||||
ent_last_origin
|
||||
ent_last_class
|
||||
```
|
||||
|
||||
### ent_list
|
||||
Print short information about antities, filtered by pattern.
|
||||
|
||||
`ent_list <pattern>`
|
||||
|
||||
## Syntax description
|
||||
|
||||
#### \<identificator\>
|
||||
* !cross: entity under aim
|
||||
* !\<number\>_\<serial\>: instance code
|
||||
* Set by ent_getvars command
|
||||
* Entity index
|
||||
* Targetname pattern
|
||||
|
||||
#### \<pattern\>
|
||||
|
||||
Pattern is like identificator, but may filter many entities by classname.
|
||||
|
||||
#### (vector)
|
||||
|
||||
Used by ent_fire command. vector means three float values, entered without quotes.
|
||||
|
||||
#### key/value
|
||||
|
||||
All entities parameters may be set by specifiing key and value strings.
|
||||
|
||||
Originally, this mechanizm is used in map/bsp format, but it can be used in enttools too.
|
||||
|
||||
Keys and values are passed to server library and processed by entity keyvalue function, setting edict and entity owns parameters.
|
||||
|
||||
If value contains spaces, it must be put in quotes:
|
||||
|
||||
`ent_fire !cross set origin "0 0 0"`
|
||||
|
||||
## Using with scripting
|
||||
|
||||
ent_create and ent_getvars commands are setting cvars on client
|
||||
|
||||
It can be used with ent_last_cb alias that is executed after setting cvars.
|
||||
|
||||
Simple example:
|
||||
|
||||
```
|
||||
ent_create weapon_c4
|
||||
alias ent_last_cb "ent_fire \$ent_last_inst use"
|
||||
```
|
||||
|
||||
Use weapon_c4 after creating it.
|
||||
|
||||
Note that you cannot use many different callbacks at the same time.
|
||||
|
||||
You can set entity name by by pattern and create special script, contatning all callbacks.
|
||||
|
||||
Example:
|
||||
|
||||
> example.cfg
|
||||
```
|
||||
alias ent_last_cb exec entity_cb.cfg
|
||||
ent create \<class\> targetname my_ent1_$name
|
||||
ent_create \<class\> targetname my_ent2_$name
|
||||
```
|
||||
> entity_cb.cfg
|
||||
```
|
||||
if $ent_last_name == my_ent1_$name
|
||||
:(ent1 actions)
|
||||
if $ent_last_name == my_ent2_$name
|
||||
:(ent2 actions)
|
||||
```
|
||||
Note that scripting cannot be blocking. You cannot wait for server answer and continue. But you can use small scripts, connected with ent_last_cb command. The best usage is user interaction. You can add touch buttons to screen or call user command menu actions by callbacks.
|
||||
|
||||
## Server side configuration
|
||||
|
||||
To enable entity tools on server, set sv_enttools_enable to 1
|
||||
|
||||
To change maximum number of entities, touched by ent_fire, change sv_enttools_maxfire to required number.
|
||||
@@ -6,10 +6,9 @@ For connecting to GoldSrc-based servers, use this command:
|
||||
connect ip:port gs
|
||||
```
|
||||
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion or Dproto.
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should accept HLTV connections.
|
||||
Without this requirement, you will just get "Steam validation rejected" error on connecting.
|
||||
|
||||
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
|
||||
|
||||
Also, we encountered that some GoldSrc-based servers are recognizing Xash3D clients as "fake clients" and banning/kicking them. Maybe this problem will be
|
||||
solved along with better compatibility with GoldSrc behavior, but may be not - we don't know logic behind this fake client checks.
|
||||
In case of ReHLDS with Reunion plugin, by default it rejects HLTV clients. But connections from HLTV can be easily enabled in `reunion.cfg` file.
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
# NAT bypass feature in Xash3D FWGS
|
||||
Since IPv6 not as widespread as we would like, NAT (Network Address Translation) still being actively used by many internet service providers in an attempts to
|
||||
mitigate IPv4 addresses exhaustion. In short, they uses one IPv4 address and doing some tricks with ports to represent many other users behind this address.
|
||||
|
||||
But this leads to a problem for users: they cannot accept direct
|
||||
incoming connections anymore. This means that if you are behind provider's NAT and will try to setup Xash3D FWGS server - nobody will be able to connect to it,
|
||||
and the server will not show up in servers public list.
|
||||
|
||||
## Is it possible to avoid this problem?
|
||||
In most cases, it is possible to bypass NAT with UDP hole punching, and Xash3D FWGS uses this method too. But this method is not 100% guaranteed to work - it depends
|
||||
on NAT configurations on both server and client side, and there is no way to control it.
|
||||
|
||||
First of all, server should not be behind symmetric NAT. You can check your NAT type on [this page](https://www.checkmynat.com/).
|
||||
If you get "Symmetric NAT" result in this test, that means you cannot setup publicly available server with internet connection that you are using.
|
||||
|
||||
Here is more detailed scheme of different NAT types compatibility, it explains are users with different NAT types can connect to each other or not.
|
||||
Client NAT type on rows, server NAT type on columns:
|
||||
|
||||
| *NAT Type* | Full Cone | Restricted Cone | Port Restricted Cone | Symmetric |
|
||||
| -------------------- | --------- | --------------- | -------------------- | --------- |
|
||||
| Full Cone | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
| Restricted Cone | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
| Port Restricted Cone | ✔️ | ✔️ | ✔️ | ❌ |
|
||||
| Symmetric | ✔️ | ✔️ | ❌ | ❌ |
|
||||
|
||||
## How to use NAT bypass feature?
|
||||
If you are starting server within the game, you need to enable option "*Use NAT Bypass instead of direct mode*" in bottom left corner of screen.
|
||||
|
||||
If you are starting dedicated server, you should add console variable `sv_nat 1` to server.cfg file, or add `+sv_nat 1` to server startup parameters.
|
||||
|
||||
If you need to connect to server behind NAT, there is separate tab named *NAT* for such servers in server browser. Note that it is useless to add NAT server to favorites,
|
||||
or somehow trying manually to store it, because it has changing address and port.
|
||||
@@ -1,15 +1,15 @@
|
||||
Xash3D FWGS is intended to be easily portable for various platforms, however main issue is maintaining such ports.
|
||||
Xash3D FWGS is intended to be easily ported to specific platform, however main issue is maintaining such ports.
|
||||
|
||||
This page is about merged ports to main source tree and responsible for it developers.
|
||||
|
||||
For porting guidelines, read engine-porting-guide.md.
|
||||
For porting guidelines, look engine-porting-guide.md.
|
||||
|
||||
Status:
|
||||
* **Supported**: active, confirmed to be fully functional, gets built on CI.
|
||||
* **Orphaned**: some work was done but not finished or actively tested due to lack of human resources.
|
||||
* **Supported**: active, was confirmed to be fully functional.
|
||||
* **In progress**: active, under development.
|
||||
* **Old Engine**: port was for old engine fork.
|
||||
* **Deprecated**: not supported anymore.
|
||||
* **Old Engine**: port was for old engine fork
|
||||
* **Not maintained**: lack of human resources
|
||||
* **Deprecated**: not supported anymore
|
||||
|
||||
Table is sorted by status and platform.
|
||||
|
||||
@@ -17,22 +17,17 @@ Table is sorted by status and platform.
|
||||
| -------- | ------ | ---------- | ----
|
||||
| Android | Supported | @Velaron |
|
||||
| *BSD | Supported | @nekonomicon |
|
||||
| DOS4GW | Supported | @mittorn |
|
||||
| GNU/Linux | Supported | @a1batross, @mittorn |
|
||||
| Haiku | Supported | not maintained | Was added by #478 and #483
|
||||
| macOS | Supported | @sofakng |
|
||||
| MotoMAGX | Supported | @a1batross |
|
||||
| PSVita | Supported | @fgsfdsfgs |
|
||||
| Switch | Supported | @fgsfdsfgs |
|
||||
| Windows | Supported | @a1batross, @SNMetamorph |
|
||||
| DOS4GW | Orphaned | N/A | Haven't been confirmed to work for a very long time
|
||||
| Haiku | Orphaned | N/A | Was added by #478 and #483
|
||||
| IRIX | Orphaned | N/A | Undone, compiles but requires big endian port
|
||||
| MotoMAGX | Orphaned | N/A | Should work but the compiler used for this platform is very unstable and easy to crash (it's GCC 3.4)
|
||||
| SerenityOS | Orphaned | N/A | Works but not throughly tested
|
||||
| Solaris | Orphaned | N/A | Works but not throughly tested
|
||||
| WebAssembly System Interface | Orphaned | N/A | Undone, WASI is missing a lot of APIs we want to use
|
||||
| Dreamcast | In progress | @maximqaxd | [GitHub Repository](https://github.com/maximqaxd/xash3d-fwgs_dc/)
|
||||
| PSP | In progress | @Crow_bar, @Velaron | [GitHub Repository](https://github.com/Crow-bar/xash3d-fwgs)
|
||||
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii)
|
||||
| Emscripten | Old Engine | N/A |
|
||||
| 3DS | Old Engine fork | N/A | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
|
||||
| Oculus Quest | Old Engine fork | N/A | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
|
||||
| iOS | Deprecated | N/A | See GitHub issue #61
|
||||
| Emscripten | Old Engine | not maintained |
|
||||
| 3DS | Old Engine fork | not maintained | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
|
||||
| Oculus Quest | Old Engine fork | @DrBeef | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
|
||||
| iOS | Deprecated | not maintained | See GitHub issue #61
|
||||
|
||||
18
README.md
18
README.md
@@ -21,7 +21,6 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
|
||||
* TrueType font rendering, as a part of mainui_cpp.
|
||||
* External VGUI support module.
|
||||
* PNG & KTX2 image format support.
|
||||
* Ogg Vorbis (`.ogg`) & Ogg Opus (`.opus`) audio formats support.
|
||||
* [A set of small improvements](Documentation/), without broken compatibility.
|
||||
|
||||
## Installation & Running
|
||||
@@ -62,24 +61,23 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
|
||||
|
||||
#### GNU/Linux
|
||||
##### Debian/Ubuntu
|
||||
* Only for 32-bit engine on 64-bit x86 operating system:
|
||||
* For 32-bit engine on 64-bit x86 operating system:
|
||||
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
|
||||
* Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude`
|
||||
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
|
||||
* Install development tools: `$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
|
||||
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
|
||||
|
||||
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
|
||||
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
|
||||
* For non-x86 systems:
|
||||
* Install development tools: `$ sudo apt install build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
|
||||
|
||||
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||
|
||||
##### RedHat/Fedora
|
||||
* Only for 32-bit engine on 64-bit x86 operating system:
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
|
||||
* For 32-bit engine on 64-bit x86 operating system:
|
||||
* Install development tools: `$ sudo dnf install gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
|
||||
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
|
||||
|
||||
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`.
|
||||
* For non-x86 systems:
|
||||
* Install development tools: `$ sudo dnf install gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`.
|
||||
|
||||
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||
|
||||
|
||||
14
android/.gitignore
vendored
14
android/.gitignore
vendored
@@ -1,14 +0,0 @@
|
||||
.gradle/
|
||||
build/
|
||||
.externalNativeBuild
|
||||
.cxx/
|
||||
.idea/
|
||||
local.properties
|
||||
.project
|
||||
.classpath
|
||||
.gradle
|
||||
.settings
|
||||
release/
|
||||
*.hprof
|
||||
.vscode/
|
||||
*.bak
|
||||
@@ -1,60 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
# Only used to build Android project
|
||||
|
||||
project(XASH_ANDROID)
|
||||
|
||||
# armeabi-v7a requires cpufeatures library
|
||||
include(AndroidNdkModules)
|
||||
android_ndk_import_module_cpufeatures()
|
||||
|
||||
find_package(PythonInterp 2.7 REQUIRED)
|
||||
|
||||
get_filename_component(C_COMPILER_ID ${CMAKE_C_COMPILER} NAME_WE)
|
||||
get_filename_component(CXX_COMPILER_ID ${CMAKE_CXX_COMPILER} NAME_WE)
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(BUILD_TYPE "debug")
|
||||
else()
|
||||
set(BUILD_TYPE "release")
|
||||
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
set(64BIT ON CACHE BOOL "" FORCE)
|
||||
list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux
|
||||
endif()
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
|
||||
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
|
||||
# not cleanest way to get upper directory
|
||||
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
CC=${WAF_CC} CXX=${WAF_CXX}
|
||||
AR=${CMAKE_AR} STRIP=${CMAKE_STRIP}
|
||||
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} ${WAF_EXTRA_ARGS} cmake
|
||||
--check-c-compiler=${C_COMPILER_ID} --check-cxx-compiler=${CXX_COMPILER_ID}
|
||||
-s "${ENGINE_SOURCE_DIR}/3rdparty/SDL" --skip-sdl2-sanity-check --enable-bundled-deps
|
||||
WORKING_DIRECTORY "${ENGINE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
|
||||
|
||||
# try to build minimal SDL. Enable features as we're gonna use them
|
||||
set(SDL_RENDER OFF)
|
||||
set(SDL_POWER OFF)
|
||||
set(SDL_VULKAN OFF)
|
||||
set(SDL_DISKAUDIO OFF)
|
||||
set(SDL_DUMMYAUDIO OFF)
|
||||
set(SDL_DUMMYVIDEO OFF)
|
||||
set(SDL_VULKAN OFF)
|
||||
set(SDL_OFFSCREEN OFF)
|
||||
set(SDL_STATIC OFF)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui)
|
||||
@@ -1,129 +0,0 @@
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Month
|
||||
import java.time.temporal.ChronoUnit
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "su.xash.engine"
|
||||
ndkVersion = "27.2.12479018"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "su.xash"
|
||||
applicationIdSuffix = "engine"
|
||||
versionName = "0.21"
|
||||
versionCode = getBuildNum()
|
||||
minSdk = 21
|
||||
targetSdk = 34
|
||||
compileSdk = 34
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
abiFilters("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
||||
arguments("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version = "3.22.1"
|
||||
path = file("CMakeLists.txt")
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
isMinifyEnabled = false
|
||||
isShrinkResources = false
|
||||
isDebuggable = true
|
||||
applicationIdSuffix = ".test"
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
|
||||
register("asan") {
|
||||
initWith(getByName("debug"))
|
||||
}
|
||||
|
||||
register("continuous") {
|
||||
initWith(getByName("release"))
|
||||
applicationIdSuffix = ".test"
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
getByName("main") {
|
||||
assets.srcDirs("../../3rdparty/extras/xash-extras", "../moddb")
|
||||
java.srcDir("../../3rdparty/SDL/android-project/app/src/main/java")
|
||||
}
|
||||
}
|
||||
|
||||
lint {
|
||||
abortOnError = false
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
androidResources {
|
||||
noCompress += ""
|
||||
}
|
||||
|
||||
packaging {
|
||||
jniLibs {
|
||||
useLegacyPackaging = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.google.android.material:material:1.11.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
|
||||
implementation("androidx.cardview:cardview:1.0.0")
|
||||
implementation("androidx.annotation:annotation:1.7.1")
|
||||
implementation("androidx.fragment:fragment-ktx:1.6.2")
|
||||
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
||||
// implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
|
||||
implementation("com.madgag.spongycastle:prov:1.58.0.0")
|
||||
implementation("in.dragonbra:javasteam:1.2.0")
|
||||
|
||||
implementation("ch.acra:acra-http:5.11.2")
|
||||
}
|
||||
|
||||
fun getBuildNum(): Int {
|
||||
val now = LocalDateTime.now()
|
||||
val releaseDate = LocalDateTime.of(2015, Month.APRIL, 1, 0, 0, 0)
|
||||
val qBuildNum = releaseDate.until(now, ChronoUnit.DAYS)
|
||||
val minuteOfDay = now.hour * 60 + now.minute
|
||||
return (qBuildNum * 10000 + minuteOfDay).toInt()
|
||||
}
|
||||
89
android/app/proguard-rules.pro
vendored
89
android/app/proguard-rules.pro
vendored
@@ -1,89 +0,0 @@
|
||||
-keep class su.xash.engine.XashActivity {
|
||||
java.lang.String loadAndroidID();
|
||||
java.lang.String getAndroidID();
|
||||
void saveAndroidID(java.lang.String);
|
||||
java.lang.String getCallingPackage();
|
||||
java.lang.String[] getAssetsList(boolean, java.lang.String);
|
||||
android.content.res.AssetManager getAssets(boolean);
|
||||
}
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLInputConnection {
|
||||
void nativeCommitText(java.lang.String, int);
|
||||
void nativeGenerateScancodeForUnichar(char);
|
||||
}
|
||||
|
||||
-keep,includedescriptorclasses class org.libsdl.app.SDLActivity {
|
||||
# for some reason these aren't compatible with allowoptimization modifier
|
||||
boolean supportsRelativeMouse();
|
||||
void setWindowStyle(boolean);
|
||||
}
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLActivity {
|
||||
java.lang.String nativeGetHint(java.lang.String); # Java-side doesn't use this, so it gets minified, but C-side still tries to register it
|
||||
boolean onNativeSoftReturnKey();
|
||||
void onNativeKeyboardFocusLost();
|
||||
boolean isScreenKeyboardShown();
|
||||
android.util.DisplayMetrics getDisplayDPI();
|
||||
java.lang.String clipboardGetText();
|
||||
boolean clipboardHasText();
|
||||
void clipboardSetText(java.lang.String);
|
||||
int createCustomCursor(int[], int, int, int, int);
|
||||
void destroyCustomCursor(int);
|
||||
android.content.Context getContext();
|
||||
boolean getManifestEnvironmentVariables();
|
||||
android.view.Surface getNativeSurface();
|
||||
void initTouch();
|
||||
boolean isAndroidTV();
|
||||
boolean isChromebook();
|
||||
boolean isDeXMode();
|
||||
boolean isTablet();
|
||||
void manualBackButton();
|
||||
int messageboxShowMessageBox(int, java.lang.String, java.lang.String, int[], int[], java.lang.String[], int[]);
|
||||
void minimizeWindow();
|
||||
int openURL(java.lang.String);
|
||||
void requestPermission(java.lang.String, int);
|
||||
int showToast(java.lang.String, int, int, int, int);
|
||||
boolean sendMessage(int, int);
|
||||
boolean setActivityTitle(java.lang.String);
|
||||
boolean setCustomCursor(int);
|
||||
void setOrientation(int, int, boolean, java.lang.String);
|
||||
boolean setRelativeMouseEnabled(boolean);
|
||||
boolean setSystemCursor(int);
|
||||
boolean shouldMinimizeOnFocusLoss();
|
||||
boolean showTextInput(int, int, int, int);
|
||||
}
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager {
|
||||
boolean initialize(boolean, boolean);
|
||||
boolean openDevice(int);
|
||||
int sendOutputReport(int, byte[]);
|
||||
int sendFeatureReport(int, byte[]);
|
||||
boolean getFeatureReport(int, byte[]);
|
||||
void closeDevice(int);
|
||||
}
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLAudioManager {
|
||||
int[] getAudioOutputDevices();
|
||||
int[] getAudioInputDevices();
|
||||
int[] audioOpen(int, int, int, int, int);
|
||||
void audioWriteFloatBuffer(float[]);
|
||||
void audioWriteShortBuffer(short[]);
|
||||
void audioWriteByteBuffer(byte[]);
|
||||
void audioClose();
|
||||
int[] captureOpen(int, int, int, int, int);
|
||||
int captureReadFloatBuffer(float[], boolean);
|
||||
int captureReadShortBuffer(short[], boolean);
|
||||
int captureReadByteBuffer(byte[], boolean);
|
||||
void captureClose();
|
||||
void audioSetThreadPriority(boolean, int);
|
||||
native int nativeSetupJNI();
|
||||
native void removeAudioDevice(boolean, int);
|
||||
native void addAudioDevice(boolean, int);
|
||||
}
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLControllerManager {
|
||||
void pollInputDevices();
|
||||
void pollHapticDevices();
|
||||
void hapticRun(int, float, int);
|
||||
void hapticStop(int);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Xash3D FWGS (Test)</string>
|
||||
<string name="authority" translatable="false">su.xash.engine.test.documents</string>
|
||||
</resources>
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
#!/system/bin/sh
|
||||
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||
cmd=$1
|
||||
shift
|
||||
# This must be called *before* `LD_PRELOAD` is set. Otherwise, if this is a 32-
|
||||
# bit app running on a 64-bit device, the 64-bit getprop will fail to load
|
||||
# because it will preload a 32-bit ASan runtime.
|
||||
# https://github.com/android/ndk/issues/1744
|
||||
os_version=$(getprop ro.build.version.sdk)
|
||||
if [ "$os_version" -eq "27" ]; then
|
||||
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||
elif [ "$os_version" -eq "28" ]; then
|
||||
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||
else
|
||||
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
|
||||
fi
|
||||
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
|
||||
ASAN_LIB=$(ls "$HERE"/libclang_rt.asan-*-android.so)
|
||||
if [ -f "$HERE/libc++_shared.so" ]; then
|
||||
# Workaround for https://github.com/android-ndk/ndk/issues/988.
|
||||
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
|
||||
else
|
||||
export LD_PRELOAD="$ASAN_LIB"
|
||||
fi
|
||||
exec $cmd
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
#!/system/bin/sh
|
||||
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||
cmd=$1
|
||||
shift
|
||||
# This must be called *before* `LD_PRELOAD` is set. Otherwise, if this is a 32-
|
||||
# bit app running on a 64-bit device, the 64-bit getprop will fail to load
|
||||
# because it will preload a 32-bit ASan runtime.
|
||||
# https://github.com/android/ndk/issues/1744
|
||||
os_version=$(getprop ro.build.version.sdk)
|
||||
if [ "$os_version" -eq "27" ]; then
|
||||
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||
elif [ "$os_version" -eq "28" ]; then
|
||||
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||
else
|
||||
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
|
||||
fi
|
||||
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
|
||||
ASAN_LIB=$(ls "$HERE"/libclang_rt.asan-*-android.so)
|
||||
if [ -f "$HERE/libc++_shared.so" ]; then
|
||||
# Workaround for https://github.com/android-ndk/ndk/issues/988.
|
||||
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
|
||||
else
|
||||
export LD_PRELOAD="$ASAN_LIB"
|
||||
fi
|
||||
exec $cmd
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
#!/system/bin/sh
|
||||
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||
cmd=$1
|
||||
shift
|
||||
# This must be called *before* `LD_PRELOAD` is set. Otherwise, if this is a 32-
|
||||
# bit app running on a 64-bit device, the 64-bit getprop will fail to load
|
||||
# because it will preload a 32-bit ASan runtime.
|
||||
# https://github.com/android/ndk/issues/1744
|
||||
os_version=$(getprop ro.build.version.sdk)
|
||||
if [ "$os_version" -eq "27" ]; then
|
||||
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||
elif [ "$os_version" -eq "28" ]; then
|
||||
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||
else
|
||||
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
|
||||
fi
|
||||
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
|
||||
ASAN_LIB=$(ls "$HERE"/libclang_rt.asan-*-android.so)
|
||||
if [ -f "$HERE/libc++_shared.so" ]; then
|
||||
# Workaround for https://github.com/android-ndk/ndk/issues/988.
|
||||
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
|
||||
else
|
||||
export LD_PRELOAD="$ASAN_LIB"
|
||||
fi
|
||||
exec $cmd
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
#!/system/bin/sh
|
||||
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||
cmd=$1
|
||||
shift
|
||||
# This must be called *before* `LD_PRELOAD` is set. Otherwise, if this is a 32-
|
||||
# bit app running on a 64-bit device, the 64-bit getprop will fail to load
|
||||
# because it will preload a 32-bit ASan runtime.
|
||||
# https://github.com/android/ndk/issues/1744
|
||||
os_version=$(getprop ro.build.version.sdk)
|
||||
if [ "$os_version" -eq "27" ]; then
|
||||
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||
elif [ "$os_version" -eq "28" ]; then
|
||||
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
|
||||
else
|
||||
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
|
||||
fi
|
||||
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
|
||||
ASAN_LIB=$(ls "$HERE"/libclang_rt.asan-*-android.so)
|
||||
if [ -f "$HERE/libc++_shared.so" ]; then
|
||||
# Workaround for https://github.com/android-ndk/ndk/issues/988.
|
||||
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
|
||||
else
|
||||
export LD_PRELOAD="$ASAN_LIB"
|
||||
fi
|
||||
exec $cmd
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Xash3D FWGS (Test)</string>
|
||||
<string name="authority" translatable="false">su.xash.engine.test.documents</string>
|
||||
</resources>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Xash3D FWGS (Test)</string>
|
||||
<string name="authority" translatable="false">su.xash.engine.test.documents</string>
|
||||
</resources>
|
||||
@@ -1,101 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:allowAudioPlaybackCapture="true"
|
||||
android:installLocation="preferExternal"
|
||||
tools:targetApi="q">
|
||||
<!-- OpenGL ES 1.1 -->
|
||||
<uses-feature android:glEsVersion="0x00010000" />
|
||||
<!-- Touchscreen support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
<!-- Game controller support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.gamepad"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.usb.host"
|
||||
android:required="false" />
|
||||
<!-- External mouse input events -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.type.pc"
|
||||
android:required="false" />
|
||||
<!-- Audio recording support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.microphone"
|
||||
android:required="false" />
|
||||
<!-- Allow downloading to the external storage on Android 5.1 and older -->
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="22" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
<!-- Allow access to Bluetooth devices -->
|
||||
<!-- Currently this is just for Steam Controller support and requires setting SDL_HINT_JOYSTICK_HIDAPI_STEAM -->
|
||||
<uses-permission
|
||||
android:name="android.permission.BLUETOOTH"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<!-- Allow access to the vibrator -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<!-- Allow recording audio -->
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<!-- Allow internet access -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- Dedicated server -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:allowBackup="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:theme="@style/Theme.App"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".XashActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation|touchscreen"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask"
|
||||
android:preferMinimalPostProcessing="true"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
tools:targetApi="r">
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name=".XashDocumentsProvider"
|
||||
android:authorities="@string/authority"
|
||||
android:exported="true"
|
||||
android:grantUriPermissions="true"
|
||||
android:permission="android.permission.MANAGE_DOCUMENTS">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
|
||||
</intent-filter>
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="su.xash.engine.MOD" />
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
@@ -1,49 +0,0 @@
|
||||
package su.xash.engine;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
public class AndroidBug5497Workaround {
|
||||
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
|
||||
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
|
||||
|
||||
public static void assistActivity(Activity activity) {
|
||||
new AndroidBug5497Workaround(activity);
|
||||
}
|
||||
|
||||
private View mChildOfContent;
|
||||
private int usableHeightPrevious;
|
||||
private FrameLayout.LayoutParams frameLayoutParams;
|
||||
|
||||
private AndroidBug5497Workaround(Activity activity) {
|
||||
FrameLayout content = activity.findViewById(android.R.id.content);
|
||||
mChildOfContent = content.getChildAt(0);
|
||||
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(this::possiblyResizeChildOfContent);
|
||||
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
|
||||
}
|
||||
|
||||
private void possiblyResizeChildOfContent() {
|
||||
int usableHeightNow = computeUsableHeight();
|
||||
if (usableHeightNow != usableHeightPrevious) {
|
||||
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
|
||||
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
|
||||
if (heightDifference > (usableHeightSansKeyboard / 4)) {
|
||||
// keyboard probably just became visible
|
||||
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
|
||||
} else {
|
||||
// keyboard probably just became hidden
|
||||
frameLayoutParams.height = usableHeightSansKeyboard;
|
||||
}
|
||||
mChildOfContent.requestLayout();
|
||||
usableHeightPrevious = usableHeightNow;
|
||||
}
|
||||
}
|
||||
|
||||
private int computeUsableHeight() {
|
||||
Rect r = new Rect();
|
||||
mChildOfContent.getWindowVisibleDisplayFrame(r);
|
||||
return (r.bottom - r.top);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package su.xash.engine
|
||||
|
||||
class DedicatedActivity {
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package su.xash.engine
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
|
||||
class DedicatedService: Service() {
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package su.xash.engine
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import su.xash.engine.databinding.ActivityMainBinding
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
private lateinit var navController: NavController
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(binding.toolbar)
|
||||
|
||||
val navHostFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment
|
||||
navController = navHostFragment.navController
|
||||
appBarConfiguration = AppBarConfiguration(navController.graph)
|
||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package su.xash.engine
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.os.StrictMode
|
||||
import org.acra.config.httpSender
|
||||
import org.acra.data.StringFormat
|
||||
import org.acra.ktx.initAcra
|
||||
|
||||
class MainApplication : Application() {
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
super.attachBaseContext(base)
|
||||
|
||||
if (!BuildConfig.DEBUG) {
|
||||
initAcra {
|
||||
buildConfigClass = BuildConfig::class.java
|
||||
reportFormat = StringFormat.JSON
|
||||
|
||||
httpSender {
|
||||
uri = "http://bodis.pp.ua:5000/report"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// enable strict mode to detect memory leaks etc.
|
||||
StrictMode.enableDefaults();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
package su.xash.engine;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import org.libsdl.app.SDLActivity;
|
||||
|
||||
public class XashActivity extends SDLActivity {
|
||||
private boolean mUseVolumeKeys;
|
||||
private String mPackageName;
|
||||
private static final String TAG = "XashActivity";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
//getWindow().addFlags(WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES);
|
||||
getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
}
|
||||
|
||||
AndroidBug5497Workaround.assistActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getLibraries() {
|
||||
return new String[]{"SDL2", "xash"};
|
||||
}
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
private String getAndroidID() {
|
||||
return Secure.getString(getContentResolver(), Secure.ANDROID_ID);
|
||||
}
|
||||
|
||||
@SuppressLint("ApplySharedPref")
|
||||
private void saveAndroidID(String id) {
|
||||
getSharedPreferences("xash_preferences", MODE_PRIVATE).edit().putString("xash_id", id).commit();
|
||||
}
|
||||
|
||||
private String loadAndroidID() {
|
||||
return getSharedPreferences("xash_preferences", MODE_PRIVATE).getString("xash_id", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCallingPackage() {
|
||||
if (mPackageName != null) {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
return super.getCallingPackage();
|
||||
}
|
||||
|
||||
private AssetManager getAssets(boolean isEngine) {
|
||||
AssetManager am = null;
|
||||
|
||||
if (isEngine) {
|
||||
am = getAssets();
|
||||
} else {
|
||||
try {
|
||||
am = getPackageManager().getResourcesForApplication(getCallingPackage()).getAssets();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to load mod assets!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return am;
|
||||
}
|
||||
|
||||
private String[] getAssetsList(boolean isEngine, String path) {
|
||||
AssetManager am = getAssets(isEngine);
|
||||
|
||||
try {
|
||||
return am.list(path);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new String[]{};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if (SDLActivity.mBrokenLibraries) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int keyCode = event.getKeyCode();
|
||||
if (!mUseVolumeKeys) {
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
|
||||
keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
|
||||
keyCode == KeyEvent.KEYCODE_CAMERA ||
|
||||
keyCode == KeyEvent.KEYCODE_ZOOM_IN ||
|
||||
keyCode == KeyEvent.KEYCODE_ZOOM_OUT) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return getWindow().superDispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
// TODO: REMOVE LATER, temporary launchers support?
|
||||
@Override
|
||||
protected String[] getArguments() {
|
||||
String gamedir = getIntent().getStringExtra("gamedir");
|
||||
if (gamedir == null) gamedir = "valve";
|
||||
nativeSetenv("XASH3D_GAME", gamedir);
|
||||
|
||||
String gamelibdir = getIntent().getStringExtra("gamelibdir");
|
||||
if (gamelibdir != null) nativeSetenv("XASH3D_GAMELIBDIR", gamelibdir);
|
||||
|
||||
String pakfile = getIntent().getStringExtra("pakfile");
|
||||
if (pakfile != null) nativeSetenv("XASH3D_EXTRAS_PAK2", pakfile);
|
||||
|
||||
mUseVolumeKeys = getIntent().getBooleanExtra("usevolume", false);
|
||||
mPackageName = getIntent().getStringExtra("package");
|
||||
|
||||
String[] env = getIntent().getStringArrayExtra("env");
|
||||
if (env != null) {
|
||||
for (int i = 0; i < env.length; i += 2)
|
||||
nativeSetenv(env[i], env[i + 1]);
|
||||
}
|
||||
|
||||
String argv = getIntent().getStringExtra("argv");
|
||||
if (argv == null) argv = "-console -log";
|
||||
return argv.split(" ");
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
package su.xash.engine;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.graphics.Point;
|
||||
import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.DocumentsContract.Document;
|
||||
import android.provider.DocumentsContract.Root;
|
||||
import android.provider.DocumentsProvider;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
public class XashDocumentsProvider extends DocumentsProvider {
|
||||
private static final String ALL_MIME_TYPES = "*/*";
|
||||
private File mRootDir;
|
||||
|
||||
private static final String TAG = "XashDocumentsProvider";
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
mRootDir = getContext().getExternalFilesDir(null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final String[] DEFAULT_ROOT_PROJECTION = new String[]{Root.COLUMN_ROOT_ID,
|
||||
Root.COLUMN_MIME_TYPES,
|
||||
Root.COLUMN_FLAGS,
|
||||
Root.COLUMN_ICON,
|
||||
Root.COLUMN_TITLE,
|
||||
Root.COLUMN_SUMMARY,
|
||||
Root.COLUMN_DOCUMENT_ID,
|
||||
Root.COLUMN_AVAILABLE_BYTES};
|
||||
|
||||
private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[]{Document.COLUMN_DOCUMENT_ID,
|
||||
Document.COLUMN_MIME_TYPE,
|
||||
Document.COLUMN_DISPLAY_NAME,
|
||||
Document.COLUMN_LAST_MODIFIED,
|
||||
Document.COLUMN_FLAGS,
|
||||
Document.COLUMN_SIZE};
|
||||
|
||||
@Override
|
||||
public Cursor queryRoots(String[] projection) {
|
||||
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION);
|
||||
|
||||
final String appName = getContext().getString(R.string.app_name);
|
||||
final String docId = getDocIdForFile(mRootDir);
|
||||
|
||||
int flags;
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_SEARCH;
|
||||
} else {
|
||||
flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
|
||||
}
|
||||
|
||||
final MatrixCursor.RowBuilder row = result.newRow();
|
||||
row.add(Root.COLUMN_ROOT_ID, docId);
|
||||
row.add(Root.COLUMN_DOCUMENT_ID, docId);
|
||||
row.add(Root.COLUMN_SUMMARY, null);
|
||||
row.add(Root.COLUMN_FLAGS, flags);
|
||||
row.add(Root.COLUMN_TITLE, appName);
|
||||
row.add(Root.COLUMN_MIME_TYPES, ALL_MIME_TYPES);
|
||||
row.add(Root.COLUMN_AVAILABLE_BYTES, mRootDir.getFreeSpace());
|
||||
row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException {
|
||||
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
|
||||
|
||||
includeFile(result, documentId, null);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder) throws FileNotFoundException {
|
||||
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
|
||||
|
||||
final File parent = getFileForDocId(parentDocumentId);
|
||||
final File[] filesList = parent.listFiles();
|
||||
|
||||
if (filesList != null) {
|
||||
for (File file : filesList) {
|
||||
includeFile(result, null, file);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openDocument(final String documentId, String mode, CancellationSignal signal) throws FileNotFoundException {
|
||||
final File file = getFileForDocId(documentId);
|
||||
|
||||
final int accessMode = ParcelFileDescriptor.parseMode(mode);
|
||||
|
||||
return ParcelFileDescriptor.open(file, accessMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssetFileDescriptor openDocumentThumbnail(String documentId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
|
||||
final File file = getFileForDocId(documentId);
|
||||
|
||||
final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
|
||||
return new AssetFileDescriptor(pfd, 0, file.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException {
|
||||
File newFile = new File(parentDocumentId, displayName);
|
||||
|
||||
int noConflictId = 1;
|
||||
|
||||
while (newFile.exists()) {
|
||||
newFile = new File(parentDocumentId, displayName + " (" + noConflictId++ + ")");
|
||||
}
|
||||
|
||||
try {
|
||||
boolean succeeded;
|
||||
|
||||
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
|
||||
succeeded = newFile.mkdir();
|
||||
} else {
|
||||
succeeded = newFile.createNewFile();
|
||||
}
|
||||
|
||||
if (!succeeded) {
|
||||
throw new FileNotFoundException("Failed to create document with id " + newFile.getPath());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FileNotFoundException("Failed to create document with id " + newFile.getPath());
|
||||
}
|
||||
|
||||
return newFile.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDocument(String documentId) throws FileNotFoundException {
|
||||
File file = getFileForDocId(documentId);
|
||||
|
||||
if (file.isDirectory()) {
|
||||
if (!deleteDirectory(file)) {
|
||||
throw new FileNotFoundException("Failed to delete document with id " + documentId);
|
||||
}
|
||||
} else if (!file.delete()) {
|
||||
throw new FileNotFoundException("Failed to delete document with id " + documentId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDocumentType(String documentId) throws FileNotFoundException {
|
||||
File file = getFileForDocId(documentId);
|
||||
|
||||
return getMimeType(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildDocument(String parentDocumentId, String documentId) {
|
||||
return documentId.startsWith(parentDocumentId);
|
||||
}
|
||||
|
||||
private static File getFileForDocId(String docId) throws FileNotFoundException {
|
||||
final File f = new File(docId);
|
||||
|
||||
if (!f.exists()) throw new FileNotFoundException(f.getAbsolutePath() + " not found");
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private static String getDocIdForFile(File file) {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
private static String getMimeType(File file) {
|
||||
if (file.isDirectory()) {
|
||||
return Document.MIME_TYPE_DIR;
|
||||
} else {
|
||||
final String name = file.getName();
|
||||
final int lastDot = name.lastIndexOf('.');
|
||||
|
||||
if (lastDot >= 0) {
|
||||
final String extension = name.substring(lastDot + 1).toLowerCase();
|
||||
final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||
|
||||
if (mime != null) return mime;
|
||||
}
|
||||
|
||||
return "application/octet-stream";
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean deleteDirectory(File dir) {
|
||||
final File[] allContents = dir.listFiles();
|
||||
|
||||
if (allContents != null) {
|
||||
for (File file : allContents) {
|
||||
deleteDirectory(file);
|
||||
}
|
||||
}
|
||||
return dir.delete();
|
||||
}
|
||||
|
||||
private void includeFile(MatrixCursor result, String docId, File file) throws FileNotFoundException {
|
||||
if (docId == null) {
|
||||
docId = getDocIdForFile(file);
|
||||
} else {
|
||||
file = getFileForDocId(docId);
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
|
||||
if (file.isDirectory()) {
|
||||
if (file.canWrite()) {
|
||||
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
|
||||
}
|
||||
} else if (file.canWrite()) {
|
||||
flags |= Document.FLAG_SUPPORTS_WRITE;
|
||||
}
|
||||
|
||||
File parentFile = file.getParentFile();
|
||||
if (parentFile != null && parentFile.canWrite()) {
|
||||
flags |= Document.FLAG_SUPPORTS_DELETE;
|
||||
}
|
||||
|
||||
final String displayName = file.getName();
|
||||
final String mimeType = getMimeType(file);
|
||||
|
||||
if (mimeType.startsWith("image/")) {
|
||||
flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
|
||||
}
|
||||
|
||||
final MatrixCursor.RowBuilder row = result.newRow();
|
||||
row.add(Document.COLUMN_DOCUMENT_ID, docId);
|
||||
row.add(Document.COLUMN_DISPLAY_NAME, displayName);
|
||||
row.add(Document.COLUMN_SIZE, file.length());
|
||||
row.add(Document.COLUMN_MIME_TYPE, mimeType);
|
||||
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
|
||||
row.add(Document.COLUMN_FLAGS, flags);
|
||||
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package su.xash.engine.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import su.xash.engine.R
|
||||
import su.xash.engine.databinding.CardGameBinding
|
||||
import su.xash.engine.model.Game
|
||||
import su.xash.engine.ui.library.LibraryViewModel
|
||||
|
||||
|
||||
class GameAdapter(private val libraryViewModel: LibraryViewModel) :
|
||||
ListAdapter<Game, GameAdapter.GameViewHolder>(DiffCallback()) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameAdapter.GameViewHolder {
|
||||
val binding = CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return GameViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: GameAdapter.GameViewHolder, position: Int) {
|
||||
return holder.bind(getItem(position))
|
||||
}
|
||||
|
||||
private class DiffCallback : DiffUtil.ItemCallback<Game>() {
|
||||
override fun areItemsTheSame(oldItem: Game, newItem: Game): Boolean {
|
||||
return oldItem.basedir.name == newItem.basedir.name
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: Game, newItem: Game): Boolean {
|
||||
return oldItem.basedir.name == newItem.basedir.name && oldItem.installed == newItem.installed
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class GameViewHolder(val binding: CardGameBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(game: Game) {
|
||||
binding.apply {
|
||||
gameTitle.text = game.title
|
||||
|
||||
if (game.icon != null) {
|
||||
gameIcon.setImageBitmap(game.icon)
|
||||
} else {
|
||||
gameIcon.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (game.cover != null) {
|
||||
gameCover.setImageBitmap(game.cover)
|
||||
} else {
|
||||
gameCover.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (!game.installed) {
|
||||
launchButton.visibility = View.GONE
|
||||
settingsButton.visibility = View.GONE
|
||||
progressIndicator.visibility = View.VISIBLE
|
||||
return
|
||||
}
|
||||
|
||||
settingsButton.setOnClickListener {
|
||||
libraryViewModel.setSelectedGame(game)
|
||||
it.findNavController()
|
||||
.navigate(R.id.action_libraryFragment_to_gameSettingsFragment)
|
||||
}
|
||||
|
||||
root.setOnClickListener { libraryViewModel.startEngine(it.context, game) }
|
||||
launchButton.setOnClickListener {
|
||||
libraryViewModel.startEngine(it.context, game)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package su.xash.engine.model
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import su.xash.engine.util.TGAReader
|
||||
import java.util.Scanner
|
||||
|
||||
|
||||
object BackgroundBitmap {
|
||||
private const val BACKGROUND_ROWS = 3
|
||||
private const val BACKGROUND_COLUMNS = 4
|
||||
private const val BACKGROUND_WIDTH = 800
|
||||
private const val BACKGROUND_HEIGHT = 600
|
||||
|
||||
fun createBackground(ctx: Context, file: DocumentFile): Bitmap {
|
||||
var bitmap =
|
||||
Bitmap.createBitmap(BACKGROUND_WIDTH, BACKGROUND_HEIGHT, Bitmap.Config.ARGB_8888)
|
||||
var canvas = Canvas(bitmap)
|
||||
var x: Int
|
||||
var y = 0
|
||||
var width: Int
|
||||
var height = 0
|
||||
|
||||
var bgLayout = file.findFile("resource")?.findFile("HD_BackgroundLayout.txt")
|
||||
if (bgLayout == null) {
|
||||
bgLayout = file.findFile("resource")?.findFile("BackgroundLayout.txt")
|
||||
}
|
||||
|
||||
if (bgLayout == null) {
|
||||
val dir = file.findFile("resource")?.findFile("background")
|
||||
for (i in 0 until BACKGROUND_ROWS) {
|
||||
x = 0
|
||||
for (j in 0 until BACKGROUND_COLUMNS) {
|
||||
val filename = "${BACKGROUND_WIDTH}_${i + 1}_${'a' + j}_loading.tga"
|
||||
val bmpFile = dir?.findFile(filename)
|
||||
val bmpImage = loadTga(ctx, bmpFile!!)
|
||||
|
||||
canvas.drawBitmap(bmpImage, x.toFloat(), y.toFloat(), null)
|
||||
x += bmpImage.width
|
||||
height = bmpImage.height
|
||||
|
||||
}
|
||||
y += height
|
||||
}
|
||||
return bitmap
|
||||
}
|
||||
|
||||
ctx.contentResolver.openInputStream(bgLayout.uri).use { inputStream ->
|
||||
Scanner(inputStream).use { scanner ->
|
||||
while (scanner.hasNext()) {
|
||||
when (val str = scanner.next()) {
|
||||
"resolution" -> {
|
||||
width = scanner.nextInt()
|
||||
height = scanner.nextInt()
|
||||
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
canvas = Canvas(bitmap)
|
||||
}
|
||||
|
||||
else -> {
|
||||
var bmpFile = file
|
||||
str.split("/").forEach { bmpFile = bmpFile.findFile(it)!! }
|
||||
//skip
|
||||
scanner.next()
|
||||
x = scanner.nextInt()
|
||||
y = scanner.nextInt()
|
||||
val bmp = loadTga(ctx, bmpFile)
|
||||
canvas.drawBitmap(bmp, x.toFloat(), y.toFloat(), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bitmap
|
||||
}
|
||||
|
||||
private fun loadTga(ctx: Context, file: DocumentFile): Bitmap {
|
||||
ctx.contentResolver.openInputStream(file.uri).use {
|
||||
val buffer = it?.readBytes()
|
||||
val pixels = TGAReader.read(buffer, TGAReader.ARGB)
|
||||
|
||||
val width = TGAReader.getWidth(buffer)
|
||||
val height = TGAReader.getHeight(buffer)
|
||||
|
||||
return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.ARGB_8888)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
package su.xash.engine.model
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import su.xash.engine.XashActivity
|
||||
|
||||
|
||||
class Game(val ctx: Context, val basedir: DocumentFile, var installed: Boolean = true) {
|
||||
private var iconName = "game.ico"
|
||||
var title = "Unknown Game"
|
||||
var icon: Bitmap? = null
|
||||
var cover: Bitmap? = null
|
||||
|
||||
private val pref = ctx.getSharedPreferences(basedir.name, Context.MODE_PRIVATE)
|
||||
|
||||
init {
|
||||
basedir.findFile("gameinfo.txt")?.let {
|
||||
parseGameInfo(it)
|
||||
} ?: basedir.findFile("liblist.gam")?.let { parseGameInfo(it) }
|
||||
|
||||
basedir.findFile(iconName)
|
||||
?.let { icon = MediaStore.Images.Media.getBitmap(ctx.contentResolver, it.uri) }
|
||||
|
||||
try {
|
||||
cover = BackgroundBitmap.createBackground(ctx, basedir)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun startEngine(ctx: Context) {
|
||||
ctx.startActivity(Intent(ctx, XashActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
putExtra("gamedir", basedir.name)
|
||||
putExtra("argv", pref.getString("arguments", "-console -log"))
|
||||
putExtra("usevolume", pref.getBoolean("use_volume_buttons", false))
|
||||
//.putExtra("gamelibdir", getGameLibDir(context))
|
||||
//.putExtra("package", getPackageName()) }
|
||||
})
|
||||
}
|
||||
|
||||
private fun parseGameInfo(file: DocumentFile) {
|
||||
ctx.contentResolver.openInputStream(file.uri).use { inputStream ->
|
||||
inputStream?.bufferedReader().use { reader ->
|
||||
reader?.forEachLine {
|
||||
val tokens = it.split("\\s+".toRegex(), limit = 2)
|
||||
if (tokens.size >= 2) {
|
||||
val k = tokens[0]
|
||||
val v = tokens[1].trim('"')
|
||||
|
||||
if (k == "title" || k == "game") title = v
|
||||
if (k == "icon") iconName = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPackageName(): String? {
|
||||
// return if (mDbEntry != null) {
|
||||
// mDbEntry.getPackageName()
|
||||
// } else null
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getGameLibDir(ctx: Context): String? {
|
||||
val pkgName = getPackageName()
|
||||
if (pkgName != null) {
|
||||
val pkgInfo: PackageInfo = try {
|
||||
ctx.packageManager.getPackageInfo(pkgName, 0)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
ctx.startActivity(
|
||||
Intent(
|
||||
Intent.ACTION_VIEW, Uri.parse("market://details?id=$pkgName")
|
||||
).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
)
|
||||
return null
|
||||
}
|
||||
return pkgInfo.applicationInfo.nativeLibraryDir
|
||||
}
|
||||
return ctx.applicationInfo.nativeLibraryDir
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getGames(ctx: Context, file: DocumentFile): List<Game> {
|
||||
val games = mutableListOf<Game>()
|
||||
|
||||
if (checkIfGamedir(file)) {
|
||||
games.add(Game(ctx, file))
|
||||
} else {
|
||||
file.listFiles().forEach {
|
||||
if (it.isDirectory) {
|
||||
if (checkIfGamedir(it)) {
|
||||
games.add(Game(ctx, it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return games
|
||||
}
|
||||
|
||||
fun checkIfGamedir(file: DocumentFile): Boolean {
|
||||
// exclude unfinished downloads
|
||||
if (file.name?.startsWith('.') == true)
|
||||
return false
|
||||
|
||||
file.findFile("liblist.gam")?.let { return true }
|
||||
file.findFile("gameinfo.txt")?.let { return true }
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Intent intent = new Intent("su.xash.engine.MOD");
|
||||
// for (ResolveInfo info : context.getPackageManager()
|
||||
// .queryIntentActivities(intent, PackageManager.GET_META_DATA)) {
|
||||
// String packageName = info.activityInfo.applicationInfo.packageName;
|
||||
// String gameDir = info.activityInfo.applicationInfo.metaData.getString(
|
||||
// "su.xash.engine.gamedir");
|
||||
// Log.d(TAG, "package = " + packageName + " gamedir = " + gameDir);
|
||||
// }
|
||||
|
||||
//public void startEngine(Context context) {
|
||||
// context.startActivity(new Intent(context, XashActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).putExtra("gamedir", getGameDir()).putExtra("argv", getArguments()).putExtra("usevolume", getVolumeState()).putExtra("gamelibdir", getGameLibDir(context)).putExtra("package", getPackageName()));
|
||||
//}
|
||||
@@ -1,59 +0,0 @@
|
||||
package su.xash.engine.model
|
||||
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.InputStream
|
||||
|
||||
class ModDatabase(inputStream: InputStream) {
|
||||
val entries = mutableListOf<Entry>()
|
||||
|
||||
companion object {
|
||||
const val VERSION = 1
|
||||
|
||||
fun getFilename(): String {
|
||||
return "v${VERSION}.json"
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
inputStream.bufferedReader().use {
|
||||
val jsonArray = JSONArray(it.readText())
|
||||
|
||||
for (i in 0..<jsonArray.length()) {
|
||||
entries.add(Entry(jsonArray.getJSONObject(i)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getByGameDir(gamedir: String): Entry? {
|
||||
return entries.filter { it.gamedir.equals(gamedir) }.firstOrNull()
|
||||
}
|
||||
|
||||
|
||||
inner class Entry(jsonObject: JSONObject) {
|
||||
var name: String? = null
|
||||
var appid: Int? = null
|
||||
var gamedir: String? = null
|
||||
|
||||
// TODO Depots
|
||||
var pkgname: String? = null
|
||||
|
||||
init {
|
||||
if (jsonObject.has("name")) {
|
||||
name = jsonObject.getString("name");
|
||||
}
|
||||
|
||||
if (jsonObject.has("app_id")) {
|
||||
appid = jsonObject.getInt("app_id");
|
||||
}
|
||||
|
||||
if (jsonObject.has("gamedir")) {
|
||||
gamedir = jsonObject.getString("gamedir");
|
||||
}
|
||||
|
||||
if (jsonObject.has("package_name")) {
|
||||
pkgname = jsonObject.getString("package_name");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package su.xash.engine.ui.library
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import kotlinx.coroutines.launch
|
||||
import su.xash.engine.R
|
||||
import su.xash.engine.adapters.GameAdapter
|
||||
import su.xash.engine.databinding.FragmentLibraryBinding
|
||||
|
||||
class LibraryFragment : Fragment(), MenuProvider {
|
||||
private var _binding: FragmentLibraryBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val libraryViewModel: LibraryViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentLibraryBinding.inflate(inflater, container, false)
|
||||
|
||||
val adapter = GameAdapter(libraryViewModel)
|
||||
binding.gamesList.adapter = adapter
|
||||
|
||||
requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
binding.swipeRefresh.setOnRefreshListener { libraryViewModel.reloadGames(requireContext()) }
|
||||
|
||||
libraryViewModel.isReloading.observe(viewLifecycleOwner) {
|
||||
binding.swipeRefresh.isRefreshing = it
|
||||
}
|
||||
|
||||
libraryViewModel.installedGames.observe(viewLifecycleOwner) {
|
||||
(binding.gamesList.adapter as GameAdapter).submitList(it)
|
||||
}
|
||||
|
||||
libraryViewModel.workInfos.observe(viewLifecycleOwner) {
|
||||
libraryViewModel.refreshDownloads(requireContext())
|
||||
}
|
||||
|
||||
libraryViewModel.downloads.observe(viewLifecycleOwner) {
|
||||
libraryViewModel.reloadGames(requireContext())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||
menuInflater.inflate(R.menu.menu_library, menu)
|
||||
}
|
||||
|
||||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||
when (menuItem.itemId) {
|
||||
R.id.action_browse -> {
|
||||
startActivity(
|
||||
Intent(Intent.ACTION_VIEW).setDataAndType(
|
||||
null, "vnd.android.document/directory"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
R.id.action_install -> {
|
||||
findNavController().navigate(R.id.action_libraryFragment_to_setupFragment)
|
||||
}
|
||||
|
||||
R.id.action_settings -> {
|
||||
findNavController().navigate(R.id.action_libraryFragment_to_appSettingsFragment)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package su.xash.engine.ui.library
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.work.Data
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.OutOfQuotaPolicy
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import su.xash.engine.model.Game
|
||||
import su.xash.engine.model.ModDatabase
|
||||
import su.xash.engine.workers.FileCopyWorker
|
||||
import su.xash.engine.workers.KEY_FILE_URI
|
||||
import java.util.Locale
|
||||
|
||||
const val TAG_INSTALL = "TAG_INSTALL"
|
||||
|
||||
class LibraryViewModel(application: Application) : AndroidViewModel(application) {
|
||||
val installedGames: LiveData<List<Game>> get() = _installedGames
|
||||
private val _installedGames = MutableLiveData(emptyList<Game>())
|
||||
|
||||
val downloads: LiveData<List<Game>> get() = _downloads
|
||||
private val _downloads = MutableLiveData(emptyList<Game>())
|
||||
|
||||
val isReloading: LiveData<Boolean> get() = _isReloading
|
||||
private val _isReloading = MutableLiveData(false)
|
||||
|
||||
private val workManager = WorkManager.getInstance(application.applicationContext)
|
||||
val workInfos: LiveData<List<WorkInfo>> = workManager.getWorkInfosByTagLiveData(TAG_INSTALL)
|
||||
|
||||
val selectedItem: LiveData<Game> get() = _selectedItem
|
||||
private val _selectedItem = MutableLiveData<Game>()
|
||||
|
||||
val appPreferences = application.getSharedPreferences("app_preferences", Context.MODE_PRIVATE)
|
||||
val modDb: ModDatabase
|
||||
|
||||
init {
|
||||
modDb = application.assets.open(ModDatabase.getFilename()).use { ModDatabase(it) }
|
||||
reloadGames(application.applicationContext)
|
||||
}
|
||||
|
||||
fun reloadGames(ctx: Context) {
|
||||
if (isReloading.value == true) {
|
||||
return
|
||||
}
|
||||
_isReloading.value = true
|
||||
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val games = mutableListOf<Game>()
|
||||
val root = DocumentFile.fromFile(ctx.getExternalFilesDir(null)!!)
|
||||
|
||||
val installedGames = Game.getGames(ctx, root)
|
||||
.filter { p -> _downloads.value?.any { p.basedir.name == it.basedir.name } == false }
|
||||
|
||||
games.addAll(installedGames)
|
||||
downloads.value?.let { games.addAll(it) }
|
||||
|
||||
_installedGames.postValue(games)
|
||||
_isReloading.postValue(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshDownloads(ctx: Context) {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val games = mutableListOf<Game>()
|
||||
|
||||
workInfos.value?.filter {
|
||||
it.state == WorkInfo.State.RUNNING && !it.progress.getString(FileCopyWorker.Input)
|
||||
.isNullOrEmpty()
|
||||
}?.forEach {
|
||||
val uri = Uri.parse(it.progress.getString(FileCopyWorker.Input))
|
||||
val file = DocumentFile.fromTreeUri(ctx, uri)
|
||||
games.addAll(Game.getGames(ctx, file!!))
|
||||
games.forEach { g -> g.installed = false }
|
||||
}
|
||||
|
||||
_downloads.postValue(games)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun installGame(uri: Uri) {
|
||||
val data = Data.Builder().putString(KEY_FILE_URI, uri.toString()).build()
|
||||
val request = OneTimeWorkRequestBuilder<FileCopyWorker>().run {
|
||||
setInputData(data)
|
||||
addTag(TAG_INSTALL)
|
||||
build()
|
||||
}
|
||||
workManager.enqueue(request)
|
||||
}
|
||||
|
||||
fun setSelectedGame(game: Game) {
|
||||
_selectedItem.value = game
|
||||
}
|
||||
|
||||
fun uninstallGame(game: Game) {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
game.installed = false
|
||||
game.basedir.delete()
|
||||
_installedGames.postValue(_installedGames.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun startEngine(ctx: Context, game: Game) {
|
||||
game.startEngine(ctx)
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package su.xash.engine.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import su.xash.engine.databinding.FragmentAppSettingsBinding
|
||||
|
||||
class AppSettingsFragment : Fragment() {
|
||||
private var _binding: FragmentAppSettingsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentAppSettingsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
childFragmentManager.beginTransaction()
|
||||
.add(binding.settingsFragment.id, AppSettingsPreferenceFragment()).commit();
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package su.xash.engine.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import su.xash.engine.R
|
||||
|
||||
class AppSettingsPreferenceFragment() : PreferenceFragmentCompat() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
preferenceManager.sharedPreferencesName = "app_preferences";
|
||||
setPreferencesFromResource(R.xml.app_preferences, rootKey);
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package su.xash.engine.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import su.xash.engine.R
|
||||
import su.xash.engine.databinding.FragmentGameSettingsBinding
|
||||
import su.xash.engine.ui.library.LibraryViewModel
|
||||
|
||||
class GameSettingsFragment : Fragment() {
|
||||
private var _binding: FragmentGameSettingsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val libraryViewModel: LibraryViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentGameSettingsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val game = libraryViewModel.selectedItem.value!!
|
||||
|
||||
binding.gameCard.apply {
|
||||
gameTitle.text = game.title
|
||||
|
||||
if (game.icon != null) {
|
||||
gameIcon.setImageBitmap(game.icon)
|
||||
} else {
|
||||
gameIcon.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (game.cover != null) {
|
||||
gameCover.setImageBitmap(game.cover)
|
||||
} else {
|
||||
gameCover.visibility = View.GONE
|
||||
}
|
||||
|
||||
buttonsContainer.visibility = View.GONE
|
||||
}
|
||||
|
||||
childFragmentManager.beginTransaction()
|
||||
.add(binding.settingsFragment.id, GameSettingsPreferenceFragment(game))
|
||||
.commit();
|
||||
|
||||
binding.bottomNavigation.menu.findItem(R.id.action_uninstall).setOnMenuItemClickListener {
|
||||
libraryViewModel.uninstallGame(game)
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package su.xash.engine.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import su.xash.engine.R
|
||||
import su.xash.engine.model.Game
|
||||
|
||||
class GameSettingsPreferenceFragment(val game: Game) : PreferenceFragmentCompat() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
preferenceManager.sharedPreferencesName = game.basedir.name;
|
||||
setPreferencesFromResource(R.xml.game_preferences, rootKey);
|
||||
|
||||
val packageList = findPreference<ListPreference>("package_name")!!
|
||||
packageList.entries = arrayOf(getString(R.string.app_name))
|
||||
packageList.entryValues = arrayOf(requireContext().packageName)
|
||||
|
||||
if (packageList.value == null) {
|
||||
packageList.setValueIndex(0);
|
||||
}
|
||||
|
||||
val separatePackages = findPreference<SwitchPreferenceCompat>("separate_libraries")!!
|
||||
val clientPackage = findPreference<ListPreference>("client_package")!!
|
||||
val serverPackage = findPreference<ListPreference>("server_package")!!
|
||||
separatePackages.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue == true) {
|
||||
packageList.isVisible = false
|
||||
clientPackage.isVisible = true
|
||||
serverPackage.isVisible = true
|
||||
} else {
|
||||
packageList.isVisible = true
|
||||
clientPackage.isVisible = false
|
||||
serverPackage.isVisible = false
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package su.xash.engine.ui.setup
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import su.xash.engine.databinding.FragmentSetupBinding
|
||||
import su.xash.engine.ui.setup.pages.LocationPageFragment
|
||||
import su.xash.engine.ui.setup.pages.WelcomePageFragment
|
||||
|
||||
class SetupFragment : Fragment() {
|
||||
private var _binding: FragmentSetupBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val setupViewModel: SetupViewModel by activityViewModels()
|
||||
|
||||
private lateinit var setupPageAdapter: SetupPageAdapter
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentSetupBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
setupPageAdapter = SetupPageAdapter(this)
|
||||
binding.viewPager.isUserInputEnabled = false
|
||||
binding.viewPager.adapter = setupPageAdapter
|
||||
|
||||
setupViewModel.pageNumber.observe(viewLifecycleOwner) {
|
||||
binding.viewPager.setCurrentItem(it, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
|
||||
class SetupPageAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
|
||||
val pages = listOf(WelcomePageFragment(), LocationPageFragment())
|
||||
override fun getItemCount(): Int = 2
|
||||
override fun createFragment(position: Int): Fragment = pages[position]
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package su.xash.engine.ui.setup
|
||||
|
||||
import android.app.Application
|
||||
import android.net.Uri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import su.xash.engine.MainApplication
|
||||
import su.xash.engine.model.Game
|
||||
|
||||
class SetupViewModel(application: Application) : AndroidViewModel(application) {
|
||||
val pageNumber: LiveData<Int> get() = _pageNumber
|
||||
private val _pageNumber = MutableLiveData(0)
|
||||
|
||||
fun checkIfGameDir(uri: Uri): Boolean {
|
||||
val ctx = getApplication<MainApplication>().applicationContext
|
||||
val file = DocumentFile.fromTreeUri(ctx, uri)!!
|
||||
return Game.checkIfGamedir(file)
|
||||
}
|
||||
|
||||
fun setPageNumber(pos: Int) {
|
||||
_pageNumber.value = pos
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package su.xash.engine.ui.setup.pages
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import su.xash.engine.R
|
||||
import su.xash.engine.databinding.PageLocationBinding
|
||||
import su.xash.engine.ui.library.LibraryViewModel
|
||||
import su.xash.engine.ui.setup.SetupViewModel
|
||||
|
||||
class LocationPageFragment : Fragment() {
|
||||
private var _binding: PageLocationBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val setupViewModel: SetupViewModel by activityViewModels()
|
||||
private val libraryViewModel: LibraryViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = PageLocationBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
binding.pageButton.setOnClickListener {
|
||||
getGamesDirectory.launch(null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
private val getGamesDirectory =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) {
|
||||
it?.let {
|
||||
if (!setupViewModel.checkIfGameDir(it)) {
|
||||
MaterialAlertDialogBuilder(requireContext()).apply {
|
||||
setTitle(R.string.error)
|
||||
setMessage(R.string.setup_location_empty)
|
||||
setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
requireContext().contentResolver.takePersistableUriPermission(it, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
libraryViewModel.installGame(it)
|
||||
findNavController().navigate(R.id.action_setupFragment_to_libraryFragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package su.xash.engine.ui.setup.pages
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import su.xash.engine.databinding.PageWelcomeBinding
|
||||
import su.xash.engine.ui.setup.SetupViewModel
|
||||
|
||||
class WelcomePageFragment : Fragment() {
|
||||
private var _binding: PageWelcomeBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val setupViewModel: SetupViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = PageWelcomeBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
binding.pageButton.setOnClickListener {
|
||||
setupViewModel.setPageNumber(1)
|
||||
}
|
||||
setupViewModel.setPageNumber(0)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
@@ -1,589 +0,0 @@
|
||||
/**
|
||||
* TGAReader.java
|
||||
* <p>
|
||||
* Copyright (c) 2014 Kenji Sasaki
|
||||
* Released under the MIT license.
|
||||
* https://github.com/npedotnet/TGAReader/blob/master/LICENSE
|
||||
* <p>
|
||||
* English document
|
||||
* https://github.com/npedotnet/TGAReader/blob/master/README.md
|
||||
* <p>
|
||||
* Japanese document
|
||||
* http://3dtech.jp/wiki/index.php?TGAReader
|
||||
*/
|
||||
|
||||
package su.xash.engine.util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class TGAReader {
|
||||
|
||||
public static final Order ARGB = new Order(16, 8, 0, 24);
|
||||
public static final Order ABGR = new Order(0, 8, 16, 24);
|
||||
|
||||
public static int getWidth(byte[] buffer) {
|
||||
return (buffer[12] & 0xFF) | (buffer[13] & 0xFF) << 8;
|
||||
}
|
||||
|
||||
public static int getHeight(byte[] buffer) {
|
||||
return (buffer[14] & 0xFF) | (buffer[15] & 0xFF) << 8;
|
||||
}
|
||||
|
||||
public static int[] read(byte[] buffer, Order order) throws IOException {
|
||||
|
||||
// header
|
||||
// int idFieldLength = buffer[0] & 0xFF;
|
||||
// int colormapType = buffer[1] & 0xFF;
|
||||
int type = buffer[2] & 0xFF;
|
||||
int colormapOrigin = (buffer[3] & 0xFF) | (buffer[4] & 0xFF) << 8;
|
||||
int colormapLength = (buffer[5] & 0xFF) | (buffer[6] & 0xFF) << 8;
|
||||
int colormapDepth = buffer[7] & 0xFF;
|
||||
// int originX = (buffer[8] & 0xFF) | (buffer[9] & 0xFF) << 8; // unsupported
|
||||
// int originY = (buffer[10] & 0xFF) | (buffer[11] & 0xFF) << 8; // unsupported
|
||||
int width = getWidth(buffer);
|
||||
int height = getHeight(buffer);
|
||||
int depth = buffer[16] & 0xFF;
|
||||
int descriptor = buffer[17] & 0xFF;
|
||||
|
||||
int[] pixels;
|
||||
|
||||
// data
|
||||
switch (type) {
|
||||
case COLORMAP: {
|
||||
int imageDataOffset = 18 + (colormapDepth / 8) * colormapLength;
|
||||
pixels = createPixelsFromColormap(width, height, colormapDepth, buffer, imageDataOffset, buffer, colormapOrigin, descriptor, order);
|
||||
}
|
||||
break;
|
||||
case RGB:
|
||||
pixels = createPixelsFromRGB(width, height, depth, buffer, 18, descriptor, order);
|
||||
break;
|
||||
case GRAYSCALE:
|
||||
pixels = createPixelsFromGrayscale(width, height, depth, buffer, 18, descriptor, order);
|
||||
break;
|
||||
case COLORMAP_RLE: {
|
||||
int imageDataOffset = 18 + (colormapDepth / 8) * colormapLength;
|
||||
byte[] decodeBuffer = decodeRLE(width, height, depth, buffer, imageDataOffset);
|
||||
pixels = createPixelsFromColormap(width, height, colormapDepth, decodeBuffer, 0, buffer, colormapOrigin, descriptor, order);
|
||||
}
|
||||
break;
|
||||
case RGB_RLE: {
|
||||
byte[] decodeBuffer = decodeRLE(width, height, depth, buffer, 18);
|
||||
pixels = createPixelsFromRGB(width, height, depth, decodeBuffer, 0, descriptor, order);
|
||||
}
|
||||
break;
|
||||
case GRAYSCALE_RLE: {
|
||||
byte[] decodeBuffer = decodeRLE(width, height, depth, buffer, 18);
|
||||
pixels = createPixelsFromGrayscale(width, height, depth, decodeBuffer, 0, descriptor, order);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unsupported image type: " + type);
|
||||
}
|
||||
|
||||
return pixels;
|
||||
|
||||
}
|
||||
|
||||
private static final int COLORMAP = 1;
|
||||
private static final int RGB = 2;
|
||||
private static final int GRAYSCALE = 3;
|
||||
private static final int COLORMAP_RLE = 9;
|
||||
private static final int RGB_RLE = 10;
|
||||
private static final int GRAYSCALE_RLE = 11;
|
||||
|
||||
private static final int RIGHT_ORIGIN = 0x10;
|
||||
private static final int UPPER_ORIGIN = 0x20;
|
||||
|
||||
private static byte[] decodeRLE(int width, int height, int depth, byte[] buffer, int offset) {
|
||||
int elementCount = depth / 8;
|
||||
byte[] elements = new byte[elementCount];
|
||||
int decodeBufferLength = elementCount * width * height;
|
||||
byte[] decodeBuffer = new byte[decodeBufferLength];
|
||||
int decoded = 0;
|
||||
while (decoded < decodeBufferLength) {
|
||||
int packet = buffer[offset++] & 0xFF;
|
||||
if ((packet & 0x80) != 0) { // RLE
|
||||
for (int i = 0; i < elementCount; i++) {
|
||||
elements[i] = buffer[offset++];
|
||||
}
|
||||
int count = (packet & 0x7F) + 1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (int j = 0; j < elementCount; j++) {
|
||||
decodeBuffer[decoded++] = elements[j];
|
||||
}
|
||||
}
|
||||
} else { // RAW
|
||||
int count = (packet + 1) * elementCount;
|
||||
for (int i = 0; i < count; i++) {
|
||||
decodeBuffer[decoded++] = buffer[offset++];
|
||||
}
|
||||
}
|
||||
}
|
||||
return decodeBuffer;
|
||||
}
|
||||
|
||||
private static int[] createPixelsFromColormap(int width, int height, int depth, byte[] bytes, int offset, byte[] palette, int colormapOrigin, int descriptor, Order order) throws IOException {
|
||||
int[] pixels;
|
||||
int rs = order.redShift;
|
||||
int gs = order.greenShift;
|
||||
int bs = order.blueShift;
|
||||
int as = order.alphaShift;
|
||||
switch (depth) {
|
||||
case 24:
|
||||
pixels = new int[width * height];
|
||||
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int colormapIndex = bytes[offset + width * i + j] &
|
||||
0xFF - colormapOrigin;
|
||||
int color = 0xFFFFFFFF;
|
||||
if (colormapIndex >= 0) {
|
||||
int index = 3 * colormapIndex + 18;
|
||||
int b = palette[index] & 0xFF;
|
||||
int g = palette[index + 1] & 0xFF;
|
||||
int r = palette[index + 2] & 0xFF;
|
||||
int a = 0xFF;
|
||||
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||
}
|
||||
pixels[width * i + (width - j - 1)] = color;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int colormapIndex = bytes[offset + width * i + j] &
|
||||
0xFF - colormapOrigin;
|
||||
int color = 0xFFFFFFFF;
|
||||
if (colormapIndex >= 0) {
|
||||
int index = 3 * colormapIndex + 18;
|
||||
int b = palette[index] & 0xFF;
|
||||
int g = palette[index + 1] & 0xFF;
|
||||
int r = palette[index + 2] & 0xFF;
|
||||
int a = 0xFF;
|
||||
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||
}
|
||||
pixels[width * (height - i - 1) + (width - j - 1)] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int colormapIndex = bytes[offset + width * i + j] &
|
||||
0xFF - colormapOrigin;
|
||||
int color = 0xFFFFFFFF;
|
||||
if (colormapIndex >= 0) {
|
||||
int index = 3 * colormapIndex + 18;
|
||||
int b = palette[index] & 0xFF;
|
||||
int g = palette[index + 1] & 0xFF;
|
||||
int r = palette[index + 2] & 0xFF;
|
||||
int a = 0xFF;
|
||||
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||
}
|
||||
pixels[width * i + j] = color;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int colormapIndex = bytes[offset + width * i + j] &
|
||||
0xFF - colormapOrigin;
|
||||
int color = 0xFFFFFFFF;
|
||||
if (colormapIndex >= 0) {
|
||||
int index = 3 * colormapIndex + 18;
|
||||
int b = palette[index] & 0xFF;
|
||||
int g = palette[index + 1] & 0xFF;
|
||||
int r = palette[index + 2] & 0xFF;
|
||||
int a = 0xFF;
|
||||
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||
}
|
||||
pixels[width * (height - i - 1) + j] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
pixels = new int[width * height];
|
||||
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int colormapIndex = bytes[offset + width * i + j] &
|
||||
0xFF - colormapOrigin;
|
||||
int color = 0xFFFFFFFF;
|
||||
if (colormapIndex >= 0) {
|
||||
int index = 4 * colormapIndex + 18;
|
||||
int b = palette[index] & 0xFF;
|
||||
int g = palette[index + 1] & 0xFF;
|
||||
int r = palette[index + 2] & 0xFF;
|
||||
int a = palette[index + 3] & 0xFF;
|
||||
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||
}
|
||||
pixels[width * i + (width - j - 1)] = color;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int colormapIndex = bytes[offset + width * i + j] &
|
||||
0xFF - colormapOrigin;
|
||||
int color = 0xFFFFFFFF;
|
||||
if (colormapIndex >= 0) {
|
||||
int index = 4 * colormapIndex + 18;
|
||||
int b = palette[index] & 0xFF;
|
||||
int g = palette[index + 1] & 0xFF;
|
||||
int r = palette[index + 2] & 0xFF;
|
||||
int a = palette[index + 3] & 0xFF;
|
||||
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||
}
|
||||
pixels[width * (height - i - 1) + (width - j - 1)] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int colormapIndex = bytes[offset + width * i + j] &
|
||||
0xFF - colormapOrigin;
|
||||
int color = 0xFFFFFFFF;
|
||||
if (colormapIndex >= 0) {
|
||||
int index = 4 * colormapIndex + 18;
|
||||
int b = palette[index] & 0xFF;
|
||||
int g = palette[index + 1] & 0xFF;
|
||||
int r = palette[index + 2] & 0xFF;
|
||||
int a = palette[index + 3] & 0xFF;
|
||||
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||
}
|
||||
pixels[width * i + j] = color;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int colormapIndex = bytes[offset + width * i + j] &
|
||||
0xFF - colormapOrigin;
|
||||
int color = 0xFFFFFFFF;
|
||||
if (colormapIndex >= 0) {
|
||||
int index = 4 * colormapIndex + 18;
|
||||
int b = palette[index] & 0xFF;
|
||||
int g = palette[index + 1] & 0xFF;
|
||||
int r = palette[index + 2] & 0xFF;
|
||||
int a = palette[index + 3] & 0xFF;
|
||||
color = (r << rs) | (g << gs) | (b << bs) | (a << as);
|
||||
}
|
||||
pixels[width * (height - i - 1) + j] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unsupported depth:" + depth);
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
private static int[] createPixelsFromRGB(int width, int height, int depth, byte[] bytes, int offset, int descriptor, Order order) throws IOException {
|
||||
int[] pixels;
|
||||
int rs = order.redShift;
|
||||
int gs = order.greenShift;
|
||||
int bs = order.blueShift;
|
||||
int as = order.alphaShift;
|
||||
switch (depth) {
|
||||
case 24:
|
||||
pixels = new int[width * height];
|
||||
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int index = offset + 3 * width * i + 3 * j;
|
||||
int b = bytes[index] & 0xFF;
|
||||
int g = bytes[index + 1] & 0xFF;
|
||||
int r = bytes[index + 2] & 0xFF;
|
||||
int a = 0xFF;
|
||||
pixels[width * i + (width - j - 1)] = (r << rs) |
|
||||
(g << gs) |
|
||||
(b << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int index = offset + 3 * width * i + 3 * j;
|
||||
int b = bytes[index] & 0xFF;
|
||||
int g = bytes[index + 1] & 0xFF;
|
||||
int r = bytes[index + 2] & 0xFF;
|
||||
int a = 0xFF;
|
||||
pixels[width * (height - i - 1) + (width - j - 1)] = (r << rs) |
|
||||
(g << gs) |
|
||||
(b << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int index = offset + 3 * width * i + 3 * j;
|
||||
int b = bytes[index] & 0xFF;
|
||||
int g = bytes[index + 1] & 0xFF;
|
||||
int r = bytes[index + 2] & 0xFF;
|
||||
int a = 0xFF;
|
||||
pixels[width * i + j] = (r << rs) |
|
||||
(g << gs) |
|
||||
(b << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int index = offset + 3 * width * i + 3 * j;
|
||||
int b = bytes[index] & 0xFF;
|
||||
int g = bytes[index + 1] & 0xFF;
|
||||
int r = bytes[index + 2] & 0xFF;
|
||||
int a = 0xFF;
|
||||
pixels[width * (height - i - 1) + j] = (r << rs) |
|
||||
(g << gs) |
|
||||
(b << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
pixels = new int[width * height];
|
||||
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int index = offset + 4 * width * i + 4 * j;
|
||||
int b = bytes[index] & 0xFF;
|
||||
int g = bytes[index + 1] & 0xFF;
|
||||
int r = bytes[index + 2] & 0xFF;
|
||||
int a = bytes[index + 3] & 0xFF;
|
||||
pixels[width * i + (width - j - 1)] = (r << rs) |
|
||||
(g << gs) |
|
||||
(b << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int index = offset + 4 * width * i + 4 * j;
|
||||
int b = bytes[index] & 0xFF;
|
||||
int g = bytes[index + 1] & 0xFF;
|
||||
int r = bytes[index + 2] & 0xFF;
|
||||
int a = bytes[index + 3] & 0xFF;
|
||||
pixels[width * (height - i - 1) + (width - j - 1)] = (r << rs) |
|
||||
(g << gs) |
|
||||
(b << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int index = offset + 4 * width * i + 4 * j;
|
||||
int b = bytes[index] & 0xFF;
|
||||
int g = bytes[index + 1] & 0xFF;
|
||||
int r = bytes[index + 2] & 0xFF;
|
||||
int a = bytes[index + 3] & 0xFF;
|
||||
pixels[width * i + j] = (r << rs) |
|
||||
(g << gs) |
|
||||
(b << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int index = offset + 4 * width * i + 4 * j;
|
||||
int b = bytes[index] & 0xFF;
|
||||
int g = bytes[index + 1] & 0xFF;
|
||||
int r = bytes[index + 2] & 0xFF;
|
||||
int a = bytes[index + 3] & 0xFF;
|
||||
pixels[width * (height - i - 1) + j] = (r << rs) |
|
||||
(g << gs) |
|
||||
(b << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unsupported depth:" + depth);
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
private static int[] createPixelsFromGrayscale(int width, int height, int depth, byte[] bytes, int offset, int descriptor, Order order) throws IOException {
|
||||
int[] pixels;
|
||||
int rs = order.redShift;
|
||||
int gs = order.greenShift;
|
||||
int bs = order.blueShift;
|
||||
int as = order.alphaShift;
|
||||
switch (depth) {
|
||||
case 8:
|
||||
pixels = new int[width * height];
|
||||
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int e = bytes[offset + width * i + j] & 0xFF;
|
||||
int a = 0xFF;
|
||||
pixels[width * i + (width - j - 1)] = (e << rs) |
|
||||
(e << gs) |
|
||||
(e << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int e = bytes[offset + width * i + j] & 0xFF;
|
||||
int a = 0xFF;
|
||||
pixels[width * (height - i - 1) + (width - j - 1)] = (e << rs) |
|
||||
(e << gs) |
|
||||
(e << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int e = bytes[offset + width * i + j] & 0xFF;
|
||||
int a = 0xFF;
|
||||
pixels[width * i + j] = (e << rs) |
|
||||
(e << gs) |
|
||||
(e << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int e = bytes[offset + width * i + j] & 0xFF;
|
||||
int a = 0xFF;
|
||||
pixels[width * (height - i - 1) + j] = (e << rs) |
|
||||
(e << gs) |
|
||||
(e << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
pixels = new int[width * height];
|
||||
if ((descriptor & RIGHT_ORIGIN) != 0) {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int e = bytes[offset + 2 * width * i + 2 * j] & 0xFF;
|
||||
int a = bytes[offset + 2 * width * i + 2 * j + 1] & 0xFF;
|
||||
pixels[width * i + (width - j - 1)] = (e << rs) |
|
||||
(e << gs) |
|
||||
(e << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerRight
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int e = bytes[offset + 2 * width * i + 2 * j] & 0xFF;
|
||||
int a = bytes[offset + 2 * width * i + 2 * j + 1] & 0xFF;
|
||||
pixels[width * (height - i - 1) + (width - j - 1)] = (e << rs) |
|
||||
(e << gs) |
|
||||
(e << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((descriptor & UPPER_ORIGIN) != 0) {
|
||||
// UpperLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int e = bytes[offset + 2 * width * i + 2 * j] & 0xFF;
|
||||
int a = bytes[offset + 2 * width * i + 2 * j + 1] & 0xFF;
|
||||
pixels[width * i + j] = (e << rs) |
|
||||
(e << gs) |
|
||||
(e << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LowerLeft
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
int e = bytes[offset + 2 * width * i + 2 * j] & 0xFF;
|
||||
int a = bytes[offset + 2 * width * i + 2 * j + 1] & 0xFF;
|
||||
pixels[width * (height - i - 1) + j] = (e << rs) |
|
||||
(e << gs) |
|
||||
(e << bs) |
|
||||
(a << as);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unsupported depth:" + depth);
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
private TGAReader() {
|
||||
}
|
||||
|
||||
public static final class Order {
|
||||
Order(int redShift, int greenShift, int blueShift, int alphaShift) {
|
||||
this.redShift = redShift;
|
||||
this.greenShift = greenShift;
|
||||
this.blueShift = blueShift;
|
||||
this.alphaShift = alphaShift;
|
||||
}
|
||||
|
||||
public int redShift;
|
||||
public int greenShift;
|
||||
public int blueShift;
|
||||
public int alphaShift;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package su.xash.engine.workers
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
const val KEY_FILE_URI = "KEY_FILE_URI"
|
||||
|
||||
class FileCopyWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {
|
||||
companion object {
|
||||
const val Input = "Input"
|
||||
const val Progress = "Progress"
|
||||
}
|
||||
|
||||
private var fileCount = 0
|
||||
private var fileCopied = 0
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
withContext(Dispatchers.IO) {
|
||||
val fileUri = inputData.getString(KEY_FILE_URI)
|
||||
setProgress(workDataOf(Input to fileUri))
|
||||
|
||||
val uri = Uri.parse(fileUri)
|
||||
val source = DocumentFile.fromTreeUri(applicationContext, uri)
|
||||
|
||||
fileCount = source?.countDirFiles() ?: return@withContext Result.failure()
|
||||
|
||||
setProgress(workDataOf(Progress to 0f))
|
||||
|
||||
val gamedir = source.name!!
|
||||
val externalFilesDir = DocumentFile.fromFile(applicationContext.getExternalFilesDir(null)!!)
|
||||
|
||||
// create a directory to store staged files
|
||||
val target = externalFilesDir.createDirectory(".$gamedir")!!
|
||||
|
||||
source.copyDirTo(applicationContext, this@FileCopyWorker, target)
|
||||
|
||||
target.renameTo(gamedir)
|
||||
|
||||
setProgress(workDataOf(Progress to 1f))
|
||||
}
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
suspend fun fileCopied(count: Int) {
|
||||
if(count == 0)
|
||||
return
|
||||
|
||||
fileCopied += count
|
||||
val percentage: Float = fileCopied.toFloat() / fileCount.toFloat();
|
||||
setProgress(workDataOf(Progress to percentage))
|
||||
}
|
||||
}
|
||||
|
||||
fun DocumentFile.countDirFiles(): Int {
|
||||
var count: Int = 0
|
||||
|
||||
listFiles().forEach {
|
||||
if (it.isDirectory)
|
||||
count += it.countDirFiles()
|
||||
else
|
||||
count++
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
fun DocumentFile.copyFileTo(ctx: Context, file: DocumentFile) {
|
||||
val outFile = file.createFile("application", name!!)!!
|
||||
|
||||
ctx.contentResolver.openOutputStream(outFile.uri).use { os ->
|
||||
ctx.contentResolver.openInputStream(uri).use {
|
||||
it?.copyTo(os!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun DocumentFile.copyDirTo(ctx: Context, worker: FileCopyWorker, dir: DocumentFile) {
|
||||
var count: Int = 0
|
||||
|
||||
listFiles().forEach {
|
||||
if (it.isDirectory) {
|
||||
val outDir = dir.createDirectory(it.name!!)!!
|
||||
it.copyDirTo(ctx, worker, outDir)
|
||||
} else {
|
||||
it.copyFileTo(ctx, dir)
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
worker.fileCopied(count)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
||||
</vector>
|
||||
@@ -1,10 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z" />
|
||||
</vector>
|
||||
@@ -1,10 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z" />
|
||||
</vector>
|
||||
@@ -1,5 +0,0 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M21,10h-8.35C11.83,7.67 9.61,6 7,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6c2.61,0 4.83,-1.67 5.65,-4H13l2,2l2,-2l2,2l4,-4.04L21,10zM7,15c-1.65,0 -3,-1.35 -3,-3c0,-1.65 1.35,-3 3,-3s3,1.35 3,3C10,13.65 8.65,15 7,15z"/>
|
||||
</vector>
|
||||
@@ -1,5 +0,0 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user