mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-02 13:01:18 +12:00
Add all the files
This commit is contained in:
parent
e3db07a16a
commit
d60742f52b
1445 changed files with 430238 additions and 0 deletions
1282
dependencies/DirectX_2010/XAudio2.h
vendored
Normal file
1282
dependencies/DirectX_2010/XAudio2.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
263
dependencies/DirectX_2010/audiodefs.h
vendored
Normal file
263
dependencies/DirectX_2010/audiodefs.h
vendored
Normal file
|
@ -0,0 +1,263 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* File: audiodefs.h
|
||||
* Content: Basic constants and data types for audio work.
|
||||
*
|
||||
* Remarks: This header file defines all of the audio format constants and
|
||||
* structures required for XAudio2 and XACT work. Providing these
|
||||
* in a single location avoids certain dependency problems in the
|
||||
* legacy audio headers (mmreg.h, mmsystem.h, ksmedia.h).
|
||||
*
|
||||
* NOTE: Including the legacy headers after this one may cause a
|
||||
* compilation error, because they define some of the same types
|
||||
* defined here without preprocessor guards to avoid multiple
|
||||
* definitions. If a source file needs one of the old headers,
|
||||
* it must include it before including audiodefs.h.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __AUDIODEFS_INCLUDED__
|
||||
#define __AUDIODEFS_INCLUDED__
|
||||
|
||||
#include <windef.h> // For WORD, DWORD, etc.
|
||||
|
||||
#pragma pack(push, 1) // Pack structures to 1-byte boundaries
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* WAVEFORMATEX: Base structure for many audio formats. Format-specific
|
||||
* extensions can be defined for particular formats by using a non-zero
|
||||
* cbSize value and adding extra fields to the end of this structure.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _WAVEFORMATEX_
|
||||
|
||||
#define _WAVEFORMATEX_
|
||||
typedef struct tWAVEFORMATEX
|
||||
{
|
||||
WORD wFormatTag; // Integer identifier of the format
|
||||
WORD nChannels; // Number of audio channels
|
||||
DWORD nSamplesPerSec; // Audio sample rate
|
||||
DWORD nAvgBytesPerSec; // Bytes per second (possibly approximate)
|
||||
WORD nBlockAlign; // Size in bytes of a sample block (all channels)
|
||||
WORD wBitsPerSample; // Size in bits of a single per-channel sample
|
||||
WORD cbSize; // Bytes of extra data appended to this struct
|
||||
} WAVEFORMATEX;
|
||||
|
||||
#endif
|
||||
|
||||
// Defining pointer types outside of the #if block to make sure they are
|
||||
// defined even if mmreg.h or mmsystem.h is #included before this file
|
||||
|
||||
typedef WAVEFORMATEX *PWAVEFORMATEX, *NPWAVEFORMATEX, *LPWAVEFORMATEX;
|
||||
typedef const WAVEFORMATEX *PCWAVEFORMATEX, *LPCWAVEFORMATEX;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* WAVEFORMATEXTENSIBLE: Extended version of WAVEFORMATEX that should be
|
||||
* used as a basis for all new audio formats. The format tag is replaced
|
||||
* with a GUID, allowing new formats to be defined without registering a
|
||||
* format tag with Microsoft. There are also new fields that can be used
|
||||
* to specify the spatial positions for each channel and the bit packing
|
||||
* used for wide samples (e.g. 24-bit PCM samples in 32-bit containers).
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||
|
||||
#define _WAVEFORMATEXTENSIBLE_
|
||||
typedef struct
|
||||
{
|
||||
WAVEFORMATEX Format; // Base WAVEFORMATEX data
|
||||
union
|
||||
{
|
||||
WORD wValidBitsPerSample; // Valid bits in each sample container
|
||||
WORD wSamplesPerBlock; // Samples per block of audio data; valid
|
||||
// if wBitsPerSample=0 (but rarely used).
|
||||
WORD wReserved; // Zero if neither case above applies.
|
||||
} Samples;
|
||||
DWORD dwChannelMask; // Positions of the audio channels
|
||||
GUID SubFormat; // Format identifier GUID
|
||||
} WAVEFORMATEXTENSIBLE;
|
||||
|
||||
#endif
|
||||
|
||||
typedef WAVEFORMATEXTENSIBLE *PWAVEFORMATEXTENSIBLE, *LPWAVEFORMATEXTENSIBLE;
|
||||
typedef const WAVEFORMATEXTENSIBLE *PCWAVEFORMATEXTENSIBLE, *LPCWAVEFORMATEXTENSIBLE;
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Define the most common wave format tags used in WAVEFORMATEX formats.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef WAVE_FORMAT_PCM // Pulse Code Modulation
|
||||
|
||||
// If WAVE_FORMAT_PCM is not defined, we need to define some legacy types
|
||||
// for compatibility with the Windows mmreg.h / mmsystem.h header files.
|
||||
|
||||
// Old general format structure (information common to all formats)
|
||||
typedef struct waveformat_tag
|
||||
{
|
||||
WORD wFormatTag;
|
||||
WORD nChannels;
|
||||
DWORD nSamplesPerSec;
|
||||
DWORD nAvgBytesPerSec;
|
||||
WORD nBlockAlign;
|
||||
} WAVEFORMAT, *PWAVEFORMAT, NEAR *NPWAVEFORMAT, FAR *LPWAVEFORMAT;
|
||||
|
||||
// Specific format structure for PCM data
|
||||
typedef struct pcmwaveformat_tag
|
||||
{
|
||||
WAVEFORMAT wf;
|
||||
WORD wBitsPerSample;
|
||||
} PCMWAVEFORMAT, *PPCMWAVEFORMAT, NEAR *NPPCMWAVEFORMAT, FAR *LPPCMWAVEFORMAT;
|
||||
|
||||
#define WAVE_FORMAT_PCM 0x0001
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_ADPCM // Microsoft Adaptive Differental PCM
|
||||
|
||||
// Replicate the Microsoft ADPCM type definitions from mmreg.h.
|
||||
|
||||
typedef struct adpcmcoef_tag
|
||||
{
|
||||
short iCoef1;
|
||||
short iCoef2;
|
||||
} ADPCMCOEFSET;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200) // Disable zero-sized array warnings
|
||||
|
||||
typedef struct adpcmwaveformat_tag {
|
||||
WAVEFORMATEX wfx;
|
||||
WORD wSamplesPerBlock;
|
||||
WORD wNumCoef;
|
||||
ADPCMCOEFSET aCoef[]; // Always 7 coefficient pairs for MS ADPCM
|
||||
} ADPCMWAVEFORMAT;
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#define WAVE_FORMAT_ADPCM 0x0002
|
||||
|
||||
#endif
|
||||
|
||||
// Other frequently used format tags
|
||||
|
||||
#ifndef WAVE_FORMAT_UNKNOWN
|
||||
#define WAVE_FORMAT_UNKNOWN 0x0000 // Unknown or invalid format tag
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_IEEE_FLOAT
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003 // 32-bit floating-point
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_MPEGLAYER3
|
||||
#define WAVE_FORMAT_MPEGLAYER3 0x0055 // ISO/MPEG Layer3
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF
|
||||
#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 // Dolby Audio Codec 3 over S/PDIF
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_WMAUDIO2
|
||||
#define WAVE_FORMAT_WMAUDIO2 0x0161 // Windows Media Audio
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_WMAUDIO3
|
||||
#define WAVE_FORMAT_WMAUDIO3 0x0162 // Windows Media Audio Pro
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_WMASPDIF
|
||||
#define WAVE_FORMAT_WMASPDIF 0x0164 // Windows Media Audio over S/PDIF
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_EXTENSIBLE
|
||||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE // All WAVEFORMATEXTENSIBLE formats
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Define the most common wave format GUIDs used in WAVEFORMATEXTENSIBLE
|
||||
* formats. Note that including the Windows ksmedia.h header after this
|
||||
* one will cause build problems; this cannot be avoided, since ksmedia.h
|
||||
* defines these macros without preprocessor guards.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus // uuid() and __uuidof() are only available in C++
|
||||
|
||||
#ifndef KSDATAFORMAT_SUBTYPE_PCM
|
||||
struct __declspec(uuid("00000001-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_PCM_STRUCT;
|
||||
#define KSDATAFORMAT_SUBTYPE_PCM __uuidof(KSDATAFORMAT_SUBTYPE_PCM_STRUCT)
|
||||
#endif
|
||||
|
||||
#ifndef KSDATAFORMAT_SUBTYPE_ADPCM
|
||||
struct __declspec(uuid("00000002-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_ADPCM_STRUCT;
|
||||
#define KSDATAFORMAT_SUBTYPE_ADPCM __uuidof(KSDATAFORMAT_SUBTYPE_ADPCM_STRUCT)
|
||||
#endif
|
||||
|
||||
#ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
|
||||
struct __declspec(uuid("00000003-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRUCT;
|
||||
#define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT __uuidof(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRUCT)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Speaker positions used in the WAVEFORMATEXTENSIBLE dwChannelMask field.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef SPEAKER_FRONT_LEFT
|
||||
#define SPEAKER_FRONT_LEFT 0x00000001
|
||||
#define SPEAKER_FRONT_RIGHT 0x00000002
|
||||
#define SPEAKER_FRONT_CENTER 0x00000004
|
||||
#define SPEAKER_LOW_FREQUENCY 0x00000008
|
||||
#define SPEAKER_BACK_LEFT 0x00000010
|
||||
#define SPEAKER_BACK_RIGHT 0x00000020
|
||||
#define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040
|
||||
#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080
|
||||
#define SPEAKER_BACK_CENTER 0x00000100
|
||||
#define SPEAKER_SIDE_LEFT 0x00000200
|
||||
#define SPEAKER_SIDE_RIGHT 0x00000400
|
||||
#define SPEAKER_TOP_CENTER 0x00000800
|
||||
#define SPEAKER_TOP_FRONT_LEFT 0x00001000
|
||||
#define SPEAKER_TOP_FRONT_CENTER 0x00002000
|
||||
#define SPEAKER_TOP_FRONT_RIGHT 0x00004000
|
||||
#define SPEAKER_TOP_BACK_LEFT 0x00008000
|
||||
#define SPEAKER_TOP_BACK_CENTER 0x00010000
|
||||
#define SPEAKER_TOP_BACK_RIGHT 0x00020000
|
||||
#define SPEAKER_RESERVED 0x7FFC0000
|
||||
#define SPEAKER_ALL 0x80000000
|
||||
#define _SPEAKER_POSITIONS_
|
||||
#endif
|
||||
|
||||
#ifndef SPEAKER_STEREO
|
||||
#define SPEAKER_MONO (SPEAKER_FRONT_CENTER)
|
||||
#define SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
|
||||
#define SPEAKER_2POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY)
|
||||
#define SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER)
|
||||
#define SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
|
||||
#define SPEAKER_4POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
|
||||
#define SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
|
||||
#define SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER)
|
||||
#define SPEAKER_5POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)
|
||||
#define SPEAKER_7POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)
|
||||
#endif
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // #ifndef __AUDIODEFS_INCLUDED__
|
59
dependencies/DirectX_2010/comdecl.h
vendored
Normal file
59
dependencies/DirectX_2010/comdecl.h
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
// comdecl.h: Macros to facilitate COM interface and GUID declarations.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
#ifndef _COMDECL_H_
|
||||
#define _COMDECL_H_
|
||||
|
||||
#ifndef _XBOX
|
||||
#include <basetyps.h> // For standard COM interface macros
|
||||
#else
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4061)
|
||||
#include <xtl.h> // Required by xobjbase.h
|
||||
#include <xobjbase.h> // Special definitions for Xbox build
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// The DEFINE_CLSID() and DEFINE_IID() macros defined below allow COM GUIDs to
|
||||
// be declared and defined in such a way that clients can obtain the GUIDs using
|
||||
// either the __uuidof() extension or the old-style CLSID_Foo / IID_IFoo names.
|
||||
// If using the latter approach, the client can also choose whether to get the
|
||||
// GUID definitions by defining the INITGUID preprocessor constant or by linking
|
||||
// to a GUID library. This works in either C or C++.
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#define DECLSPEC_UUID_WRAPPER(x) __declspec(uuid(#x))
|
||||
#ifdef INITGUID
|
||||
|
||||
#define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
class DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) className; \
|
||||
EXTERN_C const GUID DECLSPEC_SELECTANY CLSID_##className = __uuidof(className)
|
||||
|
||||
#define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
interface DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) interfaceName; \
|
||||
EXTERN_C const GUID DECLSPEC_SELECTANY IID_##interfaceName = __uuidof(interfaceName)
|
||||
|
||||
#else // INITGUID
|
||||
|
||||
#define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
class DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) className; \
|
||||
EXTERN_C const GUID CLSID_##className
|
||||
|
||||
#define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
interface DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) interfaceName; \
|
||||
EXTERN_C const GUID IID_##interfaceName
|
||||
|
||||
#endif // INITGUID
|
||||
|
||||
#else // __cplusplus
|
||||
|
||||
#define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
DEFINE_GUID(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
|
||||
|
||||
#define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
DEFINE_GUID(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // #ifndef _COMDECL_H_
|
718
dependencies/DirectX_2010/xma2defs.h
vendored
Normal file
718
dependencies/DirectX_2010/xma2defs.h
vendored
Normal file
|
@ -0,0 +1,718 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* File: xma2defs.h
|
||||
* Content: Constants, data types and functions for XMA2 compressed audio.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __XMA2DEFS_INCLUDED__
|
||||
#define __XMA2DEFS_INCLUDED__
|
||||
|
||||
#include <sal.h> // Markers for documenting API semantics
|
||||
#include <winerror.h> // For S_OK, E_FAIL
|
||||
#include "audiodefs.h" // Basic data types and constants for audio work
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Overview
|
||||
***************************************************************************/
|
||||
|
||||
// A typical XMA2 file contains these RIFF chunks:
|
||||
//
|
||||
// 'fmt' or 'XMA2' chunk (or both): A description of the XMA data's structure
|
||||
// and characteristics (length, channels, sample rate, loops, block size, etc).
|
||||
//
|
||||
// 'seek' chunk: A seek table to help navigate the XMA data.
|
||||
//
|
||||
// 'data' chunk: The encoded XMA2 data.
|
||||
//
|
||||
// The encoded XMA2 data is structured as a set of BLOCKS, which contain PACKETS,
|
||||
// which contain FRAMES, which contain SUBFRAMES (roughly speaking). The frames
|
||||
// in a file may also be divided into several subsets, called STREAMS.
|
||||
//
|
||||
// FRAME: A variable-sized segment of XMA data that decodes to exactly 512 mono
|
||||
// or stereo PCM samples. This is the smallest unit of XMA data that can
|
||||
// be decoded in isolation. Frames are an arbitrary number of bits in
|
||||
// length, and need not be byte-aligned. See "XMA frame structure" below.
|
||||
//
|
||||
// SUBFRAME: A region of bits in an XMA frame that decodes to 128 mono or stereo
|
||||
// samples. The XMA decoder cannot decode a subframe in isolation; it needs
|
||||
// a whole frame to work with. However, it can begin emitting the frame's
|
||||
// decoded samples at any one of the four subframe boundaries. Subframes
|
||||
// can be addressed for seeking and looping purposes.
|
||||
//
|
||||
// PACKET: A 2Kb region containing a 32-bit header and some XMA frames. Frames
|
||||
// can (and usually do) span packets. A packet's header includes the offset
|
||||
// in bits of the first frame that begins within that packet. All of the
|
||||
// frames that begin in a given packet belong to the same "stream" (see the
|
||||
// Multichannel Audio section below).
|
||||
//
|
||||
// STREAM: A set of packets within an XMA file that all contain data for the
|
||||
// same mono or stereo component of a PCM file with more than two channels.
|
||||
// The packets comprising a given stream may be interleaved with each other
|
||||
// more or less arbitrarily; see Multichannel Audio.
|
||||
//
|
||||
// BLOCK: An array of XMA packets; or, to break it down differently, a series of
|
||||
// consecutive XMA frames, padded at the end with reserved data. A block
|
||||
// must contain at least one 2Kb packet per stream, and it can hold up to
|
||||
// 4095 packets (8190Kb), but its size is typically in the 32Kb-128Kb range.
|
||||
// (The size chosen involves a trade-off between memory use and efficiency
|
||||
// of reading from permanent storage.)
|
||||
//
|
||||
// XMA frames do not span blocks, so a block is guaranteed to begin with a
|
||||
// set of complete frames, one per stream. Also, a block in a multi-stream
|
||||
// XMA2 file always contains the same number of samples for each stream;
|
||||
// see Multichannel Audio.
|
||||
//
|
||||
// The 'data' chunk in an XMA2 file is an array of XMA2WAVEFORMAT.BlockCount XMA
|
||||
// blocks, all the same size (as specified in XMA2WAVEFORMAT.BlockSizeInBytes)
|
||||
// except for the last one, which may be shorter.
|
||||
|
||||
|
||||
// MULTICHANNEL AUDIO: the XMA decoder can only decode raw XMA data into either
|
||||
// mono or stereo PCM data. In order to encode a 6-channel file (say), the file
|
||||
// must be deinterleaved into 3 stereo streams that are encoded independently,
|
||||
// producing 3 encoded XMA data streams. Then the packets in these 3 streams
|
||||
// are interleaved to produce a single XMA2 file, and some information is added
|
||||
// to the file so that the original 6-channel audio can be reconstructed at
|
||||
// decode time. This works using the concept of an XMA stream (see above).
|
||||
//
|
||||
// The frames for all the streams in an XMA file are interleaved in an arbitrary
|
||||
// order. To locate a frame that belongs to a given stream in a given XMA block,
|
||||
// you must examine the first few packets in the block. Here (and only here) the
|
||||
// packets are guaranteed to be presented in stream order, so that all frames
|
||||
// beginning in packet 0 belong to stream 0 (the first stereo pair), etc.
|
||||
//
|
||||
// (This means that when decoding multi-stream XMA files, only entire XMA blocks
|
||||
// should be submitted to the decoder; otherwise it cannot know which frames
|
||||
// belong to which stream.)
|
||||
//
|
||||
// Once you have one frame that belongs to a given stream, you can find the next
|
||||
// one by looking at the frame's 'NextFrameOffsetBits' value (which is stored in
|
||||
// its first 15 bits; see XMAFRAME below). The GetXmaFrameBitPosition function
|
||||
// uses this technique.
|
||||
|
||||
|
||||
// SEEKING IN XMA2 FILES: Here is some pseudocode to find the byte position and
|
||||
// subframe in an XMA2 file which will contain sample S when decoded.
|
||||
//
|
||||
// 1. Traverse the seek table to find the XMA2 block containing sample S. The
|
||||
// seek table is an array of big-endian DWORDs, one per block in the file.
|
||||
// The Nth DWORD is the total number of PCM samples that would be obtained
|
||||
// by decoding the entire XMA file up to the end of block N. Hence, the
|
||||
// block we want is the first one whose seek table entry is greater than S.
|
||||
// (See the GetXmaBlockContainingSample helper function.)
|
||||
//
|
||||
// 2. Calculate which frame F within the block found above contains sample S.
|
||||
// Since each frame decodes to 512 samples, this is straightforward. The
|
||||
// first frame in the block produces samples X to X + 512, where X is the
|
||||
// seek table entry for the prior block. So F is (S - X) / 512.
|
||||
//
|
||||
// 3. Find the bit offset within the block where frame F starts. Since frames
|
||||
// are variable-sized, this can only be done by traversing all the frames in
|
||||
// the block until we reach frame F. (See GetXmaFrameBitPosition.)
|
||||
//
|
||||
// 4. Frame F has four 128-sample subframes. To find the subframe containing S,
|
||||
// we can use the formula (S % 512) / 128.
|
||||
//
|
||||
// In the case of multi-stream XMA files, sample S is a multichannel sample with
|
||||
// parts coming from several frames, one per stream. To find all these frames,
|
||||
// steps 2-4 need to be repeated for each stream N, using the knowledge that the
|
||||
// first packets in a block are presented in stream order. The frame traversal
|
||||
// in step 3 must be started at the first frame in the Nth packet of the block,
|
||||
// which will be the first frame for stream N. (And the packet header will tell
|
||||
// you the first frame's start position within the packet.)
|
||||
//
|
||||
// Step 1 can be performed using the GetXmaBlockContainingSample function below,
|
||||
// and steps 2-4 by calling GetXmaDecodePositionForSample once for each stream.
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* XMA constants
|
||||
***************************************************************************/
|
||||
|
||||
// Size of the PCM samples produced by the XMA decoder
|
||||
#define XMA_OUTPUT_SAMPLE_BYTES 2u
|
||||
#define XMA_OUTPUT_SAMPLE_BITS (XMA_OUTPUT_SAMPLE_BYTES * 8u)
|
||||
|
||||
// Size of an XMA packet
|
||||
#define XMA_BYTES_PER_PACKET 2048u
|
||||
#define XMA_BITS_PER_PACKET (XMA_BYTES_PER_PACKET * 8u)
|
||||
|
||||
// Size of an XMA packet header
|
||||
#define XMA_PACKET_HEADER_BYTES 4u
|
||||
#define XMA_PACKET_HEADER_BITS (XMA_PACKET_HEADER_BYTES * 8u)
|
||||
|
||||
// Sample blocks in a decoded XMA frame
|
||||
#define XMA_SAMPLES_PER_FRAME 512u
|
||||
|
||||
// Sample blocks in a decoded XMA subframe
|
||||
#define XMA_SAMPLES_PER_SUBFRAME 128u
|
||||
|
||||
// Maximum encoded data that can be submitted to the XMA decoder at a time
|
||||
#define XMA_READBUFFER_MAX_PACKETS 4095u
|
||||
#define XMA_READBUFFER_MAX_BYTES (XMA_READBUFFER_MAX_PACKETS * XMA_BYTES_PER_PACKET)
|
||||
|
||||
// Maximum size allowed for the XMA decoder's output buffers
|
||||
#define XMA_WRITEBUFFER_MAX_BYTES (31u * 256u)
|
||||
|
||||
// Required byte alignment of the XMA decoder's output buffers
|
||||
#define XMA_WRITEBUFFER_BYTE_ALIGNMENT 256u
|
||||
|
||||
// Decode chunk sizes for the XMA_PLAYBACK_INIT.subframesToDecode field
|
||||
#define XMA_MIN_SUBFRAMES_TO_DECODE 1u
|
||||
#define XMA_MAX_SUBFRAMES_TO_DECODE 8u
|
||||
#define XMA_OPTIMAL_SUBFRAMES_TO_DECODE 4u
|
||||
|
||||
// LoopCount<255 means finite repetitions; LoopCount=255 means infinite looping
|
||||
#define XMA_MAX_LOOPCOUNT 254u
|
||||
#define XMA_INFINITE_LOOP 255u
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* XMA format structures
|
||||
***************************************************************************/
|
||||
|
||||
// The currently recommended way to express format information for XMA2 files
|
||||
// is the XMA2WAVEFORMATEX structure. This structure is fully compliant with
|
||||
// the WAVEFORMATEX standard and contains all the information needed to parse
|
||||
// and manage XMA2 files in a compact way.
|
||||
|
||||
#define WAVE_FORMAT_XMA2 0x166
|
||||
|
||||
typedef struct XMA2WAVEFORMATEX
|
||||
{
|
||||
WAVEFORMATEX wfx;
|
||||
// Meaning of the WAVEFORMATEX fields here:
|
||||
// wFormatTag; // Audio format type; always WAVE_FORMAT_XMA2
|
||||
// nChannels; // Channel count of the decoded audio
|
||||
// nSamplesPerSec; // Sample rate of the decoded audio
|
||||
// nAvgBytesPerSec; // Used internally by the XMA encoder
|
||||
// nBlockAlign; // Decoded sample size; channels * wBitsPerSample / 8
|
||||
// wBitsPerSample; // Bits per decoded mono sample; always 16 for XMA
|
||||
// cbSize; // Size in bytes of the rest of this structure (34)
|
||||
|
||||
WORD NumStreams; // Number of audio streams (1 or 2 channels each)
|
||||
DWORD ChannelMask; // Spatial positions of the channels in this file,
|
||||
// stored as SPEAKER_xxx values (see audiodefs.h)
|
||||
DWORD SamplesEncoded; // Total number of PCM samples the file decodes to
|
||||
DWORD BytesPerBlock; // XMA block size (but the last one may be shorter)
|
||||
DWORD PlayBegin; // First valid sample in the decoded audio
|
||||
DWORD PlayLength; // Length of the valid part of the decoded audio
|
||||
DWORD LoopBegin; // Beginning of the loop region in decoded sample terms
|
||||
DWORD LoopLength; // Length of the loop region in decoded sample terms
|
||||
BYTE LoopCount; // Number of loop repetitions; 255 = infinite
|
||||
BYTE EncoderVersion; // Version of XMA encoder that generated the file
|
||||
WORD BlockCount; // XMA blocks in file (and entries in its seek table)
|
||||
} XMA2WAVEFORMATEX, *PXMA2WAVEFORMATEX;
|
||||
|
||||
|
||||
// The legacy XMA format structures are described here for reference, but they
|
||||
// should not be used in new content. XMAWAVEFORMAT was the structure used in
|
||||
// XMA version 1 files. XMA2WAVEFORMAT was used in early XMA2 files; it is not
|
||||
// placed in the usual 'fmt' RIFF chunk but in its own 'XMA2' chunk.
|
||||
|
||||
#ifndef WAVE_FORMAT_XMA
|
||||
#define WAVE_FORMAT_XMA 0x0165
|
||||
|
||||
// Values used in the ChannelMask fields below. Similar to the SPEAKER_xxx
|
||||
// values defined in audiodefs.h, but modified to fit in a single byte.
|
||||
#ifndef XMA_SPEAKER_LEFT
|
||||
#define XMA_SPEAKER_LEFT 0x01
|
||||
#define XMA_SPEAKER_RIGHT 0x02
|
||||
#define XMA_SPEAKER_CENTER 0x04
|
||||
#define XMA_SPEAKER_LFE 0x08
|
||||
#define XMA_SPEAKER_LEFT_SURROUND 0x10
|
||||
#define XMA_SPEAKER_RIGHT_SURROUND 0x20
|
||||
#define XMA_SPEAKER_LEFT_BACK 0x40
|
||||
#define XMA_SPEAKER_RIGHT_BACK 0x80
|
||||
#endif
|
||||
|
||||
|
||||
// Used in XMAWAVEFORMAT for per-stream data
|
||||
typedef struct XMASTREAMFORMAT
|
||||
{
|
||||
DWORD PsuedoBytesPerSec; // Used by the XMA encoder (typo preserved for legacy reasons)
|
||||
DWORD SampleRate; // The stream's decoded sample rate (in XMA2 files,
|
||||
// this is the same for all streams in the file).
|
||||
DWORD LoopStart; // Bit offset of the frame containing the loop start
|
||||
// point, relative to the beginning of the stream.
|
||||
DWORD LoopEnd; // Bit offset of the frame containing the loop end.
|
||||
BYTE SubframeData; // Two 4-bit numbers specifying the exact location of
|
||||
// the loop points within the frames that contain them.
|
||||
// SubframeEnd: Subframe of the loop end frame where
|
||||
// the loop ends. Ranges from 0 to 3.
|
||||
// SubframeSkip: Subframes to skip in the start frame to
|
||||
// reach the loop. Ranges from 0 to 4.
|
||||
BYTE Channels; // Number of channels in the stream (1 or 2)
|
||||
WORD ChannelMask; // Spatial positions of the channels in the stream
|
||||
} XMASTREAMFORMAT;
|
||||
|
||||
// Legacy XMA1 format structure
|
||||
typedef struct XMAWAVEFORMAT
|
||||
{
|
||||
WORD FormatTag; // Audio format type (always WAVE_FORMAT_XMA)
|
||||
WORD BitsPerSample; // Bit depth (currently required to be 16)
|
||||
WORD EncodeOptions; // Options for XMA encoder/decoder
|
||||
WORD LargestSkip; // Largest skip used in interleaving streams
|
||||
WORD NumStreams; // Number of interleaved audio streams
|
||||
BYTE LoopCount; // Number of loop repetitions; 255 = infinite
|
||||
BYTE Version; // XMA encoder version that generated the file.
|
||||
// Always 3 or higher for XMA2 files.
|
||||
XMASTREAMFORMAT XmaStreams[1]; // Per-stream format information; the actual
|
||||
// array length is in the NumStreams field.
|
||||
} XMAWAVEFORMAT;
|
||||
|
||||
|
||||
// Used in XMA2WAVEFORMAT for per-stream data
|
||||
typedef struct XMA2STREAMFORMAT
|
||||
{
|
||||
BYTE Channels; // Number of channels in the stream (1 or 2)
|
||||
BYTE RESERVED; // Reserved for future use
|
||||
WORD ChannelMask; // Spatial positions of the channels in the stream
|
||||
} XMA2STREAMFORMAT;
|
||||
|
||||
// Legacy XMA2 format structure (big-endian byte ordering)
|
||||
typedef struct XMA2WAVEFORMAT
|
||||
{
|
||||
BYTE Version; // XMA encoder version that generated the file.
|
||||
// Always 3 or higher for XMA2 files.
|
||||
BYTE NumStreams; // Number of interleaved audio streams
|
||||
BYTE RESERVED; // Reserved for future use
|
||||
BYTE LoopCount; // Number of loop repetitions; 255 = infinite
|
||||
DWORD LoopBegin; // Loop begin point, in samples
|
||||
DWORD LoopEnd; // Loop end point, in samples
|
||||
DWORD SampleRate; // The file's decoded sample rate
|
||||
DWORD EncodeOptions; // Options for the XMA encoder/decoder
|
||||
DWORD PsuedoBytesPerSec; // Used internally by the XMA encoder
|
||||
DWORD BlockSizeInBytes; // Size in bytes of this file's XMA blocks (except
|
||||
// possibly the last one). Always a multiple of
|
||||
// 2Kb, since XMA blocks are arrays of 2Kb packets.
|
||||
DWORD SamplesEncoded; // Total number of PCM samples encoded in this file
|
||||
DWORD SamplesInSource; // Actual number of PCM samples in the source
|
||||
// material used to generate this file
|
||||
DWORD BlockCount; // Number of XMA blocks in this file (and hence
|
||||
// also the number of entries in its seek table)
|
||||
XMA2STREAMFORMAT Streams[1]; // Per-stream format information; the actual
|
||||
// array length is in the NumStreams field.
|
||||
} XMA2WAVEFORMAT;
|
||||
|
||||
#endif // #ifndef WAVE_FORMAT_XMA
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* XMA packet structure (in big-endian form)
|
||||
***************************************************************************/
|
||||
|
||||
typedef struct XMA2PACKET
|
||||
{
|
||||
int FrameCount : 6; // Number of XMA frames that begin in this packet
|
||||
int FrameOffsetInBits : 15; // Bit of XmaData where the first complete frame begins
|
||||
int PacketMetaData : 3; // Metadata stored in the packet (always 1 for XMA2)
|
||||
int PacketSkipCount : 8; // How many packets belonging to other streams must be
|
||||
// skipped to find the next packet belonging to this one
|
||||
BYTE XmaData[XMA_BYTES_PER_PACKET - sizeof(DWORD)]; // XMA encoded data
|
||||
} XMA2PACKET;
|
||||
|
||||
// E.g. if the first DWORD of a packet is 0x30107902:
|
||||
//
|
||||
// 001100 000001000001111 001 00000010
|
||||
// | | | |____ Skip 2 packets to find the next one for this stream
|
||||
// | | |___________ XMA2 signature (always 001)
|
||||
// | |_____________________ First frame starts 527 bits into packet
|
||||
// |________________________________ Packet contains 12 frames
|
||||
|
||||
|
||||
// Helper functions to extract the fields above from an XMA packet. (Note that
|
||||
// the bitfields cannot be read directly on little-endian architectures such as
|
||||
// the Intel x86, as they are laid out in big-endian form.)
|
||||
|
||||
__inline DWORD GetXmaPacketFrameCount(__in_bcount(1) const BYTE* pPacket)
|
||||
{
|
||||
return (DWORD)(pPacket[0] >> 2);
|
||||
}
|
||||
|
||||
__inline DWORD GetXmaPacketFirstFrameOffsetInBits(__in_bcount(3) const BYTE* pPacket)
|
||||
{
|
||||
return ((DWORD)(pPacket[0] & 0x3) << 13) |
|
||||
((DWORD)(pPacket[1]) << 5) |
|
||||
((DWORD)(pPacket[2]) >> 3);
|
||||
}
|
||||
|
||||
__inline DWORD GetXmaPacketMetadata(__in_bcount(3) const BYTE* pPacket)
|
||||
{
|
||||
return (DWORD)(pPacket[2] & 0x7);
|
||||
}
|
||||
|
||||
__inline DWORD GetXmaPacketSkipCount(__in_bcount(4) const BYTE* pPacket)
|
||||
{
|
||||
return (DWORD)(pPacket[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* XMA frame structure
|
||||
***************************************************************************/
|
||||
|
||||
// There is no way to represent the XMA frame as a C struct, since it is a
|
||||
// variable-sized string of bits that need not be stored at a byte-aligned
|
||||
// position in memory. This is the layout:
|
||||
//
|
||||
// XMAFRAME
|
||||
// {
|
||||
// LengthInBits: A 15-bit number representing the length of this frame.
|
||||
// XmaData: Encoded XMA data; its size in bits is (LengthInBits - 15).
|
||||
// }
|
||||
|
||||
// Size in bits of the frame's initial LengthInBits field
|
||||
#define XMA_BITS_IN_FRAME_LENGTH_FIELD 15
|
||||
|
||||
// Special LengthInBits value that marks an invalid final frame
|
||||
#define XMA_FINAL_FRAME_MARKER 0x7FFF
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* XMA helper functions
|
||||
***************************************************************************/
|
||||
|
||||
// We define a local ASSERT macro to equal the global one if it exists.
|
||||
// You can define XMA2DEFS_ASSERT in advance to override this default.
|
||||
#ifndef XMA2DEFS_ASSERT
|
||||
#ifdef ASSERT
|
||||
#define XMA2DEFS_ASSERT ASSERT
|
||||
#else
|
||||
#define XMA2DEFS_ASSERT(a) /* No-op by default */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// GetXmaBlockContainingSample: Use a given seek table to find the XMA block
|
||||
// containing a given decoded sample. Note that the seek table entries in an
|
||||
// XMA file are stored in big-endian form and may need to be converted prior
|
||||
// to calling this function.
|
||||
|
||||
__inline HRESULT GetXmaBlockContainingSample
|
||||
(
|
||||
DWORD nBlockCount, // Blocks in the file (= seek table entries)
|
||||
__in_ecount(nBlockCount) const DWORD* pSeekTable, // Pointer to the seek table data
|
||||
DWORD nDesiredSample, // Decoded sample to locate
|
||||
__out DWORD* pnBlockContainingSample, // Index of the block containing the sample
|
||||
__out DWORD* pnSampleOffsetWithinBlock // Position of the sample in this block
|
||||
)
|
||||
{
|
||||
DWORD nPreviousTotalSamples = 0;
|
||||
DWORD nBlock;
|
||||
DWORD nTotalSamplesSoFar;
|
||||
|
||||
XMA2DEFS_ASSERT(pSeekTable);
|
||||
XMA2DEFS_ASSERT(pnBlockContainingSample);
|
||||
XMA2DEFS_ASSERT(pnSampleOffsetWithinBlock);
|
||||
|
||||
for (nBlock = 0; nBlock < nBlockCount; ++nBlock)
|
||||
{
|
||||
nTotalSamplesSoFar = pSeekTable[nBlock];
|
||||
if (nTotalSamplesSoFar > nDesiredSample)
|
||||
{
|
||||
*pnBlockContainingSample = nBlock;
|
||||
*pnSampleOffsetWithinBlock = nDesiredSample - nPreviousTotalSamples;
|
||||
return S_OK;
|
||||
}
|
||||
nPreviousTotalSamples = nTotalSamplesSoFar;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
// GetXmaFrameLengthInBits: Reads a given frame's LengthInBits field.
|
||||
|
||||
__inline DWORD GetXmaFrameLengthInBits
|
||||
(
|
||||
__in_bcount(nBitPosition / 8 + 3)
|
||||
__in const BYTE* pPacket, // Pointer to XMA packet[s] containing the frame
|
||||
DWORD nBitPosition // Bit offset of the frame within this packet
|
||||
)
|
||||
{
|
||||
DWORD nRegion;
|
||||
DWORD nBytePosition = nBitPosition / 8;
|
||||
DWORD nBitOffset = nBitPosition % 8;
|
||||
|
||||
if (nBitOffset < 2) // Only need to read 2 bytes (and might not be safe to read more)
|
||||
{
|
||||
nRegion = (DWORD)(pPacket[nBytePosition+0]) << 8 |
|
||||
(DWORD)(pPacket[nBytePosition+1]);
|
||||
return (nRegion >> (1 - nBitOffset)) & 0x7FFF; // Last 15 bits
|
||||
}
|
||||
else // Need to read 3 bytes
|
||||
{
|
||||
nRegion = (DWORD)(pPacket[nBytePosition+0]) << 16 |
|
||||
(DWORD)(pPacket[nBytePosition+1]) << 8 |
|
||||
(DWORD)(pPacket[nBytePosition+2]);
|
||||
return (nRegion >> (9 - nBitOffset)) & 0x7FFF; // Last 15 bits
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GetXmaFrameBitPosition: Calculates the bit offset of a given frame within
|
||||
// an XMA block or set of blocks. Returns 0 on failure.
|
||||
|
||||
__inline DWORD GetXmaFrameBitPosition
|
||||
(
|
||||
__in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s]
|
||||
DWORD nXmaDataBytes, // Size of pXmaData in bytes
|
||||
DWORD nStreamIndex, // Stream within which to seek
|
||||
DWORD nDesiredFrame // Frame sought
|
||||
)
|
||||
{
|
||||
const BYTE* pCurrentPacket;
|
||||
DWORD nPacketsExamined = 0;
|
||||
DWORD nFrameCountSoFar = 0;
|
||||
DWORD nFramesToSkip;
|
||||
DWORD nFrameBitOffset;
|
||||
|
||||
XMA2DEFS_ASSERT(pXmaData);
|
||||
XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0);
|
||||
|
||||
// Get the first XMA packet belonging to the desired stream, relying on the
|
||||
// fact that the first packets for each stream are in consecutive order at
|
||||
// the beginning of an XMA block.
|
||||
|
||||
pCurrentPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET;
|
||||
for (;;)
|
||||
{
|
||||
// If we have exceeded the size of the XMA data, return failure
|
||||
if (pCurrentPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the current packet contains the frame we are looking for...
|
||||
if (nFrameCountSoFar + GetXmaPacketFrameCount(pCurrentPacket) > nDesiredFrame)
|
||||
{
|
||||
// See how many frames in this packet we need to skip to get to it
|
||||
XMA2DEFS_ASSERT(nDesiredFrame >= nFrameCountSoFar);
|
||||
nFramesToSkip = nDesiredFrame - nFrameCountSoFar;
|
||||
|
||||
// Get the bit offset of the first frame in this packet
|
||||
nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pCurrentPacket);
|
||||
|
||||
// Advance nFrameBitOffset to the frame of interest
|
||||
while (nFramesToSkip--)
|
||||
{
|
||||
nFrameBitOffset += GetXmaFrameLengthInBits(pCurrentPacket, nFrameBitOffset);
|
||||
}
|
||||
|
||||
// The bit offset to return is the number of bits from pXmaData to
|
||||
// pCurrentPacket plus the bit offset of the frame of interest
|
||||
return (DWORD)(pCurrentPacket - pXmaData) * 8 + nFrameBitOffset;
|
||||
}
|
||||
|
||||
// If we haven't found the right packet yet, advance our counters
|
||||
++nPacketsExamined;
|
||||
nFrameCountSoFar += GetXmaPacketFrameCount(pCurrentPacket);
|
||||
|
||||
// And skip to the next packet belonging to the same stream
|
||||
pCurrentPacket += XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pCurrentPacket) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GetLastXmaFrameBitPosition: Calculates the bit offset of the last complete
|
||||
// frame in an XMA block or set of blocks.
|
||||
|
||||
__inline DWORD GetLastXmaFrameBitPosition
|
||||
(
|
||||
__in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s]
|
||||
DWORD nXmaDataBytes, // Size of pXmaData in bytes
|
||||
DWORD nStreamIndex // Stream within which to seek
|
||||
)
|
||||
{
|
||||
const BYTE* pLastPacket;
|
||||
DWORD nBytesToNextPacket;
|
||||
DWORD nFrameBitOffset;
|
||||
DWORD nFramesInLastPacket;
|
||||
|
||||
XMA2DEFS_ASSERT(pXmaData);
|
||||
XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0);
|
||||
XMA2DEFS_ASSERT(nXmaDataBytes >= XMA_BYTES_PER_PACKET * (nStreamIndex + 1));
|
||||
|
||||
// Get the first XMA packet belonging to the desired stream, relying on the
|
||||
// fact that the first packets for each stream are in consecutive order at
|
||||
// the beginning of an XMA block.
|
||||
pLastPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET;
|
||||
|
||||
// Search for the last packet belonging to the desired stream
|
||||
for (;;)
|
||||
{
|
||||
nBytesToNextPacket = XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pLastPacket) + 1);
|
||||
XMA2DEFS_ASSERT(nBytesToNextPacket);
|
||||
if (pLastPacket + nBytesToNextPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes)
|
||||
{
|
||||
break; // The next packet would extend beyond the end of pXmaData
|
||||
}
|
||||
pLastPacket += nBytesToNextPacket;
|
||||
}
|
||||
|
||||
// The last packet can sometimes have no seekable frames, in which case we
|
||||
// have to use the previous one
|
||||
if (GetXmaPacketFrameCount(pLastPacket) == 0)
|
||||
{
|
||||
pLastPacket -= nBytesToNextPacket;
|
||||
}
|
||||
|
||||
// Found the last packet. Get the bit offset of its first frame.
|
||||
nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pLastPacket);
|
||||
|
||||
// Traverse frames until we reach the last one
|
||||
nFramesInLastPacket = GetXmaPacketFrameCount(pLastPacket);
|
||||
while (--nFramesInLastPacket)
|
||||
{
|
||||
nFrameBitOffset += GetXmaFrameLengthInBits(pLastPacket, nFrameBitOffset);
|
||||
}
|
||||
|
||||
// The bit offset to return is the number of bits from pXmaData to
|
||||
// pLastPacket plus the offset of the last frame in this packet.
|
||||
return (DWORD)(pLastPacket - pXmaData) * 8 + nFrameBitOffset;
|
||||
}
|
||||
|
||||
|
||||
// GetXmaDecodePositionForSample: Obtains the information needed to make the
|
||||
// decoder generate audio starting at a given sample position relative to the
|
||||
// beginning of the given XMA block: the bit offset of the appropriate frame,
|
||||
// and the right subframe within that frame. This data can be passed directly
|
||||
// to the XMAPlaybackSetDecodePosition function.
|
||||
|
||||
__inline HRESULT GetXmaDecodePositionForSample
|
||||
(
|
||||
__in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s]
|
||||
DWORD nXmaDataBytes, // Size of pXmaData in bytes
|
||||
DWORD nStreamIndex, // Stream within which to seek
|
||||
DWORD nDesiredSample, // Sample sought
|
||||
__out DWORD* pnBitOffset, // Returns the bit offset within pXmaData of
|
||||
// the frame containing the sample sought
|
||||
__out DWORD* pnSubFrame // Returns the subframe containing the sample
|
||||
)
|
||||
{
|
||||
DWORD nDesiredFrame = nDesiredSample / XMA_SAMPLES_PER_FRAME;
|
||||
DWORD nSubFrame = (nDesiredSample % XMA_SAMPLES_PER_FRAME) / XMA_SAMPLES_PER_SUBFRAME;
|
||||
DWORD nBitOffset = GetXmaFrameBitPosition(pXmaData, nXmaDataBytes, nStreamIndex, nDesiredFrame);
|
||||
|
||||
XMA2DEFS_ASSERT(pnBitOffset);
|
||||
XMA2DEFS_ASSERT(pnSubFrame);
|
||||
|
||||
if (nBitOffset)
|
||||
{
|
||||
*pnBitOffset = nBitOffset;
|
||||
*pnSubFrame = nSubFrame;
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GetXmaSampleRate: Obtains the legal XMA sample rate (24, 32, 44.1 or 48Khz)
|
||||
// corresponding to a generic sample rate.
|
||||
|
||||
__inline DWORD GetXmaSampleRate(DWORD dwGeneralRate)
|
||||
{
|
||||
DWORD dwXmaRate = 48000; // Default XMA rate for all rates above 44100Hz
|
||||
|
||||
if (dwGeneralRate <= 24000) dwXmaRate = 24000;
|
||||
else if (dwGeneralRate <= 32000) dwXmaRate = 32000;
|
||||
else if (dwGeneralRate <= 44100) dwXmaRate = 44100;
|
||||
|
||||
return dwXmaRate;
|
||||
}
|
||||
|
||||
|
||||
// Functions to convert between WAVEFORMATEXTENSIBLE channel masks (combinations
|
||||
// of the SPEAKER_xxx flags defined in audiodefs.h) and XMA channel masks (which
|
||||
// are limited to eight possible speaker positions: left, right, center, low
|
||||
// frequency, side left, side right, back left and back right).
|
||||
|
||||
__inline DWORD GetStandardChannelMaskFromXmaMask(BYTE bXmaMask)
|
||||
{
|
||||
DWORD dwStandardMask = 0;
|
||||
|
||||
if (bXmaMask & XMA_SPEAKER_LEFT) dwStandardMask |= SPEAKER_FRONT_LEFT;
|
||||
if (bXmaMask & XMA_SPEAKER_RIGHT) dwStandardMask |= SPEAKER_FRONT_RIGHT;
|
||||
if (bXmaMask & XMA_SPEAKER_CENTER) dwStandardMask |= SPEAKER_FRONT_CENTER;
|
||||
if (bXmaMask & XMA_SPEAKER_LFE) dwStandardMask |= SPEAKER_LOW_FREQUENCY;
|
||||
if (bXmaMask & XMA_SPEAKER_LEFT_SURROUND) dwStandardMask |= SPEAKER_SIDE_LEFT;
|
||||
if (bXmaMask & XMA_SPEAKER_RIGHT_SURROUND) dwStandardMask |= SPEAKER_SIDE_RIGHT;
|
||||
if (bXmaMask & XMA_SPEAKER_LEFT_BACK) dwStandardMask |= SPEAKER_BACK_LEFT;
|
||||
if (bXmaMask & XMA_SPEAKER_RIGHT_BACK) dwStandardMask |= SPEAKER_BACK_RIGHT;
|
||||
|
||||
return dwStandardMask;
|
||||
}
|
||||
|
||||
__inline BYTE GetXmaChannelMaskFromStandardMask(DWORD dwStandardMask)
|
||||
{
|
||||
BYTE bXmaMask = 0;
|
||||
|
||||
if (dwStandardMask & SPEAKER_FRONT_LEFT) bXmaMask |= XMA_SPEAKER_LEFT;
|
||||
if (dwStandardMask & SPEAKER_FRONT_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT;
|
||||
if (dwStandardMask & SPEAKER_FRONT_CENTER) bXmaMask |= XMA_SPEAKER_CENTER;
|
||||
if (dwStandardMask & SPEAKER_LOW_FREQUENCY) bXmaMask |= XMA_SPEAKER_LFE;
|
||||
if (dwStandardMask & SPEAKER_SIDE_LEFT) bXmaMask |= XMA_SPEAKER_LEFT_SURROUND;
|
||||
if (dwStandardMask & SPEAKER_SIDE_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT_SURROUND;
|
||||
if (dwStandardMask & SPEAKER_BACK_LEFT) bXmaMask |= XMA_SPEAKER_LEFT_BACK;
|
||||
if (dwStandardMask & SPEAKER_BACK_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT_BACK;
|
||||
|
||||
return bXmaMask;
|
||||
}
|
||||
|
||||
|
||||
// LocalizeXma2Format: Modifies a XMA2WAVEFORMATEX structure in place to comply
|
||||
// with the current platform's byte-ordering rules (little- or big-endian).
|
||||
|
||||
__inline HRESULT LocalizeXma2Format(__inout XMA2WAVEFORMATEX* pXma2Format)
|
||||
{
|
||||
#define XMASWAP2BYTES(n) ((WORD)(((n) >> 8) | (((n) & 0xff) << 8)))
|
||||
#define XMASWAP4BYTES(n) ((DWORD)((n) >> 24 | (n) << 24 | ((n) & 0xff00) << 8 | ((n) & 0xff0000) >> 8))
|
||||
|
||||
if (pXma2Format->wfx.wFormatTag == WAVE_FORMAT_XMA2)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
else if (XMASWAP2BYTES(pXma2Format->wfx.wFormatTag) == WAVE_FORMAT_XMA2)
|
||||
{
|
||||
pXma2Format->wfx.wFormatTag = XMASWAP2BYTES(pXma2Format->wfx.wFormatTag);
|
||||
pXma2Format->wfx.nChannels = XMASWAP2BYTES(pXma2Format->wfx.nChannels);
|
||||
pXma2Format->wfx.nSamplesPerSec = XMASWAP4BYTES(pXma2Format->wfx.nSamplesPerSec);
|
||||
pXma2Format->wfx.nAvgBytesPerSec = XMASWAP4BYTES(pXma2Format->wfx.nAvgBytesPerSec);
|
||||
pXma2Format->wfx.nBlockAlign = XMASWAP2BYTES(pXma2Format->wfx.nBlockAlign);
|
||||
pXma2Format->wfx.wBitsPerSample = XMASWAP2BYTES(pXma2Format->wfx.wBitsPerSample);
|
||||
pXma2Format->wfx.cbSize = XMASWAP2BYTES(pXma2Format->wfx.cbSize);
|
||||
pXma2Format->NumStreams = XMASWAP2BYTES(pXma2Format->NumStreams);
|
||||
pXma2Format->ChannelMask = XMASWAP4BYTES(pXma2Format->ChannelMask);
|
||||
pXma2Format->SamplesEncoded = XMASWAP4BYTES(pXma2Format->SamplesEncoded);
|
||||
pXma2Format->BytesPerBlock = XMASWAP4BYTES(pXma2Format->BytesPerBlock);
|
||||
pXma2Format->PlayBegin = XMASWAP4BYTES(pXma2Format->PlayBegin);
|
||||
pXma2Format->PlayLength = XMASWAP4BYTES(pXma2Format->PlayLength);
|
||||
pXma2Format->LoopBegin = XMASWAP4BYTES(pXma2Format->LoopBegin);
|
||||
pXma2Format->LoopLength = XMASWAP4BYTES(pXma2Format->LoopLength);
|
||||
pXma2Format->BlockCount = XMASWAP2BYTES(pXma2Format->BlockCount);
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_FAIL; // Not a recognizable XMA2 format
|
||||
}
|
||||
|
||||
#undef XMASWAP2BYTES
|
||||
#undef XMASWAP4BYTES
|
||||
}
|
||||
|
||||
|
||||
#endif // #ifndef __XMA2DEFS_INCLUDED__
|
92
dependencies/discord-rpc/.clang-format
vendored
Normal file
92
dependencies/discord-rpc/.clang-format
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: true
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Stroustrup
|
||||
BreakBeforeInheritanceComma: true
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: ''
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros: []
|
||||
IndentCaseLabels: false
|
||||
IncludeCategories:
|
||||
- Regex: '^("|<)stdafx\.h(pp)?("|>)'
|
||||
Priority: -1
|
||||
- Regex: '^<(W|w)indows.h>'
|
||||
Priority: 1
|
||||
- Regex: '^<'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
IncludeIsMainRegex: '(_test|_win|_linux|_mac|_ios|_osx|_null)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PenaltyBreakAssignment: 0
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 9999999
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
---
|
||||
Language: Cpp
|
||||
---
|
||||
Language: ObjC
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
---
|
||||
Language: Java
|
||||
BasedOnStyle: Google
|
||||
BreakAfterJavaFieldAnnotations: true
|
||||
...
|
5
dependencies/discord-rpc/.gitignore
vendored
Normal file
5
dependencies/discord-rpc/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/build*/
|
||||
/.vscode/
|
||||
/thirdparty/
|
||||
.vs/
|
||||
.DS_Store
|
47
dependencies/discord-rpc/.travis.yml
vendored
Normal file
47
dependencies/discord-rpc/.travis.yml
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
language: cpp
|
||||
|
||||
env:
|
||||
global:
|
||||
- CLANG_FORMAT_SUFFIX="-dummy" # don't use formatting on Travis, this is
|
||||
# needed not to use default 3.5 version
|
||||
# which is too old.
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-trusty-4.0
|
||||
packages:
|
||||
- clang-4.0
|
||||
- os: linux
|
||||
env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-trusty-5.0
|
||||
packages:
|
||||
- clang-5.0
|
||||
- os: osx
|
||||
osx_image: xcode9
|
||||
|
||||
# prevent Travis from overwriting our CXX variables
|
||||
before_install:
|
||||
- eval "${MATRIX_EVAL}"
|
||||
- echo $CXX
|
||||
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DCLANG_FORMAT_SUFFIX=$CLANG_FORMAT_SUFFIX -DWARNINGS_AS_ERRORS=On --config Release ..
|
||||
- cmake --build . -- -j2
|
42
dependencies/discord-rpc/CMakeLists.txt
vendored
Normal file
42
dependencies/discord-rpc/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
cmake_minimum_required (VERSION 3.2.0)
|
||||
project (DiscordRPC)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
option(BUILD_EXAMPLES "Build example apps" OFF)
|
||||
|
||||
# format
|
||||
file(GLOB_RECURSE ALL_SOURCE_FILES
|
||||
examples/*.cpp examples/*.h examples/*.c
|
||||
include/*.h
|
||||
src/*.cpp src/*.h src/*.c
|
||||
)
|
||||
|
||||
# thirdparty stuff
|
||||
execute_process(
|
||||
COMMAND mkdir ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
#find_file(RAPIDJSONTEST NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH)
|
||||
#if (NOT RAPIDJSONTEST)
|
||||
# message("no rapidjson, download")
|
||||
# set(RJ_TAR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/v1.1.0.tar.gz)
|
||||
# file(DOWNLOAD https://github.com/miloyip/rapidjson/archive/v1.1.0.tar.gz ${RJ_TAR_FILE})
|
||||
# execute_process(
|
||||
# COMMAND ${CMAKE_COMMAND} -E tar xzf ${RJ_TAR_FILE}
|
||||
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty
|
||||
# )
|
||||
# file(REMOVE ${RJ_TAR_FILE})
|
||||
#endif(NOT RAPIDJSONTEST)
|
||||
|
||||
#find_file(RAPIDJSON NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH)
|
||||
|
||||
#add_library(rapidjson STATIC IMPORTED ${RAPIDJSON})
|
||||
|
||||
# add subdirs
|
||||
|
||||
add_subdirectory(src)
|
||||
if (BUILD_EXAMPLES)
|
||||
add_subdirectory(examples/send-presence)
|
||||
endif(BUILD_EXAMPLES)
|
19
dependencies/discord-rpc/LICENSE
vendored
Normal file
19
dependencies/discord-rpc/LICENSE
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright 2017 Discord, Inc.
|
||||
|
||||
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.
|
158
dependencies/discord-rpc/README.md
vendored
Normal file
158
dependencies/discord-rpc/README.md
vendored
Normal file
|
@ -0,0 +1,158 @@
|
|||
# Discord RPC
|
||||
|
||||
## Deprecation Notice
|
||||
|
||||
This library has been deprecated in favor of Discord's GameSDK. [Learn more here](https://discordapp.com/developers/docs/game-sdk/sdk-starter-guide)
|
||||
|
||||
---
|
||||
|
||||
This is a library for interfacing your game with a locally running Discord desktop client. It's known to work on Windows, macOS, and Linux. You can use the lib directly if you like, or use it as a guide to writing your own if it doesn't suit your game as is. PRs/feedback welcome if you have an improvement everyone might want, or can describe how this doesn't meet your needs.
|
||||
|
||||
Included here are some quick demos that implement the very minimal subset to show current status, and
|
||||
have callbacks for where a more complete game would do more things (joining, spectating, etc).
|
||||
|
||||
## Documentation
|
||||
|
||||
The most up to date documentation for Rich Presence can always be found on our [developer site](https://discordapp.com/developers/docs/rich-presence/how-to)! If you're interested in rolling your own native implementation of Rich Presence via IPC sockets instead of using our SDK—hey, you've got free time, right?—check out the ["Hard Mode" documentation](https://github.com/discordapp/discord-rpc/blob/master/documentation/hard-mode.md).
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Zeroith, you should be set up to build things because you are a game developer, right?
|
||||
|
||||
First, head on over to the [Discord developers site](https://discordapp.com/developers/applications/me) and make yourself an app. Keep track of `Client ID` -- you'll need it here to pass to the init function.
|
||||
|
||||
### Unreal Engine 4 Setup
|
||||
|
||||
To use the Rich Presense plugin with Unreal Engine Projects:
|
||||
|
||||
1. Download the latest [release](https://github.com/discordapp/discord-rpc/releases) for each operating system you are targeting and the zipped source code
|
||||
2. In the source code zip, copy the UE plugin—`examples/unrealstatus/Plugins/discordrpc`—to your project's plugin directory
|
||||
3. At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create an `Include` folder and copy `discord_rpc.h` and `discord_register.h` to it from the zip
|
||||
4. Follow the steps below for each OS
|
||||
5. Build your UE4 project
|
||||
6. Launch the editor, and enable the Discord plugin.
|
||||
|
||||
#### Windows
|
||||
|
||||
- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Win64` folder
|
||||
- Copy `lib/discord-rpc.lib` and `bin/discord-rpc.dll` from `[RELEASE_ZIP]/win64-dynamic` to the `Win64` folder
|
||||
|
||||
#### Mac
|
||||
|
||||
- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Mac` folder
|
||||
- Copy `libdiscord-rpc.dylib` from `[RELEASE_ZIP]/osx-dynamic/lib` to the `Mac` folder
|
||||
|
||||
#### Linux
|
||||
|
||||
- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Linux` folder
|
||||
- Inside, create another folder `x86_64-unknown-linux-gnu`
|
||||
- Copy `libdiscord-rpc.so` from `[RELEASE_ZIP]/linux-dynamic/lib` to `Linux/x86_64-unknown-linux-gnu`
|
||||
|
||||
### Unity Setup
|
||||
|
||||
If you're a Unity developer looking to integrate Rich Presence into your game, follow this simple guide to get started towards success:
|
||||
|
||||
1. Download the DLLs for any platform that you need from [our releases](https://github.com/discordapp/discord-rpc/releases)
|
||||
2. In your Unity project, create a `Plugins` folder inside your `Assets` folder if you don't already have one
|
||||
3. Copy the file `DiscordRpc.cs` from [here](https://github.com/discordapp/discord-rpc/blob/master/examples/button-clicker/Assets/DiscordRpc.cs) into your `Assets` folder. This is basically your header file for the SDK
|
||||
|
||||
We've got our `Plugins` folder ready, so let's get platform-specific!
|
||||
|
||||
#### Windows
|
||||
|
||||
4. Create `x86` and `x86_64` folders inside `Assets/Plugins/`
|
||||
5. Copy `discord-rpc-win/win64-dynamic/bin/discord-rpc.dll` to `Assets/Plugins/x86_64/`
|
||||
6. Copy `discord-rpc-win/win32-dynamic/bin/discord-rpc.dll` to `Assets/Plugins/x86/`
|
||||
7. Click on both DLLs and make sure they are targetting the correct architectures in the Unity editor properties pane
|
||||
8. Done!
|
||||
|
||||
#### MacOS
|
||||
|
||||
4. Copy `discord-rpc-osx/osx-dynamic/lib/libdiscord-rpc.dylib` to `Assets/Plugins/`
|
||||
5. Rename `libdiscord-rpc.dylib` to `discord-rpc.bundle`
|
||||
6. Done!
|
||||
|
||||
#### Linux
|
||||
|
||||
4. Copy `discord-rpc-linux/linux-dynamic-lib/libdiscord-rpc.so` to `Assets/Plugins/`
|
||||
5. Done!
|
||||
|
||||
You're ready to roll! For code examples on how to interact with the SDK using the `DiscordRpc.cs` header file, check out [our example](https://github.com/discordapp/discord-rpc/blob/master/examples/button-clicker/Assets/DiscordController.cs)
|
||||
|
||||
### From package
|
||||
|
||||
Download a release package for your platform(s) -- they have subdirs with various prebuilt options, select the one you need add `/include` to your compile includes, `/lib` to your linker paths, and link with `discord-rpc`. For the dynamically linked builds, you'll need to ship the associated file along with your game.
|
||||
|
||||
### From repo
|
||||
|
||||
First-eth, you'll want `CMake`. There's a few different ways to install it on your system, and you should refer to [their website](https://cmake.org/install/). Many package managers provide ways of installing CMake as well.
|
||||
|
||||
To make sure it's installed correctly, type `cmake --version` into your flavor of terminal/cmd. If you get a response with a version number, you're good to go!
|
||||
|
||||
There's a [CMake](https://cmake.org/download/) file that should be able to generate the lib for you; Sometimes I use it like this:
|
||||
|
||||
```sh
|
||||
cd <path to discord-rpc>
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=<path to install discord-rpc to>
|
||||
cmake --build . --config Release --target install
|
||||
```
|
||||
|
||||
There is a wrapper build script `build.py` that runs `cmake` with a few different options.
|
||||
|
||||
Usually, I run `build.py` to get things started, then use the generated project files as I work on things. It does depend on `click` library, so do a quick `pip install click` to make sure you have it if you want to run `build.py`.
|
||||
|
||||
There are some CMake options you might care about:
|
||||
|
||||
| flag | default | does |
|
||||
| ---------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `ENABLE_IO_THREAD` | `ON` | When enabled, we start up a thread to do io processing, if disabled you should call `Discord_UpdateConnection` yourself. |
|
||||
| `USE_STATIC_CRT` | `OFF` | (Windows) Enable to statically link the CRT, avoiding requiring users install the redistributable package. (The prebuilt binaries enable this option) |
|
||||
| [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/v3.7/variable/BUILD_SHARED_LIBS.html) | `OFF` | Build library as a DLL |
|
||||
| `WARNINGS_AS_ERRORS` | `OFF` | When enabled, compiles with `-Werror` (on \*nix platforms). |
|
||||
|
||||
## Continuous Builds
|
||||
|
||||
Why do we have three of these? Three times the fun!
|
||||
|
||||
| CI | badge |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| TravisCI | [](https://travis-ci.org/discordapp/discord-rpc) |
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/crmarsh/discord-rpc) |
|
||||
| Buildkite (internal) | [](https://buildkite.com/discord/discord-rpc) |
|
||||
|
||||
## Sample: send-presence
|
||||
|
||||
This is a text adventure "game" that inits/deinits the connection to Discord, and sends a presence update on each command.
|
||||
|
||||
## Sample: button-clicker
|
||||
|
||||
This is a sample [Unity](https://unity3d.com/) project that wraps a DLL version of the library, and sends presence updates when you click on a button. Run `python build.py unity` in the root directory to build the correct library files and place them in their respective folders.
|
||||
|
||||
## Sample: unrealstatus
|
||||
|
||||
This is a sample [Unreal](https://www.unrealengine.com) project that wraps the DLL version of the library with an Unreal plugin, exposes a blueprint class for interacting with it, and uses that to make a very simple UI. Run `python build.py unreal` in the root directory to build the correct library files and place them in their respective folders.
|
||||
|
||||
## Wrappers and Implementations
|
||||
|
||||
Below is a table of unofficial, community-developed wrappers for and implementations of Rich Presence in various languages. If you would like to have yours added, please make a pull request adding your repository to the table. The repository should include:
|
||||
|
||||
- The code
|
||||
- A brief ReadMe of how to use it
|
||||
- A working example
|
||||
|
||||
###### Rich Presence Wrappers and Implementations
|
||||
|
||||
| Name | Language |
|
||||
| ------------------------------------------------------------------------- | --------------------------------- |
|
||||
| [Discord RPC C#](https://github.com/Lachee/discord-rpc-csharp) | C# |
|
||||
| [Discord RPC D](https://github.com/voidblaster/discord-rpc-d) | [D](https://dlang.org/) |
|
||||
| [discord-rpc.jar](https://github.com/Vatuu/discord-rpc 'Discord-RPC.jar') | Java |
|
||||
| [java-discord-rpc](https://github.com/MinnDevelopment/java-discord-rpc) | Java |
|
||||
| [Discord-IPC](https://github.com/jagrosh/DiscordIPC) | Java |
|
||||
| [Discord Rich Presence](https://npmjs.org/discord-rich-presence) | JavaScript |
|
||||
| [drpc4k](https://github.com/Bluexin/drpc4k) | [Kotlin](https://kotlinlang.org/) |
|
||||
| [lua-discordRPC](https://github.com/pfirsich/lua-discordRPC) | LuaJIT (FFI) |
|
||||
| [pypresence](https://github.com/qwertyquerty/pypresence) | [Python](https://python.org/) |
|
||||
| [SwordRPC](https://github.com/Azoy/SwordRPC) | [Swift](https://swift.org) |
|
17
dependencies/discord-rpc/appveyor.yml
vendored
Normal file
17
dependencies/discord-rpc/appveyor.yml
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
version: '{build}'
|
||||
install:
|
||||
- python -m pip install click
|
||||
|
||||
build_script:
|
||||
- mkdir examples\unrealstatus\Plugins\discordrpc\Binaries\ThirdParty\discordrpcLibrary\Win64
|
||||
- python build.py
|
||||
|
||||
artifacts:
|
||||
- path: builds\install\win32-dynamic
|
||||
name: win32-dynamic
|
||||
- path: builds\install\win32-static
|
||||
name: win32-static
|
||||
- path: builds\install\win64-dynamic
|
||||
name: win64-dynamic
|
||||
- path: builds\install\win64-static
|
||||
name: win64-static
|
304
dependencies/discord-rpc/build.py
vendored
Normal file
304
dependencies/discord-rpc/build.py
vendored
Normal file
|
@ -0,0 +1,304 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import shutil
|
||||
import zipfile
|
||||
from contextlib import contextmanager
|
||||
import click
|
||||
|
||||
|
||||
def get_platform():
|
||||
""" a name for the platform """
|
||||
if sys.platform.startswith('win'):
|
||||
return 'win'
|
||||
elif sys.platform == 'darwin':
|
||||
return 'osx'
|
||||
elif sys.platform.startswith('linux'):
|
||||
return 'linux'
|
||||
raise Exception('Unsupported platform ' + sys.platform)
|
||||
|
||||
|
||||
SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
# we use Buildkite which sets this env variable by default
|
||||
IS_BUILD_MACHINE = os.environ.get('CI', '') == 'true'
|
||||
PLATFORM = get_platform()
|
||||
INSTALL_ROOT = os.path.join(SCRIPT_PATH, 'builds', 'install')
|
||||
|
||||
|
||||
def get_signtool():
|
||||
""" get path to code signing tool """
|
||||
if PLATFORM == 'win':
|
||||
sdk_dir = 'c:\\Program Files (x86)\\Windows Kits\\10' # os.environ['WindowsSdkDir']
|
||||
return os.path.join(sdk_dir, 'bin', 'x86', 'signtool.exe')
|
||||
elif PLATFORM == 'osx':
|
||||
return '/usr/bin/codesign'
|
||||
|
||||
|
||||
@contextmanager
|
||||
def cd(new_dir):
|
||||
""" Temporarily change current directory """
|
||||
if new_dir:
|
||||
old_dir = os.getcwd()
|
||||
os.chdir(new_dir)
|
||||
yield
|
||||
if new_dir:
|
||||
os.chdir(old_dir)
|
||||
|
||||
|
||||
def mkdir_p(path):
|
||||
""" mkdir -p """
|
||||
if not os.path.isdir(path):
|
||||
click.secho('Making ' + path, fg='yellow')
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
@click.group(invoke_without_command=True)
|
||||
@click.pass_context
|
||||
@click.option('--clean', is_flag=True)
|
||||
def cli(ctx, clean):
|
||||
""" click wrapper for command line stuff """
|
||||
if ctx.invoked_subcommand is None:
|
||||
ctx.invoke(libs, clean=clean)
|
||||
if IS_BUILD_MACHINE:
|
||||
ctx.invoke(sign)
|
||||
ctx.invoke(archive)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.pass_context
|
||||
def unity(ctx):
|
||||
""" build just dynamic libs for use in unity project """
|
||||
ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True)
|
||||
BUILDS = []
|
||||
|
||||
click.echo('--- Copying libs and header into unity example')
|
||||
UNITY_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'button-clicker', 'Assets', 'Plugins')
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
LIBRARY_NAME = 'discord-rpc.dll'
|
||||
BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release')
|
||||
UNITY_64_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86_64')
|
||||
BUILDS.append({BUILD_64_BASE_PATH: UNITY_64_DLL_PATH})
|
||||
|
||||
BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release')
|
||||
UNITY_32_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86')
|
||||
BUILDS.append({BUILD_32_BASE_PATH: UNITY_32_DLL_PATH})
|
||||
|
||||
elif sys.platform == 'darwin':
|
||||
LIBRARY_NAME = 'discord-rpc.bundle'
|
||||
BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src')
|
||||
UNITY_DLL_PATH = UNITY_PROJECT_PATH
|
||||
os.rename(
|
||||
os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.dylib'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.bundle'))
|
||||
|
||||
BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH})
|
||||
|
||||
elif sys.platform.startswith('linux'):
|
||||
LIBRARY_NAME = 'discord-rpc.so'
|
||||
BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src')
|
||||
UNITY_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86')
|
||||
os.rename(os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.so'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.so'))
|
||||
|
||||
BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH})
|
||||
|
||||
else:
|
||||
raise Exception('Unsupported platform ' + sys.platform)
|
||||
|
||||
for build in BUILDS:
|
||||
for i in build:
|
||||
mkdir_p(build[i])
|
||||
shutil.copy(os.path.join(i, LIBRARY_NAME), build[i])
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.pass_context
|
||||
def unreal(ctx):
|
||||
""" build libs and copy them into the unreal project """
|
||||
ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True)
|
||||
BUILDS = []
|
||||
|
||||
click.echo('--- Copying libs and header into unreal example')
|
||||
UNREAL_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'unrealstatus', 'Plugins', 'discordrpc')
|
||||
UNREAL_INCLUDE_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Include')
|
||||
mkdir_p(UNREAL_INCLUDE_PATH)
|
||||
shutil.copy(os.path.join(SCRIPT_PATH, 'include', 'discord_rpc.h'), UNREAL_INCLUDE_PATH)
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
LIBRARY_NAME = 'discord-rpc.lib'
|
||||
BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release')
|
||||
UNREAL_64_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win64')
|
||||
BUILDS.append({BUILD_64_BASE_PATH: UNREAL_64_DLL_PATH})
|
||||
|
||||
BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release')
|
||||
UNREAL_32_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win32')
|
||||
BUILDS.append({BUILD_32_BASE_PATH: UNREAL_32_DLL_PATH})
|
||||
|
||||
elif sys.platform == 'darwin':
|
||||
LIBRARY_NAME = 'libdiscord-rpc.dylib'
|
||||
BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src')
|
||||
UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Mac')
|
||||
|
||||
BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH})
|
||||
|
||||
elif sys.platform.startswith('linux'):
|
||||
LIBRARY_NAME = 'libdiscord-rpc.so'
|
||||
BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src')
|
||||
UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Linux')
|
||||
|
||||
BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH})
|
||||
|
||||
else:
|
||||
raise Exception('Unsupported platform ' + sys.platform)
|
||||
|
||||
for build in BUILDS:
|
||||
for i in build:
|
||||
mkdir_p(build[i])
|
||||
shutil.copy(os.path.join(i, LIBRARY_NAME), build[i])
|
||||
|
||||
|
||||
def build_lib(build_name, generator, options, just_release):
|
||||
""" Create a dir under builds, run build and install in it """
|
||||
build_path = os.path.join(SCRIPT_PATH, 'builds', build_name)
|
||||
install_path = os.path.join(INSTALL_ROOT, build_name)
|
||||
mkdir_p(build_path)
|
||||
mkdir_p(install_path)
|
||||
with cd(build_path):
|
||||
initial_cmake = ['cmake', SCRIPT_PATH, '-DCMAKE_INSTALL_PREFIX=%s' % os.path.join('..', 'install', build_name)]
|
||||
if generator:
|
||||
initial_cmake.extend(['-G', generator])
|
||||
for key in options:
|
||||
val = options[key]
|
||||
if type(val) is bool:
|
||||
val = 'ON' if val else 'OFF'
|
||||
initial_cmake.append('-D%s=%s' % (key, val))
|
||||
click.echo('--- Building ' + build_name)
|
||||
subprocess.check_call(initial_cmake)
|
||||
if not just_release:
|
||||
subprocess.check_call(['cmake', '--build', '.', '--config', 'Debug'])
|
||||
subprocess.check_call(['cmake', '--build', '.', '--config', 'Release', '--target', 'install'])
|
||||
|
||||
|
||||
@cli.command()
|
||||
def archive():
|
||||
""" create zip of install dir """
|
||||
click.echo('--- Archiving')
|
||||
archive_file_path = os.path.join(SCRIPT_PATH, 'builds', 'discord-rpc-%s.zip' % get_platform())
|
||||
archive_file = zipfile.ZipFile(archive_file_path, 'w', zipfile.ZIP_DEFLATED)
|
||||
archive_src_base_path = INSTALL_ROOT
|
||||
archive_dst_base_path = 'discord-rpc'
|
||||
with cd(archive_src_base_path):
|
||||
for path, _, filenames in os.walk('.'):
|
||||
for fname in filenames:
|
||||
fpath = os.path.join(path, fname)
|
||||
dst_path = os.path.normpath(os.path.join(archive_dst_base_path, fpath))
|
||||
click.echo('Adding ' + dst_path)
|
||||
archive_file.write(fpath, dst_path)
|
||||
|
||||
|
||||
@cli.command()
|
||||
def sign():
|
||||
""" Do code signing within install directory using our cert """
|
||||
tool = get_signtool()
|
||||
signable_extensions = set()
|
||||
if PLATFORM == 'win':
|
||||
signable_extensions.add('.dll')
|
||||
sign_command_base = [
|
||||
tool,
|
||||
'sign',
|
||||
'/n',
|
||||
'Discord Inc.',
|
||||
'/a',
|
||||
'/tr',
|
||||
'http://timestamp.digicert.com/rfc3161',
|
||||
'/as',
|
||||
'/td',
|
||||
'sha256',
|
||||
'/fd',
|
||||
'sha256',
|
||||
]
|
||||
elif PLATFORM == 'osx':
|
||||
signable_extensions.add('.dylib')
|
||||
sign_command_base = [
|
||||
tool,
|
||||
'--keychain',
|
||||
os.path.expanduser('~/Library/Keychains/login.keychain'),
|
||||
'-vvvv',
|
||||
'--deep',
|
||||
'--force',
|
||||
'--sign',
|
||||
'Developer ID Application: Hammer & Chisel Inc. (53Q6R32WPB)',
|
||||
]
|
||||
else:
|
||||
click.secho('Not signing things on this platform yet', fg='red')
|
||||
return
|
||||
|
||||
click.echo('--- Signing')
|
||||
for path, _, filenames in os.walk(INSTALL_ROOT):
|
||||
for fname in filenames:
|
||||
ext = os.path.splitext(fname)[1]
|
||||
if ext not in signable_extensions:
|
||||
continue
|
||||
fpath = os.path.join(path, fname)
|
||||
click.echo('Sign ' + fpath)
|
||||
sign_command = sign_command_base + [fpath]
|
||||
subprocess.check_call(sign_command)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('--clean', is_flag=True)
|
||||
@click.option('--static', is_flag=True)
|
||||
@click.option('--shared', is_flag=True)
|
||||
@click.option('--skip_formatter', is_flag=True)
|
||||
@click.option('--just_release', is_flag=True)
|
||||
def libs(clean, static, shared, skip_formatter, just_release):
|
||||
""" Do all the builds for this platform """
|
||||
if clean:
|
||||
shutil.rmtree('builds', ignore_errors=True)
|
||||
|
||||
mkdir_p('builds')
|
||||
|
||||
if not (static or shared):
|
||||
static = True
|
||||
shared = True
|
||||
|
||||
static_options = {}
|
||||
dynamic_options = {
|
||||
'BUILD_SHARED_LIBS': True,
|
||||
'USE_STATIC_CRT': True,
|
||||
}
|
||||
|
||||
if skip_formatter or IS_BUILD_MACHINE:
|
||||
static_options['CLANG_FORMAT_SUFFIX'] = 'none'
|
||||
dynamic_options['CLANG_FORMAT_SUFFIX'] = 'none'
|
||||
|
||||
if IS_BUILD_MACHINE:
|
||||
just_release = True
|
||||
static_options['WARNINGS_AS_ERRORS'] = True
|
||||
dynamic_options['WARNINGS_AS_ERRORS'] = True
|
||||
|
||||
if PLATFORM == 'win':
|
||||
generator32 = 'Visual Studio 14 2015'
|
||||
generator64 = 'Visual Studio 14 2015 Win64'
|
||||
if static:
|
||||
build_lib('win32-static', generator32, static_options, just_release)
|
||||
build_lib('win64-static', generator64, static_options, just_release)
|
||||
if shared:
|
||||
build_lib('win32-dynamic', generator32, dynamic_options, just_release)
|
||||
build_lib('win64-dynamic', generator64, dynamic_options, just_release)
|
||||
elif PLATFORM == 'osx':
|
||||
if static:
|
||||
build_lib('osx-static', None, static_options, just_release)
|
||||
if shared:
|
||||
build_lib('osx-dynamic', None, dynamic_options, just_release)
|
||||
elif PLATFORM == 'linux':
|
||||
if static:
|
||||
build_lib('linux-static', None, static_options, just_release)
|
||||
if shared:
|
||||
build_lib('linux-dynamic', None, dynamic_options, just_release)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.chdir(SCRIPT_PATH)
|
||||
sys.exit(cli())
|
164
dependencies/discord-rpc/documentation/hard-mode.md
vendored
Normal file
164
dependencies/discord-rpc/documentation/hard-mode.md
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
# Hard Mode: Roll Your Own Client
|
||||
|
||||
Discord's Rich Presence feature is designed as an obfuscated addition to our existing [RPC infrastructure](https://discordapp.com/developers/docs/topics/rpc). The standalone library and header files make it easy for any dev to drop it into their game.
|
||||
|
||||
Our library communicates with Discord over the local Discord RPC socket. We've already done the work in connecting properly, handling disconnects and reconnects, and other RPC intracacies, but those who have done this implementation for our private alpha Voice and Chat SDK can simply make use of the new RPC commands and events to implement Rich Presence.
|
||||
|
||||
## Hark! A warning!
|
||||
|
||||
By committing to an RPC-only integration, you decide to forego the work our library and header file have done for you in the way of error handling, state storage, disconnecting and reconnecting, and other quality of life abstractions. While simply implementing the new RPC command and events will enable Rich Presence for your game, we highly suggest that you do your best to mimic the functionality of the SDK the most that you can. It ensure not only code quality on your part, but also an excellent experience on the part of your players.
|
||||
|
||||
## Application Protocol Registration
|
||||
|
||||
One thing that cannot be explicitly done over RPC is registering an application protocol for your game. If you choose to do an RPC-only implementation, you will have to register your application protocol yourself in the format of `discord-[your_app_id]://`. You can use `Discord_Register()` as a good(?) example of how to properly register an application protocol for use with Discord. For OSX and Linux it is probably simpler to handle the protocol registration as part of your install/packaging.
|
||||
|
||||
## New RPC Command
|
||||
|
||||
The new RPC command for Rich Presence is `SET_ACTIVITY`. The fields are similar to what is outlined in the SDK; we've combined similar fields into objects for the sake of less data on the wire.
|
||||
|
||||
The one major difference is the `party.size` field. It is an array with a size of two. The first element is the current party size, `partySize` from the main documentation. The second element is the maximum party size, `partyMax` from the main documentation.
|
||||
|
||||
Below is a full example of a `SET_ACTIVITY` command. Field restrictions like size are the same as outlined in the main documentation.
|
||||
|
||||
```
|
||||
{
|
||||
"cmd": "SET_ACTIVITY",
|
||||
"args": {
|
||||
"pid": 9999, // Your application's process id - required field
|
||||
"activity": {
|
||||
"state": "In a Group",
|
||||
"details": "Competitive | In a Match",
|
||||
"timestamps": {
|
||||
"start": time(nullptr),
|
||||
"end": time(nullptr) + ((60 * 5) + 23)
|
||||
},
|
||||
"assets": {
|
||||
"large_image": "numbani_map",
|
||||
"large_text": "Numbani",
|
||||
"small_image": "pharah_profile",
|
||||
"small_text": "Pharah"
|
||||
},
|
||||
"party": {
|
||||
"id": GameEngine.GetPartyId(),
|
||||
"size": [3, 6]
|
||||
},
|
||||
"secrets": {
|
||||
"join": "025ed05c71f639de8bfaa0d679d7c94b2fdce12f",
|
||||
"spectate": "e7eb30d2ee025ed05c71ea495f770b76454ee4e0",
|
||||
"match": "4b2fdce12f639de8bfa7e3591b71a0d679d7c93f"
|
||||
},
|
||||
"instance": true
|
||||
}
|
||||
},
|
||||
"nonce": "647d814a-4cf8-4fbb-948f-898abd24f55b"
|
||||
}
|
||||
```
|
||||
|
||||
## New RPC Events
|
||||
|
||||
The three new RPC events for Rich Presence power the ability to join and spectate your friends' games.
|
||||
|
||||
First is the `ACTIVITY_JOIN` event:
|
||||
|
||||
```json
|
||||
{
|
||||
"cmd": "DISPATCH",
|
||||
"data": {
|
||||
"secret": "025ed05c71f639de8bfaa0d679d7c94b2fdce12f"
|
||||
},
|
||||
"evt": "ACTIVITY_JOIN"
|
||||
}
|
||||
```
|
||||
|
||||
Second is the `ACTIVITY_SPECTATE` event:
|
||||
|
||||
```json
|
||||
{
|
||||
"cmd": "DISPATCH",
|
||||
"data": {
|
||||
"secret": "e7eb30d2ee025ed05c71ea495f770b76454ee4e0"
|
||||
},
|
||||
"evt": "ACTIVITY_SPECTATE"
|
||||
}
|
||||
```
|
||||
|
||||
And third is the `ACTIVITY_JOIN_REQUEST` event:
|
||||
|
||||
```json
|
||||
{
|
||||
"cmd": "DISPATCH",
|
||||
"data": {
|
||||
"user": {
|
||||
"id": "53908232506183680",
|
||||
"username": "Mason",
|
||||
"discriminator": "1337",
|
||||
"avatar": "a_bab14f271d565501444b2ca3be944b25"
|
||||
}
|
||||
},
|
||||
"evt": "ACTIVITY_JOIN_REQUEST"
|
||||
}
|
||||
```
|
||||
|
||||
In order to receive these events, you need to [subscribe](https://discordapp.com/developers/docs/topics/rpc#subscribe) to them like so:
|
||||
|
||||
```json
|
||||
{
|
||||
"nonce": "be9a6de3-31d0-4767-a8e9-4818c5690015",
|
||||
"evt": "ACTIVITY_JOIN",
|
||||
"cmd": "SUBSCRIBE"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"nonce": "ae9qdde3-31d0-8989-a8e9-dnakwy174he",
|
||||
"evt": "ACTIVITY_SPECTATE",
|
||||
"cmd": "SUBSCRIBE"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"nonce": "5dc0c062-98c6-47a0-8922-bbb52e9d6afa",
|
||||
"evt": "ACTIVITY_JOIN_REQUEST",
|
||||
"cmd": "SUBSCRIBE"
|
||||
}
|
||||
```
|
||||
|
||||
To unsubscribe from these events, resend with the command `UNSUBSCRIBE`
|
||||
|
||||
## Responding
|
||||
A discord user will request access to the game. If the ACTIVITY_JOIN_REQUEST has been subscribed too, the ACTIVITY_JOIN_REQUEST event will be sent to the host's game. Accept it with following model:
|
||||
```json
|
||||
{
|
||||
"nonce": "5dc0c062-98c6-47a0-8922-15aerg126",
|
||||
"cmd": "SEND_ACTIVITY_JOIN_INVITE",
|
||||
"args":
|
||||
{
|
||||
"user_id": "53908232506183680"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To reject the request, use `CLOSE_ACTIVITY_REQUEST`:
|
||||
```json
|
||||
{
|
||||
"nonce": "5dc0c062-98c6-47a0-8922-dasg256eafg",
|
||||
"cmd": "CLOSE_ACTIVITY_REQUEST",
|
||||
"args":
|
||||
{
|
||||
"user_id": "53908232506183680"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
Here are just some quick notes to help with some common troubleshooting problems.
|
||||
* IPC will echo back every command you send as a response. Use this as a lock-step feature to avoid flooding messages. Can be used to validate messages such as the Presence or Subscribes.
|
||||
* The pipe expects for frames to be written in a single byte array. You cannot do multiple `stream.Write(opcode);` `stream.Write(length);` as it will break the pipe. Instead create a buffer, write the data to the buffer, then send the entire buffer to the stream.
|
||||
* Discord can be on any pipe ranging from `discord-ipc-0` to `discord-ipc-9`. It is a good idea to try and connect to each one and keeping the first one you connect too. For multiple clients (eg Discord and Canary), you might want to add a feature to manually select the pipe so you can more easily debug the application.
|
||||
* All enums are `lower_snake_case`.
|
||||
* The opcode and length in the header are `Little Endian Unsigned Integers (32bits)`. In some languages, you must convert them as they can be architecture specific.
|
||||
* [Discord Rich Presence How-To](https://discordapp.com/developers/docs/rich-presence/how-to) contains a lot of the information this document doesn't. For example, it will tell you about the response payload.
|
||||
* In the documentation, DISCORD_REPLY_IGNORE is just implemented the same as DISCORD_REPLY_NO.
|
||||
* You can test the Join / Spectate feature by enabling them in your profile and whitelisting a test account. Use Canary to run 2 accounts on the same machine.
|
BIN
dependencies/discord-rpc/documentation/images/rp-dev-dashboard.png
vendored
Normal file
BIN
dependencies/discord-rpc/documentation/images/rp-dev-dashboard.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 318 KiB |
BIN
dependencies/discord-rpc/documentation/images/rp-profile-view.png
vendored
Normal file
BIN
dependencies/discord-rpc/documentation/images/rp-profile-view.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
BIN
dependencies/discord-rpc/documentation/images/rp-secret-example.png
vendored
Normal file
BIN
dependencies/discord-rpc/documentation/images/rp-secret-example.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
8
dependencies/discord-rpc/examples/button-clicker/.gitignore
vendored
Normal file
8
dependencies/discord-rpc/examples/button-clicker/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
/Library/
|
||||
/Temp/
|
||||
/obj/
|
||||
/Assets/Plugins/
|
||||
/Assets/Plugins.meta
|
||||
*.sln
|
||||
*.csproj
|
||||
*.userprefs
|
125
dependencies/discord-rpc/examples/button-clicker/Assets/DiscordController.cs
vendored
Normal file
125
dependencies/discord-rpc/examples/button-clicker/Assets/DiscordController.cs
vendored
Normal file
|
@ -0,0 +1,125 @@
|
|||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class DiscordJoinEvent : UnityEngine.Events.UnityEvent<string> { }
|
||||
|
||||
[System.Serializable]
|
||||
public class DiscordSpectateEvent : UnityEngine.Events.UnityEvent<string> { }
|
||||
|
||||
[System.Serializable]
|
||||
public class DiscordJoinRequestEvent : UnityEngine.Events.UnityEvent<DiscordRpc.DiscordUser> { }
|
||||
|
||||
public class DiscordController : MonoBehaviour
|
||||
{
|
||||
public DiscordRpc.RichPresence presence = new DiscordRpc.RichPresence();
|
||||
public string applicationId;
|
||||
public string optionalSteamId;
|
||||
public int clickCounter;
|
||||
public DiscordRpc.DiscordUser joinRequest;
|
||||
public UnityEngine.Events.UnityEvent onConnect;
|
||||
public UnityEngine.Events.UnityEvent onDisconnect;
|
||||
public UnityEngine.Events.UnityEvent hasResponded;
|
||||
public DiscordJoinEvent onJoin;
|
||||
public DiscordJoinEvent onSpectate;
|
||||
public DiscordJoinRequestEvent onJoinRequest;
|
||||
|
||||
DiscordRpc.EventHandlers handlers;
|
||||
|
||||
public void OnClick()
|
||||
{
|
||||
Debug.Log("Discord: on click!");
|
||||
clickCounter++;
|
||||
|
||||
presence.details = string.Format("Button clicked {0} times", clickCounter);
|
||||
presence.joinSecret = "aSecret";
|
||||
presence.partyId = "aPartyId";
|
||||
presence.partySize = 1;
|
||||
presence.partyMax = 3;
|
||||
presence.partyPrivacy = DiscordRpc.PartyPrivacy.Public;
|
||||
|
||||
DiscordRpc.UpdatePresence(presence);
|
||||
}
|
||||
|
||||
public void RequestRespondYes()
|
||||
{
|
||||
Debug.Log("Discord: responding yes to Ask to Join request");
|
||||
DiscordRpc.Respond(joinRequest.userId, DiscordRpc.Reply.Yes);
|
||||
hasResponded.Invoke();
|
||||
}
|
||||
|
||||
public void RequestRespondNo()
|
||||
{
|
||||
Debug.Log("Discord: responding no to Ask to Join request");
|
||||
DiscordRpc.Respond(joinRequest.userId, DiscordRpc.Reply.No);
|
||||
hasResponded.Invoke();
|
||||
}
|
||||
|
||||
public void ReadyCallback(ref DiscordRpc.DiscordUser connectedUser)
|
||||
{
|
||||
Debug.Log(string.Format("Discord: connected to {0}#{1}: {2}", connectedUser.username, connectedUser.discriminator, connectedUser.userId));
|
||||
onConnect.Invoke();
|
||||
}
|
||||
|
||||
public void DisconnectedCallback(int errorCode, string message)
|
||||
{
|
||||
Debug.Log(string.Format("Discord: disconnect {0}: {1}", errorCode, message));
|
||||
onDisconnect.Invoke();
|
||||
}
|
||||
|
||||
public void ErrorCallback(int errorCode, string message)
|
||||
{
|
||||
Debug.Log(string.Format("Discord: error {0}: {1}", errorCode, message));
|
||||
}
|
||||
|
||||
public void JoinCallback(string secret)
|
||||
{
|
||||
Debug.Log(string.Format("Discord: join ({0})", secret));
|
||||
onJoin.Invoke(secret);
|
||||
}
|
||||
|
||||
public void SpectateCallback(string secret)
|
||||
{
|
||||
Debug.Log(string.Format("Discord: spectate ({0})", secret));
|
||||
onSpectate.Invoke(secret);
|
||||
}
|
||||
|
||||
public void RequestCallback(ref DiscordRpc.DiscordUser request)
|
||||
{
|
||||
Debug.Log(string.Format("Discord: join request {0}#{1}: {2}", request.username, request.discriminator, request.userId));
|
||||
joinRequest = request;
|
||||
onJoinRequest.Invoke(request);
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
DiscordRpc.RunCallbacks();
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
Debug.Log("Discord: init");
|
||||
handlers = new DiscordRpc.EventHandlers();
|
||||
handlers.readyCallback += ReadyCallback;
|
||||
handlers.disconnectedCallback += DisconnectedCallback;
|
||||
handlers.errorCallback += ErrorCallback;
|
||||
handlers.joinCallback += JoinCallback;
|
||||
handlers.spectateCallback += SpectateCallback;
|
||||
handlers.requestCallback += RequestCallback;
|
||||
DiscordRpc.Initialize(applicationId, ref handlers, true, optionalSteamId);
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
Debug.Log("Discord: shutdown");
|
||||
DiscordRpc.Shutdown();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
12
dependencies/discord-rpc/examples/button-clicker/Assets/DiscordController.cs.meta
vendored
Normal file
12
dependencies/discord-rpc/examples/button-clicker/Assets/DiscordController.cs.meta
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 27f0a5f59ffffa84c86547736e2e730a
|
||||
timeCreated: 1501697692
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
231
dependencies/discord-rpc/examples/button-clicker/Assets/DiscordRpc.cs
vendored
Normal file
231
dependencies/discord-rpc/examples/button-clicker/Assets/DiscordRpc.cs
vendored
Normal file
|
@ -0,0 +1,231 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using AOT;
|
||||
|
||||
public class DiscordRpc
|
||||
{
|
||||
[MonoPInvokeCallback(typeof(OnReadyInfo))]
|
||||
public static void ReadyCallback(ref DiscordUser connectedUser) { Callbacks.readyCallback(ref connectedUser); }
|
||||
public delegate void OnReadyInfo(ref DiscordUser connectedUser);
|
||||
|
||||
[MonoPInvokeCallback(typeof(OnDisconnectedInfo))]
|
||||
public static void DisconnectedCallback(int errorCode, string message) { Callbacks.disconnectedCallback(errorCode, message); }
|
||||
public delegate void OnDisconnectedInfo(int errorCode, string message);
|
||||
|
||||
[MonoPInvokeCallback(typeof(OnErrorInfo))]
|
||||
public static void ErrorCallback(int errorCode, string message) { Callbacks.errorCallback(errorCode, message); }
|
||||
public delegate void OnErrorInfo(int errorCode, string message);
|
||||
|
||||
[MonoPInvokeCallback(typeof(OnJoinInfo))]
|
||||
public static void JoinCallback(string secret) { Callbacks.joinCallback(secret); }
|
||||
public delegate void OnJoinInfo(string secret);
|
||||
|
||||
[MonoPInvokeCallback(typeof(OnSpectateInfo))]
|
||||
public static void SpectateCallback(string secret) { Callbacks.spectateCallback(secret); }
|
||||
public delegate void OnSpectateInfo(string secret);
|
||||
|
||||
[MonoPInvokeCallback(typeof(OnRequestInfo))]
|
||||
public static void RequestCallback(ref DiscordUser request) { Callbacks.requestCallback(ref request); }
|
||||
public delegate void OnRequestInfo(ref DiscordUser request);
|
||||
|
||||
static EventHandlers Callbacks { get; set; }
|
||||
|
||||
public struct EventHandlers
|
||||
{
|
||||
public OnReadyInfo readyCallback;
|
||||
public OnDisconnectedInfo disconnectedCallback;
|
||||
public OnErrorInfo errorCallback;
|
||||
public OnJoinInfo joinCallback;
|
||||
public OnSpectateInfo spectateCallback;
|
||||
public OnRequestInfo requestCallback;
|
||||
}
|
||||
|
||||
[Serializable, StructLayout(LayoutKind.Sequential)]
|
||||
public struct RichPresenceStruct
|
||||
{
|
||||
public IntPtr state; /* max 128 bytes */
|
||||
public IntPtr details; /* max 128 bytes */
|
||||
public long startTimestamp;
|
||||
public long endTimestamp;
|
||||
public IntPtr largeImageKey; /* max 32 bytes */
|
||||
public IntPtr largeImageText; /* max 128 bytes */
|
||||
public IntPtr smallImageKey; /* max 32 bytes */
|
||||
public IntPtr smallImageText; /* max 128 bytes */
|
||||
public IntPtr partyId; /* max 128 bytes */
|
||||
public int partySize;
|
||||
public int partyMax;
|
||||
public int partyPrivacy;
|
||||
public IntPtr matchSecret; /* max 128 bytes */
|
||||
public IntPtr joinSecret; /* max 128 bytes */
|
||||
public IntPtr spectateSecret; /* max 128 bytes */
|
||||
public bool instance;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct DiscordUser
|
||||
{
|
||||
public string userId;
|
||||
public string username;
|
||||
public string discriminator;
|
||||
public string avatar;
|
||||
}
|
||||
|
||||
public enum Reply
|
||||
{
|
||||
No = 0,
|
||||
Yes = 1,
|
||||
Ignore = 2
|
||||
}
|
||||
|
||||
public enum PartyPrivacy
|
||||
{
|
||||
Private = 0,
|
||||
Public = 1
|
||||
}
|
||||
|
||||
public static void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId)
|
||||
{
|
||||
Callbacks = handlers;
|
||||
|
||||
EventHandlers staticEventHandlers = new EventHandlers();
|
||||
staticEventHandlers.readyCallback += DiscordRpc.ReadyCallback;
|
||||
staticEventHandlers.disconnectedCallback += DiscordRpc.DisconnectedCallback;
|
||||
staticEventHandlers.errorCallback += DiscordRpc.ErrorCallback;
|
||||
staticEventHandlers.joinCallback += DiscordRpc.JoinCallback;
|
||||
staticEventHandlers.spectateCallback += DiscordRpc.SpectateCallback;
|
||||
staticEventHandlers.requestCallback += DiscordRpc.RequestCallback;
|
||||
|
||||
InitializeInternal(applicationId, ref staticEventHandlers, autoRegister, optionalSteamId);
|
||||
}
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_Initialize", CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern void InitializeInternal(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId);
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_Shutdown", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void Shutdown();
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_RunCallbacks", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void RunCallbacks();
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_UpdatePresence", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void UpdatePresenceNative(ref RichPresenceStruct presence);
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_ClearPresence", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void ClearPresence();
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_Respond", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void Respond(string userId, Reply reply);
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_UpdateHandlers", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void UpdateHandlers(ref EventHandlers handlers);
|
||||
|
||||
public static void UpdatePresence(RichPresence presence)
|
||||
{
|
||||
var presencestruct = presence.GetStruct();
|
||||
UpdatePresenceNative(ref presencestruct);
|
||||
presence.FreeMem();
|
||||
}
|
||||
|
||||
public class RichPresence
|
||||
{
|
||||
private RichPresenceStruct _presence;
|
||||
private readonly List<IntPtr> _buffers = new List<IntPtr>(10);
|
||||
|
||||
public string state; /* max 128 bytes */
|
||||
public string details; /* max 128 bytes */
|
||||
public long startTimestamp;
|
||||
public long endTimestamp;
|
||||
public string largeImageKey; /* max 32 bytes */
|
||||
public string largeImageText; /* max 128 bytes */
|
||||
public string smallImageKey; /* max 32 bytes */
|
||||
public string smallImageText; /* max 128 bytes */
|
||||
public string partyId; /* max 128 bytes */
|
||||
public int partySize;
|
||||
public int partyMax;
|
||||
public PartyPrivacy partyPrivacy;
|
||||
public string matchSecret; /* max 128 bytes */
|
||||
public string joinSecret; /* max 128 bytes */
|
||||
public string spectateSecret; /* max 128 bytes */
|
||||
public bool instance;
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="RichPresenceStruct"/> reprensentation of this instance
|
||||
/// </summary>
|
||||
/// <returns><see cref="RichPresenceStruct"/> reprensentation of this instance</returns>
|
||||
internal RichPresenceStruct GetStruct()
|
||||
{
|
||||
if (_buffers.Count > 0)
|
||||
{
|
||||
FreeMem();
|
||||
}
|
||||
|
||||
_presence.state = StrToPtr(state);
|
||||
_presence.details = StrToPtr(details);
|
||||
_presence.startTimestamp = startTimestamp;
|
||||
_presence.endTimestamp = endTimestamp;
|
||||
_presence.largeImageKey = StrToPtr(largeImageKey);
|
||||
_presence.largeImageText = StrToPtr(largeImageText);
|
||||
_presence.smallImageKey = StrToPtr(smallImageKey);
|
||||
_presence.smallImageText = StrToPtr(smallImageText);
|
||||
_presence.partyId = StrToPtr(partyId);
|
||||
_presence.partySize = partySize;
|
||||
_presence.partyMax = partyMax;
|
||||
_presence.partyPrivacy = (int)partyPrivacy;
|
||||
_presence.matchSecret = StrToPtr(matchSecret);
|
||||
_presence.joinSecret = StrToPtr(joinSecret);
|
||||
_presence.spectateSecret = StrToPtr(spectateSecret);
|
||||
_presence.instance = instance;
|
||||
|
||||
return _presence;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a pointer to a representation of the given string with a size of maxbytes
|
||||
/// </summary>
|
||||
/// <param name="input">String to convert</param>
|
||||
/// <returns>Pointer to the UTF-8 representation of <see cref="input"/></returns>
|
||||
private IntPtr StrToPtr(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input)) return IntPtr.Zero;
|
||||
var convbytecnt = Encoding.UTF8.GetByteCount(input);
|
||||
var buffer = Marshal.AllocHGlobal(convbytecnt + 1);
|
||||
for (int i = 0; i < convbytecnt + 1; i++)
|
||||
{
|
||||
Marshal.WriteByte(buffer, i, 0);
|
||||
}
|
||||
_buffers.Add(buffer);
|
||||
Marshal.Copy(Encoding.UTF8.GetBytes(input), 0, buffer, convbytecnt);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert string to UTF-8 and add null termination
|
||||
/// </summary>
|
||||
/// <param name="toconv">string to convert</param>
|
||||
/// <returns>UTF-8 representation of <see cref="toconv"/> with added null termination</returns>
|
||||
private static string StrToUtf8NullTerm(string toconv)
|
||||
{
|
||||
var str = toconv.Trim();
|
||||
var bytes = Encoding.Default.GetBytes(str);
|
||||
if (bytes.Length > 0 && bytes[bytes.Length - 1] != 0)
|
||||
{
|
||||
str += "\0\0";
|
||||
}
|
||||
return Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free the allocated memory for conversion to <see cref="RichPresenceStruct"/>
|
||||
/// </summary>
|
||||
internal void FreeMem()
|
||||
{
|
||||
for (var i = _buffers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Marshal.FreeHGlobal(_buffers[i]);
|
||||
_buffers.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
dependencies/discord-rpc/examples/button-clicker/Assets/DiscordRpc.cs.meta
vendored
Normal file
12
dependencies/discord-rpc/examples/button-clicker/Assets/DiscordRpc.cs.meta
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b4474a677de9d80409e98c5393ec5b1e
|
||||
timeCreated: 1501697692
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
101
dependencies/discord-rpc/examples/button-clicker/Assets/Editor/BuildHelper.cs
vendored
Normal file
101
dependencies/discord-rpc/examples/button-clicker/Assets/Editor/BuildHelper.cs
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
using UnityEditor;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
[InitializeOnLoad]
|
||||
public class ScriptBatch
|
||||
{
|
||||
static ScriptBatch()
|
||||
{
|
||||
EnsureDLL();
|
||||
}
|
||||
|
||||
public static bool FileExists(string filename)
|
||||
{
|
||||
return new FileInfo(filename).Exists;
|
||||
}
|
||||
|
||||
public static bool RunRpcBuildScript()
|
||||
{
|
||||
UnityEngine.Debug.Log("Try to run build script");
|
||||
|
||||
Process proc = new Process();
|
||||
#if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
|
||||
proc.StartInfo.UseShellExecute = false;
|
||||
// brew installs cmake in /usr/local/bin, which Unity seems to strip from PATH?
|
||||
string newPath = proc.StartInfo.EnvironmentVariables["PATH"] + ":/usr/local/bin";
|
||||
proc.StartInfo.EnvironmentVariables["PATH"] = newPath;
|
||||
#endif
|
||||
proc.StartInfo.FileName = "python";
|
||||
proc.StartInfo.Arguments = "build.py unity";
|
||||
proc.StartInfo.WorkingDirectory = "../..";
|
||||
proc.Start();
|
||||
proc.WaitForExit();
|
||||
return proc.ExitCode == 0;
|
||||
}
|
||||
|
||||
public static void EnsureDLL()
|
||||
{
|
||||
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
|
||||
string[] dstDirs = { "Assets/Plugins", "Assets/Plugins/x86", "Assets/Plugins/x86_64" };
|
||||
string[] dstDlls = { "Assets/Plugins/x86/discord-rpc.dll", "Assets/Plugins/x86_64/discord-rpc.dll" };
|
||||
string[] srcDlls = { "../../builds/install/win64-dynamic/bin/discord-rpc.dll", "../../builds/install/win64-dynamic/bin/discord-rpc.dll" };
|
||||
#elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
|
||||
string[] dstDirs = { "Assets/Plugins" };
|
||||
string[] dstDlls = { "Assets/Plugins/discord-rpc.bundle" };
|
||||
string[] srcDlls = { "../../builds/install/osx-dynamic/lib/libdiscord-rpc.dylib" };
|
||||
#else
|
||||
string[] dstDirs = { "Assets/Plugins", "Assets/Plugins/x86", "Assets/Plugins/x86_64" };
|
||||
string[] dstDlls = { "Assets/Plugins/discord-rpc.so" };
|
||||
string[] srcDlls = { "../../builds/install/linux-dynamic/lib/libdiscord-rpc.so" };
|
||||
#endif
|
||||
|
||||
Debug.Assert(dstDlls.Length == srcDlls.Length);
|
||||
|
||||
bool exists = true;
|
||||
foreach (string fname in dstDlls)
|
||||
{
|
||||
if (!FileExists(fname))
|
||||
{
|
||||
exists = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
exists = true;
|
||||
foreach (string fname in srcDlls)
|
||||
{
|
||||
if (!FileExists(fname))
|
||||
{
|
||||
exists = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
if (!RunRpcBuildScript())
|
||||
{
|
||||
UnityEngine.Debug.LogError("Build failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the dirs exist
|
||||
foreach (string dirname in dstDirs)
|
||||
{
|
||||
Directory.CreateDirectory(dirname);
|
||||
}
|
||||
|
||||
// Copy dlls
|
||||
for (int i = 0; i < dstDlls.Length; ++i)
|
||||
{
|
||||
FileUtil.CopyFileOrDirectory(srcDlls[i], dstDlls[i]);
|
||||
}
|
||||
}
|
||||
}
|
13
dependencies/discord-rpc/examples/button-clicker/Assets/Editor/BuildHelper.cs.meta
vendored
Normal file
13
dependencies/discord-rpc/examples/button-clicker/Assets/Editor/BuildHelper.cs.meta
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e5aecc4633e5f594b85eaa39f49bb402
|
||||
timeCreated: 1512071254
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
1278
dependencies/discord-rpc/examples/button-clicker/Assets/main.unity
vendored
Normal file
1278
dependencies/discord-rpc/examples/button-clicker/Assets/main.unity
vendored
Normal file
File diff suppressed because it is too large
Load diff
8
dependencies/discord-rpc/examples/button-clicker/Assets/main.unity.meta
vendored
Normal file
8
dependencies/discord-rpc/examples/button-clicker/Assets/main.unity.meta
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3b03d21bb25fa494e8694cd6e4b6d769
|
||||
timeCreated: 1501696924
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
17
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/AudioManager.asset
vendored
Normal file
17
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/AudioManager.asset
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!11 &1
|
||||
AudioManager:
|
||||
m_ObjectHideFlags: 0
|
||||
m_Volume: 1
|
||||
Rolloff Scale: 1
|
||||
Doppler Factor: 1
|
||||
Default Speaker Mode: 2
|
||||
m_SampleRate: 0
|
||||
m_DSPBufferSize: 0
|
||||
m_VirtualVoiceCount: 512
|
||||
m_RealVoiceCount: 32
|
||||
m_SpatializerPlugin:
|
||||
m_AmbisonicDecoderPlugin:
|
||||
m_DisableAudio: 0
|
||||
m_VirtualizeEffects: 1
|
6
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/ClusterInputManager.asset
vendored
Normal file
6
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/ClusterInputManager.asset
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!236 &1
|
||||
ClusterInputManager:
|
||||
m_ObjectHideFlags: 0
|
||||
m_Inputs: []
|
20
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/DynamicsManager.asset
vendored
Normal file
20
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/DynamicsManager.asset
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!55 &1
|
||||
PhysicsManager:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 3
|
||||
m_Gravity: {x: 0, y: -9.81, z: 0}
|
||||
m_DefaultMaterial: {fileID: 0}
|
||||
m_BounceThreshold: 2
|
||||
m_SleepThreshold: 0.005
|
||||
m_DefaultContactOffset: 0.01
|
||||
m_DefaultSolverIterations: 6
|
||||
m_DefaultSolverVelocityIterations: 1
|
||||
m_QueriesHitBackfaces: 0
|
||||
m_QueriesHitTriggers: 1
|
||||
m_EnableAdaptiveForce: 0
|
||||
m_EnablePCM: 1
|
||||
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
m_AutoSimulation: 1
|
||||
m_AutoSyncTransforms: 1
|
10
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/EditorBuildSettings.asset
vendored
Normal file
10
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/EditorBuildSettings.asset
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1045 &1
|
||||
EditorBuildSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Scenes:
|
||||
- enabled: 1
|
||||
path: Assets/main.unity
|
||||
guid: 3b03d21bb25fa494e8694cd6e4b6d769
|
16
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/EditorSettings.asset
vendored
Normal file
16
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/EditorSettings.asset
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!159 &1
|
||||
EditorSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 4
|
||||
m_ExternalVersionControlSupport: Visible Meta Files
|
||||
m_SerializationMode: 2
|
||||
m_DefaultBehaviorMode: 1
|
||||
m_SpritePackerMode: 4
|
||||
m_SpritePackerPaddingPower: 1
|
||||
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd
|
||||
m_ProjectGenerationRootNamespace:
|
||||
m_UserGeneratedProjectSuffix:
|
||||
m_CollabEditorSettings:
|
||||
inProgressEnabled: 1
|
61
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/GraphicsSettings.asset
vendored
Normal file
61
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/GraphicsSettings.asset
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!30 &1
|
||||
GraphicsSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 12
|
||||
m_Deferred:
|
||||
m_Mode: 1
|
||||
m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_DeferredReflections:
|
||||
m_Mode: 1
|
||||
m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ScreenSpaceShadows:
|
||||
m_Mode: 1
|
||||
m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_LegacyDeferred:
|
||||
m_Mode: 1
|
||||
m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_DepthNormals:
|
||||
m_Mode: 1
|
||||
m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_MotionVectors:
|
||||
m_Mode: 1
|
||||
m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_LightHalo:
|
||||
m_Mode: 1
|
||||
m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_LensFlare:
|
||||
m_Mode: 1
|
||||
m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_AlwaysIncludedShaders:
|
||||
- {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
|
||||
- {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
|
||||
- {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
|
||||
- {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
|
||||
- {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
|
||||
- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_PreloadedShaders: []
|
||||
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
|
||||
type: 0}
|
||||
m_CustomRenderPipeline: {fileID: 0}
|
||||
m_TransparencySortMode: 0
|
||||
m_TransparencySortAxis: {x: 0, y: 0, z: 1}
|
||||
m_DefaultRenderingPath: 1
|
||||
m_DefaultMobileRenderingPath: 1
|
||||
m_TierSettings: []
|
||||
m_LightmapStripping: 0
|
||||
m_FogStripping: 0
|
||||
m_InstancingStripping: 0
|
||||
m_LightmapKeepPlain: 1
|
||||
m_LightmapKeepDirCombined: 1
|
||||
m_LightmapKeepDynamicPlain: 1
|
||||
m_LightmapKeepDynamicDirCombined: 1
|
||||
m_LightmapKeepShadowMask: 1
|
||||
m_LightmapKeepSubtractive: 1
|
||||
m_FogKeepLinear: 1
|
||||
m_FogKeepExp: 1
|
||||
m_FogKeepExp2: 1
|
||||
m_AlbedoSwatchInfos: []
|
||||
m_LightsUseLinearIntensity: 0
|
||||
m_LightsUseColorTemperature: 0
|
295
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/InputManager.asset
vendored
Normal file
295
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/InputManager.asset
vendored
Normal file
|
@ -0,0 +1,295 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!13 &1
|
||||
InputManager:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Axes:
|
||||
- serializedVersion: 3
|
||||
m_Name: Horizontal
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton: left
|
||||
positiveButton: right
|
||||
altNegativeButton: a
|
||||
altPositiveButton: d
|
||||
gravity: 3
|
||||
dead: 0.001
|
||||
sensitivity: 3
|
||||
snap: 1
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Vertical
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton: down
|
||||
positiveButton: up
|
||||
altNegativeButton: s
|
||||
altPositiveButton: w
|
||||
gravity: 3
|
||||
dead: 0.001
|
||||
sensitivity: 3
|
||||
snap: 1
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Fire1
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: left ctrl
|
||||
altNegativeButton:
|
||||
altPositiveButton: mouse 0
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Fire2
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: left alt
|
||||
altNegativeButton:
|
||||
altPositiveButton: mouse 1
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Fire3
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: left shift
|
||||
altNegativeButton:
|
||||
altPositiveButton: mouse 2
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Jump
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: space
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Mouse X
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton:
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 0
|
||||
dead: 0
|
||||
sensitivity: 0.1
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 1
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Mouse Y
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton:
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 0
|
||||
dead: 0
|
||||
sensitivity: 0.1
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 1
|
||||
axis: 1
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Mouse ScrollWheel
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton:
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 0
|
||||
dead: 0
|
||||
sensitivity: 0.1
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 1
|
||||
axis: 2
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Horizontal
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton:
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 0
|
||||
dead: 0.19
|
||||
sensitivity: 1
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 2
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Vertical
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton:
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 0
|
||||
dead: 0.19
|
||||
sensitivity: 1
|
||||
snap: 0
|
||||
invert: 1
|
||||
type: 2
|
||||
axis: 1
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Fire1
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: joystick button 0
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Fire2
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: joystick button 1
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Fire3
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: joystick button 2
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Jump
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: joystick button 3
|
||||
altNegativeButton:
|
||||
altPositiveButton:
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Submit
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: return
|
||||
altNegativeButton:
|
||||
altPositiveButton: joystick button 0
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Submit
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: enter
|
||||
altNegativeButton:
|
||||
altPositiveButton: space
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
||||
- serializedVersion: 3
|
||||
m_Name: Cancel
|
||||
descriptiveName:
|
||||
descriptiveNegativeName:
|
||||
negativeButton:
|
||||
positiveButton: escape
|
||||
altNegativeButton:
|
||||
altPositiveButton: joystick button 1
|
||||
gravity: 1000
|
||||
dead: 0.001
|
||||
sensitivity: 1000
|
||||
snap: 0
|
||||
invert: 0
|
||||
type: 0
|
||||
axis: 0
|
||||
joyNum: 0
|
89
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/NavMeshAreas.asset
vendored
Normal file
89
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/NavMeshAreas.asset
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!126 &1
|
||||
NavMeshProjectSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
areas:
|
||||
- name: Walkable
|
||||
cost: 1
|
||||
- name: Not Walkable
|
||||
cost: 1
|
||||
- name: Jump
|
||||
cost: 2
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
- name:
|
||||
cost: 1
|
||||
m_LastAgentTypeID: -887442657
|
||||
m_Settings:
|
||||
- serializedVersion: 2
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.75
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
m_SettingNames:
|
||||
- Humanoid
|
8
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/NetworkManager.asset
vendored
Normal file
8
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/NetworkManager.asset
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!149 &1
|
||||
NetworkManager:
|
||||
m_ObjectHideFlags: 0
|
||||
m_DebugLevel: 0
|
||||
m_Sendrate: 15
|
||||
m_AssetToPrefab: {}
|
37
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/Physics2DSettings.asset
vendored
Normal file
37
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/Physics2DSettings.asset
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!19 &1
|
||||
Physics2DSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 3
|
||||
m_Gravity: {x: 0, y: -9.81}
|
||||
m_DefaultMaterial: {fileID: 0}
|
||||
m_VelocityIterations: 8
|
||||
m_PositionIterations: 3
|
||||
m_VelocityThreshold: 1
|
||||
m_MaxLinearCorrection: 0.2
|
||||
m_MaxAngularCorrection: 8
|
||||
m_MaxTranslationSpeed: 100
|
||||
m_MaxRotationSpeed: 360
|
||||
m_BaumgarteScale: 0.2
|
||||
m_BaumgarteTimeOfImpactScale: 0.75
|
||||
m_TimeToSleep: 0.5
|
||||
m_LinearSleepTolerance: 0.01
|
||||
m_AngularSleepTolerance: 2
|
||||
m_DefaultContactOffset: 0.01
|
||||
m_AutoSimulation: 1
|
||||
m_QueriesHitTriggers: 1
|
||||
m_QueriesStartInColliders: 1
|
||||
m_ChangeStopsCallbacks: 0
|
||||
m_CallbacksOnDisable: 1
|
||||
m_AutoSyncTransforms: 1
|
||||
m_AlwaysShowColliders: 0
|
||||
m_ShowColliderSleep: 1
|
||||
m_ShowColliderContacts: 0
|
||||
m_ShowColliderAABB: 0
|
||||
m_ContactArrowScale: 0.2
|
||||
m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412}
|
||||
m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432}
|
||||
m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745}
|
||||
m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804}
|
||||
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
610
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/ProjectSettings.asset
vendored
Normal file
610
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/ProjectSettings.asset
vendored
Normal file
|
@ -0,0 +1,610 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!129 &1
|
||||
PlayerSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 13
|
||||
productGUID: 5eccc60d3e382a346a65f512d6b81b84
|
||||
AndroidProfiler: 0
|
||||
AndroidFilterTouchesWhenObscured: 0
|
||||
defaultScreenOrientation: 4
|
||||
targetDevice: 2
|
||||
useOnDemandResources: 0
|
||||
accelerometerFrequency: 60
|
||||
companyName: Discord Inc.
|
||||
productName: button-clicker
|
||||
defaultCursor: {fileID: 0}
|
||||
cursorHotspot: {x: 0, y: 0}
|
||||
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
|
||||
m_ShowUnitySplashScreen: 1
|
||||
m_ShowUnitySplashLogo: 1
|
||||
m_SplashScreenOverlayOpacity: 1
|
||||
m_SplashScreenAnimation: 1
|
||||
m_SplashScreenLogoStyle: 1
|
||||
m_SplashScreenDrawMode: 0
|
||||
m_SplashScreenBackgroundAnimationZoom: 1
|
||||
m_SplashScreenLogoAnimationZoom: 1
|
||||
m_SplashScreenBackgroundLandscapeAspect: 1
|
||||
m_SplashScreenBackgroundPortraitAspect: 1
|
||||
m_SplashScreenBackgroundLandscapeUvs:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
m_SplashScreenBackgroundPortraitUvs:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
m_SplashScreenLogos: []
|
||||
m_VirtualRealitySplashScreen: {fileID: 0}
|
||||
m_HolographicTrackingLossScreen: {fileID: 0}
|
||||
defaultScreenWidth: 1024
|
||||
defaultScreenHeight: 768
|
||||
defaultScreenWidthWeb: 960
|
||||
defaultScreenHeightWeb: 600
|
||||
m_StereoRenderingPath: 0
|
||||
m_ActiveColorSpace: 0
|
||||
m_MTRendering: 1
|
||||
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
|
||||
iosShowActivityIndicatorOnLoading: -1
|
||||
androidShowActivityIndicatorOnLoading: -1
|
||||
tizenShowActivityIndicatorOnLoading: -1
|
||||
iosAppInBackgroundBehavior: 0
|
||||
displayResolutionDialog: 1
|
||||
iosAllowHTTPDownload: 1
|
||||
allowedAutorotateToPortrait: 1
|
||||
allowedAutorotateToPortraitUpsideDown: 1
|
||||
allowedAutorotateToLandscapeRight: 1
|
||||
allowedAutorotateToLandscapeLeft: 1
|
||||
useOSAutorotation: 1
|
||||
use32BitDisplayBuffer: 1
|
||||
disableDepthAndStencilBuffers: 0
|
||||
androidBlitType: 0
|
||||
defaultIsFullScreen: 1
|
||||
defaultIsNativeResolution: 1
|
||||
macRetinaSupport: 1
|
||||
runInBackground: 0
|
||||
captureSingleScreen: 0
|
||||
muteOtherAudioSources: 0
|
||||
Prepare IOS For Recording: 0
|
||||
Force IOS Speakers When Recording: 0
|
||||
submitAnalytics: 1
|
||||
usePlayerLog: 1
|
||||
bakeCollisionMeshes: 0
|
||||
forceSingleInstance: 0
|
||||
resizableWindow: 0
|
||||
useMacAppStoreValidation: 0
|
||||
macAppStoreCategory: public.app-category.games
|
||||
gpuSkinning: 0
|
||||
graphicsJobs: 0
|
||||
xboxPIXTextureCapture: 0
|
||||
xboxEnableAvatar: 0
|
||||
xboxEnableKinect: 0
|
||||
xboxEnableKinectAutoTracking: 0
|
||||
xboxEnableFitness: 0
|
||||
visibleInBackground: 1
|
||||
allowFullscreenSwitch: 1
|
||||
graphicsJobMode: 0
|
||||
macFullscreenMode: 2
|
||||
d3d9FullscreenMode: 1
|
||||
d3d11FullscreenMode: 1
|
||||
xboxSpeechDB: 0
|
||||
xboxEnableHeadOrientation: 0
|
||||
xboxEnableGuest: 0
|
||||
xboxEnablePIXSampling: 0
|
||||
metalFramebufferOnly: 0
|
||||
n3dsDisableStereoscopicView: 0
|
||||
n3dsEnableSharedListOpt: 1
|
||||
n3dsEnableVSync: 0
|
||||
ignoreAlphaClear: 0
|
||||
xboxOneResolution: 0
|
||||
xboxOneMonoLoggingLevel: 0
|
||||
xboxOneLoggingLevel: 1
|
||||
xboxOneDisableEsram: 0
|
||||
xboxOnePresentImmediateThreshold: 0
|
||||
videoMemoryForVertexBuffers: 0
|
||||
psp2PowerMode: 0
|
||||
psp2AcquireBGM: 1
|
||||
wiiUTVResolution: 0
|
||||
wiiUGamePadMSAA: 1
|
||||
wiiUSupportsNunchuk: 0
|
||||
wiiUSupportsClassicController: 0
|
||||
wiiUSupportsBalanceBoard: 0
|
||||
wiiUSupportsMotionPlus: 0
|
||||
wiiUSupportsProController: 0
|
||||
wiiUAllowScreenCapture: 1
|
||||
wiiUControllerCount: 0
|
||||
m_SupportedAspectRatios:
|
||||
4:3: 1
|
||||
5:4: 1
|
||||
16:10: 1
|
||||
16:9: 1
|
||||
Others: 1
|
||||
bundleVersion: 1.0
|
||||
preloadedAssets: []
|
||||
metroInputSource: 0
|
||||
m_HolographicPauseOnTrackingLoss: 1
|
||||
xboxOneDisableKinectGpuReservation: 0
|
||||
xboxOneEnable7thCore: 0
|
||||
vrSettings:
|
||||
cardboard:
|
||||
depthFormat: 0
|
||||
enableTransitionView: 0
|
||||
daydream:
|
||||
depthFormat: 0
|
||||
useSustainedPerformanceMode: 0
|
||||
enableVideoLayer: 0
|
||||
useProtectedVideoMemory: 0
|
||||
hololens:
|
||||
depthFormat: 1
|
||||
protectGraphicsMemory: 0
|
||||
useHDRDisplay: 0
|
||||
m_ColorGamuts: 00000000
|
||||
targetPixelDensity: 0
|
||||
resolutionScalingMode: 0
|
||||
androidSupportedAspectRatio: 1
|
||||
androidMaxAspectRatio: 2.1
|
||||
applicationIdentifier: {}
|
||||
buildNumber: {}
|
||||
AndroidBundleVersionCode: 1
|
||||
AndroidMinSdkVersion: 16
|
||||
AndroidTargetSdkVersion: 0
|
||||
AndroidPreferredInstallLocation: 1
|
||||
aotOptions:
|
||||
stripEngineCode: 1
|
||||
iPhoneStrippingLevel: 0
|
||||
iPhoneScriptCallOptimization: 0
|
||||
ForceInternetPermission: 0
|
||||
ForceSDCardPermission: 0
|
||||
CreateWallpaper: 0
|
||||
APKExpansionFiles: 0
|
||||
keepLoadedShadersAlive: 0
|
||||
StripUnusedMeshComponents: 0
|
||||
VertexChannelCompressionMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 238
|
||||
iPhoneSdkVersion: 988
|
||||
iOSTargetOSVersionString: 7.0
|
||||
tvOSSdkVersion: 0
|
||||
tvOSRequireExtendedGameController: 0
|
||||
tvOSTargetOSVersionString: 9.0
|
||||
uIPrerenderedIcon: 0
|
||||
uIRequiresPersistentWiFi: 0
|
||||
uIRequiresFullScreen: 1
|
||||
uIStatusBarHidden: 1
|
||||
uIExitOnSuspend: 0
|
||||
uIStatusBarStyle: 0
|
||||
iPhoneSplashScreen: {fileID: 0}
|
||||
iPhoneHighResSplashScreen: {fileID: 0}
|
||||
iPhoneTallHighResSplashScreen: {fileID: 0}
|
||||
iPhone47inSplashScreen: {fileID: 0}
|
||||
iPhone55inPortraitSplashScreen: {fileID: 0}
|
||||
iPhone55inLandscapeSplashScreen: {fileID: 0}
|
||||
iPadPortraitSplashScreen: {fileID: 0}
|
||||
iPadHighResPortraitSplashScreen: {fileID: 0}
|
||||
iPadLandscapeSplashScreen: {fileID: 0}
|
||||
iPadHighResLandscapeSplashScreen: {fileID: 0}
|
||||
appleTVSplashScreen: {fileID: 0}
|
||||
tvOSSmallIconLayers: []
|
||||
tvOSLargeIconLayers: []
|
||||
tvOSTopShelfImageLayers: []
|
||||
tvOSTopShelfImageWideLayers: []
|
||||
iOSLaunchScreenType: 0
|
||||
iOSLaunchScreenPortrait: {fileID: 0}
|
||||
iOSLaunchScreenLandscape: {fileID: 0}
|
||||
iOSLaunchScreenBackgroundColor:
|
||||
serializedVersion: 2
|
||||
rgba: 0
|
||||
iOSLaunchScreenFillPct: 100
|
||||
iOSLaunchScreenSize: 100
|
||||
iOSLaunchScreenCustomXibPath:
|
||||
iOSLaunchScreeniPadType: 0
|
||||
iOSLaunchScreeniPadImage: {fileID: 0}
|
||||
iOSLaunchScreeniPadBackgroundColor:
|
||||
serializedVersion: 2
|
||||
rgba: 0
|
||||
iOSLaunchScreeniPadFillPct: 100
|
||||
iOSLaunchScreeniPadSize: 100
|
||||
iOSLaunchScreeniPadCustomXibPath:
|
||||
iOSDeviceRequirements: []
|
||||
iOSURLSchemes: []
|
||||
iOSBackgroundModes: 0
|
||||
iOSMetalForceHardShadows: 0
|
||||
metalEditorSupport: 1
|
||||
metalAPIValidation: 1
|
||||
iOSRenderExtraFrameOnPause: 0
|
||||
appleDeveloperTeamID:
|
||||
iOSManualSigningProvisioningProfileID:
|
||||
tvOSManualSigningProvisioningProfileID:
|
||||
appleEnableAutomaticSigning: 0
|
||||
AndroidTargetDevice: 0
|
||||
AndroidSplashScreenScale: 0
|
||||
androidSplashScreen: {fileID: 0}
|
||||
AndroidKeystoreName:
|
||||
AndroidKeyaliasName:
|
||||
AndroidTVCompatibility: 1
|
||||
AndroidIsGame: 1
|
||||
AndroidEnableTango: 0
|
||||
androidEnableBanner: 1
|
||||
androidUseLowAccuracyLocation: 0
|
||||
m_AndroidBanners:
|
||||
- width: 320
|
||||
height: 180
|
||||
banner: {fileID: 0}
|
||||
androidGamepadSupportLevel: 0
|
||||
resolutionDialogBanner: {fileID: 0}
|
||||
m_BuildTargetIcons: []
|
||||
m_BuildTargetBatching: []
|
||||
m_BuildTargetGraphicsAPIs: []
|
||||
m_BuildTargetVRSettings: []
|
||||
m_BuildTargetEnableVuforiaSettings: []
|
||||
openGLRequireES31: 0
|
||||
openGLRequireES31AEP: 0
|
||||
m_TemplateCustomTags: {}
|
||||
mobileMTRendering:
|
||||
Android: 1
|
||||
iPhone: 1
|
||||
tvOS: 1
|
||||
wiiUTitleID: 0005000011000000
|
||||
wiiUGroupID: 00010000
|
||||
wiiUCommonSaveSize: 4096
|
||||
wiiUAccountSaveSize: 2048
|
||||
wiiUOlvAccessKey: 0
|
||||
wiiUTinCode: 0
|
||||
wiiUJoinGameId: 0
|
||||
wiiUJoinGameModeMask: 0000000000000000
|
||||
wiiUCommonBossSize: 0
|
||||
wiiUAccountBossSize: 0
|
||||
wiiUAddOnUniqueIDs: []
|
||||
wiiUMainThreadStackSize: 3072
|
||||
wiiULoaderThreadStackSize: 1024
|
||||
wiiUSystemHeapSize: 128
|
||||
wiiUTVStartupScreen: {fileID: 0}
|
||||
wiiUGamePadStartupScreen: {fileID: 0}
|
||||
wiiUDrcBufferDisabled: 0
|
||||
wiiUProfilerLibPath:
|
||||
playModeTestRunnerEnabled: 0
|
||||
actionOnDotNetUnhandledException: 1
|
||||
enableInternalProfiler: 0
|
||||
logObjCUncaughtExceptions: 1
|
||||
enableCrashReportAPI: 0
|
||||
cameraUsageDescription:
|
||||
locationUsageDescription:
|
||||
microphoneUsageDescription:
|
||||
switchNetLibKey:
|
||||
switchSocketMemoryPoolSize: 6144
|
||||
switchSocketAllocatorPoolSize: 128
|
||||
switchSocketConcurrencyLimit: 14
|
||||
switchScreenResolutionBehavior: 2
|
||||
switchUseCPUProfiler: 0
|
||||
switchApplicationID: 0x01004b9000490000
|
||||
switchNSODependencies:
|
||||
switchTitleNames_0:
|
||||
switchTitleNames_1:
|
||||
switchTitleNames_2:
|
||||
switchTitleNames_3:
|
||||
switchTitleNames_4:
|
||||
switchTitleNames_5:
|
||||
switchTitleNames_6:
|
||||
switchTitleNames_7:
|
||||
switchTitleNames_8:
|
||||
switchTitleNames_9:
|
||||
switchTitleNames_10:
|
||||
switchTitleNames_11:
|
||||
switchPublisherNames_0:
|
||||
switchPublisherNames_1:
|
||||
switchPublisherNames_2:
|
||||
switchPublisherNames_3:
|
||||
switchPublisherNames_4:
|
||||
switchPublisherNames_5:
|
||||
switchPublisherNames_6:
|
||||
switchPublisherNames_7:
|
||||
switchPublisherNames_8:
|
||||
switchPublisherNames_9:
|
||||
switchPublisherNames_10:
|
||||
switchPublisherNames_11:
|
||||
switchIcons_0: {fileID: 0}
|
||||
switchIcons_1: {fileID: 0}
|
||||
switchIcons_2: {fileID: 0}
|
||||
switchIcons_3: {fileID: 0}
|
||||
switchIcons_4: {fileID: 0}
|
||||
switchIcons_5: {fileID: 0}
|
||||
switchIcons_6: {fileID: 0}
|
||||
switchIcons_7: {fileID: 0}
|
||||
switchIcons_8: {fileID: 0}
|
||||
switchIcons_9: {fileID: 0}
|
||||
switchIcons_10: {fileID: 0}
|
||||
switchIcons_11: {fileID: 0}
|
||||
switchSmallIcons_0: {fileID: 0}
|
||||
switchSmallIcons_1: {fileID: 0}
|
||||
switchSmallIcons_2: {fileID: 0}
|
||||
switchSmallIcons_3: {fileID: 0}
|
||||
switchSmallIcons_4: {fileID: 0}
|
||||
switchSmallIcons_5: {fileID: 0}
|
||||
switchSmallIcons_6: {fileID: 0}
|
||||
switchSmallIcons_7: {fileID: 0}
|
||||
switchSmallIcons_8: {fileID: 0}
|
||||
switchSmallIcons_9: {fileID: 0}
|
||||
switchSmallIcons_10: {fileID: 0}
|
||||
switchSmallIcons_11: {fileID: 0}
|
||||
switchManualHTML:
|
||||
switchAccessibleURLs:
|
||||
switchLegalInformation:
|
||||
switchMainThreadStackSize: 1048576
|
||||
switchPresenceGroupId: 0x01004b9000490000
|
||||
switchLogoHandling: 0
|
||||
switchReleaseVersion: 0
|
||||
switchDisplayVersion: 1.0.0
|
||||
switchStartupUserAccount: 0
|
||||
switchTouchScreenUsage: 0
|
||||
switchSupportedLanguagesMask: 0
|
||||
switchLogoType: 0
|
||||
switchApplicationErrorCodeCategory:
|
||||
switchUserAccountSaveDataSize: 0
|
||||
switchUserAccountSaveDataJournalSize: 0
|
||||
switchApplicationAttribute: 0
|
||||
switchCardSpecSize: 4
|
||||
switchCardSpecClock: 25
|
||||
switchRatingsMask: 0
|
||||
switchRatingsInt_0: 0
|
||||
switchRatingsInt_1: 0
|
||||
switchRatingsInt_2: 0
|
||||
switchRatingsInt_3: 0
|
||||
switchRatingsInt_4: 0
|
||||
switchRatingsInt_5: 0
|
||||
switchRatingsInt_6: 0
|
||||
switchRatingsInt_7: 0
|
||||
switchRatingsInt_8: 0
|
||||
switchRatingsInt_9: 0
|
||||
switchRatingsInt_10: 0
|
||||
switchRatingsInt_11: 0
|
||||
switchLocalCommunicationIds_0: 0x01004b9000490000
|
||||
switchLocalCommunicationIds_1:
|
||||
switchLocalCommunicationIds_2:
|
||||
switchLocalCommunicationIds_3:
|
||||
switchLocalCommunicationIds_4:
|
||||
switchLocalCommunicationIds_5:
|
||||
switchLocalCommunicationIds_6:
|
||||
switchLocalCommunicationIds_7:
|
||||
switchParentalControl: 0
|
||||
switchAllowsScreenshot: 1
|
||||
switchDataLossConfirmation: 0
|
||||
switchSupportedNpadStyles: 3
|
||||
switchSocketConfigEnabled: 0
|
||||
switchTcpInitialSendBufferSize: 32
|
||||
switchTcpInitialReceiveBufferSize: 64
|
||||
switchTcpAutoSendBufferSizeMax: 256
|
||||
switchTcpAutoReceiveBufferSizeMax: 256
|
||||
switchUdpSendBufferSize: 9
|
||||
switchUdpReceiveBufferSize: 42
|
||||
switchSocketBufferEfficiency: 4
|
||||
switchSocketInitializeEnabled: 1
|
||||
switchNetworkInterfaceManagerInitializeEnabled: 1
|
||||
switchPlayerConnectionEnabled: 1
|
||||
ps4NPAgeRating: 12
|
||||
ps4NPTitleSecret:
|
||||
ps4NPTrophyPackPath:
|
||||
ps4ParentalLevel: 11
|
||||
ps4ContentID: ED1633-NPXX51362_00-0000000000000000
|
||||
ps4Category: 0
|
||||
ps4MasterVersion: 01.00
|
||||
ps4AppVersion: 01.00
|
||||
ps4AppType: 0
|
||||
ps4ParamSfxPath:
|
||||
ps4VideoOutPixelFormat: 0
|
||||
ps4VideoOutInitialWidth: 1920
|
||||
ps4VideoOutBaseModeInitialWidth: 1920
|
||||
ps4VideoOutReprojectionRate: 120
|
||||
ps4PronunciationXMLPath:
|
||||
ps4PronunciationSIGPath:
|
||||
ps4BackgroundImagePath:
|
||||
ps4StartupImagePath:
|
||||
ps4SaveDataImagePath:
|
||||
ps4SdkOverride:
|
||||
ps4BGMPath:
|
||||
ps4ShareFilePath:
|
||||
ps4ShareOverlayImagePath:
|
||||
ps4PrivacyGuardImagePath:
|
||||
ps4NPtitleDatPath:
|
||||
ps4RemotePlayKeyAssignment: -1
|
||||
ps4RemotePlayKeyMappingDir:
|
||||
ps4PlayTogetherPlayerCount: 0
|
||||
ps4EnterButtonAssignment: 1
|
||||
ps4ApplicationParam1: 0
|
||||
ps4ApplicationParam2: 0
|
||||
ps4ApplicationParam3: 0
|
||||
ps4ApplicationParam4: 0
|
||||
ps4DownloadDataSize: 0
|
||||
ps4GarlicHeapSize: 2048
|
||||
ps4ProGarlicHeapSize: 2560
|
||||
ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ
|
||||
ps4pnSessions: 1
|
||||
ps4pnPresence: 1
|
||||
ps4pnFriends: 1
|
||||
ps4pnGameCustomData: 1
|
||||
playerPrefsSupport: 0
|
||||
restrictedAudioUsageRights: 0
|
||||
ps4UseResolutionFallback: 0
|
||||
ps4ReprojectionSupport: 0
|
||||
ps4UseAudio3dBackend: 0
|
||||
ps4SocialScreenEnabled: 0
|
||||
ps4ScriptOptimizationLevel: 0
|
||||
ps4Audio3dVirtualSpeakerCount: 14
|
||||
ps4attribCpuUsage: 0
|
||||
ps4PatchPkgPath:
|
||||
ps4PatchLatestPkgPath:
|
||||
ps4PatchChangeinfoPath:
|
||||
ps4PatchDayOne: 0
|
||||
ps4attribUserManagement: 0
|
||||
ps4attribMoveSupport: 0
|
||||
ps4attrib3DSupport: 0
|
||||
ps4attribShareSupport: 0
|
||||
ps4attribExclusiveVR: 0
|
||||
ps4disableAutoHideSplash: 0
|
||||
ps4videoRecordingFeaturesUsed: 0
|
||||
ps4contentSearchFeaturesUsed: 0
|
||||
ps4attribEyeToEyeDistanceSettingVR: 0
|
||||
ps4IncludedModules: []
|
||||
monoEnv:
|
||||
psp2Splashimage: {fileID: 0}
|
||||
psp2NPTrophyPackPath:
|
||||
psp2NPSupportGBMorGJP: 0
|
||||
psp2NPAgeRating: 12
|
||||
psp2NPTitleDatPath:
|
||||
psp2NPCommsID:
|
||||
psp2NPCommunicationsID:
|
||||
psp2NPCommsPassphrase:
|
||||
psp2NPCommsSig:
|
||||
psp2ParamSfxPath:
|
||||
psp2ManualPath:
|
||||
psp2LiveAreaGatePath:
|
||||
psp2LiveAreaBackroundPath:
|
||||
psp2LiveAreaPath:
|
||||
psp2LiveAreaTrialPath:
|
||||
psp2PatchChangeInfoPath:
|
||||
psp2PatchOriginalPackage:
|
||||
psp2PackagePassword: F69AzBlax3CF3EDNhm3soLBPh71Yexui
|
||||
psp2KeystoneFile:
|
||||
psp2MemoryExpansionMode: 0
|
||||
psp2DRMType: 0
|
||||
psp2StorageType: 0
|
||||
psp2MediaCapacity: 0
|
||||
psp2DLCConfigPath:
|
||||
psp2ThumbnailPath:
|
||||
psp2BackgroundPath:
|
||||
psp2SoundPath:
|
||||
psp2TrophyCommId:
|
||||
psp2TrophyPackagePath:
|
||||
psp2PackagedResourcesPath:
|
||||
psp2SaveDataQuota: 10240
|
||||
psp2ParentalLevel: 1
|
||||
psp2ShortTitle: Not Set
|
||||
psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF
|
||||
psp2Category: 0
|
||||
psp2MasterVersion: 01.00
|
||||
psp2AppVersion: 01.00
|
||||
psp2TVBootMode: 0
|
||||
psp2EnterButtonAssignment: 2
|
||||
psp2TVDisableEmu: 0
|
||||
psp2AllowTwitterDialog: 1
|
||||
psp2Upgradable: 0
|
||||
psp2HealthWarning: 0
|
||||
psp2UseLibLocation: 0
|
||||
psp2InfoBarOnStartup: 0
|
||||
psp2InfoBarColor: 0
|
||||
psp2ScriptOptimizationLevel: 0
|
||||
psmSplashimage: {fileID: 0}
|
||||
splashScreenBackgroundSourceLandscape: {fileID: 0}
|
||||
splashScreenBackgroundSourcePortrait: {fileID: 0}
|
||||
spritePackerPolicy:
|
||||
webGLMemorySize: 256
|
||||
webGLExceptionSupport: 1
|
||||
webGLNameFilesAsHashes: 0
|
||||
webGLDataCaching: 0
|
||||
webGLDebugSymbols: 0
|
||||
webGLEmscriptenArgs:
|
||||
webGLModulesDirectory:
|
||||
webGLTemplate: APPLICATION:Default
|
||||
webGLAnalyzeBuildSize: 0
|
||||
webGLUseEmbeddedResources: 0
|
||||
webGLUseWasm: 0
|
||||
webGLCompressionFormat: 1
|
||||
scriptingDefineSymbols: {}
|
||||
platformArchitecture: {}
|
||||
scriptingBackend: {}
|
||||
incrementalIl2cppBuild: {}
|
||||
additionalIl2CppArgs:
|
||||
scriptingRuntimeVersion: 0
|
||||
apiCompatibilityLevelPerPlatform: {}
|
||||
m_RenderingPath: 1
|
||||
m_MobileRenderingPath: 1
|
||||
metroPackageName: button-clicker
|
||||
metroPackageVersion:
|
||||
metroCertificatePath:
|
||||
metroCertificatePassword:
|
||||
metroCertificateSubject:
|
||||
metroCertificateIssuer:
|
||||
metroCertificateNotAfter: 0000000000000000
|
||||
metroApplicationDescription: button-clicker
|
||||
wsaImages: {}
|
||||
metroTileShortName:
|
||||
metroCommandLineArgsFile:
|
||||
metroTileShowName: 0
|
||||
metroMediumTileShowName: 0
|
||||
metroLargeTileShowName: 0
|
||||
metroWideTileShowName: 0
|
||||
metroDefaultTileSize: 1
|
||||
metroTileForegroundText: 2
|
||||
metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0}
|
||||
metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628,
|
||||
a: 1}
|
||||
metroSplashScreenUseBackgroundColor: 0
|
||||
platformCapabilities: {}
|
||||
metroFTAName:
|
||||
metroFTAFileTypes: []
|
||||
metroProtocolName:
|
||||
metroCompilationOverrides: 1
|
||||
tizenProductDescription:
|
||||
tizenProductURL:
|
||||
tizenSigningProfileName:
|
||||
tizenGPSPermissions: 0
|
||||
tizenMicrophonePermissions: 0
|
||||
tizenDeploymentTarget:
|
||||
tizenDeploymentTargetType: -1
|
||||
tizenMinOSVersion: 1
|
||||
n3dsUseExtSaveData: 0
|
||||
n3dsCompressStaticMem: 1
|
||||
n3dsExtSaveDataNumber: 0x12345
|
||||
n3dsStackSize: 131072
|
||||
n3dsTargetPlatform: 2
|
||||
n3dsRegion: 7
|
||||
n3dsMediaSize: 0
|
||||
n3dsLogoStyle: 3
|
||||
n3dsTitle: GameName
|
||||
n3dsProductCode:
|
||||
n3dsApplicationId: 0xFF3FF
|
||||
stvDeviceAddress:
|
||||
stvProductDescription:
|
||||
stvProductAuthor:
|
||||
stvProductAuthorEmail:
|
||||
stvProductLink:
|
||||
stvProductCategory: 0
|
||||
XboxOneProductId:
|
||||
XboxOneUpdateKey:
|
||||
XboxOneSandboxId:
|
||||
XboxOneContentId:
|
||||
XboxOneTitleId:
|
||||
XboxOneSCId:
|
||||
XboxOneGameOsOverridePath:
|
||||
XboxOnePackagingOverridePath:
|
||||
XboxOneAppManifestOverridePath:
|
||||
XboxOnePackageEncryption: 0
|
||||
XboxOnePackageUpdateGranularity: 2
|
||||
XboxOneDescription:
|
||||
XboxOneLanguage:
|
||||
- enus
|
||||
XboxOneCapability: []
|
||||
XboxOneGameRating: {}
|
||||
XboxOneIsContentPackage: 0
|
||||
XboxOneEnableGPUVariability: 0
|
||||
XboxOneSockets: {}
|
||||
XboxOneSplashScreen: {fileID: 0}
|
||||
XboxOneAllowedProductIds: []
|
||||
XboxOnePersistentLocalStorageSize: 0
|
||||
xboxOneScriptCompiler: 0
|
||||
vrEditorSettings:
|
||||
daydream:
|
||||
daydreamIconForeground: {fileID: 0}
|
||||
daydreamIconBackground: {fileID: 0}
|
||||
cloudServicesEnabled: {}
|
||||
facebookSdkVersion: 7.9.4
|
||||
apiCompatibilityLevel: 2
|
||||
cloudProjectId:
|
||||
projectName:
|
||||
organizationId:
|
||||
cloudEnabled: 0
|
||||
enableNativePlatformBackendsForNewInputSystem: 0
|
||||
disableOldInputManagerSupport: 0
|
1
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/ProjectVersion.txt
vendored
Normal file
1
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/ProjectVersion.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
m_EditorVersion: 2017.2.0f3
|
193
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/QualitySettings.asset
vendored
Normal file
193
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/QualitySettings.asset
vendored
Normal file
|
@ -0,0 +1,193 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!47 &1
|
||||
QualitySettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 5
|
||||
m_CurrentQuality: 5
|
||||
m_QualitySettings:
|
||||
- serializedVersion: 2
|
||||
name: Very Low
|
||||
pixelLightCount: 0
|
||||
shadows: 0
|
||||
shadowResolution: 0
|
||||
shadowProjection: 1
|
||||
shadowCascades: 1
|
||||
shadowDistance: 15
|
||||
shadowNearPlaneOffset: 3
|
||||
shadowCascade2Split: 0.33333334
|
||||
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
|
||||
shadowmaskMode: 0
|
||||
blendWeights: 1
|
||||
textureQuality: 1
|
||||
anisotropicTextures: 0
|
||||
antiAliasing: 0
|
||||
softParticles: 0
|
||||
softVegetation: 0
|
||||
realtimeReflectionProbes: 0
|
||||
billboardsFaceCameraPosition: 0
|
||||
vSyncCount: 0
|
||||
lodBias: 0.3
|
||||
maximumLODLevel: 0
|
||||
particleRaycastBudget: 4
|
||||
asyncUploadTimeSlice: 2
|
||||
asyncUploadBufferSize: 4
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
excludedTargetPlatforms: []
|
||||
- serializedVersion: 2
|
||||
name: Low
|
||||
pixelLightCount: 0
|
||||
shadows: 0
|
||||
shadowResolution: 0
|
||||
shadowProjection: 1
|
||||
shadowCascades: 1
|
||||
shadowDistance: 20
|
||||
shadowNearPlaneOffset: 3
|
||||
shadowCascade2Split: 0.33333334
|
||||
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
|
||||
shadowmaskMode: 0
|
||||
blendWeights: 2
|
||||
textureQuality: 0
|
||||
anisotropicTextures: 0
|
||||
antiAliasing: 0
|
||||
softParticles: 0
|
||||
softVegetation: 0
|
||||
realtimeReflectionProbes: 0
|
||||
billboardsFaceCameraPosition: 0
|
||||
vSyncCount: 0
|
||||
lodBias: 0.4
|
||||
maximumLODLevel: 0
|
||||
particleRaycastBudget: 16
|
||||
asyncUploadTimeSlice: 2
|
||||
asyncUploadBufferSize: 4
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
excludedTargetPlatforms: []
|
||||
- serializedVersion: 2
|
||||
name: Medium
|
||||
pixelLightCount: 1
|
||||
shadows: 1
|
||||
shadowResolution: 0
|
||||
shadowProjection: 1
|
||||
shadowCascades: 1
|
||||
shadowDistance: 20
|
||||
shadowNearPlaneOffset: 3
|
||||
shadowCascade2Split: 0.33333334
|
||||
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
|
||||
shadowmaskMode: 0
|
||||
blendWeights: 2
|
||||
textureQuality: 0
|
||||
anisotropicTextures: 1
|
||||
antiAliasing: 0
|
||||
softParticles: 0
|
||||
softVegetation: 0
|
||||
realtimeReflectionProbes: 0
|
||||
billboardsFaceCameraPosition: 0
|
||||
vSyncCount: 1
|
||||
lodBias: 0.7
|
||||
maximumLODLevel: 0
|
||||
particleRaycastBudget: 64
|
||||
asyncUploadTimeSlice: 2
|
||||
asyncUploadBufferSize: 4
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
excludedTargetPlatforms: []
|
||||
- serializedVersion: 2
|
||||
name: High
|
||||
pixelLightCount: 2
|
||||
shadows: 2
|
||||
shadowResolution: 1
|
||||
shadowProjection: 1
|
||||
shadowCascades: 2
|
||||
shadowDistance: 40
|
||||
shadowNearPlaneOffset: 3
|
||||
shadowCascade2Split: 0.33333334
|
||||
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
|
||||
shadowmaskMode: 1
|
||||
blendWeights: 2
|
||||
textureQuality: 0
|
||||
anisotropicTextures: 1
|
||||
antiAliasing: 0
|
||||
softParticles: 0
|
||||
softVegetation: 1
|
||||
realtimeReflectionProbes: 1
|
||||
billboardsFaceCameraPosition: 1
|
||||
vSyncCount: 1
|
||||
lodBias: 1
|
||||
maximumLODLevel: 0
|
||||
particleRaycastBudget: 256
|
||||
asyncUploadTimeSlice: 2
|
||||
asyncUploadBufferSize: 4
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
excludedTargetPlatforms: []
|
||||
- serializedVersion: 2
|
||||
name: Very High
|
||||
pixelLightCount: 3
|
||||
shadows: 2
|
||||
shadowResolution: 2
|
||||
shadowProjection: 1
|
||||
shadowCascades: 2
|
||||
shadowDistance: 70
|
||||
shadowNearPlaneOffset: 3
|
||||
shadowCascade2Split: 0.33333334
|
||||
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
|
||||
shadowmaskMode: 1
|
||||
blendWeights: 4
|
||||
textureQuality: 0
|
||||
anisotropicTextures: 2
|
||||
antiAliasing: 2
|
||||
softParticles: 1
|
||||
softVegetation: 1
|
||||
realtimeReflectionProbes: 1
|
||||
billboardsFaceCameraPosition: 1
|
||||
vSyncCount: 1
|
||||
lodBias: 1.5
|
||||
maximumLODLevel: 0
|
||||
particleRaycastBudget: 1024
|
||||
asyncUploadTimeSlice: 2
|
||||
asyncUploadBufferSize: 4
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
excludedTargetPlatforms: []
|
||||
- serializedVersion: 2
|
||||
name: Ultra
|
||||
pixelLightCount: 4
|
||||
shadows: 2
|
||||
shadowResolution: 2
|
||||
shadowProjection: 1
|
||||
shadowCascades: 4
|
||||
shadowDistance: 150
|
||||
shadowNearPlaneOffset: 3
|
||||
shadowCascade2Split: 0.33333334
|
||||
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
|
||||
shadowmaskMode: 1
|
||||
blendWeights: 4
|
||||
textureQuality: 0
|
||||
anisotropicTextures: 2
|
||||
antiAliasing: 2
|
||||
softParticles: 1
|
||||
softVegetation: 1
|
||||
realtimeReflectionProbes: 1
|
||||
billboardsFaceCameraPosition: 1
|
||||
vSyncCount: 1
|
||||
lodBias: 2
|
||||
maximumLODLevel: 0
|
||||
particleRaycastBudget: 4096
|
||||
asyncUploadTimeSlice: 2
|
||||
asyncUploadBufferSize: 4
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
excludedTargetPlatforms: []
|
||||
m_PerPlatformDefaultQuality:
|
||||
Android: 2
|
||||
Nintendo 3DS: 5
|
||||
Nintendo Switch: 5
|
||||
PS4: 5
|
||||
PSM: 5
|
||||
PSP2: 2
|
||||
Samsung TV: 2
|
||||
Standalone: 5
|
||||
Tizen: 2
|
||||
Web: 5
|
||||
WebGL: 3
|
||||
WiiU: 5
|
||||
Windows Store Apps: 5
|
||||
XboxOne: 5
|
||||
iPhone: 2
|
||||
tvOS: 2
|
43
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/TagManager.asset
vendored
Normal file
43
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/TagManager.asset
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!78 &1
|
||||
TagManager:
|
||||
serializedVersion: 2
|
||||
tags: []
|
||||
layers:
|
||||
- Default
|
||||
- TransparentFX
|
||||
- Ignore Raycast
|
||||
-
|
||||
- Water
|
||||
- UI
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
m_SortingLayers:
|
||||
- name: Default
|
||||
uniqueID: 0
|
||||
locked: 0
|
9
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/TimeManager.asset
vendored
Normal file
9
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/TimeManager.asset
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!5 &1
|
||||
TimeManager:
|
||||
m_ObjectHideFlags: 0
|
||||
Fixed Timestep: 0.02
|
||||
Maximum Allowed Timestep: 0.33333334
|
||||
m_TimeScale: 1
|
||||
Maximum Particle Timestep: 0.03
|
34
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/UnityConnectSettings.asset
vendored
Normal file
34
dependencies/discord-rpc/examples/button-clicker/ProjectSettings/UnityConnectSettings.asset
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!310 &1
|
||||
UnityConnectSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_Enabled: 0
|
||||
m_TestMode: 0
|
||||
m_TestEventUrl:
|
||||
m_TestConfigUrl:
|
||||
m_TestInitMode: 0
|
||||
CrashReportingSettings:
|
||||
m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes
|
||||
m_Enabled: 0
|
||||
m_CaptureEditorExceptions: 1
|
||||
UnityPurchasingSettings:
|
||||
m_Enabled: 0
|
||||
m_TestMode: 0
|
||||
UnityAnalyticsSettings:
|
||||
m_Enabled: 0
|
||||
m_InitializeOnStartup: 1
|
||||
m_TestMode: 0
|
||||
m_TestEventUrl:
|
||||
m_TestConfigUrl:
|
||||
UnityAdsSettings:
|
||||
m_Enabled: 0
|
||||
m_InitializeOnStartup: 1
|
||||
m_TestMode: 0
|
||||
m_EnabledPlatforms: 4294967295
|
||||
m_IosGameId:
|
||||
m_AndroidGameId:
|
||||
m_GameIds: {}
|
||||
m_GameId:
|
||||
PerformanceReportingSettings:
|
||||
m_Enabled: 0
|
4
dependencies/discord-rpc/examples/button-clicker/UnityPackageManager/manifest.json
vendored
Normal file
4
dependencies/discord-rpc/examples/button-clicker/UnityPackageManager/manifest.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
21
dependencies/discord-rpc/examples/send-presence/CMakeLists.txt
vendored
Normal file
21
dependencies/discord-rpc/examples/send-presence/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
add_executable(
|
||||
send-presence
|
||||
MACOSX_BUNDLE
|
||||
send-presence.c
|
||||
)
|
||||
set_target_properties(send-presence PROPERTIES
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "Send Presence"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "com.discordapp.examples.send-presence"
|
||||
)
|
||||
target_link_libraries(send-presence discord-rpc)
|
||||
|
||||
install(
|
||||
TARGETS send-presence
|
||||
RUNTIME
|
||||
DESTINATION "bin"
|
||||
CONFIGURATIONS Release
|
||||
BUNDLE
|
||||
DESTINATION "bin"
|
||||
CONFIGURATIONS Release
|
||||
)
|
206
dependencies/discord-rpc/examples/send-presence/send-presence.c
vendored
Normal file
206
dependencies/discord-rpc/examples/send-presence/send-presence.c
vendored
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
This is a simple example in C of using the rich presence API asynchronously.
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS /* thanks Microsoft */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "discord_rpc.h"
|
||||
|
||||
static const char* APPLICATION_ID = "345229890980937739";
|
||||
static int FrustrationLevel = 0;
|
||||
static int64_t StartTime;
|
||||
static int SendPresence = 1;
|
||||
|
||||
static int prompt(char* line, size_t size)
|
||||
{
|
||||
int res;
|
||||
char* nl;
|
||||
printf("\n> ");
|
||||
fflush(stdout);
|
||||
res = fgets(line, (int)size, stdin) ? 1 : 0;
|
||||
line[size - 1] = 0;
|
||||
nl = strchr(line, '\n');
|
||||
if (nl) {
|
||||
*nl = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void updateDiscordPresence()
|
||||
{
|
||||
if (SendPresence) {
|
||||
char buffer[256];
|
||||
DiscordRichPresence discordPresence;
|
||||
memset(&discordPresence, 0, sizeof(discordPresence));
|
||||
discordPresence.state = "West of House";
|
||||
sprintf(buffer, "Frustration level: %d", FrustrationLevel);
|
||||
discordPresence.details = buffer;
|
||||
discordPresence.startTimestamp = StartTime;
|
||||
discordPresence.endTimestamp = time(0) + 5 * 60;
|
||||
discordPresence.largeImageKey = "canary-large";
|
||||
discordPresence.smallImageKey = "ptb-small";
|
||||
discordPresence.partyId = "party1234";
|
||||
discordPresence.partySize = 1;
|
||||
discordPresence.partyMax = 6;
|
||||
discordPresence.partyPrivacy = DISCORD_PARTY_PUBLIC;
|
||||
discordPresence.matchSecret = "xyzzy";
|
||||
discordPresence.joinSecret = "join";
|
||||
discordPresence.spectateSecret = "look";
|
||||
discordPresence.instance = 0;
|
||||
Discord_UpdatePresence(&discordPresence);
|
||||
}
|
||||
else {
|
||||
Discord_ClearPresence();
|
||||
}
|
||||
}
|
||||
|
||||
static void handleDiscordReady(const DiscordUser* connectedUser)
|
||||
{
|
||||
printf("\nDiscord: connected to user %s#%s - %s\n",
|
||||
connectedUser->username,
|
||||
connectedUser->discriminator,
|
||||
connectedUser->userId);
|
||||
}
|
||||
|
||||
static void handleDiscordDisconnected(int errcode, const char* message)
|
||||
{
|
||||
printf("\nDiscord: disconnected (%d: %s)\n", errcode, message);
|
||||
}
|
||||
|
||||
static void handleDiscordError(int errcode, const char* message)
|
||||
{
|
||||
printf("\nDiscord: error (%d: %s)\n", errcode, message);
|
||||
}
|
||||
|
||||
static void handleDiscordJoin(const char* secret)
|
||||
{
|
||||
printf("\nDiscord: join (%s)\n", secret);
|
||||
}
|
||||
|
||||
static void handleDiscordSpectate(const char* secret)
|
||||
{
|
||||
printf("\nDiscord: spectate (%s)\n", secret);
|
||||
}
|
||||
|
||||
static void handleDiscordJoinRequest(const DiscordUser* request)
|
||||
{
|
||||
int response = -1;
|
||||
char yn[4];
|
||||
printf("\nDiscord: join request from %s#%s - %s\n",
|
||||
request->username,
|
||||
request->discriminator,
|
||||
request->userId);
|
||||
do {
|
||||
printf("Accept? (y/n)");
|
||||
if (!prompt(yn, sizeof(yn))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!yn[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (yn[0] == 'y') {
|
||||
response = DISCORD_REPLY_YES;
|
||||
break;
|
||||
}
|
||||
|
||||
if (yn[0] == 'n') {
|
||||
response = DISCORD_REPLY_NO;
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
if (response != -1) {
|
||||
Discord_Respond(request->userId, response);
|
||||
}
|
||||
}
|
||||
|
||||
static void discordInit()
|
||||
{
|
||||
DiscordEventHandlers handlers;
|
||||
memset(&handlers, 0, sizeof(handlers));
|
||||
handlers.ready = handleDiscordReady;
|
||||
handlers.disconnected = handleDiscordDisconnected;
|
||||
handlers.errored = handleDiscordError;
|
||||
handlers.joinGame = handleDiscordJoin;
|
||||
handlers.spectateGame = handleDiscordSpectate;
|
||||
handlers.joinRequest = handleDiscordJoinRequest;
|
||||
Discord_Initialize(APPLICATION_ID, &handlers, 1, NULL);
|
||||
}
|
||||
|
||||
static void gameLoop()
|
||||
{
|
||||
char line[512];
|
||||
char* space;
|
||||
|
||||
StartTime = time(0);
|
||||
|
||||
printf("You are standing in an open field west of a white house.\n");
|
||||
while (prompt(line, sizeof(line))) {
|
||||
if (line[0]) {
|
||||
if (line[0] == 'q') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (line[0] == 't') {
|
||||
printf("Shutting off Discord.\n");
|
||||
Discord_Shutdown();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line[0] == 'c') {
|
||||
if (SendPresence) {
|
||||
printf("Clearing presence information.\n");
|
||||
SendPresence = 0;
|
||||
}
|
||||
else {
|
||||
printf("Restoring presence information.\n");
|
||||
SendPresence = 1;
|
||||
}
|
||||
updateDiscordPresence();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line[0] == 'y') {
|
||||
printf("Reinit Discord.\n");
|
||||
discordInit();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (time(NULL) & 1) {
|
||||
printf("I don't understand that.\n");
|
||||
}
|
||||
else {
|
||||
space = strchr(line, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
}
|
||||
printf("I don't know the word \"%s\".\n", line);
|
||||
}
|
||||
|
||||
++FrustrationLevel;
|
||||
|
||||
updateDiscordPresence();
|
||||
}
|
||||
|
||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||
Discord_UpdateConnection();
|
||||
#endif
|
||||
Discord_RunCallbacks();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
discordInit();
|
||||
|
||||
gameLoop();
|
||||
|
||||
Discord_Shutdown();
|
||||
return 0;
|
||||
}
|
78
dependencies/discord-rpc/examples/unrealstatus/.gitignore
vendored
Normal file
78
dependencies/discord-rpc/examples/unrealstatus/.gitignore
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
# Visual Studio 2015 user specific files
|
||||
.vs/
|
||||
|
||||
# Visual Studio 2015 database file
|
||||
*.VC.db
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.ipa
|
||||
|
||||
# These project files can be generated by the engine
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
||||
*.sln
|
||||
*.suo
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
|
||||
# Precompiled Assets
|
||||
SourceArt/**/*.png
|
||||
SourceArt/**/*.tga
|
||||
|
||||
# Binary Files
|
||||
Binaries/
|
||||
|
||||
# Builds
|
||||
Build/*
|
||||
|
||||
# Whitelist PakBlacklist-<BuildConfiguration>.txt files
|
||||
!Build/*/
|
||||
Build/*/**
|
||||
!Build/*/PakBlacklist*.txt
|
||||
|
||||
# Don't ignore icon files in Build
|
||||
!Build/**/*.ico
|
||||
|
||||
# Built data for maps
|
||||
*_BuiltData.uasset
|
||||
|
||||
# Configuration files generated by the Editor
|
||||
Saved/*
|
||||
|
||||
# Compiled source files for the engine to use
|
||||
Intermediate/
|
||||
|
||||
# Cache files for the editor to use
|
||||
DerivedDataCache/
|
||||
|
||||
# Library headers must be copied automatically by the build script (build.py unreal)
|
||||
Plugins/DiscordRpc/Source/ThirdParty/DiscordRpcLibrary/Include
|
0
dependencies/discord-rpc/examples/unrealstatus/Config/DefaultEditor.ini
vendored
Normal file
0
dependencies/discord-rpc/examples/unrealstatus/Config/DefaultEditor.ini
vendored
Normal file
54
dependencies/discord-rpc/examples/unrealstatus/Config/DefaultEngine.ini
vendored
Normal file
54
dependencies/discord-rpc/examples/unrealstatus/Config/DefaultEngine.ini
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
[URL]
|
||||
|
||||
[/Script/HardwareTargeting.HardwareTargetingSettings]
|
||||
TargetedHardwareClass=Desktop
|
||||
AppliedTargetedHardwareClass=Desktop
|
||||
DefaultGraphicsPerformance=Maximum
|
||||
AppliedDefaultGraphicsPerformance=Maximum
|
||||
|
||||
[/Script/Engine.EndUserSettings]
|
||||
bSendAnonymousUsageDataToEpic=False
|
||||
|
||||
[/Script/Engine.PhysicsSettings]
|
||||
DefaultGravityZ=-980.000000
|
||||
DefaultTerminalVelocity=4000.000000
|
||||
DefaultFluidFriction=0.300000
|
||||
SimulateScratchMemorySize=262144
|
||||
RagdollAggregateThreshold=4
|
||||
TriangleMeshTriangleMinAreaThreshold=5.000000
|
||||
bEnableAsyncScene=False
|
||||
bEnableShapeSharing=False
|
||||
bEnablePCM=False
|
||||
bEnableStabilization=False
|
||||
bWarnMissingLocks=True
|
||||
bEnable2DPhysics=False
|
||||
LockedAxis=Invalid
|
||||
DefaultDegreesOfFreedom=Full3D
|
||||
BounceThresholdVelocity=200.000000
|
||||
FrictionCombineMode=Average
|
||||
RestitutionCombineMode=Average
|
||||
MaxAngularVelocity=3600.000000
|
||||
MaxDepenetrationVelocity=0.000000
|
||||
ContactOffsetMultiplier=0.010000
|
||||
MinContactOffset=0.000100
|
||||
MaxContactOffset=1.000000
|
||||
bSimulateSkeletalMeshOnDedicatedServer=True
|
||||
DefaultShapeComplexity=CTF_UseSimpleAndComplex
|
||||
bDefaultHasComplexCollision=True
|
||||
bSuppressFaceRemapTable=False
|
||||
bSupportUVFromHitResults=False
|
||||
bDisableActiveActors=False
|
||||
bDisableCCD=False
|
||||
MaxPhysicsDeltaTime=0.033333
|
||||
bSubstepping=False
|
||||
bSubsteppingAsync=False
|
||||
MaxSubstepDeltaTime=0.016667
|
||||
MaxSubsteps=6
|
||||
SyncSceneSmoothingFactor=0.000000
|
||||
AsyncSceneSmoothingFactor=0.990000
|
||||
InitialAverageFrameRate=0.016667
|
||||
|
||||
[/Script/EngineSettings.GameMapsSettings]
|
||||
EditorStartupMap=/Game/ShowTheUILevel.ShowTheUILevel
|
||||
GameDefaultMap=/Game/ShowTheUILevel.ShowTheUILevel
|
||||
|
7
dependencies/discord-rpc/examples/unrealstatus/Config/DefaultGame.ini
vendored
Normal file
7
dependencies/discord-rpc/examples/unrealstatus/Config/DefaultGame.ini
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
[/Script/EngineSettings.GeneralProjectSettings]
|
||||
ProjectID=E5977A24492699DF20B8ADBF736AF6C6
|
||||
ProjectName=Discord RPC Example
|
||||
CompanyName=Discord Inc.
|
||||
Homepage="https://discordapp.com/"
|
||||
CopyrightNotice=
|
||||
|
BIN
dependencies/discord-rpc/examples/unrealstatus/Content/MainScreenBP.uasset
vendored
Normal file
BIN
dependencies/discord-rpc/examples/unrealstatus/Content/MainScreenBP.uasset
vendored
Normal file
Binary file not shown.
BIN
dependencies/discord-rpc/examples/unrealstatus/Content/MouseGameModeBP.uasset
vendored
Normal file
BIN
dependencies/discord-rpc/examples/unrealstatus/Content/MouseGameModeBP.uasset
vendored
Normal file
Binary file not shown.
BIN
dependencies/discord-rpc/examples/unrealstatus/Content/MousePlayerControllerBP.uasset
vendored
Normal file
BIN
dependencies/discord-rpc/examples/unrealstatus/Content/MousePlayerControllerBP.uasset
vendored
Normal file
Binary file not shown.
BIN
dependencies/discord-rpc/examples/unrealstatus/Content/ShowTheUILevel.umap
vendored
Normal file
BIN
dependencies/discord-rpc/examples/unrealstatus/Content/ShowTheUILevel.umap
vendored
Normal file
Binary file not shown.
29
dependencies/discord-rpc/examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin
vendored
Normal file
29
dependencies/discord-rpc/examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "Discord RPC",
|
||||
"Description": "Wrap the Discord RPC library.",
|
||||
"Category": "Messaging",
|
||||
"CreatedBy": "Chris Marsh <chris@discordapp.com>",
|
||||
"CreatedByURL": "https://discordapp.com/",
|
||||
"DocsURL": "",
|
||||
"MarketplaceURL": "",
|
||||
"SupportURL": "",
|
||||
"CanContainContent": true,
|
||||
"IsBetaVersion": true,
|
||||
"Installed": false,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "DiscordRpc",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms" :
|
||||
[
|
||||
"Win64",
|
||||
"Linux",
|
||||
"Mac"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
BIN
dependencies/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/Icon128.png
vendored
Normal file
BIN
dependencies/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/Icon128.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.6 KiB |
BIN
dependencies/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/discord.png
vendored
Normal file
BIN
dependencies/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/discord.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.6 KiB |
|
@ -0,0 +1,57 @@
|
|||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
|
||||
public class DiscordRpc : ModuleRules
|
||||
{
|
||||
#if WITH_FORWARDED_MODULE_RULES_CTOR
|
||||
public DiscordRpc(ReadOnlyTargetRules Target) : base(Target)
|
||||
#else
|
||||
public DiscordRpc(TargetInfo Target)
|
||||
#endif
|
||||
{
|
||||
Definitions.Add("DISCORD_DYNAMIC_LIB=1");
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"DiscordRpc/Public"
|
||||
}
|
||||
);
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"DiscordRpc/Private"
|
||||
}
|
||||
);
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"DiscordRpcLibrary"
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"Projects"
|
||||
}
|
||||
);
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
|
||||
string BaseDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "Source", "ThirdParty", "DiscordRpcLibrary"));
|
||||
PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "DiscordRpcPrivatePCH.h"
|
||||
#include "IPluginManager.h"
|
||||
#include "ModuleManager.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FDiscordRpcModule"
|
||||
|
||||
void FDiscordRpcModule::StartupModule()
|
||||
{
|
||||
#if !PLATFORM_LINUX
|
||||
#if defined(DISCORD_DYNAMIC_LIB)
|
||||
// Get the base directory of this plugin
|
||||
FString BaseDir = IPluginManager::Get().FindPlugin("DiscordRpc")->GetBaseDir();
|
||||
const FString SDKDir =
|
||||
FPaths::Combine(*BaseDir, TEXT("Source"), TEXT("ThirdParty"), TEXT("DiscordRpcLibrary"));
|
||||
#if PLATFORM_WINDOWS
|
||||
const FString LibName = TEXT("discord-rpc");
|
||||
const FString LibDir = FPaths::Combine(*SDKDir, TEXT("Win64"));
|
||||
if (!LoadDependency(LibDir, LibName, DiscordRpcLibraryHandle)) {
|
||||
FMessageDialog::Open(
|
||||
EAppMsgType::Ok,
|
||||
LOCTEXT(LOCTEXT_NAMESPACE,
|
||||
"Failed to load DiscordRpc plugin. Plug-in will not be functional."));
|
||||
FreeDependency(DiscordRpcLibraryHandle);
|
||||
}
|
||||
#elif PLATFORM_MAC
|
||||
const FString LibName = TEXT("libdiscord-rpc");
|
||||
const FString LibDir = FPaths::Combine(*SDKDir, TEXT("Mac"));
|
||||
if (!LoadDependency(LibDir, LibName, DiscordRpcLibraryHandle)) {
|
||||
FMessageDialog::Open(
|
||||
EAppMsgType::Ok,
|
||||
LOCTEXT(LOCTEXT_NAMESPACE,
|
||||
"Failed to load DiscordRpc plugin. Plug-in will not be functional."));
|
||||
FreeDependency(DiscordRpcLibraryHandle);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void FDiscordRpcModule::ShutdownModule()
|
||||
{
|
||||
// Free the dll handle
|
||||
#if !PLATFORM_LINUX
|
||||
#if defined(DISCORD_DYNAMIC_LIB)
|
||||
FreeDependency(DiscordRpcLibraryHandle);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FDiscordRpcModule::LoadDependency(const FString& Dir, const FString& Name, void*& Handle)
|
||||
{
|
||||
FString Lib = Name + TEXT(".") + FPlatformProcess::GetModuleExtension();
|
||||
FString Path = Dir.IsEmpty() ? *Lib : FPaths::Combine(*Dir, *Lib);
|
||||
|
||||
Handle = FPlatformProcess::GetDllHandle(*Path);
|
||||
|
||||
if (Handle == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FDiscordRpcModule::FreeDependency(void*& Handle)
|
||||
{
|
||||
if (Handle != nullptr) {
|
||||
FPlatformProcess::FreeDllHandle(Handle);
|
||||
Handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FDiscordRpcModule, DiscordRpc)
|
|
@ -0,0 +1,172 @@
|
|||
#include "DiscordRpcPrivatePCH.h"
|
||||
#include "DiscordRpcBlueprint.h"
|
||||
#include "discord_rpc.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(Discord)
|
||||
|
||||
static UDiscordRpc* self = nullptr;
|
||||
|
||||
static void ReadyHandler(const DiscordUser* connectedUser)
|
||||
{
|
||||
FDiscordUserData ud;
|
||||
ud.userId = ANSI_TO_TCHAR(connectedUser->userId);
|
||||
ud.username = ANSI_TO_TCHAR(connectedUser->username);
|
||||
ud.discriminator = ANSI_TO_TCHAR(connectedUser->discriminator);
|
||||
ud.avatar = ANSI_TO_TCHAR(connectedUser->avatar);
|
||||
UE_LOG(Discord,
|
||||
Log,
|
||||
TEXT("Discord connected to %s - %s#%s"),
|
||||
*ud.userId,
|
||||
*ud.username,
|
||||
*ud.discriminator);
|
||||
if (self) {
|
||||
self->IsConnected = true;
|
||||
self->OnConnected.Broadcast(ud);
|
||||
}
|
||||
}
|
||||
|
||||
static void DisconnectHandler(int errorCode, const char* message)
|
||||
{
|
||||
auto msg = FString(message);
|
||||
UE_LOG(Discord, Log, TEXT("Discord disconnected (%d): %s"), errorCode, *msg);
|
||||
if (self) {
|
||||
self->IsConnected = false;
|
||||
self->OnDisconnected.Broadcast(errorCode, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void ErroredHandler(int errorCode, const char* message)
|
||||
{
|
||||
auto msg = FString(message);
|
||||
UE_LOG(Discord, Log, TEXT("Discord error (%d): %s"), errorCode, *msg);
|
||||
if (self) {
|
||||
self->OnErrored.Broadcast(errorCode, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void JoinGameHandler(const char* joinSecret)
|
||||
{
|
||||
auto secret = FString(joinSecret);
|
||||
UE_LOG(Discord, Log, TEXT("Discord join %s"), *secret);
|
||||
if (self) {
|
||||
self->OnJoin.Broadcast(secret);
|
||||
}
|
||||
}
|
||||
|
||||
static void SpectateGameHandler(const char* spectateSecret)
|
||||
{
|
||||
auto secret = FString(spectateSecret);
|
||||
UE_LOG(Discord, Log, TEXT("Discord spectate %s"), *secret);
|
||||
if (self) {
|
||||
self->OnSpectate.Broadcast(secret);
|
||||
}
|
||||
}
|
||||
|
||||
static void JoinRequestHandler(const DiscordUser* request)
|
||||
{
|
||||
FDiscordUserData ud;
|
||||
ud.userId = ANSI_TO_TCHAR(request->userId);
|
||||
ud.username = ANSI_TO_TCHAR(request->username);
|
||||
ud.discriminator = ANSI_TO_TCHAR(request->discriminator);
|
||||
ud.avatar = ANSI_TO_TCHAR(request->avatar);
|
||||
UE_LOG(Discord,
|
||||
Log,
|
||||
TEXT("Discord join request from %s - %s#%s"),
|
||||
*ud.userId,
|
||||
*ud.username,
|
||||
*ud.discriminator);
|
||||
if (self) {
|
||||
self->OnJoinRequest.Broadcast(ud);
|
||||
}
|
||||
}
|
||||
|
||||
void UDiscordRpc::Initialize(const FString& applicationId,
|
||||
bool autoRegister,
|
||||
const FString& optionalSteamId)
|
||||
{
|
||||
self = this;
|
||||
IsConnected = false;
|
||||
DiscordEventHandlers handlers{};
|
||||
handlers.ready = ReadyHandler;
|
||||
handlers.disconnected = DisconnectHandler;
|
||||
handlers.errored = ErroredHandler;
|
||||
if (OnJoin.IsBound()) {
|
||||
handlers.joinGame = JoinGameHandler;
|
||||
}
|
||||
if (OnSpectate.IsBound()) {
|
||||
handlers.spectateGame = SpectateGameHandler;
|
||||
}
|
||||
if (OnJoinRequest.IsBound()) {
|
||||
handlers.joinRequest = JoinRequestHandler;
|
||||
}
|
||||
auto appId = StringCast<ANSICHAR>(*applicationId);
|
||||
auto steamId = StringCast<ANSICHAR>(*optionalSteamId);
|
||||
Discord_Initialize(
|
||||
(const char*)appId.Get(), &handlers, autoRegister, (const char*)steamId.Get());
|
||||
}
|
||||
|
||||
void UDiscordRpc::Shutdown()
|
||||
{
|
||||
Discord_Shutdown();
|
||||
self = nullptr;
|
||||
}
|
||||
|
||||
void UDiscordRpc::RunCallbacks()
|
||||
{
|
||||
Discord_RunCallbacks();
|
||||
}
|
||||
|
||||
void UDiscordRpc::UpdatePresence()
|
||||
{
|
||||
DiscordRichPresence rp{};
|
||||
|
||||
auto state = StringCast<ANSICHAR>(*RichPresence.state);
|
||||
rp.state = state.Get();
|
||||
|
||||
auto details = StringCast<ANSICHAR>(*RichPresence.details);
|
||||
rp.details = details.Get();
|
||||
|
||||
auto largeImageKey = StringCast<ANSICHAR>(*RichPresence.largeImageKey);
|
||||
rp.largeImageKey = largeImageKey.Get();
|
||||
|
||||
auto largeImageText = StringCast<ANSICHAR>(*RichPresence.largeImageText);
|
||||
rp.largeImageText = largeImageText.Get();
|
||||
|
||||
auto smallImageKey = StringCast<ANSICHAR>(*RichPresence.smallImageKey);
|
||||
rp.smallImageKey = smallImageKey.Get();
|
||||
|
||||
auto smallImageText = StringCast<ANSICHAR>(*RichPresence.smallImageText);
|
||||
rp.smallImageText = smallImageText.Get();
|
||||
|
||||
auto partyId = StringCast<ANSICHAR>(*RichPresence.partyId);
|
||||
rp.partyId = partyId.Get();
|
||||
|
||||
auto matchSecret = StringCast<ANSICHAR>(*RichPresence.matchSecret);
|
||||
rp.matchSecret = matchSecret.Get();
|
||||
|
||||
auto joinSecret = StringCast<ANSICHAR>(*RichPresence.joinSecret);
|
||||
rp.joinSecret = joinSecret.Get();
|
||||
|
||||
auto spectateSecret = StringCast<ANSICHAR>(*RichPresence.spectateSecret);
|
||||
rp.spectateSecret = spectateSecret.Get();
|
||||
rp.startTimestamp = RichPresence.startTimestamp;
|
||||
rp.endTimestamp = RichPresence.endTimestamp;
|
||||
rp.partySize = RichPresence.partySize;
|
||||
rp.partyMax = RichPresence.partyMax;
|
||||
rp.partyPrivacy = (int)RichPresence.partyPrivacy;
|
||||
rp.instance = RichPresence.instance;
|
||||
|
||||
Discord_UpdatePresence(&rp);
|
||||
}
|
||||
|
||||
void UDiscordRpc::ClearPresence()
|
||||
{
|
||||
Discord_ClearPresence();
|
||||
}
|
||||
|
||||
void UDiscordRpc::Respond(const FString& userId, int reply)
|
||||
{
|
||||
UE_LOG(Discord, Log, TEXT("Responding %d to join request from %s"), reply, *userId);
|
||||
FTCHARToUTF8 utf8_userid(*userId);
|
||||
Discord_Respond(utf8_userid.Get(), reply);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
#include "Core.h"
|
||||
#include "DiscordRpc.h"
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ModuleManager.h"
|
||||
|
||||
class FDiscordRpcModule : public IModuleInterface {
|
||||
public:
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
/** Handle to the test dll we will load */
|
||||
void* DiscordRpcLibraryHandle;
|
||||
|
||||
/** StartupModule is covered with defines, these functions are the place to put breakpoints */
|
||||
static bool LoadDependency(const FString& Dir, const FString& Name, void*& Handle);
|
||||
static void FreeDependency(void*& Handle);
|
||||
};
|
|
@ -0,0 +1,181 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine.h"
|
||||
#include "DiscordRpcBlueprint.generated.h"
|
||||
|
||||
// unreal's header tool hates clang-format
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* Ask to join callback data
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FDiscordUserData {
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
FString userId;
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
FString username;
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
FString discriminator;
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
FString avatar;
|
||||
};
|
||||
|
||||
/**
|
||||
* Valid response codes for Respond function
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EDiscordJoinResponseCodes : uint8
|
||||
{
|
||||
DISCORD_REPLY_NO UMETA(DisplayName="No"),
|
||||
DISCORD_REPLY_YES UMETA(DisplayName="Yes"),
|
||||
DISCORD_REPLY_IGNORE UMETA(DisplayName="Ignore")
|
||||
};
|
||||
|
||||
/**
|
||||
* Valid party privacy values
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EDiscordPartyPrivacy: uint8
|
||||
{
|
||||
DISCORD_PARTY_PRIVATE UMETA(DisplayName="Private"),
|
||||
DISCORD_PARTY_PUBLIC UMETA(DisplayName="Public")
|
||||
};
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordConnected, const FDiscordUserData&, joinRequest);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordDisconnected, int, errorCode, const FString&, errorMessage);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordErrored, int, errorCode, const FString&, errorMessage);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoin, const FString&, joinSecret);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordSpectate, const FString&, spectateSecret);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoinRequest, const FDiscordUserData&, joinRequest);
|
||||
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* Rich presence data
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FDiscordRichPresence {
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString state;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString details;
|
||||
// todo, timestamps are 64bit, does that even matter?
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
int startTimestamp;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
int endTimestamp;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString largeImageKey;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString largeImageText;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString smallImageKey;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString smallImageText;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString partyId;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
int partySize;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
int partyMax;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
EDiscordPartyPrivacy partyPrivacy;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString matchSecret;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString joinSecret;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString spectateSecret;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
bool instance;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType, meta = (DisplayName = "Discord RPC"), Category = "Discord")
|
||||
class DISCORDRPC_API UDiscordRpc : public UObject {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable,
|
||||
meta = (DisplayName = "Initialize connection", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
void Initialize(const FString& applicationId,
|
||||
bool autoRegister,
|
||||
const FString& optionalSteamId);
|
||||
|
||||
UFUNCTION(BlueprintCallable,
|
||||
meta = (DisplayName = "Shut down connection", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
void Shutdown();
|
||||
|
||||
UFUNCTION(BlueprintCallable,
|
||||
meta = (DisplayName = "Check for callbacks", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
void RunCallbacks();
|
||||
|
||||
UFUNCTION(BlueprintCallable,
|
||||
meta = (DisplayName = "Send presence", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
void UpdatePresence();
|
||||
|
||||
UFUNCTION(BlueprintCallable,
|
||||
meta = (DisplayName = "Clear presence", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
void ClearPresence();
|
||||
|
||||
UFUNCTION(BlueprintCallable,
|
||||
meta = (DisplayName = "Respond to join request", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
void Respond(const FString& userId, int reply);
|
||||
|
||||
UPROPERTY(BlueprintReadOnly,
|
||||
meta = (DisplayName = "Is Discord connected", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
bool IsConnected;
|
||||
|
||||
UPROPERTY(BlueprintAssignable,
|
||||
meta = (DisplayName = "On connection", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordConnected OnConnected;
|
||||
|
||||
UPROPERTY(BlueprintAssignable,
|
||||
meta = (DisplayName = "On disconnection", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordDisconnected OnDisconnected;
|
||||
|
||||
UPROPERTY(BlueprintAssignable,
|
||||
meta = (DisplayName = "On error message", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordErrored OnErrored;
|
||||
|
||||
UPROPERTY(BlueprintAssignable,
|
||||
meta = (DisplayName = "When Discord user presses join", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordJoin OnJoin;
|
||||
|
||||
UPROPERTY(BlueprintAssignable,
|
||||
meta = (DisplayName = "When Discord user presses spectate", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordSpectate OnSpectate;
|
||||
|
||||
UPROPERTY(BlueprintAssignable,
|
||||
meta = (DisplayName = "When Discord another user sends a join request",
|
||||
Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordJoinRequest OnJoinRequest;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite,
|
||||
meta = (DisplayName = "Rich presence info", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordRichPresence RichPresence;
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DiscordRpcLibrary : ModuleRules
|
||||
{
|
||||
#if WITH_FORWARDED_MODULE_RULES_CTOR
|
||||
public DiscordRpcLibrary(ReadOnlyTargetRules Target) : base(Target)
|
||||
#else
|
||||
public DiscordRpcLibrary(TargetInfo Target)
|
||||
#endif
|
||||
{
|
||||
Type = ModuleType.External;
|
||||
Definitions.Add("DISCORD_DYNAMIC_LIB=1");
|
||||
|
||||
string BaseDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "DiscordRpcLibrary"));
|
||||
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
string lib = Path.Combine(BaseDirectory, "Win64");
|
||||
|
||||
// Include headers
|
||||
PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include"));
|
||||
|
||||
// Add the import library
|
||||
PublicLibraryPaths.Add(lib);
|
||||
PublicAdditionalLibraries.Add(Path.Combine(lib, "discord-rpc.lib"));
|
||||
|
||||
// Dynamic
|
||||
RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "discord-rpc.dll")));
|
||||
PublicDelayLoadDLLs.Add("discord-rpc.dll");
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
string lib = Path.Combine(BaseDirectory, "Linux", "x86_64-unknown-linux-gnu");
|
||||
|
||||
// Include headers
|
||||
PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include"));
|
||||
|
||||
// Add the import library
|
||||
PublicLibraryPaths.Add(lib);
|
||||
PublicAdditionalLibraries.Add(Path.Combine(lib, "libdiscord-rpc.so"));
|
||||
RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "libdiscord-rpc.so")));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
string lib = Path.Combine(BaseDirectory, "Mac");
|
||||
|
||||
// Include headers
|
||||
PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include"));
|
||||
|
||||
// Add the import library
|
||||
PublicLibraryPaths.Add(lib);
|
||||
PublicAdditionalLibraries.Add(Path.Combine(lib, "libdiscord-rpc.dylib"));
|
||||
RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "libdiscord-rpc.dylib")));
|
||||
}
|
||||
}
|
||||
}
|
14
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus.Target.cs
vendored
Normal file
14
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus.Target.cs
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class unrealstatusTarget : TargetRules
|
||||
{
|
||||
public unrealstatusTarget(TargetInfo Target) : base(Target)
|
||||
{
|
||||
Type = TargetType.Game;
|
||||
|
||||
ExtraModuleNames.AddRange( new string[] { "unrealstatus" } );
|
||||
}
|
||||
}
|
23
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.Build.cs
vendored
Normal file
23
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.Build.cs
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class unrealstatus : ModuleRules
|
||||
{
|
||||
public unrealstatus(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { });
|
||||
|
||||
// Uncomment if you are using Slate UI
|
||||
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
|
||||
|
||||
// Uncomment if you are using online features
|
||||
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
|
||||
|
||||
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
|
||||
}
|
||||
}
|
6
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.cpp
vendored
Normal file
6
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.cpp
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "unrealstatus.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, unrealstatus, "unrealstatus");
|
5
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.h
vendored
Normal file
5
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.h
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
|
@ -0,0 +1,3 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "unrealstatusGameModeBase.h"
|
15
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.h
vendored
Normal file
15
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.h
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "unrealstatusGameModeBase.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UNREALSTATUS_API AunrealstatusGameModeBase : public AGameModeBase {
|
||||
GENERATED_BODY()
|
||||
};
|
14
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatusEditor.Target.cs
vendored
Normal file
14
dependencies/discord-rpc/examples/unrealstatus/Source/unrealstatusEditor.Target.cs
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class unrealstatusEditorTarget : TargetRules
|
||||
{
|
||||
public unrealstatusEditorTarget(TargetInfo Target) : base(Target)
|
||||
{
|
||||
Type = TargetType.Editor;
|
||||
|
||||
ExtraModuleNames.AddRange( new string[] { "unrealstatus" } );
|
||||
}
|
||||
}
|
19
dependencies/discord-rpc/examples/unrealstatus/unrealstatus.uproject
vendored
Normal file
19
dependencies/discord-rpc/examples/unrealstatus/unrealstatus.uproject
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"FileVersion": 3,
|
||||
"EngineAssociation": "4.18",
|
||||
"Category": "",
|
||||
"Description": "",
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "unrealstatus",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default"
|
||||
}
|
||||
],
|
||||
"TargetPlatforms": [
|
||||
"LinuxNoEditor",
|
||||
"MacNoEditor",
|
||||
"WindowsNoEditor",
|
||||
"AllDesktop"
|
||||
]
|
||||
}
|
26
dependencies/discord-rpc/include/discord_register.h
vendored
Normal file
26
dependencies/discord-rpc/include/discord_register.h
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#if defined(DISCORD_DYNAMIC_LIB)
|
||||
#if defined(_WIN32)
|
||||
#if defined(DISCORD_BUILDING_SDK)
|
||||
#define DISCORD_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DISCORD_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define DISCORD_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#else
|
||||
#define DISCORD_EXPORT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command);
|
||||
DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
90
dependencies/discord-rpc/include/discord_rpc.h
vendored
Normal file
90
dependencies/discord-rpc/include/discord_rpc.h
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
// clang-format off
|
||||
|
||||
#if defined(DISCORD_DYNAMIC_LIB)
|
||||
# if defined(_WIN32)
|
||||
# if defined(DISCORD_BUILDING_SDK)
|
||||
# define DISCORD_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define DISCORD_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define DISCORD_EXPORT __attribute__((visibility("default")))
|
||||
# endif
|
||||
#else
|
||||
# define DISCORD_EXPORT
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct DiscordRichPresence {
|
||||
const char* state; /* max 128 bytes */
|
||||
const char* details; /* max 128 bytes */
|
||||
int64_t startTimestamp;
|
||||
int64_t endTimestamp;
|
||||
const char* largeImageKey; /* max 32 bytes */
|
||||
const char* largeImageText; /* max 128 bytes */
|
||||
const char* smallImageKey; /* max 32 bytes */
|
||||
const char* smallImageText; /* max 128 bytes */
|
||||
const char* partyId; /* max 128 bytes */
|
||||
int partySize;
|
||||
int partyMax;
|
||||
int partyPrivacy;
|
||||
const char* matchSecret; /* max 128 bytes */
|
||||
const char* joinSecret; /* max 128 bytes */
|
||||
const char* spectateSecret; /* max 128 bytes */
|
||||
int8_t instance;
|
||||
} DiscordRichPresence;
|
||||
|
||||
typedef struct DiscordUser {
|
||||
const char* userId;
|
||||
const char* username;
|
||||
const char* discriminator;
|
||||
const char* avatar;
|
||||
} DiscordUser;
|
||||
|
||||
typedef struct DiscordEventHandlers {
|
||||
void (*ready)(const DiscordUser* request);
|
||||
void (*disconnected)(int errorCode, const char* message);
|
||||
void (*errored)(int errorCode, const char* message);
|
||||
void (*joinGame)(const char* joinSecret);
|
||||
void (*spectateGame)(const char* spectateSecret);
|
||||
void (*joinRequest)(const DiscordUser* request);
|
||||
} DiscordEventHandlers;
|
||||
|
||||
#define DISCORD_REPLY_NO 0
|
||||
#define DISCORD_REPLY_YES 1
|
||||
#define DISCORD_REPLY_IGNORE 2
|
||||
#define DISCORD_PARTY_PRIVATE 0
|
||||
#define DISCORD_PARTY_PUBLIC 1
|
||||
|
||||
DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||
DiscordEventHandlers* handlers,
|
||||
int autoRegister,
|
||||
const char* optionalSteamId);
|
||||
DISCORD_EXPORT void Discord_Shutdown(void);
|
||||
|
||||
/* checks for incoming messages, dispatches callbacks */
|
||||
DISCORD_EXPORT void Discord_RunCallbacks(void);
|
||||
|
||||
/* If you disable the lib starting its own io thread, you'll need to call this from your own */
|
||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||
DISCORD_EXPORT void Discord_UpdateConnection(void);
|
||||
#endif
|
||||
|
||||
DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence);
|
||||
DISCORD_EXPORT void Discord_ClearPresence(void);
|
||||
|
||||
DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply);
|
||||
|
||||
DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
137
dependencies/discord-rpc/src/CMakeLists.txt
vendored
Normal file
137
dependencies/discord-rpc/src/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
|
||||
option(ENABLE_IO_THREAD "Start up a separate I/O thread, otherwise I'd need to call an update function" ON)
|
||||
option(WARNINGS_AS_ERRORS "When enabled, compiles with `-Werror` (on *nix platforms)." OFF)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
set(BASE_RPC_SRC
|
||||
${PROJECT_SOURCE_DIR}/include/discord_rpc.h
|
||||
discord_rpc.cpp
|
||||
${PROJECT_SOURCE_DIR}/include/discord_register.h
|
||||
rpc_connection.h
|
||||
rpc_connection.cpp
|
||||
serialization.h
|
||||
serialization.cpp
|
||||
connection.h
|
||||
backoff.h
|
||||
msg_queue.h
|
||||
)
|
||||
|
||||
if (${BUILD_SHARED_LIBS})
|
||||
if(WIN32)
|
||||
set(BASE_RPC_SRC ${BASE_RPC_SRC} dllmain.cpp)
|
||||
endif(WIN32)
|
||||
endif(${BUILD_SHARED_LIBS})
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DDISCORD_WINDOWS)
|
||||
set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_win.cpp discord_register_win.cpp)
|
||||
add_library(discord-rpc ${BASE_RPC_SRC})
|
||||
if (MSVC)
|
||||
set_property(TARGET discord-rpc PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
target_compile_options(discord-rpc PRIVATE /EHsc
|
||||
/Wall
|
||||
/wd4100 # unreferenced formal parameter
|
||||
/wd4514 # unreferenced inline
|
||||
/wd4625 # copy constructor deleted
|
||||
/wd5026 # move constructor deleted
|
||||
/wd4626 # move assignment operator deleted
|
||||
/wd4668 # not defined preprocessor macro
|
||||
/wd4710 # function not inlined
|
||||
/wd4711 # function was inlined
|
||||
/wd4820 # structure padding
|
||||
/wd4946 # reinterpret_cast used between related classes
|
||||
/wd5027 # move assignment operator was implicitly defined as deleted
|
||||
)
|
||||
endif(MSVC)
|
||||
target_link_libraries(discord-rpc PRIVATE psapi advapi32)
|
||||
endif(WIN32)
|
||||
|
||||
if(UNIX)
|
||||
set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_unix.cpp)
|
||||
|
||||
if (APPLE)
|
||||
add_definitions(-DDISCORD_OSX)
|
||||
set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_osx.m)
|
||||
else (APPLE)
|
||||
add_definitions(-DDISCORD_LINUX)
|
||||
set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_linux.cpp)
|
||||
endif(APPLE)
|
||||
|
||||
add_library(discord-rpc ${BASE_RPC_SRC})
|
||||
target_link_libraries(discord-rpc PUBLIC pthread)
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(discord-rpc PRIVATE "-framework AppKit, -mmacosx-version-min=10.10")
|
||||
endif (APPLE)
|
||||
|
||||
target_compile_options(discord-rpc PRIVATE
|
||||
-g
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wpedantic
|
||||
)
|
||||
|
||||
if (${WARNINGS_AS_ERRORS})
|
||||
target_compile_options(discord-rpc PRIVATE -Werror)
|
||||
endif (${WARNINGS_AS_ERRORS})
|
||||
|
||||
target_compile_options(discord-rpc PRIVATE
|
||||
-Wno-unknown-pragmas # pragma push thing doesn't work on clang
|
||||
-Wno-old-style-cast # it's fine
|
||||
-Wno-c++98-compat # that was almost 2 decades ago
|
||||
-Wno-c++98-compat-pedantic
|
||||
-Wno-missing-noreturn
|
||||
-Wno-padded # structure padding
|
||||
-Wno-covered-switch-default
|
||||
-Wno-exit-time-destructors # not sure about these
|
||||
-Wno-global-constructors
|
||||
)
|
||||
|
||||
if (${BUILD_SHARED_LIBS})
|
||||
target_compile_options(discord-rpc PRIVATE -fPIC)
|
||||
endif (${BUILD_SHARED_LIBS})
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(discord-rpc PRIVATE "-framework AppKit")
|
||||
endif (APPLE)
|
||||
endif(UNIX)
|
||||
|
||||
target_link_libraries(discord-rpc PRIVATE rapidjson)
|
||||
#target_include_directories(discord-rpc PRIVATE ${RAPIDJSON}/include)
|
||||
|
||||
if (NOT ${ENABLE_IO_THREAD})
|
||||
target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DISABLE_IO_THREAD)
|
||||
endif (NOT ${ENABLE_IO_THREAD})
|
||||
|
||||
if (${BUILD_SHARED_LIBS})
|
||||
target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DYNAMIC_LIB)
|
||||
target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK)
|
||||
endif(${BUILD_SHARED_LIBS})
|
||||
|
||||
if (CLANG_FORMAT_CMD)
|
||||
add_dependencies(discord-rpc clangformat)
|
||||
endif(CLANG_FORMAT_CMD)
|
||||
|
||||
# install
|
||||
|
||||
install(
|
||||
TARGETS discord-rpc
|
||||
EXPORT "discord-rpc"
|
||||
RUNTIME
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
LIBRARY
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
ARCHIVE
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
INCLUDES
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
"../include/discord_rpc.h"
|
||||
"../include/discord_register.h"
|
||||
DESTINATION "include"
|
||||
)
|
40
dependencies/discord-rpc/src/backoff.h
vendored
Normal file
40
dependencies/discord-rpc/src/backoff.h
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
struct Backoff {
|
||||
int64_t minAmount;
|
||||
int64_t maxAmount;
|
||||
int64_t current;
|
||||
int fails;
|
||||
std::mt19937_64 randGenerator;
|
||||
std::uniform_real_distribution<> randDistribution;
|
||||
|
||||
double rand01() { return randDistribution(randGenerator); }
|
||||
|
||||
Backoff(int64_t min, int64_t max)
|
||||
: minAmount(min)
|
||||
, maxAmount(max)
|
||||
, current(min)
|
||||
, fails(0)
|
||||
, randGenerator((uint64_t)time(0))
|
||||
{
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
fails = 0;
|
||||
current = minAmount;
|
||||
}
|
||||
|
||||
int64_t nextDelay()
|
||||
{
|
||||
++fails;
|
||||
int64_t delay = (int64_t)((double)current * 2.0 * rand01());
|
||||
current = std::min(current + delay, maxAmount);
|
||||
return current;
|
||||
}
|
||||
};
|
19
dependencies/discord-rpc/src/connection.h
vendored
Normal file
19
dependencies/discord-rpc/src/connection.h
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
// This is to wrap the platform specific kinds of connect/read/write.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// not really connectiony, but need per-platform
|
||||
int GetProcessId();
|
||||
|
||||
struct BaseConnection {
|
||||
static BaseConnection* Create();
|
||||
static void Destroy(BaseConnection*&);
|
||||
bool isOpen{false};
|
||||
bool Open();
|
||||
bool Close();
|
||||
bool Write(const void* data, size_t length);
|
||||
bool Read(void* data, size_t length);
|
||||
};
|
125
dependencies/discord-rpc/src/connection_unix.cpp
vendored
Normal file
125
dependencies/discord-rpc/src/connection_unix.cpp
vendored
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include "connection.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int GetProcessId()
|
||||
{
|
||||
return ::getpid();
|
||||
}
|
||||
|
||||
struct BaseConnectionUnix : public BaseConnection {
|
||||
int sock{-1};
|
||||
};
|
||||
|
||||
static BaseConnectionUnix Connection;
|
||||
static sockaddr_un PipeAddr{};
|
||||
#ifdef MSG_NOSIGNAL
|
||||
static int MsgFlags = MSG_NOSIGNAL;
|
||||
#else
|
||||
static int MsgFlags = 0;
|
||||
#endif
|
||||
|
||||
static const char* GetTempPath()
|
||||
{
|
||||
const char* temp = getenv("XDG_RUNTIME_DIR");
|
||||
temp = temp ? temp : getenv("TMPDIR");
|
||||
temp = temp ? temp : getenv("TMP");
|
||||
temp = temp ? temp : getenv("TEMP");
|
||||
temp = temp ? temp : "/tmp";
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*static*/ BaseConnection* BaseConnection::Create()
|
||||
{
|
||||
PipeAddr.sun_family = AF_UNIX;
|
||||
return &Connection;
|
||||
}
|
||||
|
||||
/*static*/ void BaseConnection::Destroy(BaseConnection*& c)
|
||||
{
|
||||
auto self = reinterpret_cast<BaseConnectionUnix*>(c);
|
||||
self->Close();
|
||||
c = nullptr;
|
||||
}
|
||||
|
||||
bool BaseConnection::Open()
|
||||
{
|
||||
const char* tempPath = GetTempPath();
|
||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||
self->sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (self->sock == -1) {
|
||||
return false;
|
||||
}
|
||||
fcntl(self->sock, F_SETFL, O_NONBLOCK);
|
||||
#ifdef SO_NOSIGPIPE
|
||||
int optval = 1;
|
||||
setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
|
||||
#endif
|
||||
|
||||
for (int pipeNum = 0; pipeNum < 10; ++pipeNum) {
|
||||
snprintf(
|
||||
PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum);
|
||||
int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr));
|
||||
if (err == 0) {
|
||||
self->isOpen = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
self->Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BaseConnection::Close()
|
||||
{
|
||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||
if (self->sock == -1) {
|
||||
return false;
|
||||
}
|
||||
close(self->sock);
|
||||
self->sock = -1;
|
||||
self->isOpen = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaseConnection::Write(const void* data, size_t length)
|
||||
{
|
||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||
|
||||
if (self->sock == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ssize_t sentBytes = send(self->sock, data, length, MsgFlags);
|
||||
if (sentBytes < 0) {
|
||||
Close();
|
||||
}
|
||||
return sentBytes == (ssize_t)length;
|
||||
}
|
||||
|
||||
bool BaseConnection::Read(void* data, size_t length)
|
||||
{
|
||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||
|
||||
if (self->sock == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int res = (int)recv(self->sock, data, length, MsgFlags);
|
||||
if (res < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
return false;
|
||||
}
|
||||
Close();
|
||||
}
|
||||
else if (res == 0) {
|
||||
Close();
|
||||
}
|
||||
return res == (int)length;
|
||||
}
|
128
dependencies/discord-rpc/src/connection_win.cpp
vendored
Normal file
128
dependencies/discord-rpc/src/connection_win.cpp
vendored
Normal file
|
@ -0,0 +1,128 @@
|
|||
#include "connection.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMCX
|
||||
#define NOSERVICE
|
||||
#define NOIME
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
|
||||
int GetProcessId()
|
||||
{
|
||||
return (int)::GetCurrentProcessId();
|
||||
}
|
||||
|
||||
struct BaseConnectionWin : public BaseConnection {
|
||||
HANDLE pipe{INVALID_HANDLE_VALUE};
|
||||
};
|
||||
|
||||
static BaseConnectionWin Connection;
|
||||
|
||||
/*static*/ BaseConnection* BaseConnection::Create()
|
||||
{
|
||||
return &Connection;
|
||||
}
|
||||
|
||||
/*static*/ void BaseConnection::Destroy(BaseConnection*& c)
|
||||
{
|
||||
auto self = reinterpret_cast<BaseConnectionWin*>(c);
|
||||
self->Close();
|
||||
c = nullptr;
|
||||
}
|
||||
|
||||
bool BaseConnection::Open()
|
||||
{
|
||||
wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"};
|
||||
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
|
||||
pipeName[pipeDigit] = L'0';
|
||||
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||
for (;;) {
|
||||
self->pipe = ::CreateFileW(
|
||||
pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (self->pipe != INVALID_HANDLE_VALUE) {
|
||||
self->isOpen = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_FILE_NOT_FOUND) {
|
||||
if (pipeName[pipeDigit] < L'9') {
|
||||
pipeName[pipeDigit]++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (lastError == ERROR_PIPE_BUSY) {
|
||||
if (!WaitNamedPipeW(pipeName, 10000)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseConnection::Close()
|
||||
{
|
||||
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||
::CloseHandle(self->pipe);
|
||||
self->pipe = INVALID_HANDLE_VALUE;
|
||||
self->isOpen = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaseConnection::Write(const void* data, size_t length)
|
||||
{
|
||||
if (length == 0) {
|
||||
return true;
|
||||
}
|
||||
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||
assert(self);
|
||||
if (!self) {
|
||||
return false;
|
||||
}
|
||||
if (self->pipe == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
assert(data);
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
const DWORD bytesLength = (DWORD)length;
|
||||
DWORD bytesWritten = 0;
|
||||
return ::WriteFile(self->pipe, data, bytesLength, &bytesWritten, nullptr) == TRUE &&
|
||||
bytesWritten == bytesLength;
|
||||
}
|
||||
|
||||
bool BaseConnection::Read(void* data, size_t length)
|
||||
{
|
||||
assert(data);
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||
assert(self);
|
||||
if (!self) {
|
||||
return false;
|
||||
}
|
||||
if (self->pipe == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
DWORD bytesAvailable = 0;
|
||||
if (::PeekNamedPipe(self->pipe, nullptr, 0, nullptr, &bytesAvailable, nullptr)) {
|
||||
if (bytesAvailable >= length) {
|
||||
DWORD bytesToRead = (DWORD)length;
|
||||
DWORD bytesRead = 0;
|
||||
if (::ReadFile(self->pipe, data, bytesToRead, &bytesRead, nullptr) == TRUE) {
|
||||
assert(bytesToRead == bytesRead);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Close();
|
||||
}
|
||||
return false;
|
||||
}
|
102
dependencies/discord-rpc/src/discord_register_linux.cpp
vendored
Normal file
102
dependencies/discord-rpc/src/discord_register_linux.cpp
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
#include "discord_rpc.h"
|
||||
#include "discord_register.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static bool Mkdir(const char* path)
|
||||
{
|
||||
int result = mkdir(path, 0755);
|
||||
if (result == 0) {
|
||||
return true;
|
||||
}
|
||||
if (errno == EEXIST) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// we want to register games so we can run them from Discord client as discord-<appid>://
|
||||
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
|
||||
{
|
||||
// Add a desktop file and update some mime handlers so that xdg-open does the right thing.
|
||||
|
||||
const char* home = getenv("HOME");
|
||||
if (!home) {
|
||||
return;
|
||||
}
|
||||
|
||||
char exePath[1024];
|
||||
if (!command || !command[0]) {
|
||||
ssize_t size = readlink("/proc/self/exe", exePath, sizeof(exePath));
|
||||
if (size <= 0 || size >= (ssize_t)sizeof(exePath)) {
|
||||
return;
|
||||
}
|
||||
exePath[size] = '\0';
|
||||
command = exePath;
|
||||
}
|
||||
|
||||
const char* desktopFileFormat = "[Desktop Entry]\n"
|
||||
"Name=Game %s\n"
|
||||
"Exec=%s %%u\n" // note: it really wants that %u in there
|
||||
"Type=Application\n"
|
||||
"NoDisplay=true\n"
|
||||
"Categories=Discord;Games;\n"
|
||||
"MimeType=x-scheme-handler/discord-%s;\n";
|
||||
char desktopFile[2048];
|
||||
int fileLen = snprintf(
|
||||
desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId);
|
||||
if (fileLen <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char desktopFilename[256];
|
||||
snprintf(desktopFilename, sizeof(desktopFilename), "/discord-%s.desktop", applicationId);
|
||||
|
||||
char desktopFilePath[1024];
|
||||
snprintf(desktopFilePath, sizeof(desktopFilePath), "%s/.local", home);
|
||||
if (!Mkdir(desktopFilePath)) {
|
||||
return;
|
||||
}
|
||||
strcat(desktopFilePath, "/share");
|
||||
if (!Mkdir(desktopFilePath)) {
|
||||
return;
|
||||
}
|
||||
strcat(desktopFilePath, "/applications");
|
||||
if (!Mkdir(desktopFilePath)) {
|
||||
return;
|
||||
}
|
||||
strcat(desktopFilePath, desktopFilename);
|
||||
|
||||
FILE* fp = fopen(desktopFilePath, "w");
|
||||
if (fp) {
|
||||
fwrite(desktopFile, 1, fileLen, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
char xdgMimeCommand[1024];
|
||||
snprintf(xdgMimeCommand,
|
||||
sizeof(xdgMimeCommand),
|
||||
"xdg-mime default discord-%s.desktop x-scheme-handler/discord-%s",
|
||||
applicationId,
|
||||
applicationId);
|
||||
if (system(xdgMimeCommand) < 0) {
|
||||
fprintf(stderr, "Failed to register mime handler\n");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
|
||||
const char* steamId)
|
||||
{
|
||||
char command[256];
|
||||
sprintf(command, "xdg-open steam://rungameid/%s", steamId);
|
||||
Discord_Register(applicationId, command);
|
||||
}
|
80
dependencies/discord-rpc/src/discord_register_osx.m
vendored
Normal file
80
dependencies/discord-rpc/src/discord_register_osx.m
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#include "discord_register.h"
|
||||
|
||||
static void RegisterCommand(const char* applicationId, const char* command)
|
||||
{
|
||||
// There does not appear to be a way to register arbitrary commands on OSX, so instead we'll save the command
|
||||
// to a file in the Discord config path, and when it is needed, Discord can try to load the file there, open
|
||||
// the command therein (will pass to js's window.open, so requires a url-like thing)
|
||||
|
||||
// Note: will not work for sandboxed apps
|
||||
NSString *home = NSHomeDirectory();
|
||||
if (!home) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *path = [[[[[[home stringByAppendingPathComponent:@"Library"]
|
||||
stringByAppendingPathComponent:@"Application Support"]
|
||||
stringByAppendingPathComponent:@"discord"]
|
||||
stringByAppendingPathComponent:@"games"]
|
||||
stringByAppendingPathComponent:[NSString stringWithUTF8String:applicationId]]
|
||||
stringByAppendingPathExtension:@"json"];
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
|
||||
NSString *jsonBuffer = [NSString stringWithFormat:@"{\"command\": \"%s\"}", command];
|
||||
[jsonBuffer writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:nil];
|
||||
}
|
||||
|
||||
static void RegisterURL(const char* applicationId)
|
||||
{
|
||||
char url[256];
|
||||
snprintf(url, sizeof(url), "discord-%s", applicationId);
|
||||
CFStringRef cfURL = CFStringCreateWithCString(NULL, url, kCFStringEncodingUTF8);
|
||||
|
||||
NSString* myBundleId = [[NSBundle mainBundle] bundleIdentifier];
|
||||
if (!myBundleId) {
|
||||
fprintf(stderr, "No bundle id found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL* myURL = [[NSBundle mainBundle] bundleURL];
|
||||
if (!myURL) {
|
||||
fprintf(stderr, "No bundle url found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
OSStatus status = LSSetDefaultHandlerForURLScheme(cfURL, (__bridge CFStringRef)myBundleId);
|
||||
if (status != noErr) {
|
||||
fprintf(stderr, "Error in LSSetDefaultHandlerForURLScheme: %d\n", (int)status);
|
||||
return;
|
||||
}
|
||||
|
||||
status = LSRegisterURL((__bridge CFURLRef)myURL, true);
|
||||
if (status != noErr) {
|
||||
fprintf(stderr, "Error in LSRegisterURL: %d\n", (int)status);
|
||||
}
|
||||
}
|
||||
|
||||
void Discord_Register(const char* applicationId, const char* command)
|
||||
{
|
||||
if (command) {
|
||||
RegisterCommand(applicationId, command);
|
||||
}
|
||||
else {
|
||||
// raii lite
|
||||
@autoreleasepool {
|
||||
RegisterURL(applicationId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Discord_RegisterSteamGame(const char* applicationId, const char* steamId)
|
||||
{
|
||||
char command[256];
|
||||
snprintf(command, 256, "steam://rungameid/%s", steamId);
|
||||
Discord_Register(applicationId, command);
|
||||
}
|
186
dependencies/discord-rpc/src/discord_register_win.cpp
vendored
Normal file
186
dependencies/discord-rpc/src/discord_register_win.cpp
vendored
Normal file
|
@ -0,0 +1,186 @@
|
|||
#include "discord_rpc.h"
|
||||
#include "discord_register.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMCX
|
||||
#define NOSERVICE
|
||||
#define NOIME
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <cstdio>
|
||||
|
||||
/**
|
||||
* Updated fixes for MinGW and WinXP
|
||||
* This block is written the way it does not involve changing the rest of the code
|
||||
* Checked to be compiling
|
||||
* 1) strsafe.h belongs to Windows SDK and cannot be added to MinGW
|
||||
* #include guarded, functions redirected to <string.h> substitutes
|
||||
* 2) RegSetKeyValueW and LSTATUS are not declared in <winreg.h>
|
||||
* The entire function is rewritten
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
#include <wchar.h>
|
||||
/// strsafe.h fixes
|
||||
static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...)
|
||||
{
|
||||
HRESULT ret;
|
||||
va_list va;
|
||||
va_start(va, pszFormat);
|
||||
cbDest /= 2; // Size is divided by 2 to convert from bytes to wide characters - causes segfault
|
||||
// othervise
|
||||
ret = vsnwprintf(pszDest, cbDest, pszFormat, va);
|
||||
pszDest[cbDest - 1] = 0; // Terminate the string in case a buffer overflow; -1 will be returned
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#include <cwchar>
|
||||
#include <strsafe.h>
|
||||
#endif // __MINGW32__
|
||||
|
||||
/// winreg.h fixes
|
||||
#ifndef LSTATUS
|
||||
#define LSTATUS LONG
|
||||
#endif
|
||||
#ifdef RegSetKeyValueW
|
||||
#undefine RegSetKeyValueW
|
||||
#endif
|
||||
#define RegSetKeyValueW regset
|
||||
static LSTATUS regset(HKEY hkey,
|
||||
LPCWSTR subkey,
|
||||
LPCWSTR name,
|
||||
DWORD type,
|
||||
const void* data,
|
||||
DWORD len)
|
||||
{
|
||||
HKEY htkey = hkey, hsubkey = nullptr;
|
||||
LSTATUS ret;
|
||||
if (subkey && subkey[0]) {
|
||||
if ((ret = RegCreateKeyExW(hkey, subkey, 0, 0, 0, KEY_ALL_ACCESS, 0, &hsubkey, 0)) !=
|
||||
ERROR_SUCCESS)
|
||||
return ret;
|
||||
htkey = hsubkey;
|
||||
}
|
||||
ret = RegSetValueExW(htkey, name, 0, type, (const BYTE*)data, len);
|
||||
if (hsubkey && hsubkey != hkey)
|
||||
RegCloseKey(hsubkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command)
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
|
||||
// we want to register games so we can run them as discord-<appid>://
|
||||
// Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions.
|
||||
|
||||
wchar_t exeFilePath[MAX_PATH];
|
||||
DWORD exeLen = GetModuleFileNameW(nullptr, exeFilePath, MAX_PATH);
|
||||
wchar_t openCommand[1024];
|
||||
|
||||
if (command && command[0]) {
|
||||
StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", command);
|
||||
}
|
||||
else {
|
||||
// StringCbCopyW(openCommand, sizeof(openCommand), exeFilePath);
|
||||
StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", exeFilePath);
|
||||
}
|
||||
|
||||
wchar_t protocolName[64];
|
||||
StringCbPrintfW(protocolName, sizeof(protocolName), L"discord-%s", applicationId);
|
||||
wchar_t protocolDescription[128];
|
||||
StringCbPrintfW(
|
||||
protocolDescription, sizeof(protocolDescription), L"URL:Run game %s protocol", applicationId);
|
||||
wchar_t urlProtocol = 0;
|
||||
|
||||
wchar_t keyName[256];
|
||||
StringCbPrintfW(keyName, sizeof(keyName), L"Software\\Classes\\%s", protocolName);
|
||||
HKEY key;
|
||||
auto status =
|
||||
RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, nullptr, 0, KEY_WRITE, nullptr, &key, nullptr);
|
||||
if (status != ERROR_SUCCESS) {
|
||||
fprintf(stderr, "Error creating key\n");
|
||||
return;
|
||||
}
|
||||
DWORD len;
|
||||
LSTATUS result;
|
||||
len = (DWORD)lstrlenW(protocolDescription) + 1;
|
||||
result =
|
||||
RegSetKeyValueW(key, nullptr, nullptr, REG_SZ, protocolDescription, len * sizeof(wchar_t));
|
||||
if (FAILED(result)) {
|
||||
fprintf(stderr, "Error writing description\n");
|
||||
}
|
||||
|
||||
len = (DWORD)lstrlenW(protocolDescription) + 1;
|
||||
result = RegSetKeyValueW(key, nullptr, L"URL Protocol", REG_SZ, &urlProtocol, sizeof(wchar_t));
|
||||
if (FAILED(result)) {
|
||||
fprintf(stderr, "Error writing description\n");
|
||||
}
|
||||
|
||||
result = RegSetKeyValueW(
|
||||
key, L"DefaultIcon", nullptr, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t));
|
||||
if (FAILED(result)) {
|
||||
fprintf(stderr, "Error writing icon\n");
|
||||
}
|
||||
|
||||
len = (DWORD)lstrlenW(openCommand) + 1;
|
||||
result = RegSetKeyValueW(
|
||||
key, L"shell\\open\\command", nullptr, REG_SZ, openCommand, len * sizeof(wchar_t));
|
||||
if (FAILED(result)) {
|
||||
fprintf(stderr, "Error writing command\n");
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
|
||||
{
|
||||
wchar_t appId[32];
|
||||
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||
|
||||
wchar_t openCommand[1024];
|
||||
const wchar_t* wcommand = nullptr;
|
||||
if (command && command[0]) {
|
||||
const auto commandBufferLen = sizeof(openCommand) / sizeof(*openCommand);
|
||||
MultiByteToWideChar(CP_UTF8, 0, command, -1, openCommand, commandBufferLen);
|
||||
wcommand = openCommand;
|
||||
}
|
||||
|
||||
Discord_RegisterW(appId, wcommand);
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
|
||||
const char* steamId)
|
||||
{
|
||||
wchar_t appId[32];
|
||||
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||
|
||||
wchar_t wSteamId[32];
|
||||
MultiByteToWideChar(CP_UTF8, 0, steamId, -1, wSteamId, 32);
|
||||
|
||||
HKEY key;
|
||||
auto status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &key);
|
||||
if (status != ERROR_SUCCESS) {
|
||||
fprintf(stderr, "Error opening Steam key\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t steamPath[MAX_PATH];
|
||||
DWORD pathBytes = sizeof(steamPath);
|
||||
status = RegQueryValueExW(key, L"SteamExe", nullptr, nullptr, (BYTE*)steamPath, &pathBytes);
|
||||
RegCloseKey(key);
|
||||
if (status != ERROR_SUCCESS || pathBytes < 1) {
|
||||
fprintf(stderr, "Error reading SteamExe key\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD pathChars = pathBytes / sizeof(wchar_t);
|
||||
for (DWORD i = 0; i < pathChars; ++i) {
|
||||
if (steamPath[i] == L'/') {
|
||||
steamPath[i] = L'\\';
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t command[1024];
|
||||
StringCbPrintfW(command, sizeof(command), L"\"%s\" steam://rungameid/%s", steamPath, wSteamId);
|
||||
|
||||
Discord_RegisterW(appId, command);
|
||||
}
|
504
dependencies/discord-rpc/src/discord_rpc.cpp
vendored
Normal file
504
dependencies/discord-rpc/src/discord_rpc.cpp
vendored
Normal file
|
@ -0,0 +1,504 @@
|
|||
#include "discord_rpc.h"
|
||||
|
||||
#include "backoff.h"
|
||||
#include "discord_register.h"
|
||||
#include "msg_queue.h"
|
||||
#include "rpc_connection.h"
|
||||
#include "serialization.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
constexpr size_t MaxMessageSize{16 * 1024};
|
||||
constexpr size_t MessageQueueSize{8};
|
||||
constexpr size_t JoinQueueSize{8};
|
||||
|
||||
struct QueuedMessage {
|
||||
size_t length;
|
||||
char buffer[MaxMessageSize];
|
||||
|
||||
void Copy(const QueuedMessage& other)
|
||||
{
|
||||
length = other.length;
|
||||
if (length) {
|
||||
memcpy(buffer, other.buffer, length);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct User {
|
||||
// snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null
|
||||
// terminator = 21
|
||||
char userId[32];
|
||||
// 32 unicode glyphs is max name size => 4 bytes per glyph in the worst case, +1 for null
|
||||
// terminator = 129
|
||||
char username[344];
|
||||
// 4 decimal digits + 1 null terminator = 5
|
||||
char discriminator[8];
|
||||
// optional 'a_' + md5 hex digest (32 bytes) + null terminator = 35
|
||||
char avatar[128];
|
||||
// Rounded way up because I'm paranoid about games breaking from future changes in these sizes
|
||||
};
|
||||
|
||||
static RpcConnection* Connection{nullptr};
|
||||
static DiscordEventHandlers QueuedHandlers{};
|
||||
static DiscordEventHandlers Handlers{};
|
||||
static std::atomic_bool WasJustConnected{false};
|
||||
static std::atomic_bool WasJustDisconnected{false};
|
||||
static std::atomic_bool GotErrorMessage{false};
|
||||
static std::atomic_bool WasJoinGame{false};
|
||||
static std::atomic_bool WasSpectateGame{false};
|
||||
static std::atomic_bool UpdatePresence{false};
|
||||
static char JoinGameSecret[256];
|
||||
static char SpectateGameSecret[256];
|
||||
static int LastErrorCode{0};
|
||||
static char LastErrorMessage[256];
|
||||
static int LastDisconnectErrorCode{0};
|
||||
static char LastDisconnectErrorMessage[256];
|
||||
static std::mutex PresenceMutex;
|
||||
static std::mutex HandlerMutex;
|
||||
static QueuedMessage QueuedPresence{};
|
||||
static MsgQueue<QueuedMessage, MessageQueueSize> SendQueue;
|
||||
static MsgQueue<User, JoinQueueSize> JoinAskQueue;
|
||||
static User connectedUser;
|
||||
|
||||
// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential
|
||||
// backoff from 0.5 seconds to 1 minute
|
||||
static Backoff ReconnectTimeMs(500, 60 * 1000);
|
||||
static auto NextConnect = std::chrono::system_clock::now();
|
||||
static int Pid{0};
|
||||
static int Nonce{1};
|
||||
|
||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||
static void Discord_UpdateConnection(void);
|
||||
class IoThreadHolder {
|
||||
private:
|
||||
std::atomic_bool keepRunning{true};
|
||||
std::mutex waitForIOMutex;
|
||||
std::condition_variable waitForIOActivity;
|
||||
std::thread ioThread;
|
||||
|
||||
public:
|
||||
void Start()
|
||||
{
|
||||
keepRunning.store(true);
|
||||
ioThread = std::thread([&]() {
|
||||
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
||||
Discord_UpdateConnection();
|
||||
while (keepRunning.load()) {
|
||||
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
||||
waitForIOActivity.wait_for(lock, maxWait);
|
||||
Discord_UpdateConnection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Notify() { waitForIOActivity.notify_all(); }
|
||||
|
||||
void Stop()
|
||||
{
|
||||
keepRunning.exchange(false);
|
||||
Notify();
|
||||
if (ioThread.joinable()) {
|
||||
ioThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
~IoThreadHolder() { Stop(); }
|
||||
};
|
||||
#else
|
||||
class IoThreadHolder {
|
||||
public:
|
||||
void Start() {}
|
||||
void Stop() {}
|
||||
void Notify() {}
|
||||
};
|
||||
#endif // DISCORD_DISABLE_IO_THREAD
|
||||
static IoThreadHolder* IoThread{nullptr};
|
||||
|
||||
static void UpdateReconnectTime()
|
||||
{
|
||||
NextConnect = std::chrono::system_clock::now() +
|
||||
std::chrono::duration<int64_t, std::milli>{ReconnectTimeMs.nextDelay()};
|
||||
}
|
||||
|
||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||
extern "C" DISCORD_EXPORT void Discord_UpdateConnection(void)
|
||||
#else
|
||||
static void Discord_UpdateConnection(void)
|
||||
#endif
|
||||
{
|
||||
if (!Connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Connection->IsOpen()) {
|
||||
if (std::chrono::system_clock::now() >= NextConnect) {
|
||||
UpdateReconnectTime();
|
||||
Connection->Open();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// reads
|
||||
|
||||
for (;;) {
|
||||
JsonDocument message;
|
||||
|
||||
if (!Connection->Read(message)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const char* evtName = GetStrMember(&message, "evt");
|
||||
const char* nonce = GetStrMember(&message, "nonce");
|
||||
|
||||
if (nonce) {
|
||||
// in responses only -- should use to match up response when needed.
|
||||
|
||||
if (evtName && strcmp(evtName, "ERROR") == 0) {
|
||||
auto data = GetObjMember(&message, "data");
|
||||
LastErrorCode = GetIntMember(data, "code");
|
||||
StringCopy(LastErrorMessage, GetStrMember(data, "message", ""));
|
||||
GotErrorMessage.store(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// should have evt == name of event, optional data
|
||||
if (evtName == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto data = GetObjMember(&message, "data");
|
||||
|
||||
if (strcmp(evtName, "ACTIVITY_JOIN") == 0) {
|
||||
auto secret = GetStrMember(data, "secret");
|
||||
if (secret) {
|
||||
StringCopy(JoinGameSecret, secret);
|
||||
WasJoinGame.store(true);
|
||||
}
|
||||
}
|
||||
else if (strcmp(evtName, "ACTIVITY_SPECTATE") == 0) {
|
||||
auto secret = GetStrMember(data, "secret");
|
||||
if (secret) {
|
||||
StringCopy(SpectateGameSecret, secret);
|
||||
WasSpectateGame.store(true);
|
||||
}
|
||||
}
|
||||
else if (strcmp(evtName, "ACTIVITY_JOIN_REQUEST") == 0) {
|
||||
auto user = GetObjMember(data, "user");
|
||||
auto userId = GetStrMember(user, "id");
|
||||
auto username = GetStrMember(user, "username");
|
||||
auto avatar = GetStrMember(user, "avatar");
|
||||
auto joinReq = JoinAskQueue.GetNextAddMessage();
|
||||
if (userId && username && joinReq) {
|
||||
StringCopy(joinReq->userId, userId);
|
||||
StringCopy(joinReq->username, username);
|
||||
auto discriminator = GetStrMember(user, "discriminator");
|
||||
if (discriminator) {
|
||||
StringCopy(joinReq->discriminator, discriminator);
|
||||
}
|
||||
if (avatar) {
|
||||
StringCopy(joinReq->avatar, avatar);
|
||||
}
|
||||
else {
|
||||
joinReq->avatar[0] = 0;
|
||||
}
|
||||
JoinAskQueue.CommitAdd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// writes
|
||||
if (UpdatePresence.exchange(false) && QueuedPresence.length) {
|
||||
QueuedMessage local;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
local.Copy(QueuedPresence);
|
||||
}
|
||||
if (!Connection->Write(local.buffer, local.length)) {
|
||||
// if we fail to send, requeue
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
QueuedPresence.Copy(local);
|
||||
UpdatePresence.exchange(true);
|
||||
}
|
||||
}
|
||||
|
||||
while (SendQueue.HavePendingSends()) {
|
||||
auto qmessage = SendQueue.GetNextSendMessage();
|
||||
Connection->Write(qmessage->buffer, qmessage->length);
|
||||
SendQueue.CommitSend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SignalIOActivity()
|
||||
{
|
||||
if (IoThread != nullptr) {
|
||||
IoThread->Notify();
|
||||
}
|
||||
}
|
||||
|
||||
static bool RegisterForEvent(const char* evtName)
|
||||
{
|
||||
auto qmessage = SendQueue.GetNextAddMessage();
|
||||
if (qmessage) {
|
||||
qmessage->length =
|
||||
JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
|
||||
SendQueue.CommitAdd();
|
||||
SignalIOActivity();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool DeregisterForEvent(const char* evtName)
|
||||
{
|
||||
auto qmessage = SendQueue.GetNextAddMessage();
|
||||
if (qmessage) {
|
||||
qmessage->length =
|
||||
JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
|
||||
SendQueue.CommitAdd();
|
||||
SignalIOActivity();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||
DiscordEventHandlers* handlers,
|
||||
int autoRegister,
|
||||
const char* optionalSteamId)
|
||||
{
|
||||
IoThread = new (std::nothrow) IoThreadHolder();
|
||||
if (IoThread == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (autoRegister) {
|
||||
if (optionalSteamId && optionalSteamId[0]) {
|
||||
Discord_RegisterSteamGame(applicationId, optionalSteamId);
|
||||
}
|
||||
else {
|
||||
Discord_Register(applicationId, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Pid = GetProcessId();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
|
||||
if (handlers) {
|
||||
QueuedHandlers = *handlers;
|
||||
}
|
||||
else {
|
||||
QueuedHandlers = {};
|
||||
}
|
||||
|
||||
Handlers = {};
|
||||
}
|
||||
|
||||
if (Connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
Connection = RpcConnection::Create(applicationId);
|
||||
Connection->onConnect = [](JsonDocument& readyMessage) {
|
||||
Discord_UpdateHandlers(&QueuedHandlers);
|
||||
if (QueuedPresence.length > 0) {
|
||||
UpdatePresence.exchange(true);
|
||||
SignalIOActivity();
|
||||
}
|
||||
auto data = GetObjMember(&readyMessage, "data");
|
||||
auto user = GetObjMember(data, "user");
|
||||
auto userId = GetStrMember(user, "id");
|
||||
auto username = GetStrMember(user, "username");
|
||||
auto avatar = GetStrMember(user, "avatar");
|
||||
if (userId && username) {
|
||||
StringCopy(connectedUser.userId, userId);
|
||||
StringCopy(connectedUser.username, username);
|
||||
auto discriminator = GetStrMember(user, "discriminator");
|
||||
if (discriminator) {
|
||||
StringCopy(connectedUser.discriminator, discriminator);
|
||||
}
|
||||
if (avatar) {
|
||||
StringCopy(connectedUser.avatar, avatar);
|
||||
}
|
||||
else {
|
||||
connectedUser.avatar[0] = 0;
|
||||
}
|
||||
}
|
||||
WasJustConnected.exchange(true);
|
||||
ReconnectTimeMs.reset();
|
||||
};
|
||||
Connection->onDisconnect = [](int err, const char* message) {
|
||||
LastDisconnectErrorCode = err;
|
||||
StringCopy(LastDisconnectErrorMessage, message);
|
||||
WasJustDisconnected.exchange(true);
|
||||
UpdateReconnectTime();
|
||||
};
|
||||
|
||||
IoThread->Start();
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_Shutdown(void)
|
||||
{
|
||||
if (!Connection) {
|
||||
return;
|
||||
}
|
||||
Connection->onConnect = nullptr;
|
||||
Connection->onDisconnect = nullptr;
|
||||
Handlers = {};
|
||||
QueuedPresence.length = 0;
|
||||
UpdatePresence.exchange(false);
|
||||
if (IoThread != nullptr) {
|
||||
IoThread->Stop();
|
||||
delete IoThread;
|
||||
IoThread = nullptr;
|
||||
}
|
||||
|
||||
RpcConnection::Destroy(Connection);
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
QueuedPresence.length = JsonWriteRichPresenceObj(
|
||||
QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence);
|
||||
UpdatePresence.exchange(true);
|
||||
}
|
||||
SignalIOActivity();
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_ClearPresence(void)
|
||||
{
|
||||
Discord_UpdatePresence(nullptr);
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply)
|
||||
{
|
||||
// if we are not connected, let's not batch up stale messages for later
|
||||
if (!Connection || !Connection->IsOpen()) {
|
||||
return;
|
||||
}
|
||||
auto qmessage = SendQueue.GetNextAddMessage();
|
||||
if (qmessage) {
|
||||
qmessage->length =
|
||||
JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++);
|
||||
SendQueue.CommitAdd();
|
||||
SignalIOActivity();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
|
||||
{
|
||||
// Note on some weirdness: internally we might connect, get other signals, disconnect any number
|
||||
// of times inbetween calls here. Externally, we want the sequence to seem sane, so any other
|
||||
// signals are book-ended by calls to ready and disconnect.
|
||||
|
||||
if (!Connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool wasDisconnected = WasJustDisconnected.exchange(false);
|
||||
bool isConnected = Connection->IsOpen();
|
||||
|
||||
if (isConnected) {
|
||||
// if we are connected, disconnect cb first
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (wasDisconnected && Handlers.disconnected) {
|
||||
Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (WasJustConnected.exchange(false)) {
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (Handlers.ready) {
|
||||
DiscordUser du{connectedUser.userId,
|
||||
connectedUser.username,
|
||||
connectedUser.discriminator,
|
||||
connectedUser.avatar};
|
||||
Handlers.ready(&du);
|
||||
}
|
||||
}
|
||||
|
||||
if (GotErrorMessage.exchange(false)) {
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (Handlers.errored) {
|
||||
Handlers.errored(LastErrorCode, LastErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (WasJoinGame.exchange(false)) {
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (Handlers.joinGame) {
|
||||
Handlers.joinGame(JoinGameSecret);
|
||||
}
|
||||
}
|
||||
|
||||
if (WasSpectateGame.exchange(false)) {
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (Handlers.spectateGame) {
|
||||
Handlers.spectateGame(SpectateGameSecret);
|
||||
}
|
||||
}
|
||||
|
||||
// Right now this batches up any requests and sends them all in a burst; I could imagine a world
|
||||
// where the implementer would rather sequentially accept/reject each one before the next invite
|
||||
// is sent. I left it this way because I could also imagine wanting to process these all and
|
||||
// maybe show them in one common dialog and/or start fetching the avatars in parallel, and if
|
||||
// not it should be trivial for the implementer to make a queue themselves.
|
||||
while (JoinAskQueue.HavePendingSends()) {
|
||||
auto req = JoinAskQueue.GetNextSendMessage();
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (Handlers.joinRequest) {
|
||||
DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
|
||||
Handlers.joinRequest(&du);
|
||||
}
|
||||
}
|
||||
JoinAskQueue.CommitSend();
|
||||
}
|
||||
|
||||
if (!isConnected) {
|
||||
// if we are not connected, disconnect message last
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (wasDisconnected && Handlers.disconnected) {
|
||||
Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers)
|
||||
{
|
||||
if (newHandlers) {
|
||||
#define HANDLE_EVENT_REGISTRATION(handler_name, event) \
|
||||
if (!Handlers.handler_name && newHandlers->handler_name) { \
|
||||
RegisterForEvent(event); \
|
||||
} \
|
||||
else if (Handlers.handler_name && !newHandlers->handler_name) { \
|
||||
DeregisterForEvent(event); \
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN")
|
||||
HANDLE_EVENT_REGISTRATION(spectateGame, "ACTIVITY_SPECTATE")
|
||||
HANDLE_EVENT_REGISTRATION(joinRequest, "ACTIVITY_JOIN_REQUEST")
|
||||
|
||||
#undef HANDLE_EVENT_REGISTRATION
|
||||
|
||||
Handlers = *newHandlers;
|
||||
}
|
||||
else {
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
Handlers = {};
|
||||
}
|
||||
return;
|
||||
}
|
8
dependencies/discord-rpc/src/dllmain.cpp
vendored
Normal file
8
dependencies/discord-rpc/src/dllmain.cpp
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <windows.h>
|
||||
|
||||
// outsmart GCC's missing-declarations warning
|
||||
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID);
|
||||
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
36
dependencies/discord-rpc/src/msg_queue.h
vendored
Normal file
36
dependencies/discord-rpc/src/msg_queue.h
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
// A simple queue. No locks, but only works with a single thread as producer and a single thread as
|
||||
// a consumer. Mutex up as needed.
|
||||
|
||||
template <typename ElementType, size_t QueueSize>
|
||||
class MsgQueue {
|
||||
ElementType queue_[QueueSize];
|
||||
std::atomic_uint nextAdd_{0};
|
||||
std::atomic_uint nextSend_{0};
|
||||
std::atomic_uint pendingSends_{0};
|
||||
|
||||
public:
|
||||
MsgQueue() {}
|
||||
|
||||
ElementType* GetNextAddMessage()
|
||||
{
|
||||
// if we are falling behind, bail
|
||||
if (pendingSends_.load() >= QueueSize) {
|
||||
return nullptr;
|
||||
}
|
||||
auto index = (nextAdd_++) % QueueSize;
|
||||
return &queue_[index];
|
||||
}
|
||||
void CommitAdd() { ++pendingSends_; }
|
||||
|
||||
bool HavePendingSends() const { return pendingSends_.load() != 0; }
|
||||
ElementType* GetNextSendMessage()
|
||||
{
|
||||
auto index = (nextSend_++) % QueueSize;
|
||||
return &queue_[index];
|
||||
}
|
||||
void CommitSend() { --pendingSends_; }
|
||||
};
|
137
dependencies/discord-rpc/src/rpc_connection.cpp
vendored
Normal file
137
dependencies/discord-rpc/src/rpc_connection.cpp
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
#include "rpc_connection.h"
|
||||
#include "serialization.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
static const int RpcVersion = 1;
|
||||
static RpcConnection Instance;
|
||||
|
||||
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId)
|
||||
{
|
||||
Instance.connection = BaseConnection::Create();
|
||||
StringCopy(Instance.appId, applicationId);
|
||||
return &Instance;
|
||||
}
|
||||
|
||||
/*static*/ void RpcConnection::Destroy(RpcConnection*& c)
|
||||
{
|
||||
c->Close();
|
||||
BaseConnection::Destroy(c->connection);
|
||||
c = nullptr;
|
||||
}
|
||||
|
||||
void RpcConnection::Open()
|
||||
{
|
||||
if (state == State::Connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == State::Disconnected && !connection->Open()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == State::SentHandshake) {
|
||||
JsonDocument message;
|
||||
if (Read(message)) {
|
||||
auto cmd = GetStrMember(&message, "cmd");
|
||||
auto evt = GetStrMember(&message, "evt");
|
||||
if (cmd && evt && !strcmp(cmd, "DISPATCH") && !strcmp(evt, "READY")) {
|
||||
state = State::Connected;
|
||||
if (onConnect) {
|
||||
onConnect(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
sendFrame.opcode = Opcode::Handshake;
|
||||
sendFrame.length = (uint32_t)JsonWriteHandshakeObj(
|
||||
sendFrame.message, sizeof(sendFrame.message), RpcVersion, appId);
|
||||
|
||||
if (connection->Write(&sendFrame, sizeof(MessageFrameHeader) + sendFrame.length)) {
|
||||
state = State::SentHandshake;
|
||||
}
|
||||
else {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RpcConnection::Close()
|
||||
{
|
||||
if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) {
|
||||
onDisconnect(lastErrorCode, lastErrorMessage);
|
||||
}
|
||||
connection->Close();
|
||||
state = State::Disconnected;
|
||||
}
|
||||
|
||||
bool RpcConnection::Write(const void* data, size_t length)
|
||||
{
|
||||
sendFrame.opcode = Opcode::Frame;
|
||||
memcpy(sendFrame.message, data, length);
|
||||
sendFrame.length = (uint32_t)length;
|
||||
if (!connection->Write(&sendFrame, sizeof(MessageFrameHeader) + length)) {
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RpcConnection::Read(JsonDocument& message)
|
||||
{
|
||||
if (state != State::Connected && state != State::SentHandshake) {
|
||||
return false;
|
||||
}
|
||||
MessageFrame readFrame;
|
||||
for (;;) {
|
||||
bool didRead = connection->Read(&readFrame, sizeof(MessageFrameHeader));
|
||||
if (!didRead) {
|
||||
if (!connection->isOpen) {
|
||||
lastErrorCode = (int)ErrorCode::PipeClosed;
|
||||
StringCopy(lastErrorMessage, "Pipe closed");
|
||||
Close();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (readFrame.length > 0) {
|
||||
didRead = connection->Read(readFrame.message, readFrame.length);
|
||||
if (!didRead) {
|
||||
lastErrorCode = (int)ErrorCode::ReadCorrupt;
|
||||
StringCopy(lastErrorMessage, "Partial data in frame");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
readFrame.message[readFrame.length] = 0;
|
||||
}
|
||||
|
||||
switch (readFrame.opcode) {
|
||||
case Opcode::Close: {
|
||||
message.ParseInsitu(readFrame.message);
|
||||
lastErrorCode = GetIntMember(&message, "code");
|
||||
StringCopy(lastErrorMessage, GetStrMember(&message, "message", ""));
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
case Opcode::Frame:
|
||||
message.ParseInsitu(readFrame.message);
|
||||
return true;
|
||||
case Opcode::Ping:
|
||||
readFrame.opcode = Opcode::Pong;
|
||||
if (!connection->Write(&readFrame, sizeof(MessageFrameHeader) + readFrame.length)) {
|
||||
Close();
|
||||
}
|
||||
break;
|
||||
case Opcode::Pong:
|
||||
break;
|
||||
case Opcode::Handshake:
|
||||
default:
|
||||
// something bad happened
|
||||
lastErrorCode = (int)ErrorCode::ReadCorrupt;
|
||||
StringCopy(lastErrorMessage, "Bad ipc frame");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
59
dependencies/discord-rpc/src/rpc_connection.h
vendored
Normal file
59
dependencies/discord-rpc/src/rpc_connection.h
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
|
||||
#include "connection.h"
|
||||
#include "serialization.h"
|
||||
|
||||
// I took this from the buffer size libuv uses for named pipes; I suspect ours would usually be much
|
||||
// smaller.
|
||||
constexpr size_t MaxRpcFrameSize = 64 * 1024;
|
||||
|
||||
struct RpcConnection {
|
||||
enum class ErrorCode : int {
|
||||
Success = 0,
|
||||
PipeClosed = 1,
|
||||
ReadCorrupt = 2,
|
||||
};
|
||||
|
||||
enum class Opcode : uint32_t {
|
||||
Handshake = 0,
|
||||
Frame = 1,
|
||||
Close = 2,
|
||||
Ping = 3,
|
||||
Pong = 4,
|
||||
};
|
||||
|
||||
struct MessageFrameHeader {
|
||||
Opcode opcode;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
struct MessageFrame : public MessageFrameHeader {
|
||||
char message[MaxRpcFrameSize - sizeof(MessageFrameHeader)];
|
||||
};
|
||||
|
||||
enum class State : uint32_t {
|
||||
Disconnected,
|
||||
SentHandshake,
|
||||
AwaitingResponse,
|
||||
Connected,
|
||||
};
|
||||
|
||||
BaseConnection* connection{nullptr};
|
||||
State state{State::Disconnected};
|
||||
void (*onConnect)(JsonDocument& message){nullptr};
|
||||
void (*onDisconnect)(int errorCode, const char* message){nullptr};
|
||||
char appId[64]{};
|
||||
int lastErrorCode{0};
|
||||
char lastErrorMessage[256]{};
|
||||
RpcConnection::MessageFrame sendFrame;
|
||||
|
||||
static RpcConnection* Create(const char* applicationId);
|
||||
static void Destroy(RpcConnection*&);
|
||||
|
||||
inline bool IsOpen() const { return state == State::Connected; }
|
||||
|
||||
void Open();
|
||||
void Close();
|
||||
bool Write(const void* data, size_t length);
|
||||
bool Read(JsonDocument& message);
|
||||
};
|
250
dependencies/discord-rpc/src/serialization.cpp
vendored
Normal file
250
dependencies/discord-rpc/src/serialization.cpp
vendored
Normal file
|
@ -0,0 +1,250 @@
|
|||
#include "serialization.h"
|
||||
#include "connection.h"
|
||||
#include "discord_rpc.h"
|
||||
|
||||
template <typename T>
|
||||
void NumberToString(char* dest, T number)
|
||||
{
|
||||
if (!number) {
|
||||
*dest++ = '0';
|
||||
*dest++ = 0;
|
||||
return;
|
||||
}
|
||||
if (number < 0) {
|
||||
*dest++ = '-';
|
||||
number = -number;
|
||||
}
|
||||
char temp[32];
|
||||
int place = 0;
|
||||
while (number) {
|
||||
auto digit = number % 10;
|
||||
number = number / 10;
|
||||
temp[place++] = '0' + (char)digit;
|
||||
}
|
||||
for (--place; place >= 0; --place) {
|
||||
*dest++ = temp[place];
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
// it's ever so slightly faster to not have to strlen the key
|
||||
template <typename T>
|
||||
void WriteKey(JsonWriter& w, T& k)
|
||||
{
|
||||
w.Key(k, sizeof(T) - 1);
|
||||
}
|
||||
|
||||
struct WriteObject {
|
||||
JsonWriter& writer;
|
||||
WriteObject(JsonWriter& w)
|
||||
: writer(w)
|
||||
{
|
||||
writer.StartObject();
|
||||
}
|
||||
template <typename T>
|
||||
WriteObject(JsonWriter& w, T& name)
|
||||
: writer(w)
|
||||
{
|
||||
WriteKey(writer, name);
|
||||
writer.StartObject();
|
||||
}
|
||||
~WriteObject() { writer.EndObject(); }
|
||||
};
|
||||
|
||||
struct WriteArray {
|
||||
JsonWriter& writer;
|
||||
template <typename T>
|
||||
WriteArray(JsonWriter& w, T& name)
|
||||
: writer(w)
|
||||
{
|
||||
WriteKey(writer, name);
|
||||
writer.StartArray();
|
||||
}
|
||||
~WriteArray() { writer.EndArray(); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void WriteOptionalString(JsonWriter& w, T& k, const char* value)
|
||||
{
|
||||
if (value && value[0]) {
|
||||
w.Key(k, sizeof(T) - 1);
|
||||
w.String(value);
|
||||
}
|
||||
}
|
||||
|
||||
static void JsonWriteNonce(JsonWriter& writer, int nonce)
|
||||
{
|
||||
WriteKey(writer, "nonce");
|
||||
char nonceBuffer[32];
|
||||
NumberToString(nonceBuffer, nonce);
|
||||
writer.String(nonceBuffer);
|
||||
}
|
||||
|
||||
size_t JsonWriteRichPresenceObj(char* dest,
|
||||
size_t maxLen,
|
||||
int nonce,
|
||||
int pid,
|
||||
const DiscordRichPresence* presence)
|
||||
{
|
||||
JsonWriter writer(dest, maxLen);
|
||||
|
||||
{
|
||||
WriteObject top(writer);
|
||||
|
||||
JsonWriteNonce(writer, nonce);
|
||||
|
||||
WriteKey(writer, "cmd");
|
||||
writer.String("SET_ACTIVITY");
|
||||
|
||||
{
|
||||
WriteObject args(writer, "args");
|
||||
|
||||
WriteKey(writer, "pid");
|
||||
writer.Int(pid);
|
||||
|
||||
if (presence != nullptr) {
|
||||
WriteObject activity(writer, "activity");
|
||||
|
||||
WriteOptionalString(writer, "state", presence->state);
|
||||
WriteOptionalString(writer, "details", presence->details);
|
||||
|
||||
if (presence->startTimestamp || presence->endTimestamp) {
|
||||
WriteObject timestamps(writer, "timestamps");
|
||||
|
||||
if (presence->startTimestamp) {
|
||||
WriteKey(writer, "start");
|
||||
writer.Int64(presence->startTimestamp);
|
||||
}
|
||||
|
||||
if (presence->endTimestamp) {
|
||||
WriteKey(writer, "end");
|
||||
writer.Int64(presence->endTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
if ((presence->largeImageKey && presence->largeImageKey[0]) ||
|
||||
(presence->largeImageText && presence->largeImageText[0]) ||
|
||||
(presence->smallImageKey && presence->smallImageKey[0]) ||
|
||||
(presence->smallImageText && presence->smallImageText[0])) {
|
||||
WriteObject assets(writer, "assets");
|
||||
WriteOptionalString(writer, "large_image", presence->largeImageKey);
|
||||
WriteOptionalString(writer, "large_text", presence->largeImageText);
|
||||
WriteOptionalString(writer, "small_image", presence->smallImageKey);
|
||||
WriteOptionalString(writer, "small_text", presence->smallImageText);
|
||||
}
|
||||
|
||||
if ((presence->partyId && presence->partyId[0]) || presence->partySize ||
|
||||
presence->partyMax || presence->partyPrivacy) {
|
||||
WriteObject party(writer, "party");
|
||||
WriteOptionalString(writer, "id", presence->partyId);
|
||||
if (presence->partySize && presence->partyMax) {
|
||||
WriteArray size(writer, "size");
|
||||
writer.Int(presence->partySize);
|
||||
writer.Int(presence->partyMax);
|
||||
}
|
||||
|
||||
if (presence->partyPrivacy) {
|
||||
WriteKey(writer, "privacy");
|
||||
writer.Int(presence->partyPrivacy);
|
||||
}
|
||||
}
|
||||
|
||||
if ((presence->matchSecret && presence->matchSecret[0]) ||
|
||||
(presence->joinSecret && presence->joinSecret[0]) ||
|
||||
(presence->spectateSecret && presence->spectateSecret[0])) {
|
||||
WriteObject secrets(writer, "secrets");
|
||||
WriteOptionalString(writer, "match", presence->matchSecret);
|
||||
WriteOptionalString(writer, "join", presence->joinSecret);
|
||||
WriteOptionalString(writer, "spectate", presence->spectateSecret);
|
||||
}
|
||||
|
||||
writer.Key("instance");
|
||||
writer.Bool(presence->instance != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return writer.Size();
|
||||
}
|
||||
|
||||
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
|
||||
{
|
||||
JsonWriter writer(dest, maxLen);
|
||||
|
||||
{
|
||||
WriteObject obj(writer);
|
||||
WriteKey(writer, "v");
|
||||
writer.Int(version);
|
||||
WriteKey(writer, "client_id");
|
||||
writer.String(applicationId);
|
||||
}
|
||||
|
||||
return writer.Size();
|
||||
}
|
||||
|
||||
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
|
||||
{
|
||||
JsonWriter writer(dest, maxLen);
|
||||
|
||||
{
|
||||
WriteObject obj(writer);
|
||||
|
||||
JsonWriteNonce(writer, nonce);
|
||||
|
||||
WriteKey(writer, "cmd");
|
||||
writer.String("SUBSCRIBE");
|
||||
|
||||
WriteKey(writer, "evt");
|
||||
writer.String(evtName);
|
||||
}
|
||||
|
||||
return writer.Size();
|
||||
}
|
||||
|
||||
size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
|
||||
{
|
||||
JsonWriter writer(dest, maxLen);
|
||||
|
||||
{
|
||||
WriteObject obj(writer);
|
||||
|
||||
JsonWriteNonce(writer, nonce);
|
||||
|
||||
WriteKey(writer, "cmd");
|
||||
writer.String("UNSUBSCRIBE");
|
||||
|
||||
WriteKey(writer, "evt");
|
||||
writer.String(evtName);
|
||||
}
|
||||
|
||||
return writer.Size();
|
||||
}
|
||||
|
||||
size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce)
|
||||
{
|
||||
JsonWriter writer(dest, maxLen);
|
||||
|
||||
{
|
||||
WriteObject obj(writer);
|
||||
|
||||
WriteKey(writer, "cmd");
|
||||
if (reply == DISCORD_REPLY_YES) {
|
||||
writer.String("SEND_ACTIVITY_JOIN_INVITE");
|
||||
}
|
||||
else {
|
||||
writer.String("CLOSE_ACTIVITY_JOIN_REQUEST");
|
||||
}
|
||||
|
||||
WriteKey(writer, "args");
|
||||
{
|
||||
WriteObject args(writer);
|
||||
|
||||
WriteKey(writer, "user_id");
|
||||
writer.String(userId);
|
||||
}
|
||||
|
||||
JsonWriteNonce(writer, nonce);
|
||||
}
|
||||
|
||||
return writer.Size();
|
||||
}
|
215
dependencies/discord-rpc/src/serialization.h
vendored
Normal file
215
dependencies/discord-rpc/src/serialization.h
vendored
Normal file
|
@ -0,0 +1,215 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#pragma warning(push)
|
||||
|
||||
#pragma warning(disable : 4061) // enum is not explicitly handled by a case label
|
||||
#pragma warning(disable : 4365) // signed/unsigned mismatch
|
||||
#pragma warning(disable : 4464) // relative include path contains
|
||||
#pragma warning(disable : 4668) // is not defined as a preprocessor macro
|
||||
#pragma warning(disable : 6313) // Incorrect operator
|
||||
#endif // __MINGW32__
|
||||
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/stringbuffer.h"
|
||||
#include "rapidjson/writer.h"
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#pragma warning(pop)
|
||||
#endif // __MINGW32__
|
||||
|
||||
// if only there was a standard library function for this
|
||||
template <size_t Len>
|
||||
inline size_t StringCopy(char (&dest)[Len], const char* src)
|
||||
{
|
||||
if (!src || !Len) {
|
||||
return 0;
|
||||
}
|
||||
size_t copied;
|
||||
char* out = dest;
|
||||
for (copied = 1; *src && copied < Len; ++copied) {
|
||||
*out++ = *src++;
|
||||
}
|
||||
*out = 0;
|
||||
return copied - 1;
|
||||
}
|
||||
|
||||
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId);
|
||||
|
||||
// Commands
|
||||
struct DiscordRichPresence;
|
||||
size_t JsonWriteRichPresenceObj(char* dest,
|
||||
size_t maxLen,
|
||||
int nonce,
|
||||
int pid,
|
||||
const DiscordRichPresence* presence);
|
||||
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName);
|
||||
|
||||
size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName);
|
||||
|
||||
size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce);
|
||||
|
||||
// I want to use as few allocations as I can get away with, and to do that with RapidJson, you need
|
||||
// to supply some of your own allocators for stuff rather than use the defaults
|
||||
|
||||
class LinearAllocator {
|
||||
public:
|
||||
char* buffer_;
|
||||
char* end_;
|
||||
LinearAllocator()
|
||||
{
|
||||
assert(0); // needed for some default case in rapidjson, should not use
|
||||
}
|
||||
LinearAllocator(char* buffer, size_t size)
|
||||
: buffer_(buffer)
|
||||
, end_(buffer + size)
|
||||
{
|
||||
}
|
||||
static const bool kNeedFree = false;
|
||||
void* Malloc(size_t size)
|
||||
{
|
||||
char* res = buffer_;
|
||||
buffer_ += size;
|
||||
if (buffer_ > end_) {
|
||||
buffer_ = res;
|
||||
return nullptr;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
|
||||
{
|
||||
if (newSize == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
// allocate how much you need in the first place
|
||||
assert(!originalPtr && !originalSize);
|
||||
// unused parameter warning
|
||||
(void)(originalPtr);
|
||||
(void)(originalSize);
|
||||
return Malloc(newSize);
|
||||
}
|
||||
static void Free(void* ptr)
|
||||
{
|
||||
/* shrug */
|
||||
(void)ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t Size>
|
||||
class FixedLinearAllocator : public LinearAllocator {
|
||||
public:
|
||||
char fixedBuffer_[Size];
|
||||
FixedLinearAllocator()
|
||||
: LinearAllocator(fixedBuffer_, Size)
|
||||
{
|
||||
}
|
||||
static const bool kNeedFree = false;
|
||||
};
|
||||
|
||||
// wonder why this isn't a thing already, maybe I missed it
|
||||
class DirectStringBuffer {
|
||||
public:
|
||||
using Ch = char;
|
||||
char* buffer_;
|
||||
char* end_;
|
||||
char* current_;
|
||||
|
||||
DirectStringBuffer(char* buffer, size_t maxLen)
|
||||
: buffer_(buffer)
|
||||
, end_(buffer + maxLen)
|
||||
, current_(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
void Put(char c)
|
||||
{
|
||||
if (current_ < end_) {
|
||||
*current_++ = c;
|
||||
}
|
||||
}
|
||||
void Flush() {}
|
||||
size_t GetSize() const { return (size_t)(current_ - buffer_); }
|
||||
};
|
||||
|
||||
using MallocAllocator = rapidjson::CrtAllocator;
|
||||
using PoolAllocator = rapidjson::MemoryPoolAllocator<MallocAllocator>;
|
||||
using UTF8 = rapidjson::UTF8<char>;
|
||||
// Writer appears to need about 16 bytes per nested object level (with 64bit size_t)
|
||||
using StackAllocator = FixedLinearAllocator<2048>;
|
||||
constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t));
|
||||
using JsonWriterBase =
|
||||
rapidjson::Writer<DirectStringBuffer, UTF8, UTF8, StackAllocator, rapidjson::kWriteNoFlags>;
|
||||
class JsonWriter : public JsonWriterBase {
|
||||
public:
|
||||
DirectStringBuffer stringBuffer_;
|
||||
StackAllocator stackAlloc_;
|
||||
|
||||
JsonWriter(char* dest, size_t maxLen)
|
||||
: JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels)
|
||||
, stringBuffer_(dest, maxLen)
|
||||
, stackAlloc_()
|
||||
{
|
||||
}
|
||||
|
||||
size_t Size() const { return stringBuffer_.GetSize(); }
|
||||
};
|
||||
|
||||
using JsonDocumentBase = rapidjson::GenericDocument<UTF8, PoolAllocator, StackAllocator>;
|
||||
class JsonDocument : public JsonDocumentBase {
|
||||
public:
|
||||
static const int kDefaultChunkCapacity = 32 * 1024;
|
||||
// json parser will use this buffer first, then allocate more if needed; I seriously doubt we
|
||||
// send any messages that would use all of this, though.
|
||||
char parseBuffer_[32 * 1024];
|
||||
MallocAllocator mallocAllocator_;
|
||||
PoolAllocator poolAllocator_;
|
||||
StackAllocator stackAllocator_;
|
||||
JsonDocument()
|
||||
: JsonDocumentBase(rapidjson::kObjectType,
|
||||
&poolAllocator_,
|
||||
sizeof(stackAllocator_.fixedBuffer_),
|
||||
&stackAllocator_)
|
||||
, poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_)
|
||||
, stackAllocator_()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
using JsonValue = rapidjson::GenericValue<UTF8, PoolAllocator>;
|
||||
|
||||
inline JsonValue* GetObjMember(JsonValue* obj, const char* name)
|
||||
{
|
||||
if (obj) {
|
||||
auto member = obj->FindMember(name);
|
||||
if (member != obj->MemberEnd() && member->value.IsObject()) {
|
||||
return &member->value;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0)
|
||||
{
|
||||
if (obj) {
|
||||
auto member = obj->FindMember(name);
|
||||
if (member != obj->MemberEnd() && member->value.IsInt()) {
|
||||
return member->value.GetInt();
|
||||
}
|
||||
}
|
||||
return notFoundDefault;
|
||||
}
|
||||
|
||||
inline const char* GetStrMember(JsonValue* obj,
|
||||
const char* name,
|
||||
const char* notFoundDefault = nullptr)
|
||||
{
|
||||
if (obj) {
|
||||
auto member = obj->FindMember(name);
|
||||
if (member != obj->MemberEnd() && member->value.IsString()) {
|
||||
return member->value.GetString();
|
||||
}
|
||||
}
|
||||
return notFoundDefault;
|
||||
}
|
6
dependencies/ih264d/CHANGES
vendored
Normal file
6
dependencies/ih264d/CHANGES
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
Code adjustments made by Team Cemu for Cemu emulator project as of 2022-02-01:
|
||||
- Stripped encoder, tests and fuzzer. We only need the decoder
|
||||
- Extended ih264_platform_macros.h to support MSVC instrinsics
|
||||
- Extended ithread.c to use WinAPI natives instead of requiring pthread.h
|
||||
- The decoder will output images without regarding SPS crop flag and instead pass the crop values in the decode output structure
|
||||
- Modified decoder/x86/ih264d_function_selector.c ih264d_init_arch() to automatically choose the best e_processor_arch for the current CPU
|
148
dependencies/ih264d/CMakeLists.txt
vendored
Normal file
148
dependencies/ih264d/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
project ("ih264d")
|
||||
|
||||
set(LIBAVCDEC_X86_INCLUDES "common/x86" "decoder/x86")
|
||||
|
||||
include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES})
|
||||
|
||||
if((CMAKE_C_COMPILER_ID MATCHES "GNU") OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
|
||||
add_compile_options(-mssse3 -mavx2)
|
||||
endif()
|
||||
|
||||
add_library (ih264d
|
||||
"common/ih264_buf_mgr.c"
|
||||
"common/ih264_buf_mgr.h"
|
||||
"common/ih264_cabac_tables.c"
|
||||
"common/ih264_cabac_tables.h"
|
||||
"common/ih264_cavlc_tables.c"
|
||||
"common/ih264_cavlc_tables.h"
|
||||
"common/ih264_chroma_intra_pred_filters.c"
|
||||
"common/ih264_common_tables.c"
|
||||
"common/ih264_common_tables.h"
|
||||
"common/ih264_deblk_edge_filters.c"
|
||||
"common/ih264_deblk_edge_filters.h"
|
||||
"common/ih264_deblk_tables.c"
|
||||
"common/ih264_deblk_tables.h"
|
||||
"common/ih264_debug.h"
|
||||
"common/ih264_defs.h"
|
||||
"common/ih264_disp_mgr.c"
|
||||
"common/ih264_disp_mgr.h"
|
||||
"common/ih264_dpb_mgr.c"
|
||||
"common/ih264_dpb_mgr.h"
|
||||
"common/ih264_error.h"
|
||||
"common/ih264_ihadamard_scaling.c"
|
||||
"common/ih264_inter_pred_filters.c"
|
||||
"common/ih264_inter_pred_filters.h"
|
||||
"common/ih264_intra_pred_filters.h"
|
||||
"common/ih264_iquant_itrans_recon.c"
|
||||
"common/ih264_list.c"
|
||||
"common/ih264_list.h"
|
||||
"common/ih264_luma_intra_pred_filters.c"
|
||||
"common/ih264_macros.h"
|
||||
"common/ih264_mem_fns.c"
|
||||
"common/ih264_mem_fns.h"
|
||||
"common/ih264_padding.c"
|
||||
"common/ih264_padding.h"
|
||||
"common/ih264_resi_trans.h"
|
||||
"common/ih264_resi_trans_quant.c"
|
||||
"common/ih264_size_defs.h"
|
||||
"common/ih264_structs.h"
|
||||
"common/ih264_trans_data.c"
|
||||
"common/ih264_trans_data.h"
|
||||
"common/ih264_trans_macros.h"
|
||||
"common/ih264_trans_quant_itrans_iquant.h"
|
||||
"common/ih264_typedefs.h"
|
||||
"common/ih264_weighted_pred.c"
|
||||
"common/ih264_weighted_pred.h"
|
||||
"common/ithread.c"
|
||||
"common/ithread.h"
|
||||
"common/x86/ih264_chroma_intra_pred_filters_ssse3.c"
|
||||
"common/x86/ih264_deblk_chroma_ssse3.c"
|
||||
"common/x86/ih264_deblk_luma_ssse3.c"
|
||||
"common/x86/ih264_ihadamard_scaling_sse42.c"
|
||||
"common/x86/ih264_ihadamard_scaling_ssse3.c"
|
||||
"common/x86/ih264_inter_pred_filters_ssse3.c"
|
||||
"common/x86/ih264_iquant_itrans_recon_dc_ssse3.c"
|
||||
"common/x86/ih264_iquant_itrans_recon_sse42.c"
|
||||
"common/x86/ih264_iquant_itrans_recon_ssse3.c"
|
||||
"common/x86/ih264_luma_intra_pred_filters_ssse3.c"
|
||||
"common/x86/ih264_mem_fns_ssse3.c"
|
||||
"common/x86/ih264_padding_ssse3.c"
|
||||
"common/x86/ih264_platform_macros.h"
|
||||
"common/x86/ih264_resi_trans_quant_sse42.c"
|
||||
"common/x86/ih264_weighted_pred_sse42.c"
|
||||
"decoder/ih264d.h"
|
||||
"decoder/ih264d_api.c"
|
||||
"decoder/ih264d_bitstrm.c"
|
||||
"decoder/ih264d_bitstrm.h"
|
||||
"decoder/ih264d_cabac.c"
|
||||
"decoder/ih264d_cabac.h"
|
||||
"decoder/ih264d_cabac_init_tables.c"
|
||||
"decoder/ih264d_compute_bs.c"
|
||||
"decoder/ih264d_deblocking.c"
|
||||
"decoder/ih264d_deblocking.h"
|
||||
"decoder/ih264d_debug.h"
|
||||
"decoder/ih264d_defs.h"
|
||||
"decoder/ih264d_dpb_manager.h"
|
||||
"decoder/ih264d_dpb_mgr.c"
|
||||
"decoder/ih264d_error_handler.h"
|
||||
"decoder/ih264d_format_conv.c"
|
||||
"decoder/ih264d_format_conv.h"
|
||||
"decoder/ih264d_function_selector.h"
|
||||
"decoder/ih264d_function_selector_generic.c"
|
||||
"decoder/ih264d_inter_pred.c"
|
||||
"decoder/ih264d_inter_pred.h"
|
||||
"decoder/ih264d_mb_utils.c"
|
||||
"decoder/ih264d_mb_utils.h"
|
||||
"decoder/ih264d_mem_request.h"
|
||||
"decoder/ih264d_mvpred.c"
|
||||
"decoder/ih264d_mvpred.h"
|
||||
"decoder/ih264d_nal.c"
|
||||
"decoder/ih264d_nal.h"
|
||||
"decoder/ih264d_parse_bslice.c"
|
||||
"decoder/ih264d_parse_cabac.c"
|
||||
"decoder/ih264d_parse_cabac.h"
|
||||
"decoder/ih264d_parse_cavlc.c"
|
||||
"decoder/ih264d_parse_cavlc.h"
|
||||
"decoder/ih264d_parse_headers.c"
|
||||
"decoder/ih264d_parse_headers.h"
|
||||
"decoder/ih264d_parse_islice.c"
|
||||
"decoder/ih264d_parse_islice.h"
|
||||
"decoder/ih264d_parse_mb_header.c"
|
||||
"decoder/ih264d_parse_mb_header.h"
|
||||
"decoder/ih264d_parse_pslice.c"
|
||||
"decoder/ih264d_parse_slice.c"
|
||||
"decoder/ih264d_parse_slice.h"
|
||||
"decoder/ih264d_process_bslice.c"
|
||||
"decoder/ih264d_process_bslice.h"
|
||||
"decoder/ih264d_process_intra_mb.c"
|
||||
"decoder/ih264d_process_intra_mb.h"
|
||||
"decoder/ih264d_process_pslice.c"
|
||||
"decoder/ih264d_process_pslice.h"
|
||||
"decoder/ih264d_quant_scaling.c"
|
||||
"decoder/ih264d_quant_scaling.h"
|
||||
"decoder/ih264d_sei.c"
|
||||
"decoder/ih264d_sei.h"
|
||||
"decoder/ih264d_structs.h"
|
||||
"decoder/ih264d_tables.c"
|
||||
"decoder/ih264d_tables.h"
|
||||
"decoder/ih264d_thread_compute_bs.c"
|
||||
"decoder/ih264d_thread_compute_bs.h"
|
||||
"decoder/ih264d_thread_parse_decode.c"
|
||||
"decoder/ih264d_thread_parse_decode.h"
|
||||
"decoder/ih264d_transfer_address.h"
|
||||
"decoder/ih264d_utils.c"
|
||||
"decoder/ih264d_utils.h"
|
||||
"decoder/ih264d_vui.c"
|
||||
"decoder/ih264d_vui.h"
|
||||
"decoder/iv.h"
|
||||
"decoder/ivd.h"
|
||||
"decoder/x86/ih264d_function_selector.c"
|
||||
"decoder/x86/ih264d_function_selector_sse42.c"
|
||||
"decoder/x86/ih264d_function_selector_ssse3.c"
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET ih264d PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
26
dependencies/ih264d/CMakeSettings.json
vendored
Normal file
26
dependencies/ih264d/CMakeSettings.json
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"name": "x64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Release",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ]
|
||||
}
|
||||
]
|
||||
}
|
20
dependencies/ih264d/NOTICE
vendored
Normal file
20
dependencies/ih264d/NOTICE
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*****************************************************************************
|
||||
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
*/
|
||||
/*****************************************************************************/
|
76
dependencies/ih264d/common/arm/ih264_arm_memory_barrier.s
vendored
Normal file
76
dependencies/ih264d/common/arm/ih264_arm_memory_barrier.s
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
@/******************************************************************************
|
||||
@ *
|
||||
@ * Copyright (C) 2015 The Android Open Source Project
|
||||
@ *
|
||||
@ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ * you may not use this file except in compliance with the License.
|
||||
@ * You may obtain a copy of the License at:
|
||||
@ *
|
||||
@ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
@ *
|
||||
@ * Unless required by applicable law or agreed to in writing, software
|
||||
@ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ * See the License for the specific language governing permissions and
|
||||
@ * limitations under the License.
|
||||
@ *
|
||||
@ *****************************************************************************
|
||||
@ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
@*/
|
||||
@**
|
||||
@*******************************************************************************
|
||||
@* @file
|
||||
@* ih264_arm_memory_barrier.s
|
||||
@*
|
||||
@* @brief
|
||||
@* Contains function definitions for data synchronization.
|
||||
@*
|
||||
@* @author
|
||||
@* Ittiam
|
||||
@*
|
||||
@* @par List of Functions:
|
||||
@*
|
||||
@*
|
||||
@* @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
|
||||
.text
|
||||
.p2align 2
|
||||
|
||||
@*****************************************************************************
|
||||
@*
|
||||
@* Function Name : ih264_arm_dsb
|
||||
@* Description : Adds DSB
|
||||
@* Revision History :
|
||||
@* DD MM YYYY Author(s) Changes
|
||||
@* 03 07 2008 100355 First version
|
||||
@*
|
||||
@*****************************************************************************
|
||||
|
||||
.global ih264_arm_dsb
|
||||
ih264_arm_dsb:
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
|
||||
|
||||
@*****************************************************************************
|
||||
@*
|
||||
@* Function Name : ih264_arm_dmb
|
||||
@* Description : Adds DMB
|
||||
@* Revision History :
|
||||
@* DD MM YYYY Author(s) Changes
|
||||
@* 03 07 2008 100355 First version
|
||||
@*
|
||||
@*****************************************************************************
|
||||
|
||||
.global ih264_arm_dmb
|
||||
|
||||
ih264_arm_dmb:
|
||||
dmb
|
||||
bx lr
|
||||
|
||||
|
||||
|
1337
dependencies/ih264d/common/arm/ih264_deblk_chroma_a9.s
vendored
Normal file
1337
dependencies/ih264d/common/arm/ih264_deblk_chroma_a9.s
vendored
Normal file
File diff suppressed because it is too large
Load diff
1092
dependencies/ih264d/common/arm/ih264_deblk_luma_a9.s
vendored
Normal file
1092
dependencies/ih264d/common/arm/ih264_deblk_luma_a9.s
vendored
Normal file
File diff suppressed because it is too large
Load diff
358
dependencies/ih264d/common/arm/ih264_default_weighted_pred_a9q.s
vendored
Normal file
358
dependencies/ih264d/common/arm/ih264_default_weighted_pred_a9q.s
vendored
Normal file
|
@ -0,0 +1,358 @@
|
|||
@/******************************************************************************
|
||||
@ *
|
||||
@ * Copyright (C) 2015 The Android Open Source Project
|
||||
@ *
|
||||
@ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ * you may not use this file except in compliance with the License.
|
||||
@ * You may obtain a copy of the License at:
|
||||
@ *
|
||||
@ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
@ *
|
||||
@ * Unless required by applicable law or agreed to in writing, software
|
||||
@ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ * See the License for the specific language governing permissions and
|
||||
@ * limitations under the License.
|
||||
@ *
|
||||
@ *****************************************************************************
|
||||
@ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
@*/
|
||||
@**
|
||||
@******************************************************************************
|
||||
@* @file
|
||||
@* ih264_default_weighted_pred_a9q.s
|
||||
@*
|
||||
@* @brief
|
||||
@* Contains function definitions for default weighted prediction.
|
||||
@*
|
||||
@* @author
|
||||
@* Kaushik Senthoor R
|
||||
@*
|
||||
@* @par List of Functions:
|
||||
@*
|
||||
@* - ih264_default_weighted_pred_luma_a9q()
|
||||
@* - ih264_default_weighted_pred_chroma_a9q()
|
||||
@*
|
||||
@* @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@* @function
|
||||
@* ih264_default_weighted_pred_luma_a9q()
|
||||
@*
|
||||
@* @brief
|
||||
@* This routine performs the default weighted prediction as described in sec
|
||||
@* 8.4.2.3.1 titled "Default weighted sample prediction process" for luma.
|
||||
@*
|
||||
@* @par Description:
|
||||
@* This function gets two ht x wd blocks, calculates their rounded-average and
|
||||
@* stores it in the destination block.
|
||||
@*
|
||||
@* @param[in] pu1_src1:
|
||||
@* UWORD8 Pointer to the buffer containing the first input block.
|
||||
@*
|
||||
@* @param[in] pu1_src2:
|
||||
@* UWORD8 Pointer to the buffer containing the second input block.
|
||||
@*
|
||||
@* @param[out] pu1_dst
|
||||
@* UWORD8 pointer to the destination where the output block is stored.
|
||||
@*
|
||||
@* @param[in] src_strd1
|
||||
@* Stride of the first input buffer
|
||||
@*
|
||||
@* @param[in] src_strd2
|
||||
@* Stride of the second input buffer
|
||||
@*
|
||||
@* @param[in] dst_strd
|
||||
@* Stride of the destination buffer
|
||||
@*
|
||||
@* @param[in] ht
|
||||
@* integer height of the array
|
||||
@*
|
||||
@* @param[in] wd
|
||||
@* integer width of the array
|
||||
@*
|
||||
@* @returns
|
||||
@* None
|
||||
@*
|
||||
@* @remarks
|
||||
@* (ht,wd) can be (4,4), (4,8), (8,4), (8,8), (8,16), (16,8) or (16,16).
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
@void ih264_default_weighted_pred_luma_a9q(UWORD8 *pu1_src1,
|
||||
@ UWORD8 *pu1_src2,
|
||||
@ UWORD8 *pu1_dst,
|
||||
@ WORD32 src_strd1,
|
||||
@ WORD32 src_strd2,
|
||||
@ WORD32 dst_strd,
|
||||
@ WORD32 ht,
|
||||
@ WORD32 wd)
|
||||
@
|
||||
@**************Variables Vs Registers*****************************************
|
||||
@ r0 => pu1_src1
|
||||
@ r1 => pu1_src2
|
||||
@ r2 => pu1_dst
|
||||
@ r3 => src_strd1
|
||||
@ [sp] => src_strd2 (r4)
|
||||
@ [sp+4] => dst_strd (r5)
|
||||
@ [sp+8] => ht (r6)
|
||||
@ [sp+12] => wd (r7)
|
||||
@
|
||||
.text
|
||||
.p2align 2
|
||||
|
||||
.global ih264_default_weighted_pred_luma_a9q
|
||||
|
||||
ih264_default_weighted_pred_luma_a9q:
|
||||
|
||||
stmfd sp!, {r4-r7, r14} @stack stores the values of the arguments
|
||||
ldr r7, [sp, #32] @Load wd
|
||||
ldr r4, [sp, #20] @Load src_strd2
|
||||
ldr r5, [sp, #24] @Load dst_strd
|
||||
cmp r7, #16
|
||||
ldr r6, [sp, #28] @Load ht
|
||||
vpush {d8-d15}
|
||||
beq loop_16 @branch if wd is 16
|
||||
cmp r7, #8
|
||||
beq loop_8 @branch if wd is 8
|
||||
|
||||
loop_4: @each iteration processes four rows
|
||||
|
||||
vld1.32 d0[0], [r0], r3 @load row 1 in source 1
|
||||
vld1.32 d0[1], [r0], r3 @load row 2 in source 1
|
||||
vld1.32 d2[0], [r1], r4 @load row 1 in source 2
|
||||
vld1.32 d2[1], [r1], r4 @load row 2 in source 2
|
||||
|
||||
vld1.32 d1[0], [r0], r3 @load row 3 in source 1
|
||||
vld1.32 d1[1], [r0], r3 @load row 4 in source 1
|
||||
vrhadd.u8 d0, d0, d2
|
||||
vld1.32 d3[0], [r1], r4 @load row 3 in source 2
|
||||
vld1.32 d3[1], [r1], r4 @load row 4 in source 2
|
||||
|
||||
subs r6, r6, #4 @decrement ht by 4
|
||||
vst1.32 d0[0], [r2], r5 @load row 1 in destination
|
||||
vst1.32 d0[1], [r2], r5 @load row 2 in destination
|
||||
vrhadd.u8 d1, d1, d3
|
||||
vst1.32 d1[0], [r2], r5 @load row 3 in destination
|
||||
vst1.32 d1[1], [r2], r5 @load row 4 in destination
|
||||
|
||||
bgt loop_4 @if greater than 0 repeat the loop again
|
||||
|
||||
b end_loops
|
||||
|
||||
loop_8: @each iteration processes four rows
|
||||
|
||||
vld1.8 d0, [r0], r3 @load row 1 in source 1
|
||||
vld1.8 d4, [r1], r4 @load row 1 in source 2
|
||||
vld1.8 d1, [r0], r3 @load row 2 in source 1
|
||||
vld1.8 d5, [r1], r4 @load row 2 in source 2
|
||||
vld1.8 d2, [r0], r3 @load row 3 in source 1
|
||||
vrhadd.u8 q0, q0, q2
|
||||
vld1.8 d6, [r1], r4 @load row 3 in source 2
|
||||
vld1.8 d3, [r0], r3 @load row 4 in source 1
|
||||
vrhadd.u8 d2, d2, d6
|
||||
vld1.8 d7, [r1], r4 @load row 4 in source 2
|
||||
|
||||
subs r6, r6, #4 @decrement ht by 4
|
||||
vst1.8 d0, [r2], r5 @load row 1 in destination
|
||||
vrhadd.u8 d3, d3, d7
|
||||
vst1.8 d1, [r2], r5 @load row 2 in destination
|
||||
vst1.8 d2, [r2], r5 @load row 3 in destination
|
||||
vst1.8 d3, [r2], r5 @load row 4 in destination
|
||||
|
||||
bgt loop_8 @if greater than 0 repeat the loop again
|
||||
|
||||
b end_loops
|
||||
|
||||
loop_16: @each iteration processes eight rows
|
||||
|
||||
vld1.8 {q0}, [r0], r3 @load row 1 in source 1
|
||||
vld1.8 {q8}, [r1], r4 @load row 1 in source 2
|
||||
vld1.8 {q1}, [r0], r3 @load row 2 in source 1
|
||||
vld1.8 {q9}, [r1], r4 @load row 2 in source 2
|
||||
vrhadd.u8 q0, q0, q8
|
||||
vld1.8 {q2}, [r0], r3 @load row 3 in source 1
|
||||
vld1.8 {q10}, [r1], r4 @load row 3 in source 2
|
||||
vrhadd.u8 q1, q1, q9
|
||||
vld1.8 {q3}, [r0], r3 @load row 4 in source 1
|
||||
vld1.8 {q11}, [r1], r4 @load row 4 in source 2
|
||||
vrhadd.u8 q2, q2, q10
|
||||
vld1.8 {q4}, [r0], r3 @load row 5 in source 1
|
||||
vld1.8 {q12}, [r1], r4 @load row 5 in source 2
|
||||
vrhadd.u8 q3, q3, q11
|
||||
vld1.8 {q5}, [r0], r3 @load row 6 in source 1
|
||||
vld1.8 {q13}, [r1], r4 @load row 6 in source 2
|
||||
vrhadd.u8 q4, q4, q12
|
||||
vld1.8 {q6}, [r0], r3 @load row 7 in source 1
|
||||
vld1.8 {q14}, [r1], r4 @load row 7 in source 2
|
||||
vrhadd.u8 q5, q5, q13
|
||||
vld1.8 {q7}, [r0], r3 @load row 8 in source 1
|
||||
vld1.8 {q15}, [r1], r4 @load row 8 in source 2
|
||||
|
||||
vrhadd.u8 q6, q6, q14
|
||||
vst1.8 {q0}, [r2], r5 @load row 1 in destination
|
||||
vst1.8 {q1}, [r2], r5 @load row 2 in destination
|
||||
vrhadd.u8 q7, q7, q15
|
||||
vst1.8 {q2}, [r2], r5 @load row 3 in destination
|
||||
vst1.8 {q3}, [r2], r5 @load row 4 in destination
|
||||
subs r6, r6, #8 @decrement ht by 8
|
||||
vst1.8 {q4}, [r2], r5 @load row 5 in destination
|
||||
vst1.8 {q5}, [r2], r5 @load row 6 in destination
|
||||
vst1.8 {q6}, [r2], r5 @load row 7 in destination
|
||||
vst1.8 {q7}, [r2], r5 @load row 8 in destination
|
||||
|
||||
bgt loop_16 @if greater than 0 repeat the loop again
|
||||
|
||||
end_loops:
|
||||
|
||||
vpop {d8-d15}
|
||||
ldmfd sp!, {r4-r7, r15} @Reload the registers from sp
|
||||
|
||||
|
||||
@*******************************************************************************
|
||||
@* @function
|
||||
@* ih264_default_weighted_pred_chroma_a9q()
|
||||
@*
|
||||
@* @brief
|
||||
@* This routine performs the default weighted prediction as described in sec
|
||||
@* 8.4.2.3.1 titled "Default weighted sample prediction process" for chroma.
|
||||
@*
|
||||
@* @par Description:
|
||||
@* This function gets two ht x wd blocks, calculates their rounded-average and
|
||||
@* stores it in the destination block for U and V.
|
||||
@*
|
||||
@* @param[in] pu1_src1:
|
||||
@* UWORD8 Pointer to the buffer containing the first input block.
|
||||
@*
|
||||
@* @param[in] pu1_src2:
|
||||
@* UWORD8 Pointer to the buffer containing the second input block.
|
||||
@*
|
||||
@* @param[out] pu1_dst
|
||||
@* UWORD8 pointer to the destination where the output block is stored.
|
||||
@*
|
||||
@* @param[in] src_strd1
|
||||
@* Stride of the first input buffer
|
||||
@*
|
||||
@* @param[in] src_strd2
|
||||
@* Stride of the second input buffer
|
||||
@*
|
||||
@* @param[in] dst_strd
|
||||
@* Stride of the destination buffer
|
||||
@*
|
||||
@* @param[in] ht
|
||||
@* integer height of the array
|
||||
@*
|
||||
@* @param[in] wd
|
||||
@* integer width of the array
|
||||
@*
|
||||
@* @returns
|
||||
@* None
|
||||
@*
|
||||
@* @remarks
|
||||
@* (ht,wd) can be (2,2), (2,4), (4,2), (4,4), (4,8), (8,4) or (8,8).
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
@void ih264_default_weighted_pred_chroma_a9q(UWORD8 *pu1_src1,
|
||||
@ UWORD8 *pu1_src2,
|
||||
@ UWORD8 *pu1_dst,
|
||||
@ WORD32 src_strd1,
|
||||
@ WORD32 src_strd2,
|
||||
@ WORD32 dst_strd,
|
||||
@ WORD32 ht,
|
||||
@ WORD32 wd)
|
||||
@
|
||||
@**************Variables Vs Registers*****************************************
|
||||
@ r0 => pu1_src1
|
||||
@ r1 => pu1_src2
|
||||
@ r2 => pu1_dst
|
||||
@ r3 => src_strd1
|
||||
@ [sp] => src_strd2 (r4)
|
||||
@ [sp+4] => dst_strd (r5)
|
||||
@ [sp+8] => ht (r6)
|
||||
@ [sp+12] => wd (r7)
|
||||
@
|
||||
|
||||
|
||||
.global ih264_default_weighted_pred_chroma_a9q
|
||||
|
||||
ih264_default_weighted_pred_chroma_a9q:
|
||||
|
||||
stmfd sp!, {r4-r7, r14} @stack stores the values of the arguments
|
||||
ldr r7, [sp, #32] @Load wd
|
||||
ldr r4, [sp, #20] @Load src_strd2
|
||||
ldr r5, [sp, #24] @Load dst_strd
|
||||
cmp r7, #8
|
||||
ldr r6, [sp, #28] @Load ht
|
||||
vpush {d8-d15}
|
||||
beq loop_8_uv @branch if wd is 8
|
||||
cmp r7, #4
|
||||
beq loop_4_uv @branch if wd is 4
|
||||
|
||||
loop_2_uv: @each iteration processes two rows
|
||||
|
||||
vld1.32 d0[0], [r0], r3 @load row 1 in source 1
|
||||
vld1.32 d0[1], [r0], r3 @load row 2 in source 1
|
||||
|
||||
vld1.32 d1[0], [r1], r4 @load row 1 in source 2
|
||||
vld1.32 d1[1], [r1], r4 @load row 2 in source 2
|
||||
|
||||
vrhadd.u8 d0, d0, d1
|
||||
|
||||
subs r6, r6, #2 @decrement ht by 2
|
||||
vst1.32 d0[0], [r2], r5 @load row 1 in destination
|
||||
vst1.32 d0[1], [r2], r5 @load row 2 in destination
|
||||
|
||||
bgt loop_2_uv @if greater than 0 repeat the loop again
|
||||
|
||||
b end_loops_uv
|
||||
|
||||
loop_4_uv: @each iteration processes two rows
|
||||
|
||||
vld1.8 d0, [r0], r3 @load row 1 in source 1
|
||||
vld1.8 d2, [r1], r4 @load row 1 in source 2
|
||||
vld1.8 d1, [r0], r3 @load row 2 in source 1
|
||||
vrhadd.u8 d0, d0, d2
|
||||
vld1.8 d3, [r1], r4 @load row 2 in source 2
|
||||
|
||||
vrhadd.u8 d1, d1, d3
|
||||
vst1.8 d0, [r2], r5 @load row 1 in destination
|
||||
subs r6, r6, #2 @decrement ht by 2
|
||||
vst1.8 d1, [r2], r5 @load row 2 in destination
|
||||
|
||||
bgt loop_4_uv @if greater than 0 repeat the loop again
|
||||
|
||||
b end_loops_uv
|
||||
|
||||
loop_8_uv: @each iteration processes four rows
|
||||
|
||||
vld1.8 {q0}, [r0], r3 @load row 1 in source 1
|
||||
vld1.8 {q4}, [r1], r4 @load row 1 in source 2
|
||||
vld1.8 {q1}, [r0], r3 @load row 2 in source 1
|
||||
vrhadd.u8 q0, q0, q4
|
||||
vld1.8 {q5}, [r1], r4 @load row 2 in source 2
|
||||
vld1.8 {q2}, [r0], r3 @load row 3 in source 1
|
||||
vrhadd.u8 q1, q1, q5
|
||||
vld1.8 {q6}, [r1], r4 @load row 3 in source 2
|
||||
vld1.8 {q3}, [r0], r3 @load row 4 in source 1
|
||||
vrhadd.u8 q2, q2, q6
|
||||
vld1.8 {q7}, [r1], r4 @load row 4 in source 2
|
||||
|
||||
vst1.8 {q0}, [r2], r5 @load row 1 in destination
|
||||
vrhadd.u8 q3, q3, q7
|
||||
vst1.8 {q1}, [r2], r5 @load row 2 in destination
|
||||
subs r6, r6, #4 @decrement ht by 4
|
||||
vst1.8 {q2}, [r2], r5 @load row 3 in destination
|
||||
vst1.8 {q3}, [r2], r5 @load row 4 in destination
|
||||
|
||||
bgt loop_8_uv @if greater than 0 repeat the loop again
|
||||
|
||||
end_loops_uv:
|
||||
|
||||
vpop {d8-d15}
|
||||
ldmfd sp!, {r4-r7, r15} @Reload the registers from sp
|
||||
|
||||
|
250
dependencies/ih264d/common/arm/ih264_ihadamard_scaling_a9.s
vendored
Normal file
250
dependencies/ih264d/common/arm/ih264_ihadamard_scaling_a9.s
vendored
Normal file
|
@ -0,0 +1,250 @@
|
|||
@/******************************************************************************
|
||||
@ *
|
||||
@ * Copyright (C) 2015 The Android Open Source Project
|
||||
@ *
|
||||
@ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ * you may not use this file except in compliance with the License.
|
||||
@ * You may obtain a copy of the License at:
|
||||
@ *
|
||||
@ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
@ *
|
||||
@ * Unless required by applicable law or agreed to in writing, software
|
||||
@ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ * See the License for the specific language governing permissions and
|
||||
@ * limitations under the License.
|
||||
@ *
|
||||
@ *****************************************************************************
|
||||
@ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
@*/
|
||||
@**
|
||||
@ *******************************************************************************
|
||||
@ * @file
|
||||
@ * ih264_ihadamard_scaling_a9.s
|
||||
@ *
|
||||
@ * @brief
|
||||
@ * Contains function definitions for inverse hadamard transform on 4x4 DC outputs
|
||||
@ * of 16x16 intra-prediction
|
||||
@ *
|
||||
@ * @author
|
||||
@ * Mohit
|
||||
@ *
|
||||
@ * @par List of Functions:
|
||||
@ * - ih264_ihadamard_scaling_4x4_a9()
|
||||
@ * - ih264_ihadamard_scaling_2x2_uv_a9()
|
||||
@ *
|
||||
@ * @remarks
|
||||
@ * None
|
||||
@ *
|
||||
@ *******************************************************************************
|
||||
@ *
|
||||
@ * @brief This function performs a 4x4 inverse hadamard transform on the 4x4 DC coefficients
|
||||
@ * of a 16x16 intra prediction macroblock, and then performs scaling.
|
||||
@ * prediction buffer
|
||||
@ *
|
||||
@ * @par Description:
|
||||
@ * The DC coefficients pass through a 2-stage inverse hadamard transform.
|
||||
@ * This inverse transformed content is scaled to based on Qp value.
|
||||
@ *
|
||||
@ * @param[in] pi2_src
|
||||
@ * input 4x4 block of DC coefficients
|
||||
@ *
|
||||
@ * @param[out] pi2_out
|
||||
@ * output 4x4 block
|
||||
@ *
|
||||
@ * @param[in] pu2_iscal_mat
|
||||
@ * pointer to scaling list
|
||||
@ *
|
||||
@ * @param[in] pu2_weigh_mat
|
||||
@ * pointer to weight matrix
|
||||
@ *
|
||||
@ * @param[in] u4_qp_div_6
|
||||
@ * Floor (qp/6)
|
||||
@ *
|
||||
@ * @param[in] pi4_tmp
|
||||
@ * temporary buffer of size 1*16
|
||||
@ *
|
||||
@ * @returns none
|
||||
@ *
|
||||
@ * @remarks none
|
||||
@ *
|
||||
@ *******************************************************************************
|
||||
@ *
|
||||
@ *
|
||||
@ *******************************************************************************
|
||||
@ *
|
||||
@ void ih264_ihadamard_scaling_4x4(WORD16* pi2_src,
|
||||
@ WORD16* pi2_out,
|
||||
@ const UWORD16 *pu2_iscal_mat,
|
||||
@ const UWORD16 *pu2_weigh_mat,
|
||||
@ UWORD32 u4_qp_div_6,
|
||||
@ WORD32* pi4_tmp)
|
||||
@**************Variables Vs Registers*****************************************
|
||||
@r0 => *pi2_src
|
||||
@r1 => *pi2_out
|
||||
@r2 => *pu2_iscal_mat
|
||||
@r3 => *pu2_weigh_mat
|
||||
@r4 => u4_qp_div_6
|
||||
|
||||
.text
|
||||
.p2align 2
|
||||
|
||||
.global ih264_ihadamard_scaling_4x4_a9
|
||||
|
||||
ih264_ihadamard_scaling_4x4_a9:
|
||||
|
||||
@VLD4.S16 is used because the pointer is incremented by SUB_BLK_WIDTH_4x4
|
||||
@If the macro value changes need to change the instruction according to it.
|
||||
@Only one shift is done in horizontal inverse because,
|
||||
@if u4_qp_div_6 is lesser than 4 then shift value will be neagative and do negative left shift, in this case rnd_factor has value
|
||||
@if u4_qp_div_6 is greater than 4 then shift value will be positive and do left shift, here rnd_factor is 0
|
||||
|
||||
stmfd sp!, {r4-r12, r14} @ stack stores the values of the arguments
|
||||
ldr r4, [sp, #40] @ Loads u4_qp_div_6
|
||||
vdup.s32 q10, r4 @ Populate the u4_qp_div_6 in Q10
|
||||
ldrh r6, [r3] @ load pu2_weight_mat[0] , H for unsigned halfword load
|
||||
ldrh r7, [r2] @ load pu2_iscal_mat[0] , H for unsigned halfword load
|
||||
mul r6, r6, r7 @ pu2_iscal_mat[0]*pu2_weigh_mat[0]
|
||||
vdup.s32 q9, r6 @ Populate pu2_iscal_mat[0]*pu2_weigh_mat[0] 32-bit in Q9
|
||||
vpush {d8-d15}
|
||||
@=======================INVERSE HADAMARD TRANSFORM================================
|
||||
|
||||
vld4.s16 {d0, d1, d2, d3}, [r0] @load x4,x5,x6,x7
|
||||
vaddl.s16 q12, d0, d3 @x0 = x4 + x7
|
||||
vaddl.s16 q13, d1, d2 @x1 = x5 + x6
|
||||
vsubl.s16 q14, d1, d2 @x2 = x5 - x6
|
||||
vsubl.s16 q15, d0, d3 @x3 = x4 - x7
|
||||
|
||||
vadd.s32 q2, q12, q13 @pi4_tmp_ptr[0] = x0 + x1
|
||||
vadd.s32 q3, q15, q14 @pi4_tmp_ptr[1] = x3 + x2
|
||||
vsub.s32 q4, q12, q13 @pi4_tmp_ptr[2] = x0 - x1
|
||||
vsub.s32 q5, q15, q14 @pi4_tmp_ptr[3] = x3 - x2
|
||||
|
||||
vtrn.32 q2, q3 @Transpose the register for vertical transform
|
||||
vtrn.32 q4, q5
|
||||
|
||||
vswp d5, d8 @Q2 = x4, Q4 = x6
|
||||
vswp d7, d10 @Q3 = x5, Q5 = x7
|
||||
|
||||
|
||||
vadd.s32 q12, q2, q5 @x0 = x4+x7
|
||||
vadd.s32 q13, q3, q4 @x1 = x5+x6
|
||||
vsub.s32 q14, q3, q4 @x2 = x5-x6
|
||||
vsub.s32 q15, q2, q5 @x3 = x4-x7
|
||||
|
||||
vadd.s32 q0, q12, q13 @pi4_tmp_ptr[0] = x0 + x1
|
||||
vadd.s32 q1, q15, q14 @pi4_tmp_ptr[1] = x3 + x2
|
||||
vsub.s32 q2, q12, q13 @pi4_tmp_ptr[2] = x0 - x1
|
||||
vsub.s32 q3, q15, q14 @pi4_tmp_ptr[3] = x3 - x2
|
||||
|
||||
|
||||
vmul.s32 q0, q0, q9 @ Q0 = p[i] = (x[i] * trns_coeff[i]) where i = 0..3
|
||||
vmul.s32 q1, q1, q9 @ Q1 = p[i] = (x[i] * trns_coeff[i]) where i = 4..7
|
||||
vmul.s32 q2, q2, q9 @ Q2 = p[i] = (x[i] * trns_coeff[i]) where i = 8..11
|
||||
vmul.s32 q3, q3, q9 @ Q3 = p[i] = (x[i] * trns_coeff[i]) where i = 12..15
|
||||
|
||||
vshl.s32 q0, q0, q10 @ Q0 = q[i] = (p[i] << (qP/6)) where i = 0..3
|
||||
vshl.s32 q1, q1, q10 @ Q1 = q[i] = (p[i] << (qP/6)) where i = 4..7
|
||||
vshl.s32 q2, q2, q10 @ Q2 = q[i] = (p[i] << (qP/6)) where i = 8..11
|
||||
vshl.s32 q3, q3, q10 @ Q3 = q[i] = (p[i] << (qP/6)) where i = 12..15
|
||||
|
||||
vqrshrn.s32 d0, q0, #0x6 @ D0 = c[i] = ((q[i] + 32) >> 4) where i = 0..3
|
||||
vqrshrn.s32 d1, q1, #0x6 @ D1 = c[i] = ((q[i] + 32) >> 4) where i = 4..7
|
||||
vqrshrn.s32 d2, q2, #0x6 @ D2 = c[i] = ((q[i] + 32) >> 4) where i = 8..11
|
||||
vqrshrn.s32 d3, q3, #0x6 @ D3 = c[i] = ((q[i] + 32) >> 4) where i = 12..15
|
||||
|
||||
vst1.s16 {d0, d1, d2, d3}, [r1] @IV row store the value
|
||||
|
||||
vpop {d8-d15}
|
||||
ldmfd sp!, {r4-r12, r15} @Reload the registers from SP
|
||||
|
||||
|
||||
|
||||
@ *******************************************************************************
|
||||
@ *
|
||||
@ * @brief This function performs a 2x2 inverse hadamard transform for chroma block
|
||||
@ *
|
||||
@ * @par Description:
|
||||
@ * The DC coefficients pass through a 2-stage inverse hadamard transform.
|
||||
@ * This inverse transformed content is scaled to based on Qp value.
|
||||
@ * Both DC blocks of U and v blocks are processesd
|
||||
@ *
|
||||
@ * @param[in] pi2_src
|
||||
@ * input 1x8 block of ceffs. First 4 are from U and next from V
|
||||
@ *
|
||||
@ * @param[out] pi2_out
|
||||
@ * output 1x8 block
|
||||
@ *
|
||||
@ * @param[in] pu2_iscal_mat
|
||||
@ * pointer to scaling list
|
||||
@ *
|
||||
@ * @param[in] pu2_weigh_mat
|
||||
@ * pointer to weight matrix
|
||||
@ *
|
||||
@ * @param[in] u4_qp_div_6
|
||||
@ * Floor (qp/6)
|
||||
@ *
|
||||
@ * @returns none
|
||||
@ *
|
||||
@ * @remarks none
|
||||
@ *
|
||||
@ *******************************************************************************
|
||||
@ *
|
||||
@ *
|
||||
@ *******************************************************************************
|
||||
@ *
|
||||
@ void ih264_ihadamard_scaling_2x2_uv(WORD16* pi2_src,
|
||||
@ WORD16* pi2_out,
|
||||
@ const UWORD16 *pu2_iscal_mat,
|
||||
@ const UWORD16 *pu2_weigh_mat,
|
||||
@ UWORD32 u4_qp_div_6,
|
||||
|
||||
.global ih264_ihadamard_scaling_2x2_uv_a9
|
||||
ih264_ihadamard_scaling_2x2_uv_a9:
|
||||
|
||||
@Registers used
|
||||
@ r0 : *pi2_src
|
||||
@ r1 : *pi2_out
|
||||
@ r2 : *pu2_iscal_mat
|
||||
@ r3 : *pu2_weigh_mat
|
||||
|
||||
vld1.u16 d26[0], [r2]
|
||||
vld1.u16 d27[0], [r3]
|
||||
vmull.u16 q15, d26, d27 @pu2_iscal_mat[0] * pu2_weigh_mat[0]
|
||||
vdup.u32 q15, d30[0]
|
||||
|
||||
vld1.u16 d28[0], [sp] @load qp/6
|
||||
|
||||
vpush {d8-d15}
|
||||
|
||||
vmov.u16 d29, #5
|
||||
vsubl.u16 q14, d28, d29 @qp\6 - 5
|
||||
vdup.s32 q14, d28[0]
|
||||
|
||||
vld2.s16 {d0, d1}, [r0] @load 8 dc coeffs
|
||||
@i2_x4,i2_x6,i2_y4,i1_y6 -> d0
|
||||
@i2_x5,i2_x7,i2_y5,i1_y6 -> d1
|
||||
|
||||
vaddl.s16 q1, d0, d1 @ i4_x0 = i4_x4 + i4_x5;...x2
|
||||
vsubl.s16 q2, d0, d1 @ i4_x1 = i4_x4 - i4_x5;...x3
|
||||
|
||||
vtrn.s32 q1, q2 @i4_x0 i4_x1 -> q1
|
||||
|
||||
vadd.s32 q3, q1, q2 @i4_x4 = i4_x0+i4_x2;.. i4_x5
|
||||
vsub.s32 q1, q1, q2 @i4_x6 = i4_x0-i4_x2;.. i4_x7
|
||||
|
||||
vmul.s32 q5, q3, q15
|
||||
vmul.s32 q6, q1, q15
|
||||
|
||||
vshl.s32 q7, q5, q14
|
||||
vshl.s32 q8, q6, q14
|
||||
|
||||
vmovn.s32 d18, q7 @i4_x4 i4_x5 i4_y4 i4_y5
|
||||
vmovn.s32 d19, q8 @i4_x6 i4_x7 i4_y6 i4_y7
|
||||
|
||||
vst2.s32 {d18-d19}, [r1]
|
||||
|
||||
vpop {d8-d15}
|
||||
bx lr
|
||||
|
||||
|
252
dependencies/ih264d/common/arm/ih264_inter_pred_chroma_a9q.s
vendored
Normal file
252
dependencies/ih264d/common/arm/ih264_inter_pred_chroma_a9q.s
vendored
Normal file
|
@ -0,0 +1,252 @@
|
|||
@/******************************************************************************
|
||||
@ *
|
||||
@ * Copyright (C) 2015 The Android Open Source Project
|
||||
@ *
|
||||
@ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ * you may not use this file except in compliance with the License.
|
||||
@ * You may obtain a copy of the License at:
|
||||
@ *
|
||||
@ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
@ *
|
||||
@ * Unless required by applicable law or agreed to in writing, software
|
||||
@ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ * See the License for the specific language governing permissions and
|
||||
@ * limitations under the License.
|
||||
@ *
|
||||
@ *****************************************************************************
|
||||
@ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
@*/
|
||||
@**
|
||||
@******************************************************************************
|
||||
@* @file
|
||||
@* ih264_inter_pred_chroma_a9q.s
|
||||
@*
|
||||
@* @brief
|
||||
@* Contains function definitions for inter prediction interpolation.
|
||||
@*
|
||||
@* @author
|
||||
@* Ittaim
|
||||
@*
|
||||
@* @par List of Functions:
|
||||
@*
|
||||
@* - ih264_inter_pred_chroma_a9q()
|
||||
@*
|
||||
@* @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
|
||||
@* All the functions here are replicated from ih264_inter_pred_filters.c
|
||||
@
|
||||
|
||||
@**
|
||||
@**
|
||||
@**
|
||||
@
|
||||
@**
|
||||
@*******************************************************************************
|
||||
@*
|
||||
@* @brief
|
||||
@* Interprediction chroma filter
|
||||
@*
|
||||
@* @par Description:
|
||||
@* Applies filtering to chroma samples as mentioned in
|
||||
@* sec 8.4.2.2.2 titled "chroma sample interpolation process"
|
||||
@*
|
||||
@* @param[in] pu1_src
|
||||
@* UWORD8 pointer to the source containing alternate U and V samples
|
||||
@*
|
||||
@* @param[out] pu1_dst
|
||||
@* UWORD8 pointer to the destination
|
||||
@*
|
||||
@* @param[in] src_strd
|
||||
@* integer source stride
|
||||
@*
|
||||
@* @param[in] dst_strd
|
||||
@* integer destination stride
|
||||
@*
|
||||
@* @param[in]uc_dx
|
||||
@* dx value where the sample is to be produced(refer sec 8.4.2.2.2 )
|
||||
@*
|
||||
@* @param[in] uc_dy
|
||||
@* dy value where the sample is to be produced(refer sec 8.4.2.2.2 )
|
||||
@*
|
||||
@* @param[in] ht
|
||||
@* integer height of the array
|
||||
@*
|
||||
@* @param[in] wd
|
||||
@* integer width of the array
|
||||
@*
|
||||
@* @returns
|
||||
@*
|
||||
@* @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
|
||||
@void ih264_inter_pred_chroma(UWORD8 *pu1_src,
|
||||
@ UWORD8 *pu1_dst,
|
||||
@ WORD32 src_strd,
|
||||
@ WORD32 dst_strd,
|
||||
@ WORD32 u1_dx,
|
||||
@ WORD32 u1_dy,
|
||||
@ WORD32 ht,
|
||||
@ WORD32 wd)
|
||||
@**************Variables Vs Registers*****************************************
|
||||
@ r0 => *pu1_src
|
||||
@ r1 => *pu1_dst
|
||||
@ r2 => src_strd
|
||||
@ r3 => dst_strd
|
||||
@ r4 => u1_dx
|
||||
@ r5 => u1_dy
|
||||
@ r6 => height
|
||||
@ r7 => width
|
||||
@
|
||||
.text
|
||||
.p2align 2
|
||||
|
||||
.global ih264_inter_pred_chroma_a9q
|
||||
|
||||
ih264_inter_pred_chroma_a9q:
|
||||
|
||||
stmfd sp!, {r4-r12, r14} @store register values to stack
|
||||
vstmdb sp!, {d8-d15} @push neon registers to stack
|
||||
ldr r4, [sp, #104]
|
||||
ldr r5, [sp, #108]
|
||||
ldr r6, [sp, #112]
|
||||
ldr r7, [sp, #116]
|
||||
|
||||
rsb r8, r4, #8 @8-u1_dx
|
||||
rsb r9, r5, #8 @8-u1_dy
|
||||
mul r10, r8, r9
|
||||
mul r11, r4, r9
|
||||
|
||||
vdup.u8 d28, r10
|
||||
vdup.u8 d29, r11
|
||||
|
||||
mul r10, r8, r5
|
||||
mul r11, r4, r5
|
||||
|
||||
vdup.u8 d30, r10
|
||||
vdup.u8 d31, r11
|
||||
|
||||
subs r12, r7, #2 @if wd=4 branch to loop_4
|
||||
beq loop_2
|
||||
subs r12, r7, #4 @if wd=8 branch to loop_8
|
||||
beq loop_4
|
||||
|
||||
loop_8:
|
||||
sub r6, #1
|
||||
vld1.8 {d0, d1, d2}, [r0], r2 @ Load row0
|
||||
vld1.8 {d5, d6, d7}, [r0], r2 @ Load row1
|
||||
vext.8 d3, d0, d1, #2
|
||||
vext.8 d8, d5, d6, #2
|
||||
|
||||
vmull.u8 q5, d0, d28
|
||||
vmlal.u8 q5, d5, d30
|
||||
vmlal.u8 q5, d3, d29
|
||||
vmlal.u8 q5, d8, d31
|
||||
vext.8 d9, d6, d7, #2
|
||||
vext.8 d4, d1, d2, #2
|
||||
|
||||
inner_loop_8:
|
||||
vmull.u8 q6, d6, d30
|
||||
vmlal.u8 q6, d1, d28
|
||||
vmlal.u8 q6, d9, d31
|
||||
vmlal.u8 q6, d4, d29
|
||||
vmov d0, d5
|
||||
vmov d3, d8
|
||||
|
||||
vqrshrun.s16 d14, q5, #6
|
||||
vmov d1, d6
|
||||
vmov d4, d9
|
||||
|
||||
vld1.8 {d5, d6, d7}, [r0], r2 @ Load row1
|
||||
vqrshrun.s16 d15, q6, #6
|
||||
|
||||
vext.8 d8, d5, d6, #2
|
||||
subs r6, #1
|
||||
vext.8 d9, d6, d7, #2
|
||||
vst1.8 {q7}, [r1], r3 @ Store dest row
|
||||
|
||||
vmull.u8 q5, d0, d28
|
||||
vmlal.u8 q5, d5, d30
|
||||
vmlal.u8 q5, d3, d29
|
||||
vmlal.u8 q5, d8, d31
|
||||
bne inner_loop_8
|
||||
|
||||
vmull.u8 q6, d6, d30
|
||||
vmlal.u8 q6, d1, d28
|
||||
vmlal.u8 q6, d9, d31
|
||||
vmlal.u8 q6, d4, d29
|
||||
|
||||
vqrshrun.s16 d14, q5, #6
|
||||
vqrshrun.s16 d15, q6, #6
|
||||
|
||||
vst1.8 {q7}, [r1], r3 @ Store dest row
|
||||
|
||||
b end_func
|
||||
|
||||
loop_4:
|
||||
sub r6, #1
|
||||
vld1.8 {d0, d1}, [r0], r2 @ Load row0
|
||||
vld1.8 {d2, d3}, [r0], r2 @ Load row1
|
||||
vext.8 d1, d0, d1, #2
|
||||
vext.8 d3, d2, d3, #2
|
||||
|
||||
vmull.u8 q2, d2, d30
|
||||
vmlal.u8 q2, d0, d28
|
||||
vmlal.u8 q2, d3, d31
|
||||
vmlal.u8 q2, d1, d29
|
||||
|
||||
inner_loop_4:
|
||||
subs r6, #1
|
||||
vmov d0, d2
|
||||
vmov d1, d3
|
||||
|
||||
vld1.8 {d2, d3}, [r0], r2 @ Load row1
|
||||
vqrshrun.s16 d6, q2, #6
|
||||
|
||||
vext.8 d3, d2, d3, #2
|
||||
vst1.8 {d6}, [r1], r3 @ Store dest row
|
||||
|
||||
vmull.u8 q2, d0, d28
|
||||
vmlal.u8 q2, d2, d30
|
||||
vmlal.u8 q2, d1, d29
|
||||
vmlal.u8 q2, d3, d31
|
||||
bne inner_loop_4
|
||||
|
||||
vqrshrun.s16 d6, q2, #6
|
||||
vst1.8 {d6}, [r1], r3 @ Store dest row
|
||||
|
||||
b end_func
|
||||
|
||||
loop_2:
|
||||
vld1.8 {d0}, [r0], r2 @ Load row0
|
||||
vext.8 d1, d0, d0, #2
|
||||
vld1.8 {d2}, [r0], r2 @ Load row1
|
||||
vext.8 d3, d2, d2, #2
|
||||
vmull.u8 q2, d0, d28
|
||||
vmlal.u8 q2, d1, d29
|
||||
vmlal.u8 q2, d2, d30
|
||||
vmlal.u8 q2, d3, d31
|
||||
vld1.8 {d6}, [r0] @ Load row2
|
||||
vqrshrun.s16 d4, q2, #6
|
||||
vext.8 d7, d6, d6, #2
|
||||
vst1.32 d4[0], [r1], r3 @ Store dest row0
|
||||
vmull.u8 q4, d2, d28
|
||||
vmlal.u8 q4, d3, d29
|
||||
vmlal.u8 q4, d6, d30
|
||||
vmlal.u8 q4, d7, d31
|
||||
subs r6, #2
|
||||
vqrshrun.s16 d8, q4, #6
|
||||
vst1.32 d8[0], [r1], r3 @ Store dest row1
|
||||
bne loop_2 @ repeat if ht=2
|
||||
|
||||
end_func:
|
||||
vldmia sp!, {d8-d15} @ Restore neon registers that were saved
|
||||
ldmfd sp!, {r4-r12, pc} @ Restoring registers from stack
|
||||
|
248
dependencies/ih264d/common/arm/ih264_inter_pred_filters_luma_horz_a9q.s
vendored
Normal file
248
dependencies/ih264d/common/arm/ih264_inter_pred_filters_luma_horz_a9q.s
vendored
Normal file
|
@ -0,0 +1,248 @@
|
|||
@/******************************************************************************
|
||||
@ *
|
||||
@ * Copyright (C) 2015 The Android Open Source Project
|
||||
@ *
|
||||
@ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ * you may not use this file except in compliance with the License.
|
||||
@ * You may obtain a copy of the License at:
|
||||
@ *
|
||||
@ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
@ *
|
||||
@ * Unless required by applicable law or agreed to in writing, software
|
||||
@ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ * See the License for the specific language governing permissions and
|
||||
@ * limitations under the License.
|
||||
@ *
|
||||
@ *****************************************************************************
|
||||
@ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
@*/
|
||||
@**
|
||||
@******************************************************************************
|
||||
@* @file
|
||||
@* ih264_inter_pred_luma_horz_a9q.s
|
||||
@*
|
||||
@* @brief
|
||||
@* Contains function definitions for inter prediction interpolation.
|
||||
@*
|
||||
@* @author
|
||||
@* Ittiam
|
||||
@*
|
||||
@* @par List of Functions:
|
||||
@*
|
||||
@* - ih264_inter_pred_luma_horz_a9q()
|
||||
@*
|
||||
@* @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
|
||||
@* All the functions here are replicated from ih264_inter_pred_filters.c
|
||||
@
|
||||
|
||||
@**
|
||||
@**
|
||||
@*******************************************************************************
|
||||
@*
|
||||
@* @brief
|
||||
@* Interprediction luma filter for horizontal input
|
||||
@*
|
||||
@* @par Description:
|
||||
@* Applies a 6 tap horizontal filter .The output is clipped to 8 bits
|
||||
@* sec 8.4.2.2.1 titled "Luma sample interpolation process"
|
||||
@*
|
||||
@* @param[in] pu1_src
|
||||
@* UWORD8 pointer to the source
|
||||
@*
|
||||
@* @param[out] pu1_dst
|
||||
@* UWORD8 pointer to the destination
|
||||
@*
|
||||
@* @param[in] src_strd
|
||||
@* integer source stride
|
||||
@*
|
||||
@* @param[in] dst_strd
|
||||
@* integer destination stride
|
||||
@*
|
||||
@* @param[in] ht
|
||||
@* integer height of the array
|
||||
@*
|
||||
@* @param[in] wd
|
||||
@* integer width of the array
|
||||
@*
|
||||
@* @returns
|
||||
@*
|
||||
@ @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
|
||||
@void ih264_inter_pred_luma_horz (
|
||||
@ UWORD8 *pu1_src,
|
||||
@ UWORD8 *pu1_dst,
|
||||
@ WORD32 src_strd,
|
||||
@ WORD32 dst_strd,
|
||||
@ WORD32 ht,
|
||||
@ WORD32 wd )
|
||||
|
||||
@**************Variables Vs Registers*****************************************
|
||||
@ r0 => *pu1_src
|
||||
@ r1 => *pu1_dst
|
||||
@ r2 => src_strd
|
||||
@ r3 => dst_strd
|
||||
@ r5 => ht
|
||||
@ r6 => wd
|
||||
|
||||
.text
|
||||
.p2align 2
|
||||
|
||||
|
||||
.global ih264_inter_pred_luma_horz_a9q
|
||||
|
||||
ih264_inter_pred_luma_horz_a9q:
|
||||
|
||||
|
||||
|
||||
|
||||
stmfd sp!, {r4-r12, r14} @store register values to stack
|
||||
vstmdb sp!, {d8-d15} @push neon registers to stack
|
||||
ldr r5, [sp, #104] @Loads ht
|
||||
sub r0, r0, #2 @pu1_src-2
|
||||
ldr r6, [sp, #108] @Loads wd
|
||||
vmov.i8 d0, #5 @filter coeff
|
||||
subs r12, r6, #8 @if wd=8 branch to loop_8
|
||||
vmov.i8 d1, #20 @filter coeff
|
||||
beq loop_8
|
||||
|
||||
subs r12, r6, #4 @if wd=4 branch to loop_4
|
||||
beq loop_4
|
||||
|
||||
loop_16: @when wd=16
|
||||
@ Processing row0 and row1
|
||||
vld1.8 {d2, d3, d4}, [r0], r2 @// Load row0 ;for checking loop
|
||||
vext.8 d31, d2, d3, #5 @//extract a[5] (column1,row0)
|
||||
vld1.8 {d5, d6, d7}, [r0], r2 @// Load row1
|
||||
vext.8 d30, d3, d4, #5 @//extract a[5] (column2,row0)
|
||||
vaddl.u8 q4, d31, d2 @// a0 + a5 (column1,row0)
|
||||
vext.8 d28, d5, d6, #5 @//extract a[5] (column1,row1)
|
||||
vaddl.u8 q5, d30, d3 @// a0 + a5 (column2,row0)
|
||||
vext.8 d27, d6, d7, #5 @//extract a[5] (column2,row1)
|
||||
vaddl.u8 q7, d28, d5 @// a0 + a5 (column1,row1)
|
||||
vext.8 d31, d2, d3, #2 @//extract a[2] (column1,row0)
|
||||
vaddl.u8 q8, d27, d6 @// a0 + a5 (column2,row1)
|
||||
vext.8 d30, d3, d4, #2 @//extract a[2] (column2,row0)
|
||||
vmlal.u8 q4, d31, d1 @// a0 + a5 + 20a2 (column1,row0)
|
||||
vext.8 d28, d5, d6, #2 @//extract a[2] (column1,row1)
|
||||
vmlal.u8 q5, d30, d1 @// a0 + a5 + 20a2 (column2,row0)
|
||||
vext.8 d27, d6, d7, #2 @//extract a[2] (column2,row1)
|
||||
vmlal.u8 q7, d28, d1 @// a0 + a5 + 20a2 (column1,row1)
|
||||
vext.8 d31, d2, d3, #3 @//extract a[3] (column1,row0)
|
||||
vmlal.u8 q8, d27, d1 @// a0 + a5 + 20a2 (column2,row1)
|
||||
vext.8 d30, d3, d4, #3 @//extract a[3] (column2,row0)
|
||||
vmlal.u8 q4, d31, d1 @// a0 + a5 + 20a2 + 20a3 (column1,row0)
|
||||
vext.8 d28, d5, d6, #3 @//extract a[3] (column1,row1)
|
||||
vmlal.u8 q5, d30, d1 @// a0 + a5 + 20a2 + 20a3 (column2,row0)
|
||||
vext.8 d27, d6, d7, #3 @//extract a[3] (column2,row1)
|
||||
vmlal.u8 q7, d28, d1 @// a0 + a5 + 20a2 + 20a3 (column1,row1)
|
||||
vext.8 d31, d2, d3, #1 @//extract a[1] (column1,row0)
|
||||
vmlal.u8 q8, d27, d1 @// a0 + a5 + 20a2 + 20a3 (column2,row1)
|
||||
vext.8 d30, d3, d4, #1 @//extract a[1] (column2,row0)
|
||||
vmlsl.u8 q4, d31, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 (column1,row0)
|
||||
vext.8 d28, d5, d6, #1 @//extract a[1] (column1,row1)
|
||||
vmlsl.u8 q5, d30, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 (column2,row0)
|
||||
vext.8 d27, d6, d7, #1 @//extract a[1] (column2,row1)
|
||||
vmlsl.u8 q7, d28, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 (column1,row1)
|
||||
vext.8 d31, d2, d3, #4 @//extract a[4] (column1,row0)
|
||||
vmlsl.u8 q8, d27, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 (column2,row1)
|
||||
vext.8 d30, d3, d4, #4 @//extract a[4] (column2,row0)
|
||||
vmlsl.u8 q4, d31, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 (column1,row0)
|
||||
vext.8 d28, d5, d6, #4 @//extract a[4] (column1,row1)
|
||||
vmlsl.u8 q5, d30, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 (column2,row0)
|
||||
vext.8 d27, d6, d7, #4 @//extract a[4] (column2,row1)
|
||||
vmlsl.u8 q7, d28, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 (column1,row1)
|
||||
vmlsl.u8 q8, d27, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 (column2,row1)
|
||||
vqrshrun.s16 d20, q4, #5 @// (a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 + 16) >> 5 (column1,row0)
|
||||
vqrshrun.s16 d21, q5, #5 @// (a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 + 16) >> 5 (column2,row0)
|
||||
vext.8 d31, d2, d3, #5 @//extract a[5] (column1,row2)
|
||||
vst1.8 {d20, d21}, [r1], r3 @//Store dest row0
|
||||
vqrshrun.s16 d23, q7, #5 @// (a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 + 16) >> 5 (column1,row1)
|
||||
vext.8 d30, d3, d4, #5 @//extract a[5] (column2,row2)
|
||||
vqrshrun.s16 d24, q8, #5 @// (a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 + 16) >> 5 (column2,row1)
|
||||
vst1.8 {d23, d24}, [r1], r3 @//Store dest row1
|
||||
subs r5, r5, #2 @ 2 rows done, decrement by 2
|
||||
|
||||
beq end_func
|
||||
b loop_16 @ loop if height == 8 or 16
|
||||
|
||||
loop_8:
|
||||
@ Processing row0 and row1
|
||||
vld1.8 {d5, d6}, [r0], r2 @// Load row1
|
||||
vext.8 d28, d5, d6, #5 @//extract a[5] (column1,row1)
|
||||
vld1.8 {d2, d3}, [r0], r2 @// Load row0
|
||||
vext.8 d25, d5, d6, #2 @//extract a[2] (column1,row1)
|
||||
vext.8 d31, d2, d3, #5 @//extract a[5] (column1,row0)
|
||||
vext.8 d24, d5, d6, #3 @//extract a[3] (column1,row1)
|
||||
vext.8 d23, d5, d6, #1 @//extract a[1] (column1,row1)
|
||||
vext.8 d22, d5, d6, #4 @//extract a[4] (column1,row1)
|
||||
vaddl.u8 q7, d28, d5 @// a0 + a5 (column1,row1)
|
||||
vext.8 d29, d2, d3, #3 @//extract a[3] (column1,row0)
|
||||
vmlal.u8 q7, d25, d1 @// a0 + a5 + 20a2 (column1,row1)
|
||||
vmlal.u8 q7, d24, d1 @// a0 + a5 + 20a2 + 20a3 (column1,row1)
|
||||
vmlsl.u8 q7, d23, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 (column1,row1)
|
||||
vmlsl.u8 q7, d22, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 (column1,row1)
|
||||
vext.8 d30, d2, d3, #2 @//extract a[2] (column1,row0)
|
||||
vaddl.u8 q4, d31, d2 @// a0 + a5 (column1,row0)
|
||||
vext.8 d27, d2, d3, #1 @//extract a[1] (column1,row0)
|
||||
vext.8 d26, d2, d3, #4 @//extract a[4] (column1,row0)
|
||||
vmlal.u8 q4, d29, d1 @// a0 + a5 + 20a2 + 20a3 (column1,row0)
|
||||
vmlal.u8 q4, d30, d1 @// a0 + a5 + 20a2 (column1,row0)
|
||||
vmlsl.u8 q4, d27, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 (column1,row0)
|
||||
vmlsl.u8 q4, d26, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 (column1,row0)
|
||||
vqrshrun.s16 d23, q7, #5 @// (a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 + 16) >> 5 (column1,row0)
|
||||
vst1.8 {d23}, [r1], r3 @//Store dest row0
|
||||
vqrshrun.s16 d20, q4, #5 @// (a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 + 16) >> 5 (column1,row1)
|
||||
vst1.8 {d20}, [r1], r3 @//Store dest row1
|
||||
subs r5, r5, #2 @ 2 rows done, decrement by 2
|
||||
|
||||
beq end_func @ Branch if height==4
|
||||
|
||||
b loop_8 @looping if height =8 or 16
|
||||
|
||||
loop_4:
|
||||
vld1.8 {d5, d6}, [r0], r2 @// Load row1
|
||||
vext.8 d28, d5, d6, #5 @//extract a[5] (column1,row1)
|
||||
vld1.8 {d2, d3}, [r0], r2 @// Load row0
|
||||
vext.8 d25, d5, d6, #2 @//extract a[2] (column1,row1)
|
||||
vext.8 d31, d2, d3, #5 @//extract a[5] (column1,row0)
|
||||
vaddl.u8 q7, d28, d5 @// a0 + a5 (column1,row1)
|
||||
vext.8 d24, d5, d6, #3 @//extract a[3] (column1,row1)
|
||||
vext.8 d23, d5, d6, #1 @//extract a[1] (column1,row1)
|
||||
vext.8 d22, d5, d6, #4 @//extract a[4] (column1,row1)
|
||||
vext.8 d29, d2, d3, #3 @//extract a[3] (column1,row0)
|
||||
vmlal.u8 q7, d25, d1 @// a0 + a5 + 20a2 (column1,row1)
|
||||
vmlal.u8 q7, d24, d1 @// a0 + a5 + 20a2 + 20a3 (column1,row1)
|
||||
vmlsl.u8 q7, d23, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 (column1,row1)
|
||||
vmlsl.u8 q7, d22, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 (column1,row1)
|
||||
vaddl.u8 q4, d31, d2 @// a0 + a5 (column1,row0)
|
||||
vext.8 d30, d2, d3, #2 @//extract a[2] (column1,row0)
|
||||
vext.8 d27, d2, d3, #1 @//extract a[1] (column1,row0)
|
||||
vext.8 d26, d2, d3, #4 @//extract a[4] (column1,row0)
|
||||
vmlal.u8 q4, d29, d1 @// a0 + a5 + 20a2 + 20a3 (column1,row0)
|
||||
vmlal.u8 q4, d30, d1 @// a0 + a5 + 20a2 (column1,row0)
|
||||
vmlsl.u8 q4, d27, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 (column1,row0)
|
||||
vmlsl.u8 q4, d26, d0 @// a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 (column1,row0)
|
||||
vqrshrun.s16 d23, q7, #5 @// (a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 + 16) >> 5 (column1,row0)
|
||||
vst1.32 d23[0], [r1], r3 @//Store dest row0
|
||||
vqrshrun.s16 d20, q4, #5 @// (a0 + a5 + 20a2 + 20a3 - 5a1 - 5a4 + 16) >> 5 (column1,row1)
|
||||
vst1.32 d20[0], [r1], r3 @//Store dest row1
|
||||
subs r5, r5, #2 @ 2 rows done, decrement by 2
|
||||
beq end_func
|
||||
|
||||
b loop_4
|
||||
|
||||
end_func:
|
||||
vldmia sp!, {d8-d15} @ Restore neon registers that were saved
|
||||
ldmfd sp!, {r4-r12, pc} @Restoring registers from stack
|
||||
|
||||
|
301
dependencies/ih264d/common/arm/ih264_inter_pred_filters_luma_vert_a9q.s
vendored
Normal file
301
dependencies/ih264d/common/arm/ih264_inter_pred_filters_luma_vert_a9q.s
vendored
Normal file
|
@ -0,0 +1,301 @@
|
|||
@/******************************************************************************
|
||||
@ *
|
||||
@ * Copyright (C) 2015 The Android Open Source Project
|
||||
@ *
|
||||
@ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ * you may not use this file except in compliance with the License.
|
||||
@ * You may obtain a copy of the License at:
|
||||
@ *
|
||||
@ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
@ *
|
||||
@ * Unless required by applicable law or agreed to in writing, software
|
||||
@ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ * See the License for the specific language governing permissions and
|
||||
@ * limitations under the License.
|
||||
@ *
|
||||
@ *****************************************************************************
|
||||
@ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
@*/
|
||||
@**
|
||||
@******************************************************************************
|
||||
@* @file
|
||||
@* ih264_inter_pred_luma_vert_a9q.s
|
||||
@*
|
||||
@* @brief
|
||||
@* Contains function definitions for inter prediction interpolation.
|
||||
@*
|
||||
@* @author
|
||||
@* Ittiam
|
||||
@*
|
||||
@* @par List of Functions:
|
||||
@*
|
||||
@* - ih264_inter_pred_luma_vert_a9q()
|
||||
@*
|
||||
@* @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
|
||||
@* All the functions here are replicated from ih264_inter_pred_filters.c
|
||||
@
|
||||
|
||||
@**
|
||||
@**
|
||||
@**
|
||||
@ *******************************************************************************
|
||||
@ *
|
||||
@ * @brief
|
||||
@ * Interprediction luma filter for vertical input
|
||||
@ *
|
||||
@ * @par Description:
|
||||
@ * Applies a 6 tap vertcal filter.The output is clipped to 8 bits
|
||||
@ * sec 8.4.2.2.1 titled "Luma sample interpolation process"
|
||||
@ *
|
||||
@ * @param[in] pu1_src
|
||||
@ * UWORD8 pointer to the source
|
||||
@ *
|
||||
@ * @param[out] pu1_dst
|
||||
@ * UWORD8 pointer to the destination
|
||||
@ *
|
||||
@ * @param[in] src_strd
|
||||
@ * integer source stride
|
||||
@ *
|
||||
@ * @param[in] dst_strd
|
||||
@ * integer destination stride
|
||||
@ *
|
||||
@ * @param[in] ht
|
||||
@ * integer height of the array
|
||||
@ *
|
||||
@ * @param[in] wd
|
||||
@ * integer width of the array
|
||||
@ *
|
||||
@ * @returns
|
||||
@ *
|
||||
@ * @remarks
|
||||
@ * None
|
||||
@ *
|
||||
@ *******************************************************************************
|
||||
|
||||
@void ih264_inter_pred_luma_vert (
|
||||
@ UWORD8 *pu1_src,
|
||||
@ UWORD8 *pu1_dst,
|
||||
@ WORD32 src_strd,
|
||||
@ WORD32 dst_strd,
|
||||
@ WORD32 ht,
|
||||
@ WORD32 wd )
|
||||
|
||||
@**************Variables Vs Registers*****************************************
|
||||
@ r0 => *pu1_src
|
||||
@ r1 => *pu1_dst
|
||||
@ r2 => src_strd
|
||||
@ r3 => dst_strd
|
||||
@ r5 => ht
|
||||
@ r6 => wd
|
||||
|
||||
.text
|
||||
.p2align 2
|
||||
|
||||
|
||||
.global ih264_inter_pred_luma_vert_a9q
|
||||
|
||||
ih264_inter_pred_luma_vert_a9q:
|
||||
|
||||
stmfd sp!, {r4-r12, r14} @store register values to stack
|
||||
vstmdb sp!, {d8-d15} @push neon registers to stack
|
||||
ldr r5, [sp, #104] @Loads ht
|
||||
sub r0, r0, r2, lsl #1 @pu1_src-2*src_strd
|
||||
ldr r6, [sp, #108] @Loads wd
|
||||
vmov.u16 q11, #20 @ Filter coeff 0x14 into Q11
|
||||
|
||||
subs r12, r6, #8 @if wd=8 branch to loop_8
|
||||
vmov.u16 q12, #5 @ Filter coeff 0x5 into Q12
|
||||
beq loop_8
|
||||
|
||||
subs r12, r6, #4 @if wd=4 branch to loop_4
|
||||
beq loop_4
|
||||
|
||||
loop_16: @when wd=16
|
||||
|
||||
vld1.u32 {q0}, [r0], r2 @ Vector load from src[0_0]
|
||||
vld1.u32 {q1}, [r0], r2 @ Vector load from src[1_0]
|
||||
vld1.u32 {q2}, [r0], r2 @ Vector load from src[2_0]
|
||||
vld1.u32 {q3}, [r0], r2 @ Vector load from src[3_0]
|
||||
vld1.u32 {q4}, [r0], r2 @ Vector load from src[4_0]
|
||||
vaddl.u8 q6, d4, d6 @ temp1 = src[2_0] + src[3_0]
|
||||
vld1.u32 {q5}, [r0], r2 @ Vector load from src[5_0]
|
||||
|
||||
vaddl.u8 q7, d0, d10 @ temp = src[0_0] + src[5_0]
|
||||
vaddl.u8 q8, d2, d8 @ temp2 = src[1_0] + src[4_0]
|
||||
vmla.u16 q7, q6, q11 @ temp += temp1 * 20
|
||||
vaddl.u8 q10, d1, d11 @ temp4 = src[0_8] + src[5_8]
|
||||
vaddl.u8 q9, d5, d7 @ temp3 = src[2_8] + src[3_8]
|
||||
vmla.u16 q10, q9, q11 @ temp4 += temp3 * 20
|
||||
vld1.u32 {q0}, [r0], r2
|
||||
vaddl.u8 q13, d3, d9 @ temp5 = src[1_8] + src[4_8]
|
||||
vaddl.u8 q6, d6, d8
|
||||
vmls.u16 q7, q8, q12 @ temp -= temp2 * 5
|
||||
vaddl.u8 q8, d2, d0
|
||||
vaddl.u8 q9, d4, d10
|
||||
vmla.u16 q8, q6, q11
|
||||
vmls.u16 q10, q13, q12 @ temp4 -= temp5 * 5
|
||||
vaddl.u8 q13, d5, d11
|
||||
vaddl.u8 q6, d7, d9
|
||||
vqrshrun.s16 d30, q7, #5 @ dst[0_0] = CLIP_U8((temp +16) >> 5)
|
||||
vaddl.u8 q7, d3, d1
|
||||
vld1.u32 {q1}, [r0], r2
|
||||
vmla.u16 q7, q6, q11
|
||||
vmls.u16 q8, q9, q12
|
||||
vqrshrun.s16 d31, q10, #5 @ dst[0_8] = CLIP_U8((temp4 +16) >> 5)
|
||||
vaddl.u8 q9, d4, d2
|
||||
vaddl.u8 q6, d8, d10
|
||||
|
||||
vst1.u32 {q15}, [r1], r3 @ Vector store to dst[0_0]
|
||||
vmla.u16 q9, q6, q11
|
||||
vaddl.u8 q10, d6, d0
|
||||
vmls.u16 q7, q13, q12
|
||||
vqrshrun.s16 d30, q8, #5
|
||||
vaddl.u8 q6, d9, d11
|
||||
vaddl.u8 q8, d5, d3
|
||||
vaddl.u8 q13, d7, d1
|
||||
vmla.u16 q8, q6, q11
|
||||
vmls.u16 q9, q10, q12
|
||||
vld1.u32 {q2}, [r0], r2
|
||||
|
||||
vqrshrun.s16 d31, q7, #5
|
||||
vaddl.u8 q6, d10, d0
|
||||
vaddl.u8 q7, d6, d4
|
||||
vaddl.u8 q10, d8, d2
|
||||
vmla.u16 q7, q6, q11
|
||||
vmls.u16 q8, q13, q12
|
||||
vst1.u32 {q15}, [r1], r3 @store row 1
|
||||
vqrshrun.s16 d30, q9, #5
|
||||
vaddl.u8 q9, d7, d5
|
||||
vaddl.u8 q6, d11, d1
|
||||
vmla.u16 q9, q6, q11
|
||||
vaddl.u8 q13, d9, d3
|
||||
vmls.u16 q7, q10, q12
|
||||
|
||||
vqrshrun.s16 d31, q8, #5
|
||||
vmls.u16 q9, q13, q12
|
||||
vaddl.u8 q6, d0, d2 @ temp1 = src[2_0] + src[3_0]
|
||||
vst1.u32 {q15}, [r1], r3 @store row 2
|
||||
vaddl.u8 q8, d10, d4 @ temp2 = src[1_0] + src[4_0]
|
||||
vaddl.u8 q10, d9, d7 @ temp4 = src[0_8] + src[5_8]
|
||||
vqrshrun.s16 d30, q7, #5
|
||||
vaddl.u8 q13, d5, d11 @ temp5 = src[1_8] + src[4_8]
|
||||
vaddl.u8 q7, d8, d6 @ temp = src[0_0] + src[5_0]
|
||||
vqrshrun.s16 d31, q9, #5
|
||||
vmla.u16 q7, q6, q11 @ temp += temp1 * 20
|
||||
vaddl.u8 q9, d1, d3 @ temp3 = src[2_8] + src[3_8]
|
||||
vst1.u32 {q15}, [r1], r3 @store row 3
|
||||
subs r5, r5, #4 @ 4 rows processed, decrement by 4
|
||||
subne r0, r0 , r2, lsl #2
|
||||
subne r0, r0, r2
|
||||
beq end_func @ Branch if height==4
|
||||
|
||||
b loop_16 @ looping if height = 8 or 16
|
||||
|
||||
loop_8:
|
||||
@ Processing row0 and row1
|
||||
|
||||
vld1.u32 d0, [r0], r2 @ Vector load from src[0_0]
|
||||
vld1.u32 d1, [r0], r2 @ Vector load from src[1_0]
|
||||
vld1.u32 d2, [r0], r2 @ Vector load from src[2_0]
|
||||
vld1.u32 d3, [r0], r2 @ Vector load from src[3_0]
|
||||
vld1.u32 d4, [r0], r2 @ Vector load from src[4_0]
|
||||
vld1.u32 d5, [r0], r2 @ Vector load from src[5_0]
|
||||
|
||||
vaddl.u8 q3, d2, d3 @ temp1 = src[2_0] + src[3_0]
|
||||
vaddl.u8 q4, d0, d5 @ temp = src[0_0] + src[5_0]
|
||||
vaddl.u8 q5, d1, d4 @ temp2 = src[1_0] + src[4_0]
|
||||
vmla.u16 q4, q3, q11 @ temp += temp1 * 20
|
||||
vld1.u32 d6, [r0], r2
|
||||
vaddl.u8 q7, d3, d4
|
||||
vaddl.u8 q8, d1, d6
|
||||
vaddl.u8 q9, d2, d5
|
||||
vmls.u16 q4, q5, q12 @ temp -= temp2 * 5
|
||||
vmla.u16 q8, q7, q11
|
||||
vld1.u32 d7, [r0], r2
|
||||
vaddl.u8 q10, d4, d5
|
||||
vaddl.u8 q6, d2, d7
|
||||
vaddl.u8 q5, d3, d6
|
||||
vmls.u16 q8, q9, q12
|
||||
vqrshrun.s16 d26, q4, #5 @ dst[0_0] = CLIP_U8( (temp + 16) >> 5)
|
||||
vmla.u16 q6, q10, q11
|
||||
vld1.u32 d0, [r0], r2
|
||||
vaddl.u8 q7, d5, d6
|
||||
vqrshrun.s16 d27, q8, #5
|
||||
vaddl.u8 q10, d3, d0
|
||||
vmls.u16 q6, q5, q12
|
||||
vst1.u32 d26, [r1], r3 @ Vector store to dst[0_0]
|
||||
vaddl.u8 q9, d4, d7
|
||||
vmla.u16 q10, q7, q11
|
||||
vst1.u32 d27, [r1], r3
|
||||
vqrshrun.s16 d28, q6, #5
|
||||
vst1.u32 d28, [r1], r3
|
||||
vmls.u16 q10, q9, q12
|
||||
vqrshrun.s16 d29, q10, #5
|
||||
vst1.u32 d29, [r1], r3 @store row 3
|
||||
|
||||
subs r5, r5, #4 @ 4 rows processed, decrement by 4
|
||||
subne r0, r0 , r2, lsl #2
|
||||
subne r0, r0, r2
|
||||
beq end_func @ Branch if height==4
|
||||
|
||||
b loop_8 @looping if height == 8 or 16
|
||||
|
||||
|
||||
loop_4:
|
||||
@ Processing row0 and row1
|
||||
|
||||
vld1.u32 d0[0], [r0], r2 @ Vector load from src[0_0]
|
||||
vld1.u32 d1[0], [r0], r2 @ Vector load from src[1_0]
|
||||
vld1.u32 d2[0], [r0], r2 @ Vector load from src[2_0]
|
||||
vld1.u32 d3[0], [r0], r2 @ Vector load from src[3_0]
|
||||
vld1.u32 d4[0], [r0], r2 @ Vector load from src[4_0]
|
||||
vld1.u32 d5[0], [r0], r2 @ Vector load from src[5_0]
|
||||
|
||||
vaddl.u8 q3, d2, d3 @ temp1 = src[2_0] + src[3_0]
|
||||
vaddl.u8 q4, d0, d5 @ temp = src[0_0] + src[5_0]
|
||||
vaddl.u8 q5, d1, d4 @ temp2 = src[1_0] + src[4_0]
|
||||
vmla.u16 q4, q3, q11 @ temp += temp1 * 20
|
||||
vld1.u32 d6[0], [r0], r2
|
||||
vaddl.u8 q7, d3, d4
|
||||
vaddl.u8 q8, d1, d6
|
||||
vaddl.u8 q9, d2, d5
|
||||
vmls.u16 q4, q5, q12 @ temp -= temp2 * 5
|
||||
vld1.u32 d7[0], [r0], r2
|
||||
vmla.u16 q8, q7, q11
|
||||
vaddl.u8 q10, d4, d5
|
||||
vaddl.u8 q6, d2, d7
|
||||
vaddl.u8 q5, d3, d6
|
||||
vmls.u16 q8, q9, q12
|
||||
vqrshrun.s16 d26, q4, #5 @ dst[0_0] = CLIP_U8( (temp + 16) >> 5)
|
||||
vmla.u16 q6, q10, q11
|
||||
vld1.u32 d0[0], [r0], r2
|
||||
vaddl.u8 q7, d5, d6
|
||||
vqrshrun.s16 d27, q8, #5
|
||||
vaddl.u8 q10, d3, d0
|
||||
vmls.u16 q6, q5, q12
|
||||
vst1.u32 d26[0], [r1], r3 @ Vector store to dst[0_0]
|
||||
vaddl.u8 q9, d4, d7
|
||||
vmla.u16 q10, q7, q11
|
||||
vst1.u32 d27[0], [r1], r3
|
||||
vqrshrun.s16 d28, q6, #5
|
||||
vst1.u32 d28[0], [r1], r3
|
||||
vmls.u16 q10, q9, q12
|
||||
vqrshrun.s16 d29, q10, #5
|
||||
vst1.u32 d29[0], [r1], r3 @store row 3
|
||||
|
||||
subs r5, r5, #8
|
||||
subeq r0, r0, r2, lsl #2
|
||||
subeq r0, r0, r2
|
||||
beq loop_4 @ Loop if height==8
|
||||
|
||||
end_func:
|
||||
vldmia sp!, {d8-d15} @ Restore neon registers that were saved
|
||||
ldmfd sp!, {r4-r12, pc} @Restoring registers from stack
|
||||
|
||||
|
398
dependencies/ih264d/common/arm/ih264_inter_pred_luma_bilinear_a9q.s
vendored
Normal file
398
dependencies/ih264d/common/arm/ih264_inter_pred_luma_bilinear_a9q.s
vendored
Normal file
|
@ -0,0 +1,398 @@
|
|||
@/******************************************************************************
|
||||
@ *
|
||||
@ * Copyright (C) 2015 The Android Open Source Project
|
||||
@ *
|
||||
@ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ * you may not use this file except in compliance with the License.
|
||||
@ * You may obtain a copy of the License at:
|
||||
@ *
|
||||
@ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
@ *
|
||||
@ * Unless required by applicable law or agreed to in writing, software
|
||||
@ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ * See the License for the specific language governing permissions and
|
||||
@ * limitations under the License.
|
||||
@ *
|
||||
@ *****************************************************************************
|
||||
@ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
||||
@*/
|
||||
@**
|
||||
@******************************************************************************
|
||||
@* @file
|
||||
@* ih264_inter_pred_luma_bilinear_a9q.s
|
||||
@*
|
||||
@* @brief
|
||||
@* Contains function definitions for inter prediction interpolation.
|
||||
@*
|
||||
@* @author
|
||||
@* Ittiam
|
||||
@*
|
||||
@* @par List of Functions:
|
||||
@*
|
||||
@* - ih264_inter_pred_luma_bilinear_a9q()
|
||||
@*
|
||||
@* @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
|
||||
@* All the functions here are replicated from ih264_inter_pred_filters.c
|
||||
@
|
||||
|
||||
@**
|
||||
@**
|
||||
@**
|
||||
@ *******************************************************************************
|
||||
@ * function:ih264_inter_pred_luma_bilinear
|
||||
@ *
|
||||
@* @brief
|
||||
@* This routine applies the bilinear filter to the predictors .
|
||||
@* The filtering operation is described in
|
||||
@* sec 8.4.2.2.1 titled "Luma sample interpolation process"
|
||||
@*
|
||||
@* @par Description:
|
||||
@\note
|
||||
@* This function is called to obtain pixels lying at the following
|
||||
@* locations (1/4,1), (3/4,1),(1,1/4), (1,3/4) ,(1/4,1/2), (3/4,1/2),(1/2,1/4), (1/2,3/4),(3/4,1/4),(1/4,3/4),(3/4,3/4)&& (1/4,1/4) .
|
||||
@* The function averages the two adjacent values from the two input arrays in horizontal direction.
|
||||
@*
|
||||
@*
|
||||
@* @param[in] pu1_src1:
|
||||
@* UWORD8 Pointer to the buffer containing the first input array.
|
||||
@*
|
||||
@* @param[in] pu1_src2:
|
||||
@* UWORD8 Pointer to the buffer containing the second input array.
|
||||
@*
|
||||
@* @param[out] pu1_dst
|
||||
@* UWORD8 pointer to the destination where the output of bilinear filter is stored.
|
||||
@*
|
||||
@* @param[in] src_strd1
|
||||
@* Stride of the first input buffer
|
||||
@*
|
||||
@* @param[in] src_strd2
|
||||
@* Stride of the second input buffer
|
||||
@*
|
||||
@* @param[in] dst_strd
|
||||
@* integer destination stride of pu1_dst
|
||||
@*
|
||||
@* @param[in] ht
|
||||
@* integer height of the array
|
||||
@*
|
||||
@* @param[in] wd
|
||||
@* integer width of the array
|
||||
@*
|
||||
@* @returns
|
||||
@*
|
||||
@* @remarks
|
||||
@* None
|
||||
@*
|
||||
@*******************************************************************************
|
||||
@*
|
||||
|
||||
@void ih264_inter_pred_luma_bilinear(UWORD8 *pu1_src1,
|
||||
@ UWORD8 *pu1_src2,
|
||||
@ UWORD8 *pu1_dst,
|
||||
@ WORD32 src_strd1,
|
||||
@ WORD32 src_strd2,
|
||||
@ WORD32 dst_strd,
|
||||
@ WORD32 height,
|
||||
@ WORD32 width)
|
||||
@
|
||||
@**************Variables Vs Registers*****************************************
|
||||
@ r0 => *pu1_src1
|
||||
@ r1 => *pu1_src2
|
||||
@ r2 => *pu1_dst
|
||||
@ r3 => src_strd1
|
||||
@ r4 => src_strd2
|
||||
@ r5 => dst_strd
|
||||
@ r6 => height
|
||||
@ r7 => width
|
||||
@
|
||||
.text
|
||||
.p2align 2
|
||||
|
||||
.global ih264_inter_pred_luma_bilinear_a9q
|
||||
|
||||
ih264_inter_pred_luma_bilinear_a9q:
|
||||
|
||||
|
||||
|
||||
stmfd sp!, {r4-r12, r14} @store register values to stack
|
||||
vstmdb sp!, {d8-d15} @push neon registers to stack
|
||||
ldr r4, [sp, #104]
|
||||
ldr r5, [sp, #108] @
|
||||
ldr r6, [sp, #112]
|
||||
ldr r7, [sp, #116]
|
||||
|
||||
subs r12, r7, #4 @if wd=4 branch to loop_4
|
||||
beq loop_4
|
||||
subs r12, r7, #8 @if wd=8 branch to loop_8
|
||||
beq loop_8
|
||||
|
||||
loop_16: @when wd=16
|
||||
|
||||
vld1.8 {q0}, [r0], r3 @// Load row0 ;src1
|
||||
vld1.8 {q2}, [r1], r4 @// Load row0 ;src2
|
||||
vld1.8 {q1}, [r0], r3 @// Load row1 ;src1
|
||||
vaddl.u8 q10, d0, d4
|
||||
vld1.8 {q3}, [r1], r4 @// Load row1 ;src2
|
||||
vaddl.u8 q11, d1, d5
|
||||
vld1.8 {q4}, [r0], r3 @// Load row2 ;src1
|
||||
vaddl.u8 q12, d2, d6
|
||||
vld1.8 {q5}, [r0], r3 @// Load row3 ;src1
|
||||
vaddl.u8 q13, d3, d7
|
||||
vld1.8 {q6}, [r1], r4 @// Load row2 ;src2
|
||||
vaddl.u8 q8, d8, d12
|
||||
vld1.8 {q7}, [r1], r4 @// Load row3 ;src2
|
||||
vaddl.u8 q9, d9, d13
|
||||
vqrshrun.s16 d28, q10, #1
|
||||
vqrshrun.s16 d29, q11, #1
|
||||
vaddl.u8 q10, d10, d14
|
||||
vqrshrun.s16 d30, q12, #1
|
||||
vqrshrun.s16 d31, q13, #1
|
||||
vst1.8 {q14}, [r2], r5 @//Store dest row0
|
||||
vaddl.u8 q11, d11, d15
|
||||
vst1.8 {q15}, [r2], r5 @//Store dest row1
|
||||
vqrshrun.s16 d28, q8, #1
|
||||
vld1.8 {q0}, [r0], r3 @// Load row4 ;src1
|
||||
vqrshrun.s16 d29, q9, #1
|
||||
vld1.8 {q1}, [r0], r3 @// Load row5 ;src1
|
||||
vqrshrun.s16 d30, q10, #1
|
||||
vld1.8 {q2}, [r1], r4 @// Load row4 ;src2
|
||||
vqrshrun.s16 d31, q11, #1
|
||||
vld1.8 {q3}, [r1], r4 @// Load row5 ;src2
|
||||
vaddl.u8 q10, d0, d4
|
||||
vst1.8 {q14}, [r2], r5 @//Store dest row2
|
||||
vaddl.u8 q13, d3, d7
|
||||
vst1.8 {q15}, [r2], r5 @//Store dest row3
|
||||
vaddl.u8 q11, d1, d5
|
||||
vld1.8 {q4}, [r0], r3 @// Load row6 ;src1
|
||||
vaddl.u8 q12, d2, d6
|
||||
vld1.8 {q5}, [r0], r3 @// Load row7 ;src1
|
||||
vqrshrun.s16 d28, q10, #1
|
||||
vld1.8 {q6}, [r1], r4 @// Load row6 ;src2
|
||||
vqrshrun.s16 d29, q11, #1
|
||||
vld1.8 {q7}, [r1], r4 @// Load row7 ;src2
|
||||
vaddl.u8 q8, d8, d12
|
||||
vaddl.u8 q9, d9, d13
|
||||
vaddl.u8 q10, d10, d14
|
||||
vqrshrun.s16 d30, q12, #1
|
||||
vqrshrun.s16 d31, q13, #1
|
||||
vst1.8 {q14}, [r2], r5 @//Store dest row4
|
||||
vaddl.u8 q11, d11, d15
|
||||
vst1.8 {q15}, [r2], r5 @//Store dest row5
|
||||
vqrshrun.s16 d28, q8, #1
|
||||
vqrshrun.s16 d30, q10, #1
|
||||
vqrshrun.s16 d29, q9, #1
|
||||
vld1.8 {q2}, [r1], r4 @// Load row8 ;src2
|
||||
vqrshrun.s16 d31, q11, #1
|
||||
vst1.8 {q14}, [r2], r5 @//Store dest row6
|
||||
subs r12, r6, #8
|
||||
vst1.8 {q15}, [r2], r5 @//Store dest row7
|
||||
|
||||
beq end_func @ end function if ht=8
|
||||
|
||||
vld1.8 {q0}, [r0], r3 @// Load row8 ;src1
|
||||
vaddl.u8 q10, d0, d4
|
||||
vld1.8 {q1}, [r0], r3 @// Load row9 ;src1
|
||||
vaddl.u8 q11, d1, d5
|
||||
vld1.8 {q3}, [r1], r4 @// Load row9 ;src2
|
||||
vqrshrun.s16 d28, q10, #1
|
||||
vld1.8 {q4}, [r0], r3 @// Load row10 ;src1
|
||||
vqrshrun.s16 d29, q11, #1
|
||||
vld1.8 {q5}, [r0], r3 @// Load row11 ;src1
|
||||
vaddl.u8 q12, d2, d6
|
||||
vld1.8 {q6}, [r1], r4 @// Load row10 ;src2
|
||||
vaddl.u8 q13, d3, d7
|
||||
vld1.8 {q7}, [r1], r4 @// Load row11 ;src2
|
||||
vaddl.u8 q8, d8, d12
|
||||
vaddl.u8 q9, d9, d13
|
||||
vaddl.u8 q10, d10, d14
|
||||
vqrshrun.s16 d30, q12, #1
|
||||
vst1.8 {q14}, [r2], r5 @//Store dest row8
|
||||
vqrshrun.s16 d31, q13, #1
|
||||
vst1.8 {q15}, [r2], r5 @//Store dest row9
|
||||
vqrshrun.s16 d28, q8, #1
|
||||
vld1.8 {q0}, [r0], r3 @// Load row12 ;src1
|
||||
vaddl.u8 q11, d11, d15
|
||||
vld1.8 {q1}, [r0], r3 @// Load row13 ;src1
|
||||
vqrshrun.s16 d29, q9, #1
|
||||
vld1.8 {q2}, [r1], r4 @// Load row12 ;src2
|
||||
vqrshrun.s16 d30, q10, #1
|
||||
vld1.8 {q3}, [r1], r4 @// Load row13 ;src2
|
||||
vqrshrun.s16 d31, q11, #1
|
||||
vst1.8 {q14}, [r2], r5 @//Store dest row10
|
||||
vaddl.u8 q10, d0, d4
|
||||
vst1.8 {q15}, [r2], r5 @//Store dest row11
|
||||
vaddl.u8 q11, d1, d5
|
||||
vld1.8 {q4}, [r0], r3 @// Load row14 ;src1
|
||||
vaddl.u8 q13, d3, d7
|
||||
vld1.8 {q5}, [r0], r3 @// Load row15 ;src1
|
||||
vaddl.u8 q12, d2, d6
|
||||
vld1.8 {q6}, [r1], r4 @// Load row14 ;src2
|
||||
vaddl.u8 q8, d8, d12
|
||||
vld1.8 {q7}, [r1], r4 @// Load row15 ;src2
|
||||
vaddl.u8 q9, d9, d13
|
||||
vqrshrun.s16 d28, q10, #1
|
||||
vqrshrun.s16 d29, q11, #1
|
||||
vaddl.u8 q10, d10, d14
|
||||
vst1.8 {q14}, [r2], r5 @//Store dest row12
|
||||
vqrshrun.s16 d30, q12, #1
|
||||
vqrshrun.s16 d31, q13, #1
|
||||
vaddl.u8 q11, d11, d15
|
||||
vst1.8 {q15}, [r2], r5 @//Store dest row13
|
||||
vqrshrun.s16 d28, q8, #1
|
||||
vqrshrun.s16 d29, q9, #1
|
||||
vqrshrun.s16 d30, q10, #1
|
||||
vst1.8 {q14}, [r2], r5 @//Store dest row14
|
||||
vqrshrun.s16 d31, q11, #1
|
||||
vst1.8 {q15}, [r2], r5 @//Store dest row15
|
||||
b end_func
|
||||
|
||||
|
||||
|
||||
loop_8: @wd=8;
|
||||
vld1.8 {d0}, [r0], r3 @// Load row0 ;src1
|
||||
vld1.8 {d4}, [r1], r4 @// Load row0 ;src2
|
||||
vld1.8 {d1}, [r0], r3 @// Load row1 ;src1
|
||||
vaddl.u8 q10, d0, d4
|
||||
vld1.8 {d5}, [r1], r4 @// Load row1 ;src2
|
||||
vld1.8 {d2}, [r0], r3 @// Load row2 ;src1
|
||||
vqrshrun.s16 d28, q10, #1
|
||||
vld1.8 {d6}, [r1], r4 @// Load row2 ;src2
|
||||
vaddl.u8 q11, d1, d5
|
||||
vld1.8 {d3}, [r0], r3 @// Load row3 ;src1
|
||||
vaddl.u8 q12, d2, d6
|
||||
vst1.8 {d28}, [r2], r5 @//Store dest row0
|
||||
vqrshrun.s16 d29, q11, #1
|
||||
vld1.8 {d7}, [r1], r4 @// Load row3 ;src2
|
||||
vqrshrun.s16 d30, q12, #1
|
||||
vst1.8 {d29}, [r2], r5 @//Store dest row1
|
||||
vaddl.u8 q13, d3, d7
|
||||
vst1.8 {d30}, [r2], r5 @//Store dest row2
|
||||
vqrshrun.s16 d31, q13, #1
|
||||
subs r12, r6, #4
|
||||
vst1.8 {d31}, [r2], r5 @//Store dest row3
|
||||
beq end_func @ end function if ht=4
|
||||
|
||||
vld1.8 {d12}, [r1], r4 @// Load row4 ;src2
|
||||
vld1.8 {d8}, [r0], r3 @// Load row4 ;src1
|
||||
vld1.8 {d9}, [r0], r3 @// Load row5 ;src1
|
||||
vaddl.u8 q8, d8, d12
|
||||
vld1.8 {d13}, [r1], r4 @// Load row5 ;src2
|
||||
vld1.8 {d10}, [r0], r3 @// Load row6;src1
|
||||
vaddl.u8 q9, d9, d13
|
||||
vld1.8 {d14}, [r1], r4 @// Load row6 ;src2
|
||||
vqrshrun.s16 d28, q8, #1
|
||||
vld1.8 {d11}, [r0], r3 @// Load row7 ;src1
|
||||
vqrshrun.s16 d29, q9, #1
|
||||
vst1.8 {d28}, [r2], r5 @//Store dest row4
|
||||
vaddl.u8 q10, d10, d14
|
||||
vst1.8 {d29}, [r2], r5 @//Store dest row5
|
||||
vqrshrun.s16 d30, q10, #1
|
||||
vld1.8 {d15}, [r1], r4 @// Load row7 ;src2
|
||||
vaddl.u8 q11, d11, d15
|
||||
vst1.8 {d30}, [r2], r5 @//Store dest row6
|
||||
vqrshrun.s16 d31, q11, #1
|
||||
subs r12, r6, #8
|
||||
vst1.8 {d31}, [r2], r5 @//Store dest row7
|
||||
beq end_func @ end function if ht=8
|
||||
|
||||
vld1.8 {d0}, [r0], r3 @// Load row8 ;src1
|
||||
vld1.8 {d4}, [r1], r4 @// Load row8 ;src2
|
||||
vld1.8 {d1}, [r0], r3 @// Load row9 ;src1
|
||||
vaddl.u8 q10, d0, d4
|
||||
vld1.8 {d5}, [r1], r4 @// Load row9 ;src2
|
||||
vld1.8 {d2}, [r0], r3 @// Load row10 ;src1
|
||||
vaddl.u8 q11, d1, d5
|
||||
vld1.8 {d6}, [r1], r4 @// Load row10 ;src2
|
||||
vqrshrun.s16 d28, q10, #1
|
||||
vld1.8 {d3}, [r0], r3 @// Load row11 ;src1
|
||||
vaddl.u8 q12, d2, d6
|
||||
vld1.8 {d7}, [r1], r4 @// Load row11 ;src2
|
||||
vqrshrun.s16 d29, q11, #1
|
||||
vld1.8 {d8}, [r0], r3 @// Load row12 ;src1
|
||||
vaddl.u8 q13, d3, d7
|
||||
vst1.8 {d28}, [r2], r5 @//Store dest row8
|
||||
vqrshrun.s16 d30, q12, #1
|
||||
vld1.8 {d12}, [r1], r4 @// Load row12 ;src2
|
||||
vqrshrun.s16 d31, q13, #1
|
||||
vst1.8 {d29}, [r2], r5 @//Store dest row9
|
||||
vaddl.u8 q8, d8, d12
|
||||
vld1.8 {d9}, [r0], r3 @// Load row13 ;src1
|
||||
vqrshrun.s16 d28, q8, #1
|
||||
vld1.8 {d13}, [r1], r4 @// Load row13 ;src2
|
||||
vld1.8 {d10}, [r0], r3 @// Load row14;src1
|
||||
vaddl.u8 q9, d9, d13
|
||||
vld1.8 {d11}, [r0], r3 @// Load row15 ;src1
|
||||
vld1.8 {d14}, [r1], r4 @// Load row14 ;src2
|
||||
vqrshrun.s16 d29, q9, #1
|
||||
vld1.8 {d15}, [r1], r4 @// Load roW15 ;src2
|
||||
vaddl.u8 q10, d10, d14
|
||||
vst1.8 {d30}, [r2], r5 @//Store dest row10
|
||||
vaddl.u8 q11, d11, d15
|
||||
vst1.8 {d31}, [r2], r5 @//Store dest row11
|
||||
vqrshrun.s16 d30, q10, #1
|
||||
vst1.8 {d28}, [r2], r5 @//Store dest row12
|
||||
vqrshrun.s16 d31, q11, #1
|
||||
vst1.8 {d29}, [r2], r5 @//Store dest row13
|
||||
vst1.8 {d30}, [r2], r5 @//Store dest row14
|
||||
vst1.8 {d31}, [r2], r5 @//Store dest row15
|
||||
|
||||
b end_func
|
||||
|
||||
|
||||
|
||||
loop_4:
|
||||
vld1.32 d0[0], [r0], r3 @// Load row0 ;src1
|
||||
vld1.32 d4[0], [r1], r4 @// Load row0 ;src2
|
||||
vld1.32 d1[0], [r0], r3 @// Load row1 ;src1
|
||||
vaddl.u8 q10, d0, d4
|
||||
vld1.32 d5[0], [r1], r4 @// Load row1 ;src2
|
||||
vld1.32 d2[0], [r0], r3 @// Load row2 ;src1
|
||||
vqrshrun.s16 d28, q10, #1
|
||||
vld1.32 d6[0], [r1], r4 @// Load row2 ;src2
|
||||
vaddl.u8 q11, d1, d5
|
||||
vld1.32 d3[0], [r0], r3 @// Load row3 ;src1
|
||||
vaddl.u8 q12, d2, d6
|
||||
vst1.32 d28[0], [r2], r5 @//Store dest row0
|
||||
vqrshrun.s16 d29, q11, #1
|
||||
vld1.32 d7[0], [r1], r4 @// Load row3 ;src2
|
||||
vqrshrun.s16 d30, q12, #1
|
||||
vst1.32 d29[0], [r2], r5 @//Store dest row1
|
||||
vaddl.u8 q13, d3, d7
|
||||
vst1.32 d30[0], [r2], r5 @//Store dest row2
|
||||
vqrshrun.s16 d31, q13, #1
|
||||
subs r12, r6, #4
|
||||
vst1.32 d31[0], [r2], r5 @//Store dest row3
|
||||
beq end_func @ end function if ht=4
|
||||
|
||||
vld1.32 d12[0], [r1], r4 @// Load row4 ;src2
|
||||
vld1.32 d8[0], [r0], r3 @// Load row4 ;src1
|
||||
vld1.32 d9[0], [r0], r3 @// Load row5 ;src1
|
||||
vaddl.u8 q8, d8, d12
|
||||
vld1.32 d13[0], [r1], r4 @// Load row5 ;src2
|
||||
vld1.32 d10[0], [r0], r3 @// Load row6;src1
|
||||
vaddl.u8 q9, d9, d13
|
||||
vld1.32 d14[0], [r1], r4 @// Load row6 ;src2
|
||||
vqrshrun.s16 d28, q8, #1
|
||||
vld1.32 d11[0], [r0], r3 @// Load row7 ;src1
|
||||
vqrshrun.s16 d29, q9, #1
|
||||
vst1.32 d28[0], [r2], r5 @//Store dest row4
|
||||
vaddl.u8 q10, d10, d14
|
||||
vst1.32 d29[0], [r2], r5 @//Store dest row5
|
||||
vqrshrun.s16 d30, q10, #1
|
||||
vld1.32 d15[0], [r1], r4 @// Load row7 ;src2
|
||||
vaddl.u8 q11, d11, d15
|
||||
vst1.32 d30[0], [r2], r5 @//Store dest row6
|
||||
vqrshrun.s16 d31, q11, #1
|
||||
vst1.32 d31[0], [r2], r5 @//Store dest row7
|
||||
|
||||
end_func:
|
||||
|
||||
vldmia sp!, {d8-d15} @ Restore neon registers that were saved
|
||||
ldmfd sp!, {r4-r12, pc} @Restoring registers from stack
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue