Merge branch 'master' into master

This commit is contained in:
bearoso 2023-03-22 14:25:17 -05:00 committed by GitHub
commit 8ac2ac7be5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
223 changed files with 60905 additions and 21713 deletions

View File

@ -13,7 +13,7 @@ snes9x_linux-gtk-amd64_task:
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install meson gettext libsdl2-dev libgtkmm-3.0-dev libgtk-3-dev libminizip-dev portaudio19-dev glslang-dev cmake
compile_script:
- meson build gtk --buildtype=release --strip
- cmake -G Ninja -B build -S gtk -DCMAKE_BUILD_TYPE=Release
- ninja -j2 -C build
package_script:
@ -70,8 +70,8 @@ snes9x_freebsd-x11-amd64_task:
snes9x_macOS-amd64_task:
osx_instance:
image: mojave-xcode
macos_instance:
image: ghcr.io/cirruslabs/macos-ventura-xcode:latest
compile_script:
- xcodebuild -project macosx/snes9x.xcodeproj -target Snes9x -configuration Release build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
@ -161,8 +161,8 @@ libretro_emscripten_task:
libretro_macOS-amd64_task:
osx_instance:
image: mojave-xcode
macos_instance:
image: ghcr.io/cirruslabs/macos-ventura-xcode:latest
compile_script:
- make -j2 -C libretro
build_artifacts:
@ -195,12 +195,3 @@ libretro_nintendo-ngc_task:
build_artifacts:
path: "libretro/snes9x_libretro_ngc.a"
libretro_playstation-psp_task:
container:
image: bkcsoft/psptoolchain
compile_script:
- make -j2 -C libretro platform=unix
build_artifacts:
path: "libretro/snes9x_libretro.so"

5
.gitmodules vendored
View File

@ -4,15 +4,12 @@
[submodule "win32/zlib/src"]
path = win32/zlib/src
url = https://github.com/madler/zlib.git
[submodule "win32/DirectXMath"]
path = win32/DirectXMath
url = https://github.com/Microsoft/DirectXMath
[submodule "shaders/SPIRV-Cross"]
path = external/SPIRV-Cross
url = https://github.com/KhronosGroup/SPIRV-Cross.git
[submodule "shaders/glslang"]
path = external/glslang
url = https://github.com/KhronosGroup/glslang.git
[submodule "vulkan/vulkan"]
[submodule "external/vulkan-headers"]
path = external/vulkan-headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git

View File

@ -21,7 +21,7 @@
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2022 BearOso,
(c) Copyright 2009 - 2023 BearOso,
OV2
(c) Copyright 2017 qwertymodo
@ -139,7 +139,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2022 BearOso
(c) Copyright 2004 - 2023 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -147,13 +147,13 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2022 OV2
(c) Copyright 2009 - 2023 OV2
Original Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
New MacOS GUI code
(c) Copyright 2022 Michael Donald Buckley
(c) Copyright 2022 - 2023 Michael Donald Buckley
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,

View File

@ -1,36 +1,36 @@
version: 1.61-{build}
image: Visual Studio 2017
image: Visual Studio 2022
environment:
matrix:
- generator: "Visual Studio 15"
- generator: "Visual Studio 2022"
config: Release Unicode
platform: Win32
arch: win32
output: win32\snes9x.exe
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
- generator: "Visual Studio 15"
- generator: "Visual Studio 2022"
config: Release Unicode
platform: x64
arch: win32-x64
output: win32\snes9x-x64.exe
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
- generator: "Visual Studio 15"
- generator: "Visual Studio 2022"
config: libretro Release
platform: Win32
arch: libretro
output: libretro\Win32\libretro Release\snes9x_libretro.dll
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
- generator: "Visual Studio 15"
- generator: "Visual Studio 2022"
config: libretro Release
platform: x64
arch: libretro-x64
output: libretro\x64\libretro Release\snes9x_libretro.dll
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
init:
- git config --global core.autocrlf input

View File

@ -5,6 +5,7 @@
\*****************************************************************************/
#include <cmath>
#include <vector>
#include "../snes9x.h"
#include "apu.h"
#include "../msu1.h"
@ -36,10 +37,10 @@ namespace spc {
static apu_callback callback = NULL;
static void *callback_data = NULL;
static bool8 sound_in_sync = TRUE;
static bool8 sound_enabled = FALSE;
static bool8 sound_in_sync = true;
static bool8 sound_enabled = false;
static Resampler *resampler = NULL;
static Resampler resampler;
static int32 reference_time;
static uint32 remainder;
@ -56,9 +57,8 @@ static double dynamic_rate_multiplier = 1.0;
namespace msu {
// Always 16-bit, Stereo; 1.5x dsp buffer to never overflow
static Resampler *resampler = NULL;
static int16 *resample_buffer = NULL;
static int resample_buffer_size = 0;
static Resampler resampler;
static std::vector<int16_t> resampler_buffer;
} // namespace msu
static void UpdatePlaybackRate(void);
@ -74,44 +74,32 @@ bool8 S9xMixSamples(uint8 *dest, int sample_count)
{
memset(out, 0, sample_count << 1);
S9xClearSamples();
spc::sound_in_sync = true;
return true;
}
else
if (spc::resampler.avail() < sample_count)
{
if (spc::resampler->avail() >= sample_count)
{
spc::resampler->read((short *)out, sample_count);
memset(out, 0, sample_count << 1);
return false;
}
if (Settings.MSU1)
{
if (msu::resampler->avail() >= sample_count)
{
if (msu::resample_buffer_size < sample_count)
{
if (msu::resample_buffer)
delete[] msu::resample_buffer;
msu::resample_buffer = new int16[sample_count];
msu::resample_buffer_size = sample_count;
}
msu::resampler->read(msu::resample_buffer,
sample_count);
for (int i = 0; i < sample_count; ++i)
{
int32 mixed = (int32)out[i] + msu::resample_buffer[i];
out[i] = ((int16)mixed != mixed) ? (mixed >> 31) ^ 0x7fff : mixed;
}
}
else // should never occur
assert(0);
}
}
else
spc::resampler.read((short *)out, sample_count);
if (Settings.MSU1)
{
if ((int)msu::resampler_buffer.size() < sample_count)
msu::resampler_buffer.resize(sample_count);
msu::resampler.read(msu::resampler_buffer.data(), sample_count);
for (int i = 0; i < sample_count; ++i)
{
memset(out, 0, sample_count << 1);
return false;
int32 mixed = (int32)out[i] + msu::resampler_buffer[i];
out[i] = ((int16)mixed != mixed) ? (mixed >> 31) ^ 0x7fff : mixed;
}
}
if (spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync ||
if (spc::resampler.space_empty() >= 535 * 2 || !Settings.SoundSync ||
Settings.TurboMode || Settings.Mute)
spc::sound_in_sync = true;
else
@ -122,7 +110,10 @@ bool8 S9xMixSamples(uint8 *dest, int sample_count)
int S9xGetSampleCount(void)
{
return spc::resampler->avail();
int avail = spc::resampler.avail();
if (Settings.MSU1) // return minimum available samples, otherwise we can run into the assert above due to partial sample generation in msu1
avail = Resampler::min(avail, msu::resampler.avail());
return avail;
}
void S9xLandSamples(void)
@ -130,7 +121,7 @@ void S9xLandSamples(void)
if (spc::callback != NULL)
spc::callback(spc::callback_data);
if (spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync ||
if (spc::resampler.space_empty() >= 535 * 2 || !Settings.SoundSync ||
Settings.TurboMode || Settings.Mute)
spc::sound_in_sync = true;
else
@ -139,15 +130,15 @@ void S9xLandSamples(void)
void S9xClearSamples(void)
{
spc::resampler->clear();
spc::resampler.clear();
if (Settings.MSU1)
msu::resampler->clear();
msu::resampler.clear();
}
bool8 S9xSyncSound(void)
{
if (!Settings.SoundSync || spc::sound_in_sync)
return (TRUE);
return true;
S9xLandSamples();
@ -180,12 +171,12 @@ static void UpdatePlaybackRate(void)
time_ratio *= spc::dynamic_rate_multiplier;
}
spc::resampler->time_ratio(time_ratio);
spc::resampler.time_ratio(time_ratio);
if (Settings.MSU1)
{
time_ratio = (44100.0 / Settings.SoundPlaybackRate) * (Settings.SoundInputRate / 32040.0);
msu::resampler->time_ratio(time_ratio);
time_ratio = time_ratio * 44100 / 32040;
msu::resampler.time_ratio(time_ratio);
}
}
@ -198,27 +189,11 @@ bool8 S9xInitSound(int buffer_ms)
if (requested_buffer_size_samples > buffer_size_samples)
buffer_size_samples = requested_buffer_size_samples;
if (!spc::resampler)
{
spc::resampler = new Resampler(buffer_size_samples);
if (!spc::resampler)
return (FALSE);
}
else
spc::resampler->resize(buffer_size_samples);
spc::resampler.resize(buffer_size_samples);
msu::resampler.resize(buffer_size_samples * 3 / 2);
if (!msu::resampler)
{
msu::resampler = new Resampler(buffer_size_samples * 3 / 2);
if (!msu::resampler)
return (FALSE);
}
else
msu::resampler->resize(buffer_size_samples * 3 / 2);
SNES::dsp.spc_dsp.set_output(spc::resampler);
S9xMSU1SetOutput(msu::resampler);
SNES::dsp.spc_dsp.set_output(&spc::resampler);
S9xMSU1SetOutput(&msu::resampler);
UpdatePlaybackRate();
@ -236,7 +211,7 @@ void S9xSetSoundMute(bool8 mute)
{
Settings.Mute = mute;
if (!spc::sound_enabled)
Settings.Mute = TRUE;
Settings.Mute = true;
}
void S9xDumpSPCSnapshot(void)
@ -246,33 +221,22 @@ void S9xDumpSPCSnapshot(void)
static void SPCSnapshotCallback(void)
{
S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR));
S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR).c_str());
printf("Dumped key-on triggered spc snapshot.\n");
}
bool8 S9xInitAPU(void)
{
spc::resampler = NULL;
msu::resampler = NULL;
spc::resampler.clear();
msu::resampler.clear();
return (TRUE);
return true;
}
void S9xDeinitAPU(void)
{
if (spc::resampler)
{
delete spc::resampler;
spc::resampler = NULL;
}
if (msu::resampler)
{
delete msu::resampler;
msu::resampler = NULL;
}
S9xMSU1DeInit();
msu::resampler_buffer.clear();
}
static inline int S9xAPUGetClock(int32 cpucycles)
@ -306,10 +270,10 @@ void S9xAPUSetReferenceTime(int32 cpucycles)
void S9xAPUExecute(void)
{
SNES::smp.clock -= S9xAPUGetClock(CPU.Cycles);
SNES::smp.enter();
int cycles = S9xAPUGetClock(CPU.Cycles);
spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
SNES::smp.clock -= cycles;
SNES::smp.enter();
S9xAPUSetReferenceTime(CPU.Cycles);
}
@ -319,7 +283,7 @@ void S9xAPUEndScanline(void)
S9xAPUExecute();
SNES::dsp.synchronize();
if (spc::resampler->space_filled() >= APU_SAMPLE_BLOCK || !spc::sound_in_sync)
if (spc::resampler.space_filled() >= APU_SAMPLE_BLOCK)
S9xLandSamples();
}
@ -386,7 +350,6 @@ void S9xAPULoadState(uint8 *block)
SNES::smp.load_state(&ptr);
SNES::dsp.load_state(&ptr);
spc::reference_time = SNES::get_le32(ptr);
ptr += sizeof(int32);
spc::remainder = SNES::get_le32(ptr);
@ -515,9 +478,9 @@ bool8 S9xSPCDump(const char *filename)
fs = fopen(filename, "wb");
if (!fs)
return (FALSE);
return false;
S9xSetSoundMute(TRUE);
S9xSetSoundMute(true);
SNES::smp.save_spc(buf);
@ -530,7 +493,7 @@ bool8 S9xSPCDump(const char *filename)
fclose(fs);
S9xSetSoundMute(FALSE);
S9xSetSoundMute(false);
return (TRUE);
return true;
}

View File

@ -55,9 +55,11 @@ static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
// Access global DSP register
#define REG(n) m.regs [r_##n]
#define XREG(n) m.external_regs [r_##n]
// Access voice DSP register
#define VREG(r,n) r [v_##n]
#define XVREG(r,n) (m.external_regs + (r - m.regs))[v_##n]
#define WRITE_SAMPLES( l, r, out ) \
{\
@ -927,6 +929,7 @@ inline VOICE_CLOCK( V7 )
{
// Update ENDX
REG(endx) = m.endx_buf;
XREG(endx) = m.endx_buf;
m.envx_buf = v->t_envx_out;
}
@ -934,11 +937,13 @@ inline VOICE_CLOCK( V8 )
{
// Update OUTX
VREG(v->regs,outx) = m.outx_buf;
XVREG(v->regs,outx) = m.outx_buf;
}
inline VOICE_CLOCK( V9 )
{
// Update ENVX
VREG(v->regs,envx) = m.envx_buf;
XVREG(v->regs,envx) = m.envx_buf;
}
// Most voices do all these in one clock, so make a handy composite
@ -1237,7 +1242,9 @@ void SPC_DSP::soft_reset()
void SPC_DSP::load( uint8_t const regs [register_count] )
{
memcpy( m.regs, regs, sizeof m.regs );
memcpy( m.external_regs, regs, sizeof m.regs );
memset( m.regs, 0, sizeof m.regs);
m.regs[r_flg] = 0xE0;
memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
// Internal state
@ -1398,6 +1405,7 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy )
SPC_COPY( uint16_t, m.t_echo_ptr );
SPC_COPY( uint8_t, m.t_looped );
copier.copy(m.external_regs, register_count);
copier.extra();
}
#endif

View File

@ -204,6 +204,8 @@ private:
sample_t extra [extra_size];
uint8_t separate_echo_buffer [0x10000];
uint8_t external_regs [register_count];
};
state_t m;
@ -260,7 +262,7 @@ inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; }
inline int SPC_DSP::read( int addr ) const
{
assert( (unsigned) addr < register_count );
return m.regs [addr];
return m.external_regs [addr];
}
inline void SPC_DSP::write( int addr, int data )
@ -268,6 +270,7 @@ inline void SPC_DSP::write( int addr, int data )
assert( (unsigned) addr < register_count );
m.regs [addr] = (uint8_t) data;
m.external_regs [addr] = (uint8_t) data;
switch ( addr & 0x0F )
{
case v_envx:

38
bsx.cpp
View File

@ -738,16 +738,14 @@ void S9xBSXSetStream1 (uint8 count)
if (BSX.sat_stream1.is_open())
BSX.sat_stream1.close(); //If Stream already opened for one file: Close it.
char path[PATH_MAX + 1], name[PATH_MAX + 1];
std::string path = S9xGetDirectory(SAT_DIR) + SLASH_STR;
strcpy(path, S9xGetDirectory(SAT_DIR));
strcat(path, SLASH_STR);
snprintf(name, PATH_MAX + 1, "BSX%04X-%d.bin", (BSX.PPU[0x2188 - BSXPPUBASE] | (BSX.PPU[0x2189 - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
strcat(path, name);
char name[PATH_MAX];
snprintf(name, PATH_MAX, "BSX%04X-%d.bin", (BSX.PPU[0x2188 - BSXPPUBASE] | (BSX.PPU[0x2189 - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
path += name;
BSX.sat_stream1.clear();
BSX.sat_stream1.open(path, std::ios::in | std::ios::binary);
BSX.sat_stream1.open(path.c_str(), std::ios::in | std::ios::binary);
if (BSX.sat_stream1.good())
{
BSX.sat_stream1.seekg(0, BSX.sat_stream1.end);
@ -770,16 +768,15 @@ void S9xBSXSetStream2 (uint8 count)
if (BSX.sat_stream2.is_open())
BSX.sat_stream2.close(); //If Stream already opened for one file: Close it.
char path[PATH_MAX + 1], name[PATH_MAX + 1];
strcpy(path, S9xGetDirectory(SAT_DIR));
strcat(path, SLASH_STR);
std::string path = S9xGetDirectory(SAT_DIR) + SLASH_STR;
snprintf(name, PATH_MAX + 1, "BSX%04X-%d.bin", (BSX.PPU[0x218E - BSXPPUBASE] | (BSX.PPU[0x218F - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
strcat(path, name);
char name[PATH_MAX];
snprintf(name, PATH_MAX, "BSX%04X-%d.bin", (BSX.PPU[0x218E - BSXPPUBASE] | (BSX.PPU[0x218F - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
path += name;
BSX.sat_stream2.clear();
BSX.sat_stream2.open(path, std::ios::in | std::ios::binary);
BSX.sat_stream2.open(path.c_str(), std::ios::in | std::ios::binary);
if (BSX.sat_stream2.good())
{
BSX.sat_stream2.seekg(0, BSX.sat_stream2.end);
@ -1207,20 +1204,15 @@ uint8 * S9xGetBasePointerBSX (uint32 address)
static bool8 BSX_LoadBIOS (void)
{
FILE *fp;
char path[PATH_MAX + 1], name[PATH_MAX + 1];
bool8 r = FALSE;
strcpy(path, S9xGetDirectory(BIOS_DIR));
strcat(path, SLASH_STR);
strcpy(name, path);
strcat(name, "BS-X.bin");
std::string name = S9xGetDirectory(BIOS_DIR) + SLASH_STR + "BS-X.bin";
fp = fopen(name, "rb");
fp = fopen(name.c_str(), "rb");
if (!fp)
{
strcpy(name, path);
strcat(name, "BS-X.bios");
fp = fopen(name, "rb");
name = S9xGetDirectory(BIOS_DIR) + SLASH_STR + "BS-X.bios";
fp = fopen(name.c_str(), "rb");
}
if (fp)
@ -1255,7 +1247,7 @@ void S9xInitBSX (void)
{
Settings.BS = FALSE;
if (is_BSX_BIOS(Memory.ROM,Memory.CalculatedSize))
if (is_BSX_BIOS(Memory.ROM,Memory.CalculatedSize))
{
// BS-X itself

View File

@ -37,112 +37,6 @@
(s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \
((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24))))
static bool8 S9xAllHex (const char *, int);
static bool8 S9xAllHex (const char *code, int len)
{
for (int i = 0; i < len; i++)
if ((code[i] < '0' || code[i] > '9') && (code[i] < 'a' || code[i] > 'f') && (code[i] < 'A' || code[i] > 'F'))
return (FALSE);
return (TRUE);
}
const char * S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte)
{
uint32 data = 0;
if (strlen(code) != 8 || !S9xAllHex(code, 8) || sscanf(code, "%x", &data) != 1)
return ("Invalid Pro Action Replay code - should be 8 hex digits in length.");
address = data >> 8;
byte = (uint8) data;
return (NULL);
}
const char * S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, uint8 &num_bytes, uint8 bytes[3])
{
char tmp[15];
int i;
if (strlen(code) != 14)
return ("Invalid Gold Finger code - should be 14 hex digits in length.");
strncpy(tmp, code, 5);
tmp[5] = 0;
if (sscanf(tmp, "%x", &address) != 1)
return ("Invalid Gold Finger code.");
// Correct GoldFinger Address
address = (address & 0x7FFF) | ((address & 0x7F8000) << 1) | 0x8000;
for (i = 0; i < 3; i++)
{
unsigned int byte;
strncpy(tmp, code + 5 + i * 2, 2);
tmp[2] = 0;
if (sscanf(tmp, "%x", &byte) != 1)
break;
bytes[i] = (uint8) byte;
}
num_bytes = i;
sram = code[13] == '1';
return (NULL);
}
const char * S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte)
{
char new_code[12];
if (strlen(code) != 9 || *(code + 4) != '-' || !S9xAllHex(code, 4) || !S9xAllHex(code + 5, 4))
return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'.");
strcpy(new_code, "0x");
strncpy(new_code + 2, code, 4);
strcpy(new_code + 6, code + 5);
static const char *real_hex = "0123456789ABCDEF";
static const char *genie_hex = "DF4709156BC8A23E";
for (int i = 2; i < 10; i++)
{
if (islower(new_code[i]))
new_code[i] = toupper(new_code[i]);
int j;
for (j = 0; j < 16; j++)
{
if (new_code[i] == genie_hex[j])
{
new_code[i] = real_hex[j];
break;
}
}
if (j == 16)
return ("Invalid hex-character in Game Genie(tm) code.");
}
uint32 data = 0;
sscanf(new_code, "%x", &data);
byte = (uint8) (data >> 24);
address = data & 0xffffff;
address = ((address & 0x003c00) << 10) +
((address & 0x00003c) << 14) +
((address & 0xf00000) >> 8) +
((address & 0x000003) << 10) +
((address & 0x00c000) >> 6) +
((address & 0x0f0000) >> 12) +
((address & 0x0003c0) >> 6);
return (NULL);
}
void S9xStartCheatSearch (SCheatData *d)
{
memmove(d->CWRAM, d->RAM, 0x20000);

View File

@ -23,14 +23,14 @@ struct SCheat
struct SCheatGroup
{
char *name;
std::string name;
bool8 enabled;
std::vector<struct SCheat> c;
std::vector<struct SCheat> cheat;
};
struct SCheatData
{
std::vector<struct SCheatGroup> g;
std::vector<struct SCheatGroup> group;
bool8 enabled;
uint8 CWRAM[0x20000];
uint8 CSRAM[0x80000];
@ -73,20 +73,20 @@ typedef enum
extern SCheatData Cheat;
extern Watch watches[16];
int S9xAddCheatGroup (const char *name, const char *cheat);
int S9xModifyCheatGroup (uint32 index, const char *name, const char *cheat);
void S9xEnableCheatGroup (uint32 index);
void S9xDisableCheatGroup (uint32 index);
void S9xDeleteCheats (void);
char *S9xCheatGroupToText (uint32 index);
void S9xDeleteCheatGroup (uint32 index);
bool8 S9xLoadCheatFile (const char *filename);
bool8 S9xSaveCheatFile (const char *filename);
void S9xUpdateCheatsInMemory (void);
int S9xImportCheatsFromDatabase(const char *filename);
void S9xCheatsDisable (void);
void S9xCheatsEnable (void);
char *S9xCheatValidate (const char *cheat);
int S9xAddCheatGroup(const std::string &name, const std::string &cheat);
int S9xModifyCheatGroup(uint32 index, const std::string &name, const std::string &cheat);
void S9xEnableCheatGroup(uint32 index);
void S9xDisableCheatGroup(uint32 index);
void S9xDeleteCheats(void);
std::string S9xCheatGroupToText(uint32 index);
void S9xDeleteCheatGroup(uint32 index);
bool8 S9xLoadCheatFile(const std::string &filename);
bool8 S9xSaveCheatFile(const std::string &filename);
void S9xUpdateCheatsInMemory(void);
int S9xImportCheatsFromDatabase(const std::string &filename);
void S9xCheatsDisable(void);
void S9xCheatsEnable(void);
std::string S9xCheatValidate(const std::string &cheat);
void S9xInitCheatData (void);
void S9xInitWatchedAddress (void);
@ -96,8 +96,4 @@ void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize,
void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8);
void S9xOutputCheatSearchResults (SCheatData *);
const char * S9xGameGenieToRaw (const char *, uint32 &, uint8 &);
const char * S9xProActionReplayToRaw (const char *, uint32 &, uint8 &);
const char * S9xGoldFingerToRaw (const char *, uint32 &, bool8 &, uint8 &, uint8 bytes[3]);
#endif

View File

@ -4,37 +4,24 @@
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include <ctype.h>
#include "bml.h"
#include "cheats.h"
#include "snes9x.h"
#include "memmap.h"
#include "cheats.h"
#include "bml.h"
static inline char *trim (char *string)
static inline uint8 S9xGetByteFree(uint32 Address)
{
int start;
int end;
for (start = 0; string[start] && isspace (string[start]); start++) {}
for (end = start; string[end] && !isspace (string[end]); end++) {}
string[end] = '\0';
return &string[start];
}
static inline uint8 S9xGetByteFree (uint32 Address)
{
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = Memory.Map[block];
uint8 byte;
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
if (GetAddress >= (uint8 *)CMemory::MAP_LAST)
{
byte = *(GetAddress + (Address & 0xffff));
return (byte);
}
switch ((pint) GetAddress)
switch ((pint)GetAddress)
{
case CMemory::MAP_CPU:
byte = S9xGetCPU(Address & 0xffff);
@ -108,18 +95,18 @@ static inline uint8 S9xGetByteFree (uint32 Address)
}
}
static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
static inline void S9xSetByteFree(uint8 Byte, uint32 Address)
{
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *SetAddress = Memory.Map[block];
if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
if (SetAddress >= (uint8 *)CMemory::MAP_LAST)
{
*(SetAddress + (Address & 0xffff)) = Byte;
return;
}
switch ((pint) SetAddress)
switch ((pint)SetAddress)
{
case CMemory::MAP_CPU:
S9xSetCPU(Byte, Address & 0xffff);
@ -197,165 +184,229 @@ static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
}
}
void S9xInitWatchedAddress (void)
void S9xInitWatchedAddress(void)
{
for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++)
watches[i].on = false;
}
void S9xInitCheatData (void)
void S9xInitCheatData(void)
{
Cheat.RAM = Memory.RAM;
Cheat.SRAM = Memory.SRAM;
Cheat.FillRAM = Memory.FillRAM;
}
static inline std::string trim(const std::string &&string)
{
auto start = string.find_first_not_of(" \t\n\r");
auto end = string.find_last_not_of(" \t\n\r");
if (start != std::string::npos && end != std::string::npos)
return string.substr(start, end - start + 1);
return "";
}
void S9xUpdateCheatInMemory (SCheat *c)
void S9xUpdateCheatInMemory(SCheat &c)
{
uint8 byte;
if (!c->enabled)
if (!c.enabled)
return;
byte = S9xGetByteFree (c->address);
byte = S9xGetByteFree(c.address);
if (byte != c->byte)
if (byte != c.byte)
{
/* The game wrote a different byte to the address, update saved_byte */
c->saved_byte = byte;
c.saved_byte = byte;
if (c->conditional)
if (c.conditional)
{
if (c->saved_byte != c->cond_byte && c->cond_true)
if (c.saved_byte != c.cond_byte && c.cond_true)
{
/* Condition is now false, let the byte stand */
c->cond_true = false;
c.cond_true = false;
}
else if (c->saved_byte == c->cond_byte && !c->cond_true)
else if (c.saved_byte == c.cond_byte && !c.cond_true)
{
c->cond_true = true;
S9xSetByteFree (c->byte, c->address);
c.cond_true = true;
S9xSetByteFree(c.byte, c.address);
}
}
else
S9xSetByteFree (c->byte, c->address);
S9xSetByteFree(c.byte, c.address);
}
else if (c->conditional)
else if (c.conditional)
{
if (byte == c->cond_byte)
if (byte == c.cond_byte)
{
c->cond_true = true;
c->saved_byte = byte;
S9xSetByteFree (c->byte, c->address);
c.cond_true = true;
c.saved_byte = byte;
S9xSetByteFree(c.byte, c.address);
}
}
}
void S9xDisableCheat (SCheat *c)
void S9xDisableCheat(SCheat &c)
{
if (!c->enabled)
if (!c.enabled)
return;
if (!Cheat.enabled)
{
c->enabled = false;
c.enabled = false;
return;
}
/* Make sure we restore the up-to-date written byte */
S9xUpdateCheatInMemory (c);
c->enabled = false;
S9xUpdateCheatInMemory(c);
c.enabled = false;
if (c->conditional && !c->cond_true)
if (c.conditional && !c.cond_true)
return;
S9xSetByteFree (c->saved_byte, c->address);
c->cond_true = false;
S9xSetByteFree (c.saved_byte, c.address);
c.cond_true = false;
}
void S9xDeleteCheatGroup (uint32 g)
void S9xDeleteCheatGroup(uint32 g)
{
unsigned int i;
if (g >= Cheat.g.size ())
if (g >= Cheat.group.size())
return;
for (i = 0; i < Cheat.g[g].c.size (); i++)
for (i = 0; i < Cheat.group[g].cheat.size(); i++)
{
S9xDisableCheat (&Cheat.g[g].c[i]);
S9xDisableCheat(Cheat.group[g].cheat[i]);
}
delete[] Cheat.g[g].name;
Cheat.g.erase (Cheat.g.begin () + g);
Cheat.group.erase(Cheat.group.begin() + g);
}
void S9xDeleteCheats (void)
void S9xDeleteCheats(void)
{
unsigned int i;
for (i = 0; i < Cheat.g.size (); i++)
for (size_t i = 0; i < Cheat.group.size(); i++)
{
S9xDisableCheatGroup (i);
delete[] Cheat.g[i].name;
S9xDisableCheatGroup(i);
}
Cheat.g.clear ();
Cheat.group.clear();
}
void S9xEnableCheat (SCheat *c)
void S9xEnableCheat(SCheat &c)
{
uint8 byte;
if (c->enabled)
if (c.enabled)
return;
c->enabled = true;
c.enabled = true;
if (!Cheat.enabled)
return;
byte = S9xGetByteFree(c->address);
byte = S9xGetByteFree(c.address);
if (c->conditional)
if (c.conditional)
{
if (byte != c->cond_byte)
if (byte != c.cond_byte)
return;
c->cond_true = true;
c.cond_true = true;
}
c->saved_byte = byte;
S9xSetByteFree (c->byte, c->address);
c.saved_byte = byte;
S9xSetByteFree(c.byte, c.address);
}
void S9xEnableCheatGroup (uint32 num)
void S9xEnableCheatGroup(uint32 num)
{
unsigned int i;
for (auto &c : Cheat.group[num].cheat)
S9xEnableCheat(c);
for (i = 0; i < Cheat.g[num].c.size (); i++)
{
S9xEnableCheat (&Cheat.g[num].c[i]);
}
Cheat.g[num].enabled = true;
Cheat.group[num].enabled = true;
}
void S9xDisableCheatGroup (uint32 num)
void S9xDisableCheatGroup(uint32 num)
{
unsigned int i;
for (auto &c : Cheat.group[num].cheat)
S9xDisableCheat(c);
for (i = 0; i < Cheat.g[num].c.size (); i++)
{
S9xDisableCheat (&Cheat.g[num].c[i]);
}
Cheat.g[num].enabled = false;
Cheat.group[num].enabled = false;
}
SCheat S9xTextToCheat (char *text)
static bool is_all_hex(const std::string &code)
{
for (const auto &c : code)
{
if ((c < '0' || c > '9') &&
(c < 'a' || c > 'f') &&
(c < 'A' || c > 'F'))
return false;
}
return true;
}
bool S9xProActionReplayToRaw(const std::string &code, uint32 &address, uint8 &byte)
{
if (code.length() != 8 || !is_all_hex(code))
return false;
uint32 data = std::strtoul(code.c_str(), nullptr, 16);
address = data >> 8;
byte = (uint8)data;
return true;
}
bool S9xGameGenieToRaw(const std::string &code, uint32 &address, uint8 &byte)
{
if (code.length() != 9)
return false;
if (code[4] != '-')
return false;
if (!is_all_hex(code.substr(0, 4)))
return false;
if (!is_all_hex(code.substr(5, 4)))
return false;
auto new_code = code.substr(0, 4) + code.substr(5, 4);
static const char *real_hex = "0123456789ABCDEF";
static const char *genie_hex = "DF4709156BC8A23E";
for (auto &c : new_code)
{
c = toupper(c);
for (int i = 0; i < 16; i++)
{
if (genie_hex[i] == c)
{
c = real_hex[i];
break;
}
}
}
uint32 data = strtoul(new_code.c_str(), nullptr, 16);
byte = (uint8)(data >> 24);
address = data & 0xffffff;
address = ((address & 0x003c00) << 10) +
((address & 0x00003c) << 14) +
((address & 0xf00000) >> 8) +
((address & 0x000003) << 10) +
((address & 0x00c000) >> 6) +
((address & 0x0f0000) >> 12) +
((address & 0x0003c0) >> 6);
return true;
}
SCheat S9xTextToCheat(const std::string &text)
{
SCheat c;
unsigned int byte = 0;
@ -364,34 +415,28 @@ SCheat S9xTextToCheat (char *text)
c.enabled = false;
c.conditional = false;
if (!S9xGameGenieToRaw (text, c.address, c.byte))
if (S9xGameGenieToRaw(text, c.address, c.byte))
{
byte = c.byte;
}
else if (!S9xProActionReplayToRaw (text, c.address, c.byte))
else if (S9xProActionReplayToRaw(text, c.address, c.byte))
{
byte = c.byte;
}
else if (sscanf (text, "%x = %x ? %x", &c.address, &cond_byte, &byte) == 3)
else if (sscanf(text.c_str(), "%x = %x ? %x", &c.address, &cond_byte, &byte) == 3)
{
c.conditional = true;
}
else if (sscanf (text, "%x = %x", &c.address, &byte) == 2)
else if (sscanf(text.c_str(), "%x = %x", &c.address, &byte) == 2)
{
}
else if (sscanf (text, "%x / %x / %x", &c.address, &cond_byte, &byte) == 3)
else if (sscanf(text.c_str(), "%x / %x / %x", &c.address, &cond_byte, &byte) == 3)
{
c.conditional = true;
}
else if (sscanf (text, "%x / %x", &c.address, &byte) == 2)
else if (sscanf(text.c_str(), "%x / %x", &c.address, &byte) == 2)
{
}
else
{
c.address = 0;
@ -404,313 +449,287 @@ SCheat S9xTextToCheat (char *text)
return c;
}
SCheatGroup S9xCreateCheatGroup (const char *name, const char *cheat)
std::vector<std::string> split_string(const std::string &str, unsigned char delim)
{
SCheatGroup g;
char *code_string = strdup (cheat);
char *code_ptr = code_string;
int len;
std::vector<std::string> tokens;
size_t pos = 0;
size_t index;
g.name = strdup (name);
g.enabled = false;
for (len = strcspn (code_ptr, "+"); len; len = strcspn (code_ptr, "+"))
while (pos < str.length())
{
char *code = code_ptr;
code_ptr += len + (code_ptr[len] == '\0' ? 0 : 1);
code[len] = '\0';
code = trim (code);
index = str.find(delim, pos);
if (index == std::string::npos)
{
if (pos < str.length())
{
tokens.push_back(trim(str.substr(pos)));
}
SCheat c = S9xTextToCheat (code);
if (c.address)
g.c.push_back (c);
break;
}
else if (index > pos)
{
tokens.push_back(trim(str.substr(pos, index - pos)));
}
pos = index + 1;
}
free(code_string);
return tokens;
}
SCheatGroup S9xCreateCheatGroup(const std::string &name, const std::string &cheat)
{
SCheatGroup g;
g.name = name;
g.enabled = false;
auto cheats = split_string(cheat, '+');
for (const auto &c : cheats)
{
SCheat new_cheat = S9xTextToCheat(c);
if (new_cheat.address)
g.cheat.push_back(new_cheat);
}
return g;
}
int S9xAddCheatGroup (const char *name, const char *cheat)
int S9xAddCheatGroup(const std::string &name, const std::string &cheat)
{
SCheatGroup g = S9xCreateCheatGroup (name, cheat);
if (g.c.size () == 0)
SCheatGroup g = S9xCreateCheatGroup(name, cheat);
if (g.cheat.size() == 0)
return -1;
Cheat.g.push_back (g);
Cheat.group.push_back(g);
return Cheat.g.size () - 1;
return Cheat.group.size() - 1;
}
int S9xModifyCheatGroup (uint32 num, const char *name, const char *cheat)
int S9xModifyCheatGroup(uint32 num, const std::string &name, const std::string &cheat)
{
if (num >= Cheat.g.size())
if (num >= Cheat.group.size())
return -1;
S9xDisableCheatGroup (num);
delete[] Cheat.g[num].name;
S9xDisableCheatGroup(num);
Cheat.g[num] = S9xCreateCheatGroup (name, cheat);
Cheat.group[num] = S9xCreateCheatGroup(name, cheat);
return num;
}
char *S9xCheatToText (SCheat *c)
std::string S9xCheatToText(const SCheat &c)
{
int size = 10; /* 6 address, 1 =, 2 byte, 1 NUL */
char *text;
char output[256]{};
if (c->conditional)
size += 3; /* additional 2 byte, 1 ? */
text = new char[size];
if (c->conditional)
snprintf (text, size, "%06x=%02x?%02x", c->address, c->cond_byte, c->byte);
if (c.conditional)
sprintf(output, "%06x=%02x?%02x", c.address, c.cond_byte, c.byte);
else
snprintf (text, size, "%06x=%02x", c->address, c->byte);
sprintf(output, "%06x=%02x", c.address, c.byte);
return std::string(output);
}
std::string S9xCheatGroupToText(SCheatGroup &g)
{
std::string text = "";
for (size_t i = 0; i < g.cheat.size(); i++)
{
text += S9xCheatToText(g.cheat[i]);
if (i != g.cheat.size() - 1)
text += "+";
}
return text;
}
char *S9xCheatGroupToText (SCheatGroup *g)
std::string S9xCheatValidate(const std::string &code_string)
{
std::string text = "";
unsigned int i;
SCheatGroup g = S9xCreateCheatGroup("temp", code_string);
if (g->c.size () == 0)
return NULL;
for (i = 0; i < g->c.size (); i++)
if (g.cheat.size() > 0)
{
char *tmp = S9xCheatToText (&g->c[i]);
if (i != 0)
text += " + ";
text += tmp;
delete[] tmp;
return S9xCheatGroupToText(g);
}
return strdup (text.c_str ());
return "";
}
char *S9xCheatValidate (const char *code_string)
std::string S9xCheatGroupToText(uint32 num)
{
SCheatGroup g = S9xCreateCheatGroup ("temp", code_string);
if (num >= Cheat.group.size())
return "";
delete[] g.name;
if (g.c.size() > 0)
{
return S9xCheatGroupToText (&g);
}
return NULL;
return S9xCheatGroupToText(Cheat.group[num]);
}
char *S9xCheatGroupToText (uint32 num)
void S9xUpdateCheatsInMemory(void)
{
if (num >= Cheat.g.size ())
return NULL;
return S9xCheatGroupToText (&Cheat.g[num]);
}
void S9xUpdateCheatsInMemory (void)
{
unsigned int i;
unsigned int j;
if (!Cheat.enabled)
return;
for (i = 0; i < Cheat.g.size (); i++)
{
for (j = 0; j < Cheat.g[i].c.size (); j++)
{
S9xUpdateCheatInMemory (&Cheat.g[i].c[j]);
}
}
for (auto &group : Cheat.group)
for (auto &cheat : group.cheat)
S9xUpdateCheatInMemory(cheat);
}
static int S9xCheatIsDuplicate (const char *name, const char *code)
static bool S9xCheatIsDuplicate(const std::string &name, const std::string &code)
{
unsigned int i;
for (i = 0; i < Cheat.g.size(); i++)
for (size_t i = 0; i < Cheat.group.size(); i++)
{
if (!strcmp (name, Cheat.g[i].name))
if (Cheat.group[i].name == name)
{
char *code_string = S9xCheatGroupToText (i);
char *validated = S9xCheatValidate (code);
auto code_string = S9xCheatGroupToText(i);
auto validated_string = S9xCheatValidate(code);
if (validated && !strcmp (code_string, validated))
{
free (code_string);
free (validated);
return TRUE;
}
free (code_string);
free (validated);
if (validated_string == code_string)
return true;
}
}
return FALSE;
return false;
}
static void S9xLoadCheatsFromBMLNode (bml_node *n)
static void S9xLoadCheatsFromBMLNode(bml_node &n)
{
unsigned int i;
for (i = 0; i < n->child.size (); i++)
for (auto &c : n.child)
{
if (!strcasecmp (n->child[i].name.c_str(), "cheat"))
{
const char *desc = NULL;
const char *code = NULL;
bool8 enabled = false;
if (strcasecmp(c.name.c_str(), "cheat"))
continue;
bml_node *c = &n->child[i];
bml_node *tmp = NULL;
auto subnode = c.find_subnode("code");
if (!subnode)
continue;
std::string code = subnode->data;
tmp = c->find_subnode("name");
if (!tmp)
desc = (char *) "";
else
desc = tmp->data.c_str();
std::string name;
subnode = c.find_subnode("name");
if (subnode)
name = subnode->data;
tmp = c->find_subnode("code");
if (tmp)
code = tmp->data.c_str();
bool enable = false;
if (c.find_subnode("enable"))
enable = true;
if (c->find_subnode("enable"))
enabled = true;
if (S9xCheatIsDuplicate(name, code))
continue;
if (code && !S9xCheatIsDuplicate (desc, code))
{
int index = S9xAddCheatGroup (desc, code);
if (enabled)
S9xEnableCheatGroup (index);
}
}
auto index = S9xAddCheatGroup(name, code);
if (enable)
S9xEnableCheatGroup(index);
}
return;
}
static bool8 S9xLoadCheatFileClassic (const char *filename)
static bool8 S9xLoadCheatFileClassic(const std::string &filename)
{
FILE *fs;
uint8 data[28];
fs = fopen(filename, "rb");
fs = fopen(filename.c_str(), "rb");
if (!fs)
return (FALSE);
while (fread ((void *) data, 1, 28, fs) == 28)
while (fread(data, 1, 28, fs) == 28)
{
SCheat c;
char name[21];
char cheat[10];
c.enabled = (data[0] & 4) == 0;
c.byte = data[1];
c.address = data[2] | (data[3] << 8) | (data[4] << 16);
memcpy (name, &data[8], 20);
name[20] = 0;
c.address = data[2] | (data[3] << 8) | (data[4] << 16);
snprintf (cheat, 10, "%x=%x", c.address, c.byte);
S9xAddCheatGroup (name, cheat);
std::string name((const char *)&data[8], 20);
char code[32]{};
sprintf(code, "%x=%x", c.address, c.byte);
std::string cheat(code);
S9xAddCheatGroup(name, cheat);
if (c.enabled)
S9xEnableCheatGroup (Cheat.g.size () - 1);
S9xEnableCheatGroup(Cheat.group.size() - 1);
}
fclose(fs);
return (TRUE);
return TRUE;
}
bool8 S9xLoadCheatFile (const char *filename)
bool8 S9xLoadCheatFile(const std::string &filename)
{
bml_node bml;
if (!bml.parse_file(filename))
{
return S9xLoadCheatFileClassic (filename);
return S9xLoadCheatFileClassic(filename);
}
bml_node *n = bml.find_subnode("cheat");
if (n)
{
S9xLoadCheatsFromBMLNode (&bml);
S9xLoadCheatsFromBMLNode(bml);
}
if (!n)
{
return S9xLoadCheatFileClassic (filename);
return S9xLoadCheatFileClassic(filename);
}
return (TRUE);
}
bool8 S9xSaveCheatFile (const char *filename)
bool8 S9xSaveCheatFile(const std::string &filename)
{
unsigned int i;
FILE *file = NULL;
if (Cheat.g.size () == 0)
if (Cheat.group.size() == 0)
{
remove (filename);
remove(filename.c_str());
return TRUE;
}
file = fopen (filename, "w");
file = fopen(filename.c_str(), "w");
if (!file)
return FALSE;
for (i = 0; i < Cheat.g.size (); i++)
for (i = 0; i < Cheat.group.size(); i++)
{
char *txt = S9xCheatGroupToText (i);
fprintf (file,
"cheat\n"
" name: %s\n"
" code: %s\n"
"%s\n",
Cheat.g[i].name ? Cheat.g[i].name : "",
txt,
Cheat.g[i].enabled ? " enable\n" : ""
);
delete[] txt;
fprintf(file,
"cheat\n"
" name: %s\n"
" code: %s\n"
"%s\n",
Cheat.group[i].name.c_str(),
S9xCheatGroupToText(i).c_str(),
Cheat.group[i].enabled ? " enable\n" : "");
}
fclose (file);
fclose(file);
return TRUE;
}
void S9xCheatsDisable (void)
void S9xCheatsDisable(void)
{
unsigned int i;
if (!Cheat.enabled)
return;
for (i = 0; i < Cheat.g.size (); i++)
for (i = 0; i < Cheat.group.size(); i++)
{
if (Cheat.g[i].enabled)
if (Cheat.group[i].enabled)
{
S9xDisableCheatGroup (i);
Cheat.g[i].enabled = TRUE;
S9xDisableCheatGroup(i);
Cheat.group[i].enabled = TRUE;
}
}
Cheat.enabled = FALSE;
}
void S9xCheatsEnable (void)
void S9xCheatsEnable(void)
{
unsigned int i;
@ -719,17 +738,17 @@ void S9xCheatsEnable (void)
Cheat.enabled = TRUE;
for (i = 0; i < Cheat.g.size (); i++)
for (i = 0; i < Cheat.group.size(); i++)
{
if (Cheat.g[i].enabled)
if (Cheat.group[i].enabled)
{
Cheat.g[i].enabled = FALSE;
S9xEnableCheatGroup (i);
Cheat.group[i].enabled = FALSE;
S9xEnableCheatGroup(i);
}
}
}
int S9xImportCheatsFromDatabase (const char *filename)
int S9xImportCheatsFromDatabase(const std::string &filename)
{
char sha256_txt[65];
char hextable[] = "0123456789abcdef";
@ -746,19 +765,16 @@ int S9xImportCheatsFromDatabase (const char *filename)
}
sha256_txt[64] = '\0';
for (i = 0; i < bml.child.size (); i++)
for (auto &c : bml.child)
{
if (!strcasecmp (bml.child[i].name.c_str(), "cartridge"))
if (!strcasecmp(c.name.c_str(), "cartridge"))
{
bml_node *n;
auto n = c.find_subnode("sha256");
if ((n = bml.child[i].find_subnode ("sha256")))
if (n && !strcasecmp(n->data.c_str(), sha256_txt))
{
if (!strcasecmp (n->data.c_str(), sha256_txt))
{
S9xLoadCheatsFromBMLNode (&bml.child[i]);
return 0;
}
S9xLoadCheatsFromBMLNode(c);
return 0;
}
}
}

View File

@ -1,67 +0,0 @@
#include <cstring>
#include "port.h"
void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
{
char *slash = strrchr((char *)path, SLASH_CHAR);
char *dot = strrchr((char *)path, '.');
*drive = '\0';
if (dot && slash && dot < slash)
{
dot = 0;
}
if (!slash)
{
*dir = '\0';
strcpy(fname, path);
if (dot)
{
fname[dot - path] = '\0';
strcpy(ext, dot + 1);
}
else
{
*ext = '\0';
}
}
else
{
strcpy(dir, path);
dir[slash - path] = '\0';
strcpy(fname, slash + 1);
if (dot)
{
fname[(dot - slash) - 1] = '\0';
strcpy(ext, dot + 1);
}
else
{
*ext = '\0';
}
}
}
void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext)
{
if (dir && *dir)
{
strcpy(path, dir);
strcat(path, "/");
}
else
*path = '\0';
strcat(path, fname);
if (ext && *ext)
{
if (*ext != '.')
strcat(path, ".");
strcat(path, ext);
}
}

View File

@ -328,14 +328,12 @@ static void DoGunLatch (int x, int y)
if (x > 295)
x = 295;
else
if (x < 40)
else if (x < 40)
x = 40;
if (y > PPU.ScreenHeight - 1)
y = PPU.ScreenHeight - 1;
else
if (y < 0)
else if (y < 0)
y = 0;
PPU.GunVLatch = (uint16) (y + 1);
@ -1164,8 +1162,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
if (!strcmp(name, "None"))
cmd.type = S9xNoMapping;
else
if (!strncmp(name, "Joypad", 6))
else if (!strncmp(name, "Joypad", 6))
{
if (name[6] < '1' || name[6] > '8' || name[7] != ' ')
return (cmd);
@ -1176,24 +1173,15 @@ s9xcommand_t S9xGetCommandT (const char *name)
s = name + 13;
if (!strncmp(s, "Left/Right ", 11)) { j = 0; i = 0; s += 11; }
else
if (!strncmp(s, "Right/Left ", 11)) { j = 0; i = 1; s += 11; }
else
if (!strncmp(s, "Up/Down ", 8)) { j = 1; i = 0; s += 8; }
else
if (!strncmp(s, "Down/Up ", 8)) { j = 1; i = 1; s += 8; }
else
if (!strncmp(s, "Y/A ", 4)) { j = 2; i = 0; s += 4; }
else
if (!strncmp(s, "A/Y ", 4)) { j = 2; i = 1; s += 4; }
else
if (!strncmp(s, "X/B ", 4)) { j = 3; i = 0; s += 4; }
else
if (!strncmp(s, "B/X ", 4)) { j = 3; i = 1; s += 4; }
else
if (!strncmp(s, "L/R ", 4)) { j = 4; i = 0; s += 4; }
else
if (!strncmp(s, "R/L ", 4)) { j = 4; i = 1; s += 4; }
else if (!strncmp(s, "Right/Left ", 11)) { j = 0; i = 1; s += 11; }
else if (!strncmp(s, "Up/Down ", 8)) { j = 1; i = 0; s += 8; }
else if (!strncmp(s, "Down/Up ", 8)) { j = 1; i = 1; s += 8; }
else if (!strncmp(s, "Y/A ", 4)) { j = 2; i = 0; s += 4; }
else if (!strncmp(s, "A/Y ", 4)) { j = 2; i = 1; s += 4; }
else if (!strncmp(s, "X/B ", 4)) { j = 3; i = 0; s += 4; }
else if (!strncmp(s, "B/X ", 4)) { j = 3; i = 1; s += 4; }
else if (!strncmp(s, "L/R ", 4)) { j = 4; i = 0; s += 4; }
else if (!strncmp(s, "R/L ", 4)) { j = 4; i = 1; s += 4; }
else
return (cmd);
@ -1374,8 +1362,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
if (*s == 'h')
cmd.axis.pointer.HV = 0;
else
if (*s == 'v')
else if (*s == 'v')
cmd.axis.pointer.HV = 1;
else
return (cmd);
@ -1523,8 +1510,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
j = i;
}
else
if (name[i] == ',')
else if (name[i] == ',')
{
free(c);
return (cmd);
@ -1537,8 +1523,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
{
if (name[i] == '+')
press = 1;
else
if (name[i] == '-')
else if (name[i] == '-')
press = 2;
else
{
@ -2007,14 +1992,12 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
uint16 x = r; r = st; st = x;
x = s; s = t; t = x;
}
else
if (cmd.button.joypad.turbo)
else if (cmd.button.joypad.turbo)
{
uint16 x = r; r = t; t = x;
x = s; s = st; st = x;
}
else
if (cmd.button.joypad.sticky)
else if (cmd.button.joypad.sticky)
{
uint16 x = r; r = s; s = x;
x = t; t = st; st = x;
@ -2276,16 +2259,12 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
case LoadOopsFile:
{
char filename[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
std::string filename = S9xGetFilename("oops", SNAPSHOT_DIR);
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops");
if (S9xUnfreezeGame(filename))
if (S9xUnfreezeGame(filename.c_str()))
{
snprintf(buf, 256, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops");
S9xSetInfoString (buf);
snprintf(buf, 256, "%.240s.oops loaded", S9xBasename(Memory.ROMFilename).c_str());
S9xSetInfoString(buf);
}
else
S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Oops file not found");
@ -2313,15 +2292,15 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
case QuickLoad009:
case QuickLoad010:
{
char filename[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
std::string ext = std::to_string(i - QuickLoad000);
while (ext.length() < 3)
ext = '0' + ext;
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickLoad000);
auto filename = S9xGetFilename(ext, SNAPSHOT_DIR);
if (S9xUnfreezeGame(filename))
if (S9xUnfreezeGame(filename.c_str()))
{
snprintf(buf, 256, "%s.%03d loaded", def, i - QuickLoad000);
snprintf(buf, 256, "Quick save-state %s loaded", ext.c_str());
S9xSetInfoString(buf);
}
else
@ -2342,16 +2321,16 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
case QuickSave009:
case QuickSave010:
{
char filename[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
std::string ext = std::to_string(i - QuickLoad000);
while (ext.length() < 3)
ext = '0' + ext;
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickSave000);
auto filename = S9xGetFilename(ext, SNAPSHOT_DIR);
snprintf(buf, 256, "%s.%03d saved", def, i - QuickSave000);
snprintf(buf, 256, "Quick save-state %s saved", ext.c_str());
S9xSetInfoString(buf);
S9xFreezeGame(filename);
S9xFreezeGame(filename.c_str());
break;
}
@ -2771,14 +2750,12 @@ static void UpdatePolledMouse (int i)
mouse[i - MOUSE0].delta_x = 0xff;
mouse[i - MOUSE0].old_x -= 127;
}
else
if (j < 0)
else if (j < 0)
{
mouse[i - MOUSE0].delta_x = 0x80 | -j;
mouse[i - MOUSE0].old_x = mouse[i - MOUSE0].cur_x;
}
else
if (j > 127)
else if (j > 127)
{
mouse[i - MOUSE0].delta_x = 0x7f;
mouse[i - MOUSE0].old_x += 127;
@ -2796,14 +2773,12 @@ static void UpdatePolledMouse (int i)
mouse[i - MOUSE0].delta_y = 0xff;
mouse[i - MOUSE0].old_y -= 127;
}
else
if (j < 0)
else if (j < 0)
{
mouse[i - MOUSE0].delta_y = 0x80 | -j;
mouse[i - MOUSE0].old_y = mouse[i - MOUSE0].cur_y;
}
else
if (j > 127)
else if (j > 127)
{
mouse[i - MOUSE0].delta_y = 0x7f;
mouse[i - MOUSE0].old_y += 127;
@ -3265,8 +3240,7 @@ void S9xControlEOF (void)
pseudopointer[n].x += pseudopointer[n].H_adj;
if (pseudopointer[n].x < 0)
pseudopointer[n].x = 0;
else
if (pseudopointer[n].x > 255)
else if (pseudopointer[n].x > 255)
pseudopointer[n].x = 255;
if (pseudopointer[n].H_var)
@ -3289,8 +3263,7 @@ void S9xControlEOF (void)
pseudopointer[n].y += pseudopointer[n].V_adj;
if (pseudopointer[n].y < 0)
pseudopointer[n].y = 0;
else
if (pseudopointer[n].y > PPU.ScreenHeight - 1)
else if (pseudopointer[n].y > PPU.ScreenHeight - 1)
pseudopointer[n].y = PPU.ScreenHeight - 1;
if (pseudopointer[n].V_var)

View File

@ -13,7 +13,6 @@
#include "srtc.h"
#include "snapshot.h"
#include "cheats.h"
#include "logger.h"
#ifdef DEBUGGER
#include "debug.h"
#endif
@ -76,7 +75,6 @@ static void S9xSoftResetCPU (void)
SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
ClearFlags(Decimal);
Timings.InterlaceField = FALSE;
Timings.H_Max = Timings.H_Max_Master;
Timings.V_Max = Timings.V_Max_Master;
Timings.NMITriggerPos = 0xffff;
@ -99,10 +97,9 @@ static void S9xSoftResetCPU (void)
void S9xReset (void)
{
S9xResetSaveTimer(FALSE);
S9xResetLogger();
memset(Memory.RAM, 0x55, 0x20000);
memset(Memory.VRAM, 0x00, 0x10000);
memset(Memory.RAM, 0x55, sizeof(Memory.RAM));
memset(Memory.VRAM, 0x00, sizeof(Memory.VRAM));
memset(Memory.FillRAM, 0, 0x8000);
S9xResetBSX();

View File

@ -513,7 +513,6 @@ static inline uint32 StackRelativeIndirectIndexed (AccessMode a) // (d,S),Y
if (a & READ)
OpenBus = (uint8) (addr >> 8);
addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff;
AddCycles(ONE_CYCLE);
return (addr);
}

View File

@ -132,13 +132,6 @@ void S9xMainLoop (void)
if (CPU.Flags & SCAN_KEYS_FLAG)
{
#ifdef DEBUGGER
if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
#endif
{
S9xSyncSpeed();
}
break;
}
@ -276,7 +269,6 @@ void S9xDoHEventProcessing (void)
if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1
{
CPU.V_Counter = 0;
Timings.InterlaceField ^= 1;
// From byuu:
// [NTSC]
@ -285,7 +277,7 @@ void S9xDoHEventProcessing (void)
// [PAL] <PAL info is unverified on hardware>
// interlace mode has 625 scanlines: 313 on the even frame, and 312 on the odd.
// non-interlace mode has 624 scanlines: 312 scanlines on both even and odd frames.
if (IPPU.Interlace && !Timings.InterlaceField)
if (IPPU.Interlace && S9xInterlaceField())
Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL)
else
Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL)
@ -306,14 +298,14 @@ void S9xDoHEventProcessing (void)
// In interlace mode, there are always 341 dots per scanline. Even frames have 263 scanlines,
// and odd frames have 262 scanlines.
// Interlace mode scanline 240 on odd frames is not missing a dot.
if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField) // V=240
if (CPU.V_Counter == 240 && !IPPU.Interlace && S9xInterlaceField()) // V=240
Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360
else
Timings.H_Max = Timings.H_Max_Master; // HC=1364
if (Model->_5A22 == 2)
{
if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField) // V=240
if (CPU.V_Counter != 240 || IPPU.Interlace || !S9xInterlaceField()) // V=240
{
if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE) // HC=534
Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; // HC=538
@ -327,6 +319,12 @@ void S9xDoHEventProcessing (void)
if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
{
S9xEndScreenRefresh();
#ifdef DEBUGGER
if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
#endif
{
S9xSyncSpeed();
}
CPU.Flags |= SCAN_KEYS_FLAG;

View File

@ -1406,11 +1406,13 @@ bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation())
static void Op82 (void)
{
S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP));
AddCycles(ONE_CYCLE);
}
static void Op82Slow (void)
{
S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP));
AddCycles(ONE_CYCLE);
}
/* Flag Instructions ******************************************************* */
@ -2847,6 +2849,7 @@ static void Op22E1 (void)
// Note: JSL is a new instruction,
// and so doesn't respect the emu-mode stack bounds.
uint32 addr = AbsoluteLong(JSR);
AddCycles(ONE_CYCLE);
PushB(Registers.PB);
PushW(Registers.PCw - 1);
Registers.SH = 1;
@ -2856,6 +2859,7 @@ static void Op22E1 (void)
static void Op22E0 (void)
{
uint32 addr = AbsoluteLong(JSR);
AddCycles(ONE_CYCLE);
PushB(Registers.PB);
PushW(Registers.PCw - 1);
S9xSetPCBase(addr);
@ -2864,6 +2868,7 @@ static void Op22E0 (void)
static void Op22Slow (void)
{
uint32 addr = AbsoluteLongSlow(JSR);
AddCycles(ONE_CYCLE);
PushB(Registers.PB);
PushW(Registers.PCw - 1);
if (CheckEmulation())

View File

@ -9,24 +9,6 @@
#include "snes9x.h"
enum s9x_getdirtype
{
DEFAULT_DIR = 0,
HOME_DIR,
ROMFILENAME_DIR,
ROM_DIR,
SRAM_DIR,
SNAPSHOT_DIR,
SCREENSHOT_DIR,
SPC_DIR,
CHEAT_DIR,
PATCH_DIR,
BIOS_DIR,
LOG_DIR,
SAT_DIR,
LAST_DIR
};
void S9xUsage (void);
char * S9xParseArgs (char **, int);
void S9xParseArgsForCheats (char **, int);
@ -44,10 +26,6 @@ void S9xToggleSoundChannel (int);
bool8 S9xOpenSnapshotFile (const char *, bool8, STREAM *);
void S9xCloseSnapshotFile (STREAM);
const char * S9xStringInput (const char *);
const char * S9xGetDirectory (enum s9x_getdirtype);
const char * S9xGetFilename (const char *, enum s9x_getdirtype);
const char * S9xGetFilenameInc (const char *, enum s9x_getdirtype);
const char * S9xBasename (const char *);
// Routines the port has to implement if it uses command-line

View File

@ -1,3 +1,32 @@
Snes9x 1.62
- Fixed SA1 division with negative dividend again. (Atari2)
- Fixed timing on several instructions. (pi1541)
- MSU1 audio with no loop point will not repeat from start.
- Modernized some old memory-related code.
- Fixed a desynchronization in interlaced modes and reporting.
- Remove SA1 access to WRAM.
- Added second set of registers between S-DSP and S-SMP. Fixes
PAL version of Virtual Bart.
Gtk + Windows:
- Added a Vulkan graphics output method. Similar to OpenGL, this
can use libretro's slang shaders.
- Changed the automatic frame skip throttle to take place immediately
before showing the frame, making VRR work better.
- Add menu item to clear recent files entries.
- Add fixed window size changes up to 10x.
Windows:
- Improved the shader parameters dialog with sliders and resize.
- Allow disabling adding registry entries. Deletes any existing
entries when the option is disabled.
Gtk:
- Switched to CMake for build system. Removed meson.
- Fixed some keys not working with modifiers. (Gutawer)
- Removed graphics options most people won't understand or need.
- Improved wayland support. Handle fractional DPI properly.
Snes9x 1.61
- Restructured tile.cpp tile renderer from heavy macros into C++
templates, significantly lowering compile time. (yoffy)

@ -1 +1 @@
Subproject commit 1458bae62ec67ea7d12c5a13b740e23ed4bb226c
Subproject commit 4e2fdb25671c742a9fbe93a6034eb1542244c7e1

View File

@ -0,0 +1,116 @@
CC0 1.0 Universal
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.
For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
#ifndef VULKAN_MEMORY_ALLOCATOR_HPP
#define VULKAN_MEMORY_ALLOCATOR_HPP
#if !defined(AMD_VULKAN_MEMORY_ALLOCATOR_H)
#include <vk_mem_alloc.h>
#endif
#include <vulkan/vulkan.hpp>
#if !defined(VMA_HPP_NAMESPACE)
#define VMA_HPP_NAMESPACE vma
#endif
#define VMA_HPP_NAMESPACE_STRING VULKAN_HPP_STRINGIFY(VMA_HPP_NAMESPACE)
#ifndef VULKAN_HPP_NO_SMART_HANDLE
namespace VMA_HPP_NAMESPACE {
struct Dispatcher {}; // VMA uses function pointers from VmaAllocator instead
class Allocator;
template<class T>
VULKAN_HPP_NAMESPACE::UniqueHandle<T, Dispatcher> createUniqueHandle(const T& t) VULKAN_HPP_NOEXCEPT {
return VULKAN_HPP_NAMESPACE::UniqueHandle<T, Dispatcher>(t);
}
template<class T, class O>
VULKAN_HPP_NAMESPACE::UniqueHandle<T, Dispatcher> createUniqueHandle(const T& t, const O* o) VULKAN_HPP_NOEXCEPT {
return VULKAN_HPP_NAMESPACE::UniqueHandle<T, Dispatcher>(t, o);
}
template<class F, class S, class O>
std::pair<VULKAN_HPP_NAMESPACE::UniqueHandle<F, Dispatcher>, VULKAN_HPP_NAMESPACE::UniqueHandle<S, Dispatcher>>
createUniqueHandle(const std::pair<F, S>& t, const O* o) VULKAN_HPP_NOEXCEPT {
return {
VULKAN_HPP_NAMESPACE::UniqueHandle<F, Dispatcher>(t.first, o),
VULKAN_HPP_NAMESPACE::UniqueHandle<S, Dispatcher>(t.second, o)
};
}
template<class T, class UniqueVectorAllocator, class VectorAllocator, class O>
std::vector<VULKAN_HPP_NAMESPACE::UniqueHandle<T, Dispatcher>, UniqueVectorAllocator>
createUniqueHandleVector(const std::vector<T, VectorAllocator>& vector, const O* o,
const UniqueVectorAllocator& vectorAllocator) VULKAN_HPP_NOEXCEPT {
std::vector<VULKAN_HPP_NAMESPACE::UniqueHandle<T, Dispatcher>, UniqueVectorAllocator> result(vectorAllocator);
result.reserve(vector.size());
for (const T& t : vector) result.emplace_back(t, o);
return result;
}
template<class T, class Owner> class Deleter {
const Owner* owner;
public:
Deleter() = default;
Deleter(const Owner* owner) VULKAN_HPP_NOEXCEPT : owner(owner) {}
protected:
void destroy(const T& t) VULKAN_HPP_NOEXCEPT; // Implemented manually for each handle type
};
template<class T> class Deleter<T, void> {
protected:
void destroy(const T& t) VULKAN_HPP_NOEXCEPT { t.destroy(); }
};
}
namespace VULKAN_HPP_NAMESPACE {
template<> struct UniqueHandleTraits<Buffer, VMA_HPP_NAMESPACE::Dispatcher> {
using deleter = VMA_HPP_NAMESPACE::Deleter<Buffer, VMA_HPP_NAMESPACE::Allocator>;
};
template<> struct UniqueHandleTraits<Image, VMA_HPP_NAMESPACE::Dispatcher> {
using deleter = VMA_HPP_NAMESPACE::Deleter<Image, VMA_HPP_NAMESPACE::Allocator>;
};
}
namespace VMA_HPP_NAMESPACE {
using UniqueBuffer = VULKAN_HPP_NAMESPACE::UniqueHandle<VULKAN_HPP_NAMESPACE::Buffer, Dispatcher>;
using UniqueImage = VULKAN_HPP_NAMESPACE::UniqueHandle<VULKAN_HPP_NAMESPACE::Image, Dispatcher>;
}
#endif
#include "vk_mem_alloc_enums.hpp"
#include "vk_mem_alloc_handles.hpp"
#include "vk_mem_alloc_structs.hpp"
#include "vk_mem_alloc_funcs.hpp"
namespace VMA_HPP_NAMESPACE {
#ifndef VULKAN_HPP_NO_SMART_HANDLE
# define VMA_HPP_DESTROY_IMPL(NAME) \
template<> VULKAN_HPP_INLINE void VULKAN_HPP_NAMESPACE::UniqueHandleTraits<NAME, Dispatcher>::deleter::destroy(const NAME& t) VULKAN_HPP_NOEXCEPT
VMA_HPP_DESTROY_IMPL(VULKAN_HPP_NAMESPACE::Buffer) { owner->destroyBuffer(t, nullptr); }
VMA_HPP_DESTROY_IMPL(VULKAN_HPP_NAMESPACE::Image) { owner->destroyImage(t, nullptr); }
VMA_HPP_DESTROY_IMPL(Pool) { owner->destroyPool(t); }
VMA_HPP_DESTROY_IMPL(Allocation) { owner->freeMemory(t); }
VMA_HPP_DESTROY_IMPL(VirtualAllocation) { owner->virtualFree(t); }
# undef VMA_HPP_DESTROY_IMPL
#endif
template<class InstanceDispatcher, class DeviceDispatcher>
VULKAN_HPP_CONSTEXPR VulkanFunctions functionsFromDispatcher(InstanceDispatcher const * instance,
DeviceDispatcher const * device) VULKAN_HPP_NOEXCEPT {
return VulkanFunctions {
instance->vkGetInstanceProcAddr,
instance->vkGetDeviceProcAddr,
instance->vkGetPhysicalDeviceProperties,
instance->vkGetPhysicalDeviceMemoryProperties,
device->vkAllocateMemory,
device->vkFreeMemory,
device->vkMapMemory,
device->vkUnmapMemory,
device->vkFlushMappedMemoryRanges,
device->vkInvalidateMappedMemoryRanges,
device->vkBindBufferMemory,
device->vkBindImageMemory,
device->vkGetBufferMemoryRequirements,
device->vkGetImageMemoryRequirements,
device->vkCreateBuffer,
device->vkDestroyBuffer,
device->vkCreateImage,
device->vkDestroyImage,
device->vkCmdCopyBuffer,
device->vkGetBufferMemoryRequirements2KHR ? device->vkGetBufferMemoryRequirements2KHR : device->vkGetBufferMemoryRequirements2,
device->vkGetImageMemoryRequirements2KHR ? device->vkGetImageMemoryRequirements2KHR : device->vkGetImageMemoryRequirements2,
device->vkBindBufferMemory2KHR ? device->vkBindBufferMemory2KHR : device->vkBindBufferMemory2,
device->vkBindImageMemory2KHR ? device->vkBindImageMemory2KHR : device->vkBindImageMemory2,
instance->vkGetPhysicalDeviceMemoryProperties2KHR ? instance->vkGetPhysicalDeviceMemoryProperties2KHR : instance->vkGetPhysicalDeviceMemoryProperties2,
device->vkGetDeviceBufferMemoryRequirements,
device->vkGetDeviceImageMemoryRequirements
};
}
template<class Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
VULKAN_HPP_CONSTEXPR VulkanFunctions functionsFromDispatcher(Dispatch const & dispatch
VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) VULKAN_HPP_NOEXCEPT {
return functionsFromDispatcher(&dispatch, &dispatch);
}
}
#endif

View File

@ -0,0 +1,450 @@
#ifndef VULKAN_MEMORY_ALLOCATOR_ENUMS_HPP
#define VULKAN_MEMORY_ALLOCATOR_ENUMS_HPP
namespace VMA_HPP_NAMESPACE {
enum class AllocatorCreateFlagBits : VmaAllocatorCreateFlags {
eExternallySynchronized = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT,
eKhrDedicatedAllocation = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT,
eKhrBindMemory2 = VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT,
eExtMemoryBudget = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT,
eAmdDeviceCoherentMemory = VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT,
eBufferDeviceAddress = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT,
eExtMemoryPriority = VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT
};
VULKAN_HPP_INLINE std::string to_string(AllocatorCreateFlagBits value) {
if (value == AllocatorCreateFlagBits::eExternallySynchronized) return "ExternallySynchronized";
if (value == AllocatorCreateFlagBits::eKhrDedicatedAllocation) return "KhrDedicatedAllocation";
if (value == AllocatorCreateFlagBits::eKhrBindMemory2) return "KhrBindMemory2";
if (value == AllocatorCreateFlagBits::eExtMemoryBudget) return "ExtMemoryBudget";
if (value == AllocatorCreateFlagBits::eAmdDeviceCoherentMemory) return "AmdDeviceCoherentMemory";
if (value == AllocatorCreateFlagBits::eBufferDeviceAddress) return "BufferDeviceAddress";
if (value == AllocatorCreateFlagBits::eExtMemoryPriority) return "ExtMemoryPriority";
return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString(static_cast<uint32_t>(value)) + " )";
}
}
namespace VULKAN_HPP_NAMESPACE {
template<> struct FlagTraits<VMA_HPP_NAMESPACE::AllocatorCreateFlagBits> {
static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true;
static VULKAN_HPP_CONST_OR_CONSTEXPR Flags<VMA_HPP_NAMESPACE::AllocatorCreateFlagBits> allFlags =
VMA_HPP_NAMESPACE::AllocatorCreateFlagBits::eExternallySynchronized
| VMA_HPP_NAMESPACE::AllocatorCreateFlagBits::eKhrDedicatedAllocation
| VMA_HPP_NAMESPACE::AllocatorCreateFlagBits::eKhrBindMemory2
| VMA_HPP_NAMESPACE::AllocatorCreateFlagBits::eExtMemoryBudget
| VMA_HPP_NAMESPACE::AllocatorCreateFlagBits::eAmdDeviceCoherentMemory
| VMA_HPP_NAMESPACE::AllocatorCreateFlagBits::eBufferDeviceAddress
| VMA_HPP_NAMESPACE::AllocatorCreateFlagBits::eExtMemoryPriority;
};
}
namespace VMA_HPP_NAMESPACE {
using AllocatorCreateFlags = VULKAN_HPP_NAMESPACE::Flags<AllocatorCreateFlagBits>;
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AllocatorCreateFlags operator|(AllocatorCreateFlagBits bit0, AllocatorCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return AllocatorCreateFlags(bit0) | bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AllocatorCreateFlags operator&(AllocatorCreateFlagBits bit0, AllocatorCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return AllocatorCreateFlags(bit0) & bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AllocatorCreateFlags operator^(AllocatorCreateFlagBits bit0, AllocatorCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return AllocatorCreateFlags(bit0) ^ bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AllocatorCreateFlags operator~(AllocatorCreateFlagBits bits) VULKAN_HPP_NOEXCEPT {
return ~(AllocatorCreateFlags(bits));
}
VULKAN_HPP_INLINE std::string to_string(AllocatorCreateFlags value) {
if (!value) return "{}";
std::string result;
if (value & AllocatorCreateFlagBits::eExternallySynchronized) result += "ExternallySynchronized | ";
if (value & AllocatorCreateFlagBits::eKhrDedicatedAllocation) result += "KhrDedicatedAllocation | ";
if (value & AllocatorCreateFlagBits::eKhrBindMemory2) result += "KhrBindMemory2 | ";
if (value & AllocatorCreateFlagBits::eExtMemoryBudget) result += "ExtMemoryBudget | ";
if (value & AllocatorCreateFlagBits::eAmdDeviceCoherentMemory) result += "AmdDeviceCoherentMemory | ";
if (value & AllocatorCreateFlagBits::eBufferDeviceAddress) result += "BufferDeviceAddress | ";
if (value & AllocatorCreateFlagBits::eExtMemoryPriority) result += "ExtMemoryPriority | ";
return "{ " + result.substr( 0, result.size() - 3 ) + " }";
}
}
namespace VMA_HPP_NAMESPACE {
enum class MemoryUsage {
eUnknown = VMA_MEMORY_USAGE_UNKNOWN,
eGpuOnly = VMA_MEMORY_USAGE_GPU_ONLY,
eCpuOnly = VMA_MEMORY_USAGE_CPU_ONLY,
eCpuToGpu = VMA_MEMORY_USAGE_CPU_TO_GPU,
eGpuToCpu = VMA_MEMORY_USAGE_GPU_TO_CPU,
eCpuCopy = VMA_MEMORY_USAGE_CPU_COPY,
eGpuLazilyAllocated = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED,
eAuto = VMA_MEMORY_USAGE_AUTO,
eAutoPreferDevice = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
eAutoPreferHost = VMA_MEMORY_USAGE_AUTO_PREFER_HOST
};
VULKAN_HPP_INLINE std::string to_string(MemoryUsage value) {
if (value == MemoryUsage::eUnknown) return "Unknown";
if (value == MemoryUsage::eGpuOnly) return "GpuOnly";
if (value == MemoryUsage::eCpuOnly) return "CpuOnly";
if (value == MemoryUsage::eCpuToGpu) return "CpuToGpu";
if (value == MemoryUsage::eGpuToCpu) return "GpuToCpu";
if (value == MemoryUsage::eCpuCopy) return "CpuCopy";
if (value == MemoryUsage::eGpuLazilyAllocated) return "GpuLazilyAllocated";
if (value == MemoryUsage::eAuto) return "Auto";
if (value == MemoryUsage::eAutoPreferDevice) return "AutoPreferDevice";
if (value == MemoryUsage::eAutoPreferHost) return "AutoPreferHost";
return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString(static_cast<uint32_t>(value)) + " )";
}
}
namespace VMA_HPP_NAMESPACE {
enum class AllocationCreateFlagBits : VmaAllocationCreateFlags {
eDedicatedMemory = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
eNeverAllocate = VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT,
eMapped = VMA_ALLOCATION_CREATE_MAPPED_BIT,
eUserDataCopyString = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,
eUpperAddress = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT,
eDontBind = VMA_ALLOCATION_CREATE_DONT_BIND_BIT,
eWithinBudget = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
eCanAlias = VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT,
eHostAccessSequentialWrite = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
eHostAccessRandom = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,
eHostAccessAllowTransferInstead = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT,
eStrategyMinMemory = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT,
eStrategyMinTime = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT,
eStrategyMinOffset = VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,
eStrategyBestFit = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT,
eStrategyFirstFit = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT
};
VULKAN_HPP_INLINE std::string to_string(AllocationCreateFlagBits value) {
if (value == AllocationCreateFlagBits::eDedicatedMemory) return "DedicatedMemory";
if (value == AllocationCreateFlagBits::eNeverAllocate) return "NeverAllocate";
if (value == AllocationCreateFlagBits::eMapped) return "Mapped";
if (value == AllocationCreateFlagBits::eUserDataCopyString) return "UserDataCopyString";
if (value == AllocationCreateFlagBits::eUpperAddress) return "UpperAddress";
if (value == AllocationCreateFlagBits::eDontBind) return "DontBind";
if (value == AllocationCreateFlagBits::eWithinBudget) return "WithinBudget";
if (value == AllocationCreateFlagBits::eCanAlias) return "CanAlias";
if (value == AllocationCreateFlagBits::eHostAccessSequentialWrite) return "HostAccessSequentialWrite";
if (value == AllocationCreateFlagBits::eHostAccessRandom) return "HostAccessRandom";
if (value == AllocationCreateFlagBits::eHostAccessAllowTransferInstead) return "HostAccessAllowTransferInstead";
if (value == AllocationCreateFlagBits::eStrategyMinMemory) return "StrategyMinMemory";
if (value == AllocationCreateFlagBits::eStrategyMinTime) return "StrategyMinTime";
if (value == AllocationCreateFlagBits::eStrategyMinOffset) return "StrategyMinOffset";
if (value == AllocationCreateFlagBits::eStrategyBestFit) return "StrategyBestFit";
if (value == AllocationCreateFlagBits::eStrategyFirstFit) return "StrategyFirstFit";
return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString(static_cast<uint32_t>(value)) + " )";
}
}
namespace VULKAN_HPP_NAMESPACE {
template<> struct FlagTraits<VMA_HPP_NAMESPACE::AllocationCreateFlagBits> {
static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true;
static VULKAN_HPP_CONST_OR_CONSTEXPR Flags<VMA_HPP_NAMESPACE::AllocationCreateFlagBits> allFlags =
VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eDedicatedMemory
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eNeverAllocate
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eMapped
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eUserDataCopyString
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eUpperAddress
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eDontBind
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eWithinBudget
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eCanAlias
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eHostAccessSequentialWrite
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eHostAccessRandom
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eHostAccessAllowTransferInstead
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eStrategyMinMemory
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eStrategyMinTime
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eStrategyMinOffset
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eStrategyBestFit
| VMA_HPP_NAMESPACE::AllocationCreateFlagBits::eStrategyFirstFit;
};
}
namespace VMA_HPP_NAMESPACE {
using AllocationCreateFlags = VULKAN_HPP_NAMESPACE::Flags<AllocationCreateFlagBits>;
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AllocationCreateFlags operator|(AllocationCreateFlagBits bit0, AllocationCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return AllocationCreateFlags(bit0) | bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AllocationCreateFlags operator&(AllocationCreateFlagBits bit0, AllocationCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return AllocationCreateFlags(bit0) & bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AllocationCreateFlags operator^(AllocationCreateFlagBits bit0, AllocationCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return AllocationCreateFlags(bit0) ^ bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AllocationCreateFlags operator~(AllocationCreateFlagBits bits) VULKAN_HPP_NOEXCEPT {
return ~(AllocationCreateFlags(bits));
}
VULKAN_HPP_INLINE std::string to_string(AllocationCreateFlags value) {
if (!value) return "{}";
std::string result;
if (value & AllocationCreateFlagBits::eDedicatedMemory) result += "DedicatedMemory | ";
if (value & AllocationCreateFlagBits::eNeverAllocate) result += "NeverAllocate | ";
if (value & AllocationCreateFlagBits::eMapped) result += "Mapped | ";
if (value & AllocationCreateFlagBits::eUserDataCopyString) result += "UserDataCopyString | ";
if (value & AllocationCreateFlagBits::eUpperAddress) result += "UpperAddress | ";
if (value & AllocationCreateFlagBits::eDontBind) result += "DontBind | ";
if (value & AllocationCreateFlagBits::eWithinBudget) result += "WithinBudget | ";
if (value & AllocationCreateFlagBits::eCanAlias) result += "CanAlias | ";
if (value & AllocationCreateFlagBits::eHostAccessSequentialWrite) result += "HostAccessSequentialWrite | ";
if (value & AllocationCreateFlagBits::eHostAccessRandom) result += "HostAccessRandom | ";
if (value & AllocationCreateFlagBits::eHostAccessAllowTransferInstead) result += "HostAccessAllowTransferInstead | ";
if (value & AllocationCreateFlagBits::eStrategyMinMemory) result += "StrategyMinMemory | ";
if (value & AllocationCreateFlagBits::eStrategyMinTime) result += "StrategyMinTime | ";
if (value & AllocationCreateFlagBits::eStrategyMinOffset) result += "StrategyMinOffset | ";
if (value & AllocationCreateFlagBits::eStrategyBestFit) result += "StrategyBestFit | ";
if (value & AllocationCreateFlagBits::eStrategyFirstFit) result += "StrategyFirstFit | ";
return "{ " + result.substr( 0, result.size() - 3 ) + " }";
}
}
namespace VMA_HPP_NAMESPACE {
enum class PoolCreateFlagBits : VmaPoolCreateFlags {
eIgnoreBufferImageGranularity = VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT,
eLinearAlgorithm = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT
};
VULKAN_HPP_INLINE std::string to_string(PoolCreateFlagBits value) {
if (value == PoolCreateFlagBits::eIgnoreBufferImageGranularity) return "IgnoreBufferImageGranularity";
if (value == PoolCreateFlagBits::eLinearAlgorithm) return "LinearAlgorithm";
return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString(static_cast<uint32_t>(value)) + " )";
}
}
namespace VULKAN_HPP_NAMESPACE {
template<> struct FlagTraits<VMA_HPP_NAMESPACE::PoolCreateFlagBits> {
static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true;
static VULKAN_HPP_CONST_OR_CONSTEXPR Flags<VMA_HPP_NAMESPACE::PoolCreateFlagBits> allFlags =
VMA_HPP_NAMESPACE::PoolCreateFlagBits::eIgnoreBufferImageGranularity
| VMA_HPP_NAMESPACE::PoolCreateFlagBits::eLinearAlgorithm;
};
}
namespace VMA_HPP_NAMESPACE {
using PoolCreateFlags = VULKAN_HPP_NAMESPACE::Flags<PoolCreateFlagBits>;
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PoolCreateFlags operator|(PoolCreateFlagBits bit0, PoolCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return PoolCreateFlags(bit0) | bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PoolCreateFlags operator&(PoolCreateFlagBits bit0, PoolCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return PoolCreateFlags(bit0) & bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PoolCreateFlags operator^(PoolCreateFlagBits bit0, PoolCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return PoolCreateFlags(bit0) ^ bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PoolCreateFlags operator~(PoolCreateFlagBits bits) VULKAN_HPP_NOEXCEPT {
return ~(PoolCreateFlags(bits));
}
VULKAN_HPP_INLINE std::string to_string(PoolCreateFlags value) {
if (!value) return "{}";
std::string result;
if (value & PoolCreateFlagBits::eIgnoreBufferImageGranularity) result += "IgnoreBufferImageGranularity | ";
if (value & PoolCreateFlagBits::eLinearAlgorithm) result += "LinearAlgorithm | ";
return "{ " + result.substr( 0, result.size() - 3 ) + " }";
}
}
namespace VMA_HPP_NAMESPACE {
enum class DefragmentationFlagBits : VmaDefragmentationFlags {
eFlagAlgorithmFast = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT,
eFlagAlgorithmBalanced = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT,
eFlagAlgorithmFull = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT,
eFlagAlgorithmExtensive = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT
};
VULKAN_HPP_INLINE std::string to_string(DefragmentationFlagBits value) {
if (value == DefragmentationFlagBits::eFlagAlgorithmFast) return "FlagAlgorithmFast";
if (value == DefragmentationFlagBits::eFlagAlgorithmBalanced) return "FlagAlgorithmBalanced";
if (value == DefragmentationFlagBits::eFlagAlgorithmFull) return "FlagAlgorithmFull";
if (value == DefragmentationFlagBits::eFlagAlgorithmExtensive) return "FlagAlgorithmExtensive";
return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString(static_cast<uint32_t>(value)) + " )";
}
}
namespace VULKAN_HPP_NAMESPACE {
template<> struct FlagTraits<VMA_HPP_NAMESPACE::DefragmentationFlagBits> {
static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true;
static VULKAN_HPP_CONST_OR_CONSTEXPR Flags<VMA_HPP_NAMESPACE::DefragmentationFlagBits> allFlags =
VMA_HPP_NAMESPACE::DefragmentationFlagBits::eFlagAlgorithmFast
| VMA_HPP_NAMESPACE::DefragmentationFlagBits::eFlagAlgorithmBalanced
| VMA_HPP_NAMESPACE::DefragmentationFlagBits::eFlagAlgorithmFull
| VMA_HPP_NAMESPACE::DefragmentationFlagBits::eFlagAlgorithmExtensive;
};
}
namespace VMA_HPP_NAMESPACE {
using DefragmentationFlags = VULKAN_HPP_NAMESPACE::Flags<DefragmentationFlagBits>;
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DefragmentationFlags operator|(DefragmentationFlagBits bit0, DefragmentationFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return DefragmentationFlags(bit0) | bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DefragmentationFlags operator&(DefragmentationFlagBits bit0, DefragmentationFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return DefragmentationFlags(bit0) & bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DefragmentationFlags operator^(DefragmentationFlagBits bit0, DefragmentationFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return DefragmentationFlags(bit0) ^ bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DefragmentationFlags operator~(DefragmentationFlagBits bits) VULKAN_HPP_NOEXCEPT {
return ~(DefragmentationFlags(bits));
}
VULKAN_HPP_INLINE std::string to_string(DefragmentationFlags value) {
if (!value) return "{}";
std::string result;
if (value & DefragmentationFlagBits::eFlagAlgorithmFast) result += "FlagAlgorithmFast | ";
if (value & DefragmentationFlagBits::eFlagAlgorithmBalanced) result += "FlagAlgorithmBalanced | ";
if (value & DefragmentationFlagBits::eFlagAlgorithmFull) result += "FlagAlgorithmFull | ";
if (value & DefragmentationFlagBits::eFlagAlgorithmExtensive) result += "FlagAlgorithmExtensive | ";
return "{ " + result.substr( 0, result.size() - 3 ) + " }";
}
}
namespace VMA_HPP_NAMESPACE {
enum class DefragmentationMoveOperation {
eCopy = VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY,
eIgnore = VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE,
eDestroy = VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY
};
VULKAN_HPP_INLINE std::string to_string(DefragmentationMoveOperation value) {
if (value == DefragmentationMoveOperation::eCopy) return "Copy";
if (value == DefragmentationMoveOperation::eIgnore) return "Ignore";
if (value == DefragmentationMoveOperation::eDestroy) return "Destroy";
return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString(static_cast<uint32_t>(value)) + " )";
}
}
namespace VMA_HPP_NAMESPACE {
enum class VirtualBlockCreateFlagBits : VmaVirtualBlockCreateFlags {
eLinearAlgorithm = VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT
};
VULKAN_HPP_INLINE std::string to_string(VirtualBlockCreateFlagBits value) {
if (value == VirtualBlockCreateFlagBits::eLinearAlgorithm) return "LinearAlgorithm";
return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString(static_cast<uint32_t>(value)) + " )";
}
}
namespace VULKAN_HPP_NAMESPACE {
template<> struct FlagTraits<VMA_HPP_NAMESPACE::VirtualBlockCreateFlagBits> {
static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true;
static VULKAN_HPP_CONST_OR_CONSTEXPR Flags<VMA_HPP_NAMESPACE::VirtualBlockCreateFlagBits> allFlags =
VMA_HPP_NAMESPACE::VirtualBlockCreateFlagBits::eLinearAlgorithm;
};
}
namespace VMA_HPP_NAMESPACE {
using VirtualBlockCreateFlags = VULKAN_HPP_NAMESPACE::Flags<VirtualBlockCreateFlagBits>;
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR VirtualBlockCreateFlags operator|(VirtualBlockCreateFlagBits bit0, VirtualBlockCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return VirtualBlockCreateFlags(bit0) | bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR VirtualBlockCreateFlags operator&(VirtualBlockCreateFlagBits bit0, VirtualBlockCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return VirtualBlockCreateFlags(bit0) & bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR VirtualBlockCreateFlags operator^(VirtualBlockCreateFlagBits bit0, VirtualBlockCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return VirtualBlockCreateFlags(bit0) ^ bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR VirtualBlockCreateFlags operator~(VirtualBlockCreateFlagBits bits) VULKAN_HPP_NOEXCEPT {
return ~(VirtualBlockCreateFlags(bits));
}
VULKAN_HPP_INLINE std::string to_string(VirtualBlockCreateFlags value) {
if (!value) return "{}";
std::string result;
if (value & VirtualBlockCreateFlagBits::eLinearAlgorithm) result += "LinearAlgorithm | ";
return "{ " + result.substr( 0, result.size() - 3 ) + " }";
}
}
namespace VMA_HPP_NAMESPACE {
enum class VirtualAllocationCreateFlagBits : VmaVirtualAllocationCreateFlags {
eUpperAddress = VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT,
eStrategyMinMemory = VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT,
eStrategyMinTime = VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT,
eStrategyMinOffset = VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT
};
VULKAN_HPP_INLINE std::string to_string(VirtualAllocationCreateFlagBits value) {
if (value == VirtualAllocationCreateFlagBits::eUpperAddress) return "UpperAddress";
if (value == VirtualAllocationCreateFlagBits::eStrategyMinMemory) return "StrategyMinMemory";
if (value == VirtualAllocationCreateFlagBits::eStrategyMinTime) return "StrategyMinTime";
if (value == VirtualAllocationCreateFlagBits::eStrategyMinOffset) return "StrategyMinOffset";
return "invalid ( " + VULKAN_HPP_NAMESPACE::toHexString(static_cast<uint32_t>(value)) + " )";
}
}
namespace VULKAN_HPP_NAMESPACE {
template<> struct FlagTraits<VMA_HPP_NAMESPACE::VirtualAllocationCreateFlagBits> {
static VULKAN_HPP_CONST_OR_CONSTEXPR bool isBitmask = true;
static VULKAN_HPP_CONST_OR_CONSTEXPR Flags<VMA_HPP_NAMESPACE::VirtualAllocationCreateFlagBits> allFlags =
VMA_HPP_NAMESPACE::VirtualAllocationCreateFlagBits::eUpperAddress
| VMA_HPP_NAMESPACE::VirtualAllocationCreateFlagBits::eStrategyMinMemory
| VMA_HPP_NAMESPACE::VirtualAllocationCreateFlagBits::eStrategyMinTime
| VMA_HPP_NAMESPACE::VirtualAllocationCreateFlagBits::eStrategyMinOffset;
};
}
namespace VMA_HPP_NAMESPACE {
using VirtualAllocationCreateFlags = VULKAN_HPP_NAMESPACE::Flags<VirtualAllocationCreateFlagBits>;
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR VirtualAllocationCreateFlags operator|(VirtualAllocationCreateFlagBits bit0, VirtualAllocationCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return VirtualAllocationCreateFlags(bit0) | bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR VirtualAllocationCreateFlags operator&(VirtualAllocationCreateFlagBits bit0, VirtualAllocationCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return VirtualAllocationCreateFlags(bit0) & bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR VirtualAllocationCreateFlags operator^(VirtualAllocationCreateFlagBits bit0, VirtualAllocationCreateFlagBits bit1) VULKAN_HPP_NOEXCEPT {
return VirtualAllocationCreateFlags(bit0) ^ bit1;
}
VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR VirtualAllocationCreateFlags operator~(VirtualAllocationCreateFlagBits bits) VULKAN_HPP_NOEXCEPT {
return ~(VirtualAllocationCreateFlags(bits));
}
VULKAN_HPP_INLINE std::string to_string(VirtualAllocationCreateFlags value) {
if (!value) return "{}";
std::string result;
if (value & VirtualAllocationCreateFlagBits::eUpperAddress) result += "UpperAddress | ";
if (value & VirtualAllocationCreateFlagBits::eStrategyMinMemory) result += "StrategyMinMemory | ";
if (value & VirtualAllocationCreateFlagBits::eStrategyMinTime) result += "StrategyMinTime | ";
if (value & VirtualAllocationCreateFlagBits::eStrategyMinOffset) result += "StrategyMinOffset | ";
return "{ " + result.substr( 0, result.size() - 3 ) + " }";
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,929 @@
#ifndef VULKAN_MEMORY_ALLOCATOR_HANDLES_HPP
#define VULKAN_MEMORY_ALLOCATOR_HANDLES_HPP
namespace VMA_HPP_NAMESPACE {
struct DeviceMemoryCallbacks;
struct VulkanFunctions;
struct AllocatorCreateInfo;
struct AllocatorInfo;
struct Statistics;
struct DetailedStatistics;
struct TotalStatistics;
struct Budget;
struct AllocationCreateInfo;
struct PoolCreateInfo;
struct AllocationInfo;
struct DefragmentationInfo;
struct DefragmentationMove;
struct DefragmentationPassMoveInfo;
struct DefragmentationStats;
struct VirtualBlockCreateInfo;
struct VirtualAllocationCreateInfo;
struct VirtualAllocationInfo;
class Pool;
class Allocation;
class DefragmentationContext;
class VirtualAllocation;
class Allocator;
class VirtualBlock;
}
namespace VMA_HPP_NAMESPACE {
class Pool {
public:
using CType = VmaPool;
using NativeType = VmaPool;
public:
VULKAN_HPP_CONSTEXPR Pool() = default;
VULKAN_HPP_CONSTEXPR Pool(std::nullptr_t) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT Pool(VmaPool pool) VULKAN_HPP_NOEXCEPT : m_pool(pool) {}
#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
Pool& operator=(VmaPool pool) VULKAN_HPP_NOEXCEPT {
m_pool = pool;
return *this;
}
#endif
Pool& operator=(std::nullptr_t) VULKAN_HPP_NOEXCEPT {
m_pool = {};
return *this;
}
#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR )
auto operator<=>(Pool const &) const = default;
#else
bool operator==(Pool const & rhs) const VULKAN_HPP_NOEXCEPT {
return m_pool == rhs.m_pool;
}
#endif
VULKAN_HPP_TYPESAFE_EXPLICIT operator VmaPool() const VULKAN_HPP_NOEXCEPT {
return m_pool;
}
explicit operator bool() const VULKAN_HPP_NOEXCEPT {
return m_pool != VK_NULL_HANDLE;
}
bool operator!() const VULKAN_HPP_NOEXCEPT {
return m_pool == VK_NULL_HANDLE;
}
private:
VmaPool m_pool = {};
};
VULKAN_HPP_STATIC_ASSERT(sizeof(Pool) == sizeof(VmaPool),
"handle and wrapper have different size!");
}
#ifndef VULKAN_HPP_NO_SMART_HANDLE
namespace VULKAN_HPP_NAMESPACE {
template<> struct UniqueHandleTraits<VMA_HPP_NAMESPACE::Pool, VMA_HPP_NAMESPACE::Dispatcher> {
using deleter = VMA_HPP_NAMESPACE::Deleter<VMA_HPP_NAMESPACE::Pool, VMA_HPP_NAMESPACE::Allocator>;
};
}
namespace VMA_HPP_NAMESPACE { using UniquePool = VULKAN_HPP_NAMESPACE::UniqueHandle<Pool, Dispatcher>; }
#endif
namespace VMA_HPP_NAMESPACE {
class Allocation {
public:
using CType = VmaAllocation;
using NativeType = VmaAllocation;
public:
VULKAN_HPP_CONSTEXPR Allocation() = default;
VULKAN_HPP_CONSTEXPR Allocation(std::nullptr_t) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT Allocation(VmaAllocation allocation) VULKAN_HPP_NOEXCEPT : m_allocation(allocation) {}
#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
Allocation& operator=(VmaAllocation allocation) VULKAN_HPP_NOEXCEPT {
m_allocation = allocation;
return *this;
}
#endif
Allocation& operator=(std::nullptr_t) VULKAN_HPP_NOEXCEPT {
m_allocation = {};
return *this;
}
#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR )
auto operator<=>(Allocation const &) const = default;
#else
bool operator==(Allocation const & rhs) const VULKAN_HPP_NOEXCEPT {
return m_allocation == rhs.m_allocation;
}
#endif
VULKAN_HPP_TYPESAFE_EXPLICIT operator VmaAllocation() const VULKAN_HPP_NOEXCEPT {
return m_allocation;
}
explicit operator bool() const VULKAN_HPP_NOEXCEPT {
return m_allocation != VK_NULL_HANDLE;
}
bool operator!() const VULKAN_HPP_NOEXCEPT {
return m_allocation == VK_NULL_HANDLE;
}
private:
VmaAllocation m_allocation = {};
};
VULKAN_HPP_STATIC_ASSERT(sizeof(Allocation) == sizeof(VmaAllocation),
"handle and wrapper have different size!");
}
#ifndef VULKAN_HPP_NO_SMART_HANDLE
namespace VULKAN_HPP_NAMESPACE {
template<> struct UniqueHandleTraits<VMA_HPP_NAMESPACE::Allocation, VMA_HPP_NAMESPACE::Dispatcher> {
using deleter = VMA_HPP_NAMESPACE::Deleter<VMA_HPP_NAMESPACE::Allocation, VMA_HPP_NAMESPACE::Allocator>;
};
}
namespace VMA_HPP_NAMESPACE { using UniqueAllocation = VULKAN_HPP_NAMESPACE::UniqueHandle<Allocation, Dispatcher>; }
#endif
namespace VMA_HPP_NAMESPACE {
class DefragmentationContext {
public:
using CType = VmaDefragmentationContext;
using NativeType = VmaDefragmentationContext;
public:
VULKAN_HPP_CONSTEXPR DefragmentationContext() = default;
VULKAN_HPP_CONSTEXPR DefragmentationContext(std::nullptr_t) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT DefragmentationContext(VmaDefragmentationContext defragmentationContext) VULKAN_HPP_NOEXCEPT : m_defragmentationContext(defragmentationContext) {}
#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
DefragmentationContext& operator=(VmaDefragmentationContext defragmentationContext) VULKAN_HPP_NOEXCEPT {
m_defragmentationContext = defragmentationContext;
return *this;
}
#endif
DefragmentationContext& operator=(std::nullptr_t) VULKAN_HPP_NOEXCEPT {
m_defragmentationContext = {};
return *this;
}
#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR )
auto operator<=>(DefragmentationContext const &) const = default;
#else
bool operator==(DefragmentationContext const & rhs) const VULKAN_HPP_NOEXCEPT {
return m_defragmentationContext == rhs.m_defragmentationContext;
}
#endif
VULKAN_HPP_TYPESAFE_EXPLICIT operator VmaDefragmentationContext() const VULKAN_HPP_NOEXCEPT {
return m_defragmentationContext;
}
explicit operator bool() const VULKAN_HPP_NOEXCEPT {
return m_defragmentationContext != VK_NULL_HANDLE;
}
bool operator!() const VULKAN_HPP_NOEXCEPT {
return m_defragmentationContext == VK_NULL_HANDLE;
}
private:
VmaDefragmentationContext m_defragmentationContext = {};
};
VULKAN_HPP_STATIC_ASSERT(sizeof(DefragmentationContext) == sizeof(VmaDefragmentationContext),
"handle and wrapper have different size!");
}
#ifndef VULKAN_HPP_NO_SMART_HANDLE
namespace VULKAN_HPP_NAMESPACE {
template<> struct UniqueHandleTraits<VMA_HPP_NAMESPACE::DefragmentationContext, VMA_HPP_NAMESPACE::Dispatcher> {
using deleter = VMA_HPP_NAMESPACE::Deleter<VMA_HPP_NAMESPACE::DefragmentationContext, void>;
};
}
namespace VMA_HPP_NAMESPACE { using UniqueDefragmentationContext = VULKAN_HPP_NAMESPACE::UniqueHandle<DefragmentationContext, Dispatcher>; }
#endif
namespace VMA_HPP_NAMESPACE {
class Allocator {
public:
using CType = VmaAllocator;
using NativeType = VmaAllocator;
public:
VULKAN_HPP_CONSTEXPR Allocator() = default;
VULKAN_HPP_CONSTEXPR Allocator(std::nullptr_t) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT Allocator(VmaAllocator allocator) VULKAN_HPP_NOEXCEPT : m_allocator(allocator) {}
#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
Allocator& operator=(VmaAllocator allocator) VULKAN_HPP_NOEXCEPT {
m_allocator = allocator;
return *this;
}
#endif
Allocator& operator=(std::nullptr_t) VULKAN_HPP_NOEXCEPT {
m_allocator = {};
return *this;
}
#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR )
auto operator<=>(Allocator const &) const = default;
#else
bool operator==(Allocator const & rhs) const VULKAN_HPP_NOEXCEPT {
return m_allocator == rhs.m_allocator;
}
#endif
VULKAN_HPP_TYPESAFE_EXPLICIT operator VmaAllocator() const VULKAN_HPP_NOEXCEPT {
return m_allocator;
}
explicit operator bool() const VULKAN_HPP_NOEXCEPT {
return m_allocator != VK_NULL_HANDLE;
}
bool operator!() const VULKAN_HPP_NOEXCEPT {
return m_allocator == VK_NULL_HANDLE;
}
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void destroy() const;
#else
void destroy() const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS AllocatorInfo getAllocatorInfo() const;
#endif
void getAllocatorInfo(AllocatorInfo* allocatorInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS const VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties* getPhysicalDeviceProperties() const;
#endif
void getPhysicalDeviceProperties(const VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties** physicalDeviceProperties) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS const VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties* getMemoryProperties() const;
#endif
void getMemoryProperties(const VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties** physicalDeviceMemoryProperties) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS VULKAN_HPP_NAMESPACE::MemoryPropertyFlags getMemoryTypeProperties(uint32_t memoryTypeIndex) const;
#endif
void getMemoryTypeProperties(uint32_t memoryTypeIndex,
VULKAN_HPP_NAMESPACE::MemoryPropertyFlags* flags) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void setCurrentFrameIndex(uint32_t frameIndex) const;
#else
void setCurrentFrameIndex(uint32_t frameIndex) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS TotalStatistics calculateStatistics() const;
#endif
void calculateStatistics(TotalStatistics* stats) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
template<typename VectorAllocator = std::allocator<Budget>,
typename B = VectorAllocator,
typename std::enable_if<std::is_same<typename B::value_type, Budget>::value, int>::type = 0>
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS std::vector<Budget, VectorAllocator> getHeapBudgets(VectorAllocator& vectorAllocator) const;
template<typename VectorAllocator = std::allocator<Budget>>
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS std::vector<Budget, VectorAllocator> getHeapBudgets() const;
#endif
void getHeapBudgets(Budget* budgets) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<uint32_t>::type findMemoryTypeIndex(uint32_t memoryTypeBits,
const AllocationCreateInfo& allocationCreateInfo) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result findMemoryTypeIndex(uint32_t memoryTypeBits,
const AllocationCreateInfo* allocationCreateInfo,
uint32_t* memoryTypeIndex) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<uint32_t>::type findMemoryTypeIndexForBufferInfo(const VULKAN_HPP_NAMESPACE::BufferCreateInfo& bufferCreateInfo,
const AllocationCreateInfo& allocationCreateInfo) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result findMemoryTypeIndexForBufferInfo(const VULKAN_HPP_NAMESPACE::BufferCreateInfo* bufferCreateInfo,
const AllocationCreateInfo* allocationCreateInfo,
uint32_t* memoryTypeIndex) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<uint32_t>::type findMemoryTypeIndexForImageInfo(const VULKAN_HPP_NAMESPACE::ImageCreateInfo& imageCreateInfo,
const AllocationCreateInfo& allocationCreateInfo) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result findMemoryTypeIndexForImageInfo(const VULKAN_HPP_NAMESPACE::ImageCreateInfo* imageCreateInfo,
const AllocationCreateInfo* allocationCreateInfo,
uint32_t* memoryTypeIndex) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<Pool>::type createPool(const PoolCreateInfo& createInfo) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<UniquePool>::type createPoolUnique(const PoolCreateInfo& createInfo) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result createPool(const PoolCreateInfo* createInfo,
Pool* pool) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void destroyPool(Pool pool) const;
#else
void destroyPool(Pool pool) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS Statistics getPoolStatistics(Pool pool) const;
#endif
void getPoolStatistics(Pool pool,
Statistics* poolStats) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS DetailedStatistics calculatePoolStatistics(Pool pool) const;
#endif
void calculatePoolStatistics(Pool pool,
DetailedStatistics* poolStats) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type checkPoolCorruption(Pool pool) const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result checkPoolCorruption(Pool pool) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS const char* getPoolName(Pool pool) const;
#endif
void getPoolName(Pool pool,
const char** name) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void setPoolName(Pool pool,
const char* name) const;
#else
void setPoolName(Pool pool,
const char* name) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<Allocation>::type allocateMemory(const VULKAN_HPP_NAMESPACE::MemoryRequirements& vkMemoryRequirements,
const AllocationCreateInfo& createInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<UniqueAllocation>::type allocateMemoryUnique(const VULKAN_HPP_NAMESPACE::MemoryRequirements& vkMemoryRequirements,
const AllocationCreateInfo& createInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result allocateMemory(const VULKAN_HPP_NAMESPACE::MemoryRequirements* vkMemoryRequirements,
const AllocationCreateInfo* createInfo,
Allocation* allocation,
AllocationInfo* allocationInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
template<typename VectorAllocator = std::allocator<Allocation>,
typename B = VectorAllocator,
typename std::enable_if<std::is_same<typename B::value_type, Allocation>::value, int>::type = 0>
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::vector<Allocation, VectorAllocator>>::type allocateMemoryPages(VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryRequirements> vkMemoryRequirements,
VULKAN_HPP_NAMESPACE::ArrayProxy<const AllocationCreateInfo> createInfo,
VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<AllocationInfo> allocationInfo,
VectorAllocator& vectorAllocator) const;
template<typename VectorAllocator = std::allocator<Allocation>>
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::vector<Allocation, VectorAllocator>>::type allocateMemoryPages(VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryRequirements> vkMemoryRequirements,
VULKAN_HPP_NAMESPACE::ArrayProxy<const AllocationCreateInfo> createInfo,
VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<AllocationInfo> allocationInfo = nullptr) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
template<typename VectorAllocator = std::allocator<UniqueAllocation>,
typename B = VectorAllocator,
typename std::enable_if<std::is_same<typename B::value_type, UniqueAllocation>::value, int>::type = 0>
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::vector<UniqueAllocation, VectorAllocator>>::type allocateMemoryPagesUnique(VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryRequirements> vkMemoryRequirements,
VULKAN_HPP_NAMESPACE::ArrayProxy<const AllocationCreateInfo> createInfo,
VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<AllocationInfo> allocationInfo,
VectorAllocator& vectorAllocator) const;
template<typename VectorAllocator = std::allocator<UniqueAllocation>>
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::vector<UniqueAllocation, VectorAllocator>>::type allocateMemoryPagesUnique(VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryRequirements> vkMemoryRequirements,
VULKAN_HPP_NAMESPACE::ArrayProxy<const AllocationCreateInfo> createInfo,
VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<AllocationInfo> allocationInfo = nullptr) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result allocateMemoryPages(const VULKAN_HPP_NAMESPACE::MemoryRequirements* vkMemoryRequirements,
const AllocationCreateInfo* createInfo,
size_t allocationCount,
Allocation* allocations,
AllocationInfo* allocationInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<Allocation>::type allocateMemoryForBuffer(VULKAN_HPP_NAMESPACE::Buffer buffer,
const AllocationCreateInfo& createInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<UniqueAllocation>::type allocateMemoryForBufferUnique(VULKAN_HPP_NAMESPACE::Buffer buffer,
const AllocationCreateInfo& createInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result allocateMemoryForBuffer(VULKAN_HPP_NAMESPACE::Buffer buffer,
const AllocationCreateInfo* createInfo,
Allocation* allocation,
AllocationInfo* allocationInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<Allocation>::type allocateMemoryForImage(VULKAN_HPP_NAMESPACE::Image image,
const AllocationCreateInfo& createInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<UniqueAllocation>::type allocateMemoryForImageUnique(VULKAN_HPP_NAMESPACE::Image image,
const AllocationCreateInfo& createInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result allocateMemoryForImage(VULKAN_HPP_NAMESPACE::Image image,
const AllocationCreateInfo* createInfo,
Allocation* allocation,
AllocationInfo* allocationInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void freeMemory(const Allocation allocation) const;
#else
void freeMemory(const Allocation allocation) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void freeMemoryPages(VULKAN_HPP_NAMESPACE::ArrayProxy<const Allocation> allocations) const;
#endif
void freeMemoryPages(size_t allocationCount,
const Allocation* allocations) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS AllocationInfo getAllocationInfo(Allocation allocation) const;
#endif
void getAllocationInfo(Allocation allocation,
AllocationInfo* allocationInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void setAllocationUserData(Allocation allocation,
void* userData) const;
#else
void setAllocationUserData(Allocation allocation,
void* userData) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void setAllocationName(Allocation allocation,
const char* name) const;
#else
void setAllocationName(Allocation allocation,
const char* name) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS VULKAN_HPP_NAMESPACE::MemoryPropertyFlags getAllocationMemoryProperties(Allocation allocation) const;
#endif
void getAllocationMemoryProperties(Allocation allocation,
VULKAN_HPP_NAMESPACE::MemoryPropertyFlags* flags) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<void*>::type mapMemory(Allocation allocation) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result mapMemory(Allocation allocation,
void** data) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void unmapMemory(Allocation allocation) const;
#else
void unmapMemory(Allocation allocation) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type flushAllocation(Allocation allocation,
VULKAN_HPP_NAMESPACE::DeviceSize offset,
VULKAN_HPP_NAMESPACE::DeviceSize size) const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result flushAllocation(Allocation allocation,
VULKAN_HPP_NAMESPACE::DeviceSize offset,
VULKAN_HPP_NAMESPACE::DeviceSize size) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type invalidateAllocation(Allocation allocation,
VULKAN_HPP_NAMESPACE::DeviceSize offset,
VULKAN_HPP_NAMESPACE::DeviceSize size) const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result invalidateAllocation(Allocation allocation,
VULKAN_HPP_NAMESPACE::DeviceSize offset,
VULKAN_HPP_NAMESPACE::DeviceSize size) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type flushAllocations(VULKAN_HPP_NAMESPACE::ArrayProxy<const Allocation> allocations,
VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> offsets,
VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> sizes) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result flushAllocations(uint32_t allocationCount,
const Allocation* allocations,
const VULKAN_HPP_NAMESPACE::DeviceSize* offsets,
const VULKAN_HPP_NAMESPACE::DeviceSize* sizes) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type invalidateAllocations(VULKAN_HPP_NAMESPACE::ArrayProxy<const Allocation> allocations,
VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> offsets,
VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> sizes) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result invalidateAllocations(uint32_t allocationCount,
const Allocation* allocations,
const VULKAN_HPP_NAMESPACE::DeviceSize* offsets,
const VULKAN_HPP_NAMESPACE::DeviceSize* sizes) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type checkCorruption(uint32_t memoryTypeBits) const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result checkCorruption(uint32_t memoryTypeBits) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<DefragmentationContext>::type beginDefragmentation(const DefragmentationInfo& info) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result beginDefragmentation(const DefragmentationInfo* info,
DefragmentationContext* context) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void endDefragmentation(DefragmentationContext context,
VULKAN_HPP_NAMESPACE::Optional<DefragmentationStats> stats = nullptr) const;
#endif
void endDefragmentation(DefragmentationContext context,
DefragmentationStats* stats) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<DefragmentationPassMoveInfo>::type beginDefragmentationPass(DefragmentationContext context) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result beginDefragmentationPass(DefragmentationContext context,
DefragmentationPassMoveInfo* passInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<DefragmentationPassMoveInfo>::type endDefragmentationPass(DefragmentationContext context) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result endDefragmentationPass(DefragmentationContext context,
DefragmentationPassMoveInfo* passInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type bindBufferMemory(Allocation allocation,
VULKAN_HPP_NAMESPACE::Buffer buffer) const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result bindBufferMemory(Allocation allocation,
VULKAN_HPP_NAMESPACE::Buffer buffer) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type bindBufferMemory2(Allocation allocation,
VULKAN_HPP_NAMESPACE::DeviceSize allocationLocalOffset,
VULKAN_HPP_NAMESPACE::Buffer buffer,
const void* next) const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result bindBufferMemory2(Allocation allocation,
VULKAN_HPP_NAMESPACE::DeviceSize allocationLocalOffset,
VULKAN_HPP_NAMESPACE::Buffer buffer,
const void* next) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type bindImageMemory(Allocation allocation,
VULKAN_HPP_NAMESPACE::Image image) const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result bindImageMemory(Allocation allocation,
VULKAN_HPP_NAMESPACE::Image image) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
typename VULKAN_HPP_NAMESPACE::ResultValueType<void>::type bindImageMemory2(Allocation allocation,
VULKAN_HPP_NAMESPACE::DeviceSize allocationLocalOffset,
VULKAN_HPP_NAMESPACE::Image image,
const void* next) const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result bindImageMemory2(Allocation allocation,
VULKAN_HPP_NAMESPACE::DeviceSize allocationLocalOffset,
VULKAN_HPP_NAMESPACE::Image image,
const void* next) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::pair<VULKAN_HPP_NAMESPACE::Buffer, Allocation>>::type createBuffer(const VULKAN_HPP_NAMESPACE::BufferCreateInfo& bufferCreateInfo,
const AllocationCreateInfo& allocationCreateInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::pair<UniqueBuffer, UniqueAllocation>>::type createBufferUnique(const VULKAN_HPP_NAMESPACE::BufferCreateInfo& bufferCreateInfo,
const AllocationCreateInfo& allocationCreateInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result createBuffer(const VULKAN_HPP_NAMESPACE::BufferCreateInfo* bufferCreateInfo,
const AllocationCreateInfo* allocationCreateInfo,
VULKAN_HPP_NAMESPACE::Buffer* buffer,
Allocation* allocation,
AllocationInfo* allocationInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::pair<VULKAN_HPP_NAMESPACE::Buffer, Allocation>>::type createBufferWithAlignment(const VULKAN_HPP_NAMESPACE::BufferCreateInfo& bufferCreateInfo,
const AllocationCreateInfo& allocationCreateInfo,
VULKAN_HPP_NAMESPACE::DeviceSize minAlignment,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::pair<UniqueBuffer, UniqueAllocation>>::type createBufferWithAlignmentUnique(const VULKAN_HPP_NAMESPACE::BufferCreateInfo& bufferCreateInfo,
const AllocationCreateInfo& allocationCreateInfo,
VULKAN_HPP_NAMESPACE::DeviceSize minAlignment,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result createBufferWithAlignment(const VULKAN_HPP_NAMESPACE::BufferCreateInfo* bufferCreateInfo,
const AllocationCreateInfo* allocationCreateInfo,
VULKAN_HPP_NAMESPACE::DeviceSize minAlignment,
VULKAN_HPP_NAMESPACE::Buffer* buffer,
Allocation* allocation,
AllocationInfo* allocationInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<VULKAN_HPP_NAMESPACE::Buffer>::type createAliasingBuffer(Allocation allocation,
const VULKAN_HPP_NAMESPACE::BufferCreateInfo& bufferCreateInfo) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result createAliasingBuffer(Allocation allocation,
const VULKAN_HPP_NAMESPACE::BufferCreateInfo* bufferCreateInfo,
VULKAN_HPP_NAMESPACE::Buffer* buffer) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void destroyBuffer(VULKAN_HPP_NAMESPACE::Buffer buffer,
Allocation allocation) const;
#else
void destroyBuffer(VULKAN_HPP_NAMESPACE::Buffer buffer,
Allocation allocation) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::pair<VULKAN_HPP_NAMESPACE::Image, Allocation>>::type createImage(const VULKAN_HPP_NAMESPACE::ImageCreateInfo& imageCreateInfo,
const AllocationCreateInfo& allocationCreateInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<std::pair<UniqueImage, UniqueAllocation>>::type createImageUnique(const VULKAN_HPP_NAMESPACE::ImageCreateInfo& imageCreateInfo,
const AllocationCreateInfo& allocationCreateInfo,
VULKAN_HPP_NAMESPACE::Optional<AllocationInfo> allocationInfo = nullptr) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result createImage(const VULKAN_HPP_NAMESPACE::ImageCreateInfo* imageCreateInfo,
const AllocationCreateInfo* allocationCreateInfo,
VULKAN_HPP_NAMESPACE::Image* image,
Allocation* allocation,
AllocationInfo* allocationInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<VULKAN_HPP_NAMESPACE::Image>::type createAliasingImage(Allocation allocation,
const VULKAN_HPP_NAMESPACE::ImageCreateInfo& imageCreateInfo) const;
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result createAliasingImage(Allocation allocation,
const VULKAN_HPP_NAMESPACE::ImageCreateInfo* imageCreateInfo,
VULKAN_HPP_NAMESPACE::Image* image) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void destroyImage(VULKAN_HPP_NAMESPACE::Image image,
Allocation allocation) const;
#else
void destroyImage(VULKAN_HPP_NAMESPACE::Image image,
Allocation allocation) const;
#endif
#if VMA_STATS_STRING_ENABLED
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS char* buildStatsString(VULKAN_HPP_NAMESPACE::Bool32 detailedMap) const;
#endif
void buildStatsString(char** statsString,
VULKAN_HPP_NAMESPACE::Bool32 detailedMap) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void freeStatsString(char* statsString) const;
#else
void freeStatsString(char* statsString) const;
#endif
#endif
private:
VmaAllocator m_allocator = {};
};
VULKAN_HPP_STATIC_ASSERT(sizeof(Allocator) == sizeof(VmaAllocator),
"handle and wrapper have different size!");
}
#ifndef VULKAN_HPP_NO_SMART_HANDLE
namespace VULKAN_HPP_NAMESPACE {
template<> struct UniqueHandleTraits<VMA_HPP_NAMESPACE::Allocator, VMA_HPP_NAMESPACE::Dispatcher> {
using deleter = VMA_HPP_NAMESPACE::Deleter<VMA_HPP_NAMESPACE::Allocator, void>;
};
}
namespace VMA_HPP_NAMESPACE { using UniqueAllocator = VULKAN_HPP_NAMESPACE::UniqueHandle<Allocator, Dispatcher>; }
#endif
namespace VMA_HPP_NAMESPACE {
class VirtualAllocation {
public:
using CType = VmaVirtualAllocation;
using NativeType = VmaVirtualAllocation;
public:
VULKAN_HPP_CONSTEXPR VirtualAllocation() = default;
VULKAN_HPP_CONSTEXPR VirtualAllocation(std::nullptr_t) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT VirtualAllocation(VmaVirtualAllocation virtualAllocation) VULKAN_HPP_NOEXCEPT : m_virtualAllocation(virtualAllocation) {}
#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
VirtualAllocation& operator=(VmaVirtualAllocation virtualAllocation) VULKAN_HPP_NOEXCEPT {
m_virtualAllocation = virtualAllocation;
return *this;
}
#endif
VirtualAllocation& operator=(std::nullptr_t) VULKAN_HPP_NOEXCEPT {
m_virtualAllocation = {};
return *this;
}
#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR )
auto operator<=>(VirtualAllocation const &) const = default;
#else
bool operator==(VirtualAllocation const & rhs) const VULKAN_HPP_NOEXCEPT {
return m_virtualAllocation == rhs.m_virtualAllocation;
}
#endif
VULKAN_HPP_TYPESAFE_EXPLICIT operator VmaVirtualAllocation() const VULKAN_HPP_NOEXCEPT {
return m_virtualAllocation;
}
explicit operator bool() const VULKAN_HPP_NOEXCEPT {
return m_virtualAllocation != VK_NULL_HANDLE;
}
bool operator!() const VULKAN_HPP_NOEXCEPT {
return m_virtualAllocation == VK_NULL_HANDLE;
}
private:
VmaVirtualAllocation m_virtualAllocation = {};
};
VULKAN_HPP_STATIC_ASSERT(sizeof(VirtualAllocation) == sizeof(VmaVirtualAllocation),
"handle and wrapper have different size!");
}
#ifndef VULKAN_HPP_NO_SMART_HANDLE
namespace VULKAN_HPP_NAMESPACE {
template<> struct UniqueHandleTraits<VMA_HPP_NAMESPACE::VirtualAllocation, VMA_HPP_NAMESPACE::Dispatcher> {
using deleter = VMA_HPP_NAMESPACE::Deleter<VMA_HPP_NAMESPACE::VirtualAllocation, VMA_HPP_NAMESPACE::VirtualBlock>;
};
}
namespace VMA_HPP_NAMESPACE { using UniqueVirtualAllocation = VULKAN_HPP_NAMESPACE::UniqueHandle<VirtualAllocation, Dispatcher>; }
#endif
namespace VMA_HPP_NAMESPACE {
class VirtualBlock {
public:
using CType = VmaVirtualBlock;
using NativeType = VmaVirtualBlock;
public:
VULKAN_HPP_CONSTEXPR VirtualBlock() = default;
VULKAN_HPP_CONSTEXPR VirtualBlock(std::nullptr_t) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT VirtualBlock(VmaVirtualBlock virtualBlock) VULKAN_HPP_NOEXCEPT : m_virtualBlock(virtualBlock) {}
#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
VirtualBlock& operator=(VmaVirtualBlock virtualBlock) VULKAN_HPP_NOEXCEPT {
m_virtualBlock = virtualBlock;
return *this;
}
#endif
VirtualBlock& operator=(std::nullptr_t) VULKAN_HPP_NOEXCEPT {
m_virtualBlock = {};
return *this;
}
#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR )
auto operator<=>(VirtualBlock const &) const = default;
#else
bool operator==(VirtualBlock const & rhs) const VULKAN_HPP_NOEXCEPT {
return m_virtualBlock == rhs.m_virtualBlock;
}
#endif
VULKAN_HPP_TYPESAFE_EXPLICIT operator VmaVirtualBlock() const VULKAN_HPP_NOEXCEPT {
return m_virtualBlock;
}
explicit operator bool() const VULKAN_HPP_NOEXCEPT {
return m_virtualBlock != VK_NULL_HANDLE;
}
bool operator!() const VULKAN_HPP_NOEXCEPT {
return m_virtualBlock == VK_NULL_HANDLE;
}
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void destroy() const;
#else
void destroy() const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS VULKAN_HPP_NAMESPACE::Bool32 isVirtualBlockEmpty() const;
#else
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Bool32 isVirtualBlockEmpty() const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS VirtualAllocationInfo getVirtualAllocationInfo(VirtualAllocation allocation) const;
#endif
void getVirtualAllocationInfo(VirtualAllocation allocation,
VirtualAllocationInfo* virtualAllocInfo) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<VirtualAllocation>::type virtualAllocate(const VirtualAllocationCreateInfo& createInfo,
VULKAN_HPP_NAMESPACE::Optional<VULKAN_HPP_NAMESPACE::DeviceSize> offset = nullptr) const;
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<UniqueVirtualAllocation>::type virtualAllocateUnique(const VirtualAllocationCreateInfo& createInfo,
VULKAN_HPP_NAMESPACE::Optional<VULKAN_HPP_NAMESPACE::DeviceSize> offset = nullptr) const;
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result virtualAllocate(const VirtualAllocationCreateInfo* createInfo,
VirtualAllocation* allocation,
VULKAN_HPP_NAMESPACE::DeviceSize* offset) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void virtualFree(VirtualAllocation allocation) const;
#else
void virtualFree(VirtualAllocation allocation) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void clearVirtualBlock() const;
#else
void clearVirtualBlock() const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void setVirtualAllocationUserData(VirtualAllocation allocation,
void* userData) const;
#else
void setVirtualAllocationUserData(VirtualAllocation allocation,
void* userData) const;
#endif
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS Statistics getVirtualBlockStatistics() const;
#endif
void getVirtualBlockStatistics(Statistics* stats) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS DetailedStatistics calculateVirtualBlockStatistics() const;
#endif
void calculateVirtualBlockStatistics(DetailedStatistics* stats) const;
#if VMA_STATS_STRING_ENABLED
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS char* buildVirtualBlockStatsString(VULKAN_HPP_NAMESPACE::Bool32 detailedMap) const;
#endif
void buildVirtualBlockStatsString(char** statsString,
VULKAN_HPP_NAMESPACE::Bool32 detailedMap) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
void freeVirtualBlockStatsString(char* statsString) const;
#else
void freeVirtualBlockStatsString(char* statsString) const;
#endif
#endif
private:
VmaVirtualBlock m_virtualBlock = {};
};
VULKAN_HPP_STATIC_ASSERT(sizeof(VirtualBlock) == sizeof(VmaVirtualBlock),
"handle and wrapper have different size!");
}
#ifndef VULKAN_HPP_NO_SMART_HANDLE
namespace VULKAN_HPP_NAMESPACE {
template<> struct UniqueHandleTraits<VMA_HPP_NAMESPACE::VirtualBlock, VMA_HPP_NAMESPACE::Dispatcher> {
using deleter = VMA_HPP_NAMESPACE::Deleter<VMA_HPP_NAMESPACE::VirtualBlock, void>;
};
}
namespace VMA_HPP_NAMESPACE { using UniqueVirtualBlock = VULKAN_HPP_NAMESPACE::UniqueHandle<VirtualBlock, Dispatcher>; }
#endif
namespace VMA_HPP_NAMESPACE {
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<Allocator>::type createAllocator(const AllocatorCreateInfo& createInfo);
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<UniqueAllocator>::type createAllocatorUnique(const AllocatorCreateInfo& createInfo);
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result createAllocator(const AllocatorCreateInfo* createInfo,
Allocator* allocator);
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<VirtualBlock>::type createVirtualBlock(const VirtualBlockCreateInfo& createInfo);
#ifndef VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS typename VULKAN_HPP_NAMESPACE::ResultValueType<UniqueVirtualBlock>::type createVirtualBlockUnique(const VirtualBlockCreateInfo& createInfo);
#endif
#endif
VULKAN_HPP_NODISCARD VULKAN_HPP_NAMESPACE::Result createVirtualBlock(const VirtualBlockCreateInfo* createInfo,
VirtualBlock* virtualBlock);
}
#endif

File diff suppressed because it is too large Load Diff

8
external/fmt/.clang-format vendored Normal file
View File

@ -0,0 +1,8 @@
# Run manually to reformat a file:
# clang-format -i --style=file <file>
Language: Cpp
BasedOnStyle: Google
IndentPPDirectives: AfterHash
IndentCaseLabels: false
AlwaysBreakTemplateDeclarations: false
DerivePointerAlignment: false

27
external/fmt/LICENSE.rst vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2012 - present, Victor Zverovich
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.
--- Optional exception to the license ---
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into a machine-executable object form of such
source code, you may redistribute such embedded portions in such object form
without including the above copyright and permission notices.

234
external/fmt/include/fmt/args.h vendored Normal file
View File

@ -0,0 +1,234 @@
// Formatting library for C++ - dynamic format arguments
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_ARGS_H_
#define FMT_ARGS_H_
#include <functional> // std::reference_wrapper
#include <memory> // std::unique_ptr
#include <vector>
#include "core.h"
FMT_BEGIN_NAMESPACE
namespace detail {
template <typename T> struct is_reference_wrapper : std::false_type {};
template <typename T>
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
template <typename T> const T& unwrap(const T& v) { return v; }
template <typename T> const T& unwrap(const std::reference_wrapper<T>& v) {
return static_cast<const T&>(v);
}
class dynamic_arg_list {
// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
// templates it doesn't complain about inability to deduce single translation
// unit for placing vtable. So storage_node_base is made a fake template.
template <typename = void> struct node {
virtual ~node() = default;
std::unique_ptr<node<>> next;
};
template <typename T> struct typed_node : node<> {
T value;
template <typename Arg>
FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {}
template <typename Char>
FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg)
: value(arg.data(), arg.size()) {}
};
std::unique_ptr<node<>> head_;
public:
template <typename T, typename Arg> const T& push(const Arg& arg) {
auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
auto& value = new_node->value;
new_node->next = std::move(head_);
head_ = std::move(new_node);
return value;
}
};
} // namespace detail
/**
\rst
A dynamic version of `fmt::format_arg_store`.
It's equipped with a storage to potentially temporary objects which lifetimes
could be shorter than the format arguments object.
It can be implicitly converted into `~fmt::basic_format_args` for passing
into type-erased formatting functions such as `~fmt::vformat`.
\endrst
*/
template <typename Context>
class dynamic_format_arg_store
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
// Workaround a GCC template argument substitution bug.
: public basic_format_args<Context>
#endif
{
private:
using char_type = typename Context::char_type;
template <typename T> struct need_copy {
static constexpr detail::type mapped_type =
detail::mapped_type_constant<T, Context>::value;
enum {
value = !(detail::is_reference_wrapper<T>::value ||
std::is_same<T, basic_string_view<char_type>>::value ||
std::is_same<T, detail::std_string_view<char_type>>::value ||
(mapped_type != detail::type::cstring_type &&
mapped_type != detail::type::string_type &&
mapped_type != detail::type::custom_type))
};
};
template <typename T>
using stored_type = conditional_t<
std::is_convertible<T, std::basic_string<char_type>>::value &&
!detail::is_reference_wrapper<T>::value,
std::basic_string<char_type>, T>;
// Storage of basic_format_arg must be contiguous.
std::vector<basic_format_arg<Context>> data_;
std::vector<detail::named_arg_info<char_type>> named_info_;
// Storage of arguments not fitting into basic_format_arg must grow
// without relocation because items in data_ refer to it.
detail::dynamic_arg_list dynamic_args_;
friend class basic_format_args<Context>;
unsigned long long get_types() const {
return detail::is_unpacked_bit | data_.size() |
(named_info_.empty()
? 0ULL
: static_cast<unsigned long long>(detail::has_named_args_bit));
}
const basic_format_arg<Context>* data() const {
return named_info_.empty() ? data_.data() : data_.data() + 1;
}
template <typename T> void emplace_arg(const T& arg) {
data_.emplace_back(detail::make_arg<Context>(arg));
}
template <typename T>
void emplace_arg(const detail::named_arg<char_type, T>& arg) {
if (named_info_.empty()) {
constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};
data_.insert(data_.begin(), {zero_ptr, 0});
}
data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
data->pop_back();
};
std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
guard{&data_, pop_one};
named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
guard.release();
}
public:
constexpr dynamic_format_arg_store() = default;
/**
\rst
Adds an argument into the dynamic store for later passing to a formatting
function.
Note that custom types and string types (but not string views) are copied
into the store dynamically allocating memory if necessary.
**Example**::
fmt::dynamic_format_arg_store<fmt::format_context> store;
store.push_back(42);
store.push_back("abc");
store.push_back(1.5f);
std::string result = fmt::vformat("{} and {} and {}", store);
\endrst
*/
template <typename T> void push_back(const T& arg) {
if (detail::const_check(need_copy<T>::value))
emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
else
emplace_arg(detail::unwrap(arg));
}
/**
\rst
Adds a reference to the argument into the dynamic store for later passing to
a formatting function.
**Example**::
fmt::dynamic_format_arg_store<fmt::format_context> store;
char band[] = "Rolling Stones";
store.push_back(std::cref(band));
band[9] = 'c'; // Changing str affects the output.
std::string result = fmt::vformat("{}", store);
// result == "Rolling Scones"
\endrst
*/
template <typename T> void push_back(std::reference_wrapper<T> arg) {
static_assert(
need_copy<T>::value,
"objects of built-in types and string views are always copied");
emplace_arg(arg.get());
}
/**
Adds named argument into the dynamic store for later passing to a formatting
function. ``std::reference_wrapper`` is supported to avoid copying of the
argument. The name is always copied into the store.
*/
template <typename T>
void push_back(const detail::named_arg<char_type, T>& arg) {
const char_type* arg_name =
dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
if (detail::const_check(need_copy<T>::value)) {
emplace_arg(
fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
} else {
emplace_arg(fmt::arg(arg_name, arg.value));
}
}
/** Erase all elements from the store */
void clear() {
data_.clear();
named_info_.clear();
dynamic_args_ = detail::dynamic_arg_list();
}
/**
\rst
Reserves space to store at least *new_cap* arguments including
*new_cap_named* named arguments.
\endrst
*/
void reserve(size_t new_cap, size_t new_cap_named) {
FMT_ASSERT(new_cap >= new_cap_named,
"Set of arguments includes set of named arguments");
data_.reserve(new_cap);
named_info_.reserve(new_cap_named);
}
};
FMT_END_NAMESPACE
#endif // FMT_ARGS_H_

2081
external/fmt/include/fmt/chrono.h vendored Normal file

File diff suppressed because it is too large Load Diff

694
external/fmt/include/fmt/color.h vendored Normal file
View File

@ -0,0 +1,694 @@
// Formatting library for C++ - color support
//
// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_COLOR_H_
#define FMT_COLOR_H_
#include "format.h"
// __declspec(deprecated) is broken in some MSVC versions.
#if FMT_MSC_VER
# define FMT_DEPRECATED_NONMSVC
#else
# define FMT_DEPRECATED_NONMSVC FMT_DEPRECATED
#endif
FMT_BEGIN_NAMESPACE
FMT_MODULE_EXPORT_BEGIN
enum class color : uint32_t {
alice_blue = 0xF0F8FF, // rgb(240,248,255)
antique_white = 0xFAEBD7, // rgb(250,235,215)
aqua = 0x00FFFF, // rgb(0,255,255)
aquamarine = 0x7FFFD4, // rgb(127,255,212)
azure = 0xF0FFFF, // rgb(240,255,255)
beige = 0xF5F5DC, // rgb(245,245,220)
bisque = 0xFFE4C4, // rgb(255,228,196)
black = 0x000000, // rgb(0,0,0)
blanched_almond = 0xFFEBCD, // rgb(255,235,205)
blue = 0x0000FF, // rgb(0,0,255)
blue_violet = 0x8A2BE2, // rgb(138,43,226)
brown = 0xA52A2A, // rgb(165,42,42)
burly_wood = 0xDEB887, // rgb(222,184,135)
cadet_blue = 0x5F9EA0, // rgb(95,158,160)
chartreuse = 0x7FFF00, // rgb(127,255,0)
chocolate = 0xD2691E, // rgb(210,105,30)
coral = 0xFF7F50, // rgb(255,127,80)
cornflower_blue = 0x6495ED, // rgb(100,149,237)
cornsilk = 0xFFF8DC, // rgb(255,248,220)
crimson = 0xDC143C, // rgb(220,20,60)
cyan = 0x00FFFF, // rgb(0,255,255)
dark_blue = 0x00008B, // rgb(0,0,139)
dark_cyan = 0x008B8B, // rgb(0,139,139)
dark_golden_rod = 0xB8860B, // rgb(184,134,11)
dark_gray = 0xA9A9A9, // rgb(169,169,169)
dark_green = 0x006400, // rgb(0,100,0)
dark_khaki = 0xBDB76B, // rgb(189,183,107)
dark_magenta = 0x8B008B, // rgb(139,0,139)
dark_olive_green = 0x556B2F, // rgb(85,107,47)
dark_orange = 0xFF8C00, // rgb(255,140,0)
dark_orchid = 0x9932CC, // rgb(153,50,204)
dark_red = 0x8B0000, // rgb(139,0,0)
dark_salmon = 0xE9967A, // rgb(233,150,122)
dark_sea_green = 0x8FBC8F, // rgb(143,188,143)
dark_slate_blue = 0x483D8B, // rgb(72,61,139)
dark_slate_gray = 0x2F4F4F, // rgb(47,79,79)
dark_turquoise = 0x00CED1, // rgb(0,206,209)
dark_violet = 0x9400D3, // rgb(148,0,211)
deep_pink = 0xFF1493, // rgb(255,20,147)
deep_sky_blue = 0x00BFFF, // rgb(0,191,255)
dim_gray = 0x696969, // rgb(105,105,105)
dodger_blue = 0x1E90FF, // rgb(30,144,255)
fire_brick = 0xB22222, // rgb(178,34,34)
floral_white = 0xFFFAF0, // rgb(255,250,240)
forest_green = 0x228B22, // rgb(34,139,34)
fuchsia = 0xFF00FF, // rgb(255,0,255)
gainsboro = 0xDCDCDC, // rgb(220,220,220)
ghost_white = 0xF8F8FF, // rgb(248,248,255)
gold = 0xFFD700, // rgb(255,215,0)
golden_rod = 0xDAA520, // rgb(218,165,32)
gray = 0x808080, // rgb(128,128,128)
green = 0x008000, // rgb(0,128,0)
green_yellow = 0xADFF2F, // rgb(173,255,47)
honey_dew = 0xF0FFF0, // rgb(240,255,240)
hot_pink = 0xFF69B4, // rgb(255,105,180)
indian_red = 0xCD5C5C, // rgb(205,92,92)
indigo = 0x4B0082, // rgb(75,0,130)
ivory = 0xFFFFF0, // rgb(255,255,240)
khaki = 0xF0E68C, // rgb(240,230,140)
lavender = 0xE6E6FA, // rgb(230,230,250)
lavender_blush = 0xFFF0F5, // rgb(255,240,245)
lawn_green = 0x7CFC00, // rgb(124,252,0)
lemon_chiffon = 0xFFFACD, // rgb(255,250,205)
light_blue = 0xADD8E6, // rgb(173,216,230)
light_coral = 0xF08080, // rgb(240,128,128)
light_cyan = 0xE0FFFF, // rgb(224,255,255)
light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210)
light_gray = 0xD3D3D3, // rgb(211,211,211)
light_green = 0x90EE90, // rgb(144,238,144)
light_pink = 0xFFB6C1, // rgb(255,182,193)
light_salmon = 0xFFA07A, // rgb(255,160,122)
light_sea_green = 0x20B2AA, // rgb(32,178,170)
light_sky_blue = 0x87CEFA, // rgb(135,206,250)
light_slate_gray = 0x778899, // rgb(119,136,153)
light_steel_blue = 0xB0C4DE, // rgb(176,196,222)
light_yellow = 0xFFFFE0, // rgb(255,255,224)
lime = 0x00FF00, // rgb(0,255,0)
lime_green = 0x32CD32, // rgb(50,205,50)
linen = 0xFAF0E6, // rgb(250,240,230)
magenta = 0xFF00FF, // rgb(255,0,255)
maroon = 0x800000, // rgb(128,0,0)
medium_aquamarine = 0x66CDAA, // rgb(102,205,170)
medium_blue = 0x0000CD, // rgb(0,0,205)
medium_orchid = 0xBA55D3, // rgb(186,85,211)
medium_purple = 0x9370DB, // rgb(147,112,219)
medium_sea_green = 0x3CB371, // rgb(60,179,113)
medium_slate_blue = 0x7B68EE, // rgb(123,104,238)
medium_spring_green = 0x00FA9A, // rgb(0,250,154)
medium_turquoise = 0x48D1CC, // rgb(72,209,204)
medium_violet_red = 0xC71585, // rgb(199,21,133)
midnight_blue = 0x191970, // rgb(25,25,112)
mint_cream = 0xF5FFFA, // rgb(245,255,250)
misty_rose = 0xFFE4E1, // rgb(255,228,225)
moccasin = 0xFFE4B5, // rgb(255,228,181)
navajo_white = 0xFFDEAD, // rgb(255,222,173)
navy = 0x000080, // rgb(0,0,128)
old_lace = 0xFDF5E6, // rgb(253,245,230)
olive = 0x808000, // rgb(128,128,0)
olive_drab = 0x6B8E23, // rgb(107,142,35)
orange = 0xFFA500, // rgb(255,165,0)
orange_red = 0xFF4500, // rgb(255,69,0)
orchid = 0xDA70D6, // rgb(218,112,214)
pale_golden_rod = 0xEEE8AA, // rgb(238,232,170)
pale_green = 0x98FB98, // rgb(152,251,152)
pale_turquoise = 0xAFEEEE, // rgb(175,238,238)
pale_violet_red = 0xDB7093, // rgb(219,112,147)
papaya_whip = 0xFFEFD5, // rgb(255,239,213)
peach_puff = 0xFFDAB9, // rgb(255,218,185)
peru = 0xCD853F, // rgb(205,133,63)
pink = 0xFFC0CB, // rgb(255,192,203)
plum = 0xDDA0DD, // rgb(221,160,221)
powder_blue = 0xB0E0E6, // rgb(176,224,230)
purple = 0x800080, // rgb(128,0,128)
rebecca_purple = 0x663399, // rgb(102,51,153)
red = 0xFF0000, // rgb(255,0,0)
rosy_brown = 0xBC8F8F, // rgb(188,143,143)
royal_blue = 0x4169E1, // rgb(65,105,225)
saddle_brown = 0x8B4513, // rgb(139,69,19)
salmon = 0xFA8072, // rgb(250,128,114)
sandy_brown = 0xF4A460, // rgb(244,164,96)
sea_green = 0x2E8B57, // rgb(46,139,87)
sea_shell = 0xFFF5EE, // rgb(255,245,238)
sienna = 0xA0522D, // rgb(160,82,45)
silver = 0xC0C0C0, // rgb(192,192,192)
sky_blue = 0x87CEEB, // rgb(135,206,235)
slate_blue = 0x6A5ACD, // rgb(106,90,205)
slate_gray = 0x708090, // rgb(112,128,144)
snow = 0xFFFAFA, // rgb(255,250,250)
spring_green = 0x00FF7F, // rgb(0,255,127)
steel_blue = 0x4682B4, // rgb(70,130,180)
tan = 0xD2B48C, // rgb(210,180,140)
teal = 0x008080, // rgb(0,128,128)
thistle = 0xD8BFD8, // rgb(216,191,216)
tomato = 0xFF6347, // rgb(255,99,71)
turquoise = 0x40E0D0, // rgb(64,224,208)
violet = 0xEE82EE, // rgb(238,130,238)
wheat = 0xF5DEB3, // rgb(245,222,179)
white = 0xFFFFFF, // rgb(255,255,255)
white_smoke = 0xF5F5F5, // rgb(245,245,245)
yellow = 0xFFFF00, // rgb(255,255,0)
yellow_green = 0x9ACD32 // rgb(154,205,50)
}; // enum class color
enum class terminal_color : uint8_t {
black = 30,
red,
green,
yellow,
blue,
magenta,
cyan,
white,
bright_black = 90,
bright_red,
bright_green,
bright_yellow,
bright_blue,
bright_magenta,
bright_cyan,
bright_white
};
enum class emphasis : uint8_t {
bold = 1,
faint = 1 << 1,
italic = 1 << 2,
underline = 1 << 3,
blink = 1 << 4,
reverse = 1 << 5,
conceal = 1 << 6,
strikethrough = 1 << 7,
};
// rgb is a struct for red, green and blue colors.
// Using the name "rgb" makes some editors show the color in a tooltip.
struct rgb {
FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {}
FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {}
FMT_CONSTEXPR rgb(uint32_t hex)
: r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {}
FMT_CONSTEXPR rgb(color hex)
: r((uint32_t(hex) >> 16) & 0xFF),
g((uint32_t(hex) >> 8) & 0xFF),
b(uint32_t(hex) & 0xFF) {}
uint8_t r;
uint8_t g;
uint8_t b;
};
FMT_BEGIN_DETAIL_NAMESPACE
// color is a struct of either a rgb color or a terminal color.
struct color_type {
FMT_CONSTEXPR color_type() noexcept : is_rgb(), value{} {}
FMT_CONSTEXPR color_type(color rgb_color) noexcept : is_rgb(true), value{} {
value.rgb_color = static_cast<uint32_t>(rgb_color);
}
FMT_CONSTEXPR color_type(rgb rgb_color) noexcept : is_rgb(true), value{} {
value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) |
(static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b;
}
FMT_CONSTEXPR color_type(terminal_color term_color) noexcept
: is_rgb(), value{} {
value.term_color = static_cast<uint8_t>(term_color);
}
bool is_rgb;
union color_union {
uint8_t term_color;
uint32_t rgb_color;
} value;
};
FMT_END_DETAIL_NAMESPACE
/** A text style consisting of foreground and background colors and emphasis. */
class text_style {
public:
FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept
: set_foreground_color(), set_background_color(), ems(em) {}
FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) {
if (!set_foreground_color) {
set_foreground_color = rhs.set_foreground_color;
foreground_color = rhs.foreground_color;
} else if (rhs.set_foreground_color) {
if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
FMT_THROW(format_error("can't OR a terminal color"));
foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color;
}
if (!set_background_color) {
set_background_color = rhs.set_background_color;
background_color = rhs.background_color;
} else if (rhs.set_background_color) {
if (!background_color.is_rgb || !rhs.background_color.is_rgb)
FMT_THROW(format_error("can't OR a terminal color"));
background_color.value.rgb_color |= rhs.background_color.value.rgb_color;
}
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) |
static_cast<uint8_t>(rhs.ems));
return *this;
}
friend FMT_CONSTEXPR text_style operator|(text_style lhs,
const text_style& rhs) {
return lhs |= rhs;
}
FMT_DEPRECATED_NONMSVC FMT_CONSTEXPR text_style& operator&=(
const text_style& rhs) {
return and_assign(rhs);
}
FMT_DEPRECATED_NONMSVC friend FMT_CONSTEXPR text_style
operator&(text_style lhs, const text_style& rhs) {
return lhs.and_assign(rhs);
}
FMT_CONSTEXPR bool has_foreground() const noexcept {
return set_foreground_color;
}
FMT_CONSTEXPR bool has_background() const noexcept {
return set_background_color;
}
FMT_CONSTEXPR bool has_emphasis() const noexcept {
return static_cast<uint8_t>(ems) != 0;
}
FMT_CONSTEXPR detail::color_type get_foreground() const noexcept {
FMT_ASSERT(has_foreground(), "no foreground specified for this style");
return foreground_color;
}
FMT_CONSTEXPR detail::color_type get_background() const noexcept {
FMT_ASSERT(has_background(), "no background specified for this style");
return background_color;
}
FMT_CONSTEXPR emphasis get_emphasis() const noexcept {
FMT_ASSERT(has_emphasis(), "no emphasis specified for this style");
return ems;
}
private:
FMT_CONSTEXPR text_style(bool is_foreground,
detail::color_type text_color) noexcept
: set_foreground_color(), set_background_color(), ems() {
if (is_foreground) {
foreground_color = text_color;
set_foreground_color = true;
} else {
background_color = text_color;
set_background_color = true;
}
}
// DEPRECATED!
FMT_CONSTEXPR text_style& and_assign(const text_style& rhs) {
if (!set_foreground_color) {
set_foreground_color = rhs.set_foreground_color;
foreground_color = rhs.foreground_color;
} else if (rhs.set_foreground_color) {
if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
FMT_THROW(format_error("can't AND a terminal color"));
foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color;
}
if (!set_background_color) {
set_background_color = rhs.set_background_color;
background_color = rhs.background_color;
} else if (rhs.set_background_color) {
if (!background_color.is_rgb || !rhs.background_color.is_rgb)
FMT_THROW(format_error("can't AND a terminal color"));
background_color.value.rgb_color &= rhs.background_color.value.rgb_color;
}
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) &
static_cast<uint8_t>(rhs.ems));
return *this;
}
friend FMT_CONSTEXPR_DECL text_style
fg(detail::color_type foreground) noexcept;
friend FMT_CONSTEXPR_DECL text_style
bg(detail::color_type background) noexcept;
detail::color_type foreground_color;
detail::color_type background_color;
bool set_foreground_color;
bool set_background_color;
emphasis ems;
};
/** Creates a text style from the foreground (text) color. */
FMT_CONSTEXPR inline text_style fg(detail::color_type foreground) noexcept {
return text_style(true, foreground);
}
/** Creates a text style from the background color. */
FMT_CONSTEXPR inline text_style bg(detail::color_type background) noexcept {
return text_style(false, background);
}
FMT_CONSTEXPR inline text_style operator|(emphasis lhs, emphasis rhs) noexcept {
return text_style(lhs) | rhs;
}
FMT_BEGIN_DETAIL_NAMESPACE
template <typename Char> struct ansi_color_escape {
FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
const char* esc) noexcept {
// If we have a terminal color, we need to output another escape code
// sequence.
if (!text_color.is_rgb) {
bool is_background = esc == string_view("\x1b[48;2;");
uint32_t value = text_color.value.term_color;
// Background ASCII codes are the same as the foreground ones but with
// 10 more.
if (is_background) value += 10u;
size_t index = 0;
buffer[index++] = static_cast<Char>('\x1b');
buffer[index++] = static_cast<Char>('[');
if (value >= 100u) {
buffer[index++] = static_cast<Char>('1');
value %= 100u;
}
buffer[index++] = static_cast<Char>('0' + value / 10u);
buffer[index++] = static_cast<Char>('0' + value % 10u);
buffer[index++] = static_cast<Char>('m');
buffer[index++] = static_cast<Char>('\0');
return;
}
for (int i = 0; i < 7; i++) {
buffer[i] = static_cast<Char>(esc[i]);
}
rgb color(text_color.value.rgb_color);
to_esc(color.r, buffer + 7, ';');
to_esc(color.g, buffer + 11, ';');
to_esc(color.b, buffer + 15, 'm');
buffer[19] = static_cast<Char>(0);
}
FMT_CONSTEXPR ansi_color_escape(emphasis em) noexcept {
uint8_t em_codes[num_emphases] = {};
if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1;
if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2;
if (has_emphasis(em, emphasis::italic)) em_codes[2] = 3;
if (has_emphasis(em, emphasis::underline)) em_codes[3] = 4;
if (has_emphasis(em, emphasis::blink)) em_codes[4] = 5;
if (has_emphasis(em, emphasis::reverse)) em_codes[5] = 7;
if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8;
if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9;
size_t index = 0;
for (size_t i = 0; i < num_emphases; ++i) {
if (!em_codes[i]) continue;
buffer[index++] = static_cast<Char>('\x1b');
buffer[index++] = static_cast<Char>('[');
buffer[index++] = static_cast<Char>('0' + em_codes[i]);
buffer[index++] = static_cast<Char>('m');
}
buffer[index++] = static_cast<Char>(0);
}
FMT_CONSTEXPR operator const Char*() const noexcept { return buffer; }
FMT_CONSTEXPR const Char* begin() const noexcept { return buffer; }
FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const noexcept {
return buffer + std::char_traits<Char>::length(buffer);
}
private:
static constexpr size_t num_emphases = 8;
Char buffer[7u + 3u * num_emphases + 1u];
static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
char delimiter) noexcept {
out[0] = static_cast<Char>('0' + c / 100);
out[1] = static_cast<Char>('0' + c / 10 % 10);
out[2] = static_cast<Char>('0' + c % 10);
out[3] = static_cast<Char>(delimiter);
}
static FMT_CONSTEXPR bool has_emphasis(emphasis em, emphasis mask) noexcept {
return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask);
}
};
template <typename Char>
FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
detail::color_type foreground) noexcept {
return ansi_color_escape<Char>(foreground, "\x1b[38;2;");
}
template <typename Char>
FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
detail::color_type background) noexcept {
return ansi_color_escape<Char>(background, "\x1b[48;2;");
}
template <typename Char>
FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) noexcept {
return ansi_color_escape<Char>(em);
}
template <typename Char> inline void fputs(const Char* chars, FILE* stream) {
int result = std::fputs(chars, stream);
if (result < 0)
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
}
template <> inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) {
int result = std::fputws(chars, stream);
if (result < 0)
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
}
template <typename Char> inline void reset_color(FILE* stream) {
fputs("\x1b[0m", stream);
}
template <> inline void reset_color<wchar_t>(FILE* stream) {
fputs(L"\x1b[0m", stream);
}
template <typename Char> inline void reset_color(buffer<Char>& buffer) {
auto reset_color = string_view("\x1b[0m");
buffer.append(reset_color.begin(), reset_color.end());
}
template <typename T> struct styled_arg {
const T& value;
text_style style;
};
template <typename Char>
void vformat_to(buffer<Char>& buf, const text_style& ts,
basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
bool has_style = false;
if (ts.has_emphasis()) {
has_style = true;
auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
buf.append(emphasis.begin(), emphasis.end());
}
if (ts.has_foreground()) {
has_style = true;
auto foreground = detail::make_foreground_color<Char>(ts.get_foreground());
buf.append(foreground.begin(), foreground.end());
}
if (ts.has_background()) {
has_style = true;
auto background = detail::make_background_color<Char>(ts.get_background());
buf.append(background.begin(), background.end());
}
detail::vformat_to(buf, format_str, args, {});
if (has_style) detail::reset_color<Char>(buf);
}
FMT_END_DETAIL_NAMESPACE
template <typename S, typename Char = char_t<S>>
void vprint(std::FILE* f, const text_style& ts, const S& format,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buf;
detail::vformat_to(buf, ts, to_string_view(format), args);
if (detail::is_utf8()) {
detail::print(f, basic_string_view<Char>(buf.begin(), buf.size()));
} else {
buf.push_back(Char(0));
detail::fputs(buf.data(), f);
}
}
/**
\rst
Formats a string and prints it to the specified file stream using ANSI
escape sequences to specify text formatting.
**Example**::
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
"Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_string<S>::value)>
void print(std::FILE* f, const text_style& ts, const S& format_str,
const Args&... args) {
vprint(f, ts, format_str,
fmt::make_format_args<buffer_context<char_t<S>>>(args...));
}
/**
\rst
Formats a string and prints it to stdout using ANSI escape sequences to
specify text formatting.
**Example**::
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
"Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_string<S>::value)>
void print(const text_style& ts, const S& format_str, const Args&... args) {
return print(stdout, ts, format_str, args...);
}
template <typename S, typename Char = char_t<S>>
inline std::basic_string<Char> vformat(
const text_style& ts, const S& format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buf;
detail::vformat_to(buf, ts, to_string_view(format_str), args);
return fmt::to_string(buf);
}
/**
\rst
Formats arguments and returns the result as a string using ANSI
escape sequences to specify text formatting.
**Example**::
#include <fmt/color.h>
std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),
"The answer is {}", 42);
\endrst
*/
template <typename S, typename... Args, typename Char = char_t<S>>
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
const Args&... args) {
return fmt::vformat(ts, to_string_view(format_str),
fmt::make_format_args<buffer_context<Char>>(args...));
}
/**
Formats a string with the given text_style and writes the output to ``out``.
*/
template <typename OutputIt, typename Char,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
OutputIt vformat_to(
OutputIt out, const text_style& ts, basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
auto&& buf = detail::get_buffer<Char>(out);
detail::vformat_to(buf, ts, format_str, args);
return detail::get_iterator(buf);
}
/**
\rst
Formats arguments with the given text_style, writes the result to the output
iterator ``out`` and returns the iterator past the end of the output range.
**Example**::
std::vector<char> out;
fmt::format_to(std::back_inserter(out),
fmt::emphasis::bold | fg(fmt::color::red), "{}", 42);
\endrst
*/
template <typename OutputIt, typename S, typename... Args,
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value&&
detail::is_string<S>::value>
inline auto format_to(OutputIt out, const text_style& ts, const S& format_str,
Args&&... args) ->
typename std::enable_if<enable, OutputIt>::type {
return vformat_to(out, ts, to_string_view(format_str),
fmt::make_format_args<buffer_context<char_t<S>>>(args...));
}
template <typename T, typename Char>
struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
template <typename FormatContext>
auto format(const detail::styled_arg<T>& arg, FormatContext& ctx) const
-> decltype(ctx.out()) {
const auto& ts = arg.style;
const auto& value = arg.value;
auto out = ctx.out();
bool has_style = false;
if (ts.has_emphasis()) {
has_style = true;
auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
out = std::copy(emphasis.begin(), emphasis.end(), out);
}
if (ts.has_foreground()) {
has_style = true;
auto foreground =
detail::make_foreground_color<Char>(ts.get_foreground());
out = std::copy(foreground.begin(), foreground.end(), out);
}
if (ts.has_background()) {
has_style = true;
auto background =
detail::make_background_color<Char>(ts.get_background());
out = std::copy(background.begin(), background.end(), out);
}
out = formatter<T, Char>::format(value, ctx);
if (has_style) {
auto reset_color = string_view("\x1b[0m");
out = std::copy(reset_color.begin(), reset_color.end(), out);
}
return out;
}
};
/**
\rst
Returns an argument that will be formatted using ANSI escape sequences,
to be used in a formatting function.
**Example**::
fmt::print("Elapsed time: {s:.2f} seconds",
fmt::styled(1.23, fmt::fg(fmt::color::green) | fmt::bg(fmt::color::blue)));
\endrst
*/
template <typename T>
FMT_CONSTEXPR auto styled(const T& value, text_style ts)
-> detail::styled_arg<remove_cvref_t<T>> {
return detail::styled_arg<remove_cvref_t<T>>{value, ts};
}
FMT_MODULE_EXPORT_END
FMT_END_NAMESPACE
#endif // FMT_COLOR_H_

602
external/fmt/include/fmt/compile.h vendored Normal file
View File

@ -0,0 +1,602 @@
// Formatting library for C++ - experimental format string compilation
//
// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_COMPILE_H_
#define FMT_COMPILE_H_
#include "format.h"
FMT_BEGIN_NAMESPACE
namespace detail {
template <typename Char, typename InputIt>
inline counting_iterator copy_str(InputIt begin, InputIt end,
counting_iterator it) {
return it + (end - begin);
}
template <typename OutputIt> class truncating_iterator_base {
protected:
OutputIt out_;
size_t limit_;
size_t count_ = 0;
truncating_iterator_base() : out_(), limit_(0) {}
truncating_iterator_base(OutputIt out, size_t limit)
: out_(out), limit_(limit) {}
public:
using iterator_category = std::output_iterator_tag;
using value_type = typename std::iterator_traits<OutputIt>::value_type;
using difference_type = std::ptrdiff_t;
using pointer = void;
using reference = void;
FMT_UNCHECKED_ITERATOR(truncating_iterator_base);
OutputIt base() const { return out_; }
size_t count() const { return count_; }
};
// An output iterator that truncates the output and counts the number of objects
// written to it.
template <typename OutputIt,
typename Enable = typename std::is_void<
typename std::iterator_traits<OutputIt>::value_type>::type>
class truncating_iterator;
template <typename OutputIt>
class truncating_iterator<OutputIt, std::false_type>
: public truncating_iterator_base<OutputIt> {
mutable typename truncating_iterator_base<OutputIt>::value_type blackhole_;
public:
using value_type = typename truncating_iterator_base<OutputIt>::value_type;
truncating_iterator() = default;
truncating_iterator(OutputIt out, size_t limit)
: truncating_iterator_base<OutputIt>(out, limit) {}
truncating_iterator& operator++() {
if (this->count_++ < this->limit_) ++this->out_;
return *this;
}
truncating_iterator operator++(int) {
auto it = *this;
++*this;
return it;
}
value_type& operator*() const {
return this->count_ < this->limit_ ? *this->out_ : blackhole_;
}
};
template <typename OutputIt>
class truncating_iterator<OutputIt, std::true_type>
: public truncating_iterator_base<OutputIt> {
public:
truncating_iterator() = default;
truncating_iterator(OutputIt out, size_t limit)
: truncating_iterator_base<OutputIt>(out, limit) {}
template <typename T> truncating_iterator& operator=(T val) {
if (this->count_++ < this->limit_) *this->out_++ = val;
return *this;
}
truncating_iterator& operator++() { return *this; }
truncating_iterator& operator++(int) { return *this; }
truncating_iterator& operator*() { return *this; }
};
// A compile-time string which is compiled into fast formatting code.
class compiled_string {};
template <typename S>
struct is_compiled_string : std::is_base_of<compiled_string, S> {};
/**
\rst
Converts a string literal *s* into a format string that will be parsed at
compile time and converted into efficient formatting code. Requires C++17
``constexpr if`` compiler support.
**Example**::
// Converts 42 into std::string using the most efficient method and no
// runtime format string processing.
std::string s = fmt::format(FMT_COMPILE("{}"), 42);
\endrst
*/
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
# define FMT_COMPILE(s) \
FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit)
#else
# define FMT_COMPILE(s) FMT_STRING(s)
#endif
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
template <typename Char, size_t N,
fmt::detail_exported::fixed_string<Char, N> Str>
struct udl_compiled_string : compiled_string {
using char_type = Char;
explicit constexpr operator basic_string_view<char_type>() const {
return {Str.data, N - 1};
}
};
#endif
template <typename T, typename... Tail>
const T& first(const T& value, const Tail&...) {
return value;
}
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
template <typename... Args> struct type_list {};
// Returns a reference to the argument at index N from [first, rest...].
template <int N, typename T, typename... Args>
constexpr const auto& get([[maybe_unused]] const T& first,
[[maybe_unused]] const Args&... rest) {
static_assert(N < 1 + sizeof...(Args), "index is out of bounds");
if constexpr (N == 0)
return first;
else
return detail::get<N - 1>(rest...);
}
template <typename Char, typename... Args>
constexpr int get_arg_index_by_name(basic_string_view<Char> name,
type_list<Args...>) {
return get_arg_index_by_name<Args...>(name);
}
template <int N, typename> struct get_type_impl;
template <int N, typename... Args> struct get_type_impl<N, type_list<Args...>> {
using type =
remove_cvref_t<decltype(detail::get<N>(std::declval<Args>()...))>;
};
template <int N, typename T>
using get_type = typename get_type_impl<N, T>::type;
template <typename T> struct is_compiled_format : std::false_type {};
template <typename Char> struct text {
basic_string_view<Char> data;
using char_type = Char;
template <typename OutputIt, typename... Args>
constexpr OutputIt format(OutputIt out, const Args&...) const {
return write<Char>(out, data);
}
};
template <typename Char>
struct is_compiled_format<text<Char>> : std::true_type {};
template <typename Char>
constexpr text<Char> make_text(basic_string_view<Char> s, size_t pos,
size_t size) {
return {{&s[pos], size}};
}
template <typename Char> struct code_unit {
Char value;
using char_type = Char;
template <typename OutputIt, typename... Args>
constexpr OutputIt format(OutputIt out, const Args&...) const {
return write<Char>(out, value);
}
};
// This ensures that the argument type is convertible to `const T&`.
template <typename T, int N, typename... Args>
constexpr const T& get_arg_checked(const Args&... args) {
const auto& arg = detail::get<N>(args...);
if constexpr (detail::is_named_arg<remove_cvref_t<decltype(arg)>>()) {
return arg.value;
} else {
return arg;
}
}
template <typename Char>
struct is_compiled_format<code_unit<Char>> : std::true_type {};
// A replacement field that refers to argument N.
template <typename Char, typename T, int N> struct field {
using char_type = Char;
template <typename OutputIt, typename... Args>
constexpr OutputIt format(OutputIt out, const Args&... args) const {
return write<Char>(out, get_arg_checked<T, N>(args...));
}
};
template <typename Char, typename T, int N>
struct is_compiled_format<field<Char, T, N>> : std::true_type {};
// A replacement field that refers to argument with name.
template <typename Char> struct runtime_named_field {
using char_type = Char;
basic_string_view<Char> name;
template <typename OutputIt, typename T>
constexpr static bool try_format_argument(
OutputIt& out,
// [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9
[[maybe_unused]] basic_string_view<Char> arg_name, const T& arg) {
if constexpr (is_named_arg<typename std::remove_cv<T>::type>::value) {
if (arg_name == arg.name) {
out = write<Char>(out, arg.value);
return true;
}
}
return false;
}
template <typename OutputIt, typename... Args>
constexpr OutputIt format(OutputIt out, const Args&... args) const {
bool found = (try_format_argument(out, name, args) || ...);
if (!found) {
FMT_THROW(format_error("argument with specified name is not found"));
}
return out;
}
};
template <typename Char>
struct is_compiled_format<runtime_named_field<Char>> : std::true_type {};
// A replacement field that refers to argument N and has format specifiers.
template <typename Char, typename T, int N> struct spec_field {
using char_type = Char;
formatter<T, Char> fmt;
template <typename OutputIt, typename... Args>
constexpr FMT_INLINE OutputIt format(OutputIt out,
const Args&... args) const {
const auto& vargs =
fmt::make_format_args<basic_format_context<OutputIt, Char>>(args...);
basic_format_context<OutputIt, Char> ctx(out, vargs);
return fmt.format(get_arg_checked<T, N>(args...), ctx);
}
};
template <typename Char, typename T, int N>
struct is_compiled_format<spec_field<Char, T, N>> : std::true_type {};
template <typename L, typename R> struct concat {
L lhs;
R rhs;
using char_type = typename L::char_type;
template <typename OutputIt, typename... Args>
constexpr OutputIt format(OutputIt out, const Args&... args) const {
out = lhs.format(out, args...);
return rhs.format(out, args...);
}
};
template <typename L, typename R>
struct is_compiled_format<concat<L, R>> : std::true_type {};
template <typename L, typename R>
constexpr concat<L, R> make_concat(L lhs, R rhs) {
return {lhs, rhs};
}
struct unknown_format {};
template <typename Char>
constexpr size_t parse_text(basic_string_view<Char> str, size_t pos) {
for (size_t size = str.size(); pos != size; ++pos) {
if (str[pos] == '{' || str[pos] == '}') break;
}
return pos;
}
template <typename Args, size_t POS, int ID, typename S>
constexpr auto compile_format_string(S format_str);
template <typename Args, size_t POS, int ID, typename T, typename S>
constexpr auto parse_tail(T head, S format_str) {
if constexpr (POS !=
basic_string_view<typename S::char_type>(format_str).size()) {
constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,
unknown_format>())
return tail;
else
return make_concat(head, tail);
} else {
return head;
}
}
template <typename T, typename Char> struct parse_specs_result {
formatter<T, Char> fmt;
size_t end;
int next_arg_id;
};
constexpr int manual_indexing_id = -1;
template <typename T, typename Char>
constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
size_t pos, int next_arg_id) {
str.remove_prefix(pos);
auto ctx = basic_format_parse_context<Char>(str, {}, next_arg_id);
auto f = formatter<T, Char>();
auto end = f.parse(ctx);
return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1,
next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()};
}
template <typename Char> struct arg_id_handler {
arg_ref<Char> arg_id;
constexpr int operator()() {
FMT_ASSERT(false, "handler cannot be used with automatic indexing");
return 0;
}
constexpr int operator()(int id) {
arg_id = arg_ref<Char>(id);
return 0;
}
constexpr int operator()(basic_string_view<Char> id) {
arg_id = arg_ref<Char>(id);
return 0;
}
constexpr void on_error(const char* message) {
FMT_THROW(format_error(message));
}
};
template <typename Char> struct parse_arg_id_result {
arg_ref<Char> arg_id;
const Char* arg_id_end;
};
template <int ID, typename Char>
constexpr auto parse_arg_id(const Char* begin, const Char* end) {
auto handler = arg_id_handler<Char>{arg_ref<Char>{}};
auto arg_id_end = parse_arg_id(begin, end, handler);
return parse_arg_id_result<Char>{handler.arg_id, arg_id_end};
}
template <typename T, typename Enable = void> struct field_type {
using type = remove_cvref_t<T>;
};
template <typename T>
struct field_type<T, enable_if_t<detail::is_named_arg<T>::value>> {
using type = remove_cvref_t<decltype(T::value)>;
};
template <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID,
typename S>
constexpr auto parse_replacement_field_then_tail(S format_str) {
using char_type = typename S::char_type;
constexpr auto str = basic_string_view<char_type>(format_str);
constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type();
if constexpr (c == '}') {
return parse_tail<Args, END_POS + 1, NEXT_ID>(
field<char_type, typename field_type<T>::type, ARG_INDEX>(),
format_str);
} else if constexpr (c == ':') {
constexpr auto result = parse_specs<typename field_type<T>::type>(
str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID);
return parse_tail<Args, result.end, result.next_arg_id>(
spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
result.fmt},
format_str);
}
}
// Compiles a non-empty format string and returns the compiled representation
// or unknown_format() on unrecognized input.
template <typename Args, size_t POS, int ID, typename S>
constexpr auto compile_format_string(S format_str) {
using char_type = typename S::char_type;
constexpr auto str = basic_string_view<char_type>(format_str);
if constexpr (str[POS] == '{') {
if constexpr (POS + 1 == str.size())
FMT_THROW(format_error("unmatched '{' in format string"));
if constexpr (str[POS + 1] == '{') {
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
} else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') {
static_assert(ID != manual_indexing_id,
"cannot switch from manual to automatic argument indexing");
constexpr auto next_id =
ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
return parse_replacement_field_then_tail<get_type<ID, Args>, Args,
POS + 1, ID, next_id>(
format_str);
} else {
constexpr auto arg_id_result =
parse_arg_id<ID>(str.data() + POS + 1, str.data() + str.size());
constexpr auto arg_id_end_pos = arg_id_result.arg_id_end - str.data();
constexpr char_type c =
arg_id_end_pos != str.size() ? str[arg_id_end_pos] : char_type();
static_assert(c == '}' || c == ':', "missing '}' in format string");
if constexpr (arg_id_result.arg_id.kind == arg_id_kind::index) {
static_assert(
ID == manual_indexing_id || ID == 0,
"cannot switch from automatic to manual argument indexing");
constexpr auto arg_index = arg_id_result.arg_id.val.index;
return parse_replacement_field_then_tail<get_type<arg_index, Args>,
Args, arg_id_end_pos,
arg_index, manual_indexing_id>(
format_str);
} else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) {
constexpr auto arg_index =
get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{});
if constexpr (arg_index != invalid_arg_index) {
constexpr auto next_id =
ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
return parse_replacement_field_then_tail<
decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos,
arg_index, next_id>(format_str);
} else {
if constexpr (c == '}') {
return parse_tail<Args, arg_id_end_pos + 1, ID>(
runtime_named_field<char_type>{arg_id_result.arg_id.val.name},
format_str);
} else if constexpr (c == ':') {
return unknown_format(); // no type info for specs parsing
}
}
}
}
} else if constexpr (str[POS] == '}') {
if constexpr (POS + 1 == str.size())
FMT_THROW(format_error("unmatched '}' in format string"));
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
} else {
constexpr auto end = parse_text(str, POS + 1);
if constexpr (end - POS > 1) {
return parse_tail<Args, end, ID>(make_text(str, POS, end - POS),
format_str);
} else {
return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]},
format_str);
}
}
}
template <typename... Args, typename S,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
constexpr auto compile(S format_str) {
constexpr auto str = basic_string_view<typename S::char_type>(format_str);
if constexpr (str.size() == 0) {
return detail::make_text(str, 0, 0);
} else {
constexpr auto result =
detail::compile_format_string<detail::type_list<Args...>, 0, 0>(
format_str);
return result;
}
}
#endif // defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
} // namespace detail
FMT_MODULE_EXPORT_BEGIN
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
template <typename CompiledFormat, typename... Args,
typename Char = typename CompiledFormat::char_type,
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,
const Args&... args) {
auto s = std::basic_string<Char>();
cf.format(std::back_inserter(s), args...);
return s;
}
template <typename OutputIt, typename CompiledFormat, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf,
const Args&... args) {
return cf.format(out, args...);
}
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
Args&&... args) {
if constexpr (std::is_same<typename S::char_type, char>::value) {
constexpr auto str = basic_string_view<typename S::char_type>(S());
if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') {
const auto& first = detail::first(args...);
if constexpr (detail::is_named_arg<
remove_cvref_t<decltype(first)>>::value) {
return fmt::to_string(first.value);
} else {
return fmt::to_string(first);
}
}
}
constexpr auto compiled = detail::compile<Args...>(S());
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
detail::unknown_format>()) {
return fmt::format(
static_cast<basic_string_view<typename S::char_type>>(S()),
std::forward<Args>(args)...);
} else {
return fmt::format(compiled, std::forward<Args>(args)...);
}
}
template <typename OutputIt, typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) {
constexpr auto compiled = detail::compile<Args...>(S());
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
detail::unknown_format>()) {
return fmt::format_to(
out, static_cast<basic_string_view<typename S::char_type>>(S()),
std::forward<Args>(args)...);
} else {
return fmt::format_to(out, compiled, std::forward<Args>(args)...);
}
}
#endif
template <typename OutputIt, typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
const S& format_str, Args&&... args) {
auto it = fmt::format_to(detail::truncating_iterator<OutputIt>(out, n),
format_str, std::forward<Args>(args)...);
return {it.base(), it.count()};
}
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
size_t formatted_size(const S& format_str, const Args&... args) {
return fmt::format_to(detail::counting_iterator(), format_str, args...)
.count();
}
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
void print(std::FILE* f, const S& format_str, const Args&... args) {
memory_buffer buffer;
fmt::format_to(std::back_inserter(buffer), format_str, args...);
detail::print(f, {buffer.data(), buffer.size()});
}
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
void print(const S& format_str, const Args&... args) {
print(stdout, format_str, args...);
}
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
inline namespace literals {
template <detail_exported::fixed_string Str> constexpr auto operator""_cf() {
using char_t = remove_cvref_t<decltype(Str.data[0])>;
return detail::udl_compiled_string<char_t, sizeof(Str.data) / sizeof(char_t),
Str>();
}
} // namespace literals
#endif
FMT_MODULE_EXPORT_END
FMT_END_NAMESPACE
#endif // FMT_COMPILE_H_

3285
external/fmt/include/fmt/core.h vendored Normal file

File diff suppressed because it is too large Load Diff

2594
external/fmt/include/fmt/format-inl.h vendored Normal file

File diff suppressed because it is too large Load Diff

3444
external/fmt/include/fmt/format.h vendored Normal file

File diff suppressed because it is too large Load Diff

2
external/fmt/include/fmt/locale.h vendored Normal file
View File

@ -0,0 +1,2 @@
#include "xchar.h"
#warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead

481
external/fmt/include/fmt/os.h vendored Normal file
View File

@ -0,0 +1,481 @@
// Formatting library for C++ - optional OS-specific functionality
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_OS_H_
#define FMT_OS_H_
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <system_error> // std::system_error
#if defined __APPLE__ || defined(__FreeBSD__)
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif
#include "format.h"
#ifndef FMT_USE_FCNTL
// UWP doesn't provide _pipe.
# if FMT_HAS_INCLUDE("winapifamily.h")
# include <winapifamily.h>
# endif
# if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
defined(__linux__)) && \
(!defined(WINAPI_FAMILY) || \
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
# include <fcntl.h> // for O_RDONLY
# define FMT_USE_FCNTL 1
# else
# define FMT_USE_FCNTL 0
# endif
#endif
#ifndef FMT_POSIX
# if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
# define FMT_POSIX(call) _##call
# else
# define FMT_POSIX(call) call
# endif
#endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
# define FMT_SYSTEM(call) ::call
# ifdef _WIN32
// Fix warnings about deprecated symbols.
# define FMT_POSIX_CALL(call) ::_##call
# else
# define FMT_POSIX_CALL(call) ::call
# endif
#endif
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
#ifndef _WIN32
# define FMT_RETRY_VAL(result, expression, error_result) \
do { \
(result) = (expression); \
} while ((result) == (error_result) && errno == EINTR)
#else
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
FMT_BEGIN_NAMESPACE
FMT_MODULE_EXPORT_BEGIN
/**
\rst
A reference to a null-terminated string. It can be constructed from a C
string or ``std::string``.
You can use one of the following type aliases for common character types:
+---------------+-----------------------------+
| Type | Definition |
+===============+=============================+
| cstring_view | basic_cstring_view<char> |
+---------------+-----------------------------+
| wcstring_view | basic_cstring_view<wchar_t> |
+---------------+-----------------------------+
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
template <typename... Args>
std::string format(cstring_view format_str, const Args & ... args);
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
template <typename Char> class basic_cstring_view {
private:
const Char* data_;
public:
/** Constructs a string reference object from a C string. */
basic_cstring_view(const Char* s) : data_(s) {}
/**
\rst
Constructs a string reference from an ``std::string`` object.
\endrst
*/
basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
/** Returns the pointer to a C string. */
const Char* c_str() const { return data_; }
};
using cstring_view = basic_cstring_view<char>;
using wcstring_view = basic_cstring_view<wchar_t>;
template <typename Char> struct formatter<std::error_code, Char> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename FormatContext>
FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const
-> decltype(ctx.out()) {
auto out = ctx.out();
out = detail::write_bytes(out, ec.category().name(),
basic_format_specs<Char>());
out = detail::write<Char>(out, Char(':'));
out = detail::write<Char>(out, ec.value());
return out;
}
};
#ifdef _WIN32
FMT_API const std::error_category& system_category() noexcept;
FMT_BEGIN_DETAIL_NAMESPACE
// A converter from UTF-16 to UTF-8.
// It is only provided for Windows since other systems support UTF-8 natively.
class utf16_to_utf8 {
private:
memory_buffer buffer_;
public:
utf16_to_utf8() {}
FMT_API explicit utf16_to_utf8(basic_string_view<wchar_t> s);
operator string_view() const { return string_view(&buffer_[0], size()); }
size_t size() const { return buffer_.size() - 1; }
const char* c_str() const { return &buffer_[0]; }
std::string str() const { return std::string(&buffer_[0], size()); }
// Performs conversion returning a system error code instead of
// throwing exception on conversion error. This method may still throw
// in case of memory allocation error.
FMT_API int convert(basic_string_view<wchar_t> s);
};
FMT_API void format_windows_error(buffer<char>& out, int error_code,
const char* message) noexcept;
FMT_END_DETAIL_NAMESPACE
FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
format_args args);
/**
\rst
Constructs a :class:`std::system_error` object with the description
of the form
.. parsed-literal::
*<message>*: *<system-message>*
where *<message>* is the formatted message and *<system-message>* is the
system message corresponding to the error code.
*error_code* is a Windows error code as given by ``GetLastError``.
If *error_code* is not a valid error code such as -1, the system message
will look like "error -1".
**Example**::
// This throws a system_error with the description
// cannot open file 'madeup': The system cannot find the file specified.
// or similar (system message may vary).
const char *filename = "madeup";
LPOFSTRUCT of = LPOFSTRUCT();
HFILE file = OpenFile(filename, &of, OF_READ);
if (file == HFILE_ERROR) {
throw fmt::windows_error(GetLastError(),
"cannot open file '{}'", filename);
}
\endrst
*/
template <typename... Args>
std::system_error windows_error(int error_code, string_view message,
const Args&... args) {
return vwindows_error(error_code, message, fmt::make_format_args(args...));
}
// Reports a Windows error without throwing an exception.
// Can be used to report errors from destructors.
FMT_API void report_windows_error(int error_code, const char* message) noexcept;
#else
inline const std::error_category& system_category() noexcept {
return std::system_category();
}
#endif // _WIN32
// std::system is not available on some platforms such as iOS (#2248).
#ifdef __OSX__
template <typename S, typename... Args, typename Char = char_t<S>>
void say(const S& format_str, Args&&... args) {
std::system(format("say \"{}\"", format(format_str, args...)).c_str());
}
#endif
// A buffered file.
class buffered_file {
private:
FILE* file_;
friend class file;
explicit buffered_file(FILE* f) : file_(f) {}
public:
buffered_file(const buffered_file&) = delete;
void operator=(const buffered_file&) = delete;
// Constructs a buffered_file object which doesn't represent any file.
buffered_file() noexcept : file_(nullptr) {}
// Destroys the object closing the file it represents if any.
FMT_API ~buffered_file() noexcept;
public:
buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
other.file_ = nullptr;
}
buffered_file& operator=(buffered_file&& other) {
close();
file_ = other.file_;
other.file_ = nullptr;
return *this;
}
// Opens a file.
FMT_API buffered_file(cstring_view filename, cstring_view mode);
// Closes the file.
FMT_API void close();
// Returns the pointer to a FILE object representing this file.
FILE* get() const noexcept { return file_; }
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
// DEPRECATED! Rename to descriptor to avoid issues with macros.
FMT_API int(fileno)() const;
void vprint(string_view format_str, format_args args) {
fmt::vprint(file_, format_str, args);
}
template <typename... Args>
inline void print(string_view format_str, const Args&... args) {
vprint(format_str, fmt::make_format_args(args...));
}
};
#if FMT_USE_FCNTL
// A file. Closed file is represented by a file object with descriptor -1.
// Methods that are not declared with noexcept may throw
// fmt::system_error in case of failure. Note that some errors such as
// closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler.
class FMT_API file {
private:
int fd_; // File descriptor.
// Constructs a file object with a given descriptor.
explicit file(int fd) : fd_(fd) {}
public:
// Possible values for the oflag argument to the constructor.
enum {
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist.
APPEND = FMT_POSIX(O_APPEND), // Open in append mode.
TRUNC = FMT_POSIX(O_TRUNC) // Truncate the content of the file.
};
// Constructs a file object which doesn't represent any file.
file() noexcept : fd_(-1) {}
// Opens a file and constructs a file object representing this file.
file(cstring_view path, int oflag);
public:
file(const file&) = delete;
void operator=(const file&) = delete;
file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
// Move assignment is not noexcept because close may throw.
file& operator=(file&& other) {
close();
fd_ = other.fd_;
other.fd_ = -1;
return *this;
}
// Destroys the object closing the file it represents if any.
~file() noexcept;
// Returns the file descriptor.
int descriptor() const noexcept { return fd_; }
// Closes the file.
void close();
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
long long size() const;
// Attempts to read count bytes from the file into the specified buffer.
size_t read(void* buffer, size_t count);
// Attempts to write count bytes from the specified buffer to the file.
size_t write(const void* buffer, size_t count);
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
static file dup(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd, std::error_code& ec) noexcept;
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
static void pipe(file& read_end, file& write_end);
// Creates a buffered_file object associated with this file and detaches
// this file object from the file.
buffered_file fdopen(const char* mode);
};
// Returns the memory page size.
long getpagesize();
FMT_BEGIN_DETAIL_NAMESPACE
struct buffer_size {
buffer_size() = default;
size_t value = 0;
buffer_size operator=(size_t val) const {
auto bs = buffer_size();
bs.value = val;
return bs;
}
};
struct ostream_params {
int oflag = file::WRONLY | file::CREATE | file::TRUNC;
size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
ostream_params() {}
template <typename... T>
ostream_params(T... params, int new_oflag) : ostream_params(params...) {
oflag = new_oflag;
}
template <typename... T>
ostream_params(T... params, detail::buffer_size bs)
: ostream_params(params...) {
this->buffer_size = bs.value;
}
// Intel has a bug that results in failure to deduce a constructor
// for empty parameter packs.
# if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000
ostream_params(int new_oflag) : oflag(new_oflag) {}
ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {}
# endif
};
FMT_END_DETAIL_NAMESPACE
// Added {} below to work around default constructor error known to
// occur in Xcode versions 7.2.1 and 8.2.1.
constexpr detail::buffer_size buffer_size{};
/** A fast output stream which is not thread-safe. */
class FMT_API ostream final : private detail::buffer<char> {
private:
file file_;
void grow(size_t) override;
ostream(cstring_view path, const detail::ostream_params& params)
: file_(path, params.oflag) {
set(new char[params.buffer_size], params.buffer_size);
}
public:
ostream(ostream&& other)
: detail::buffer<char>(other.data(), other.size(), other.capacity()),
file_(std::move(other.file_)) {
other.clear();
other.set(nullptr, 0);
}
~ostream() {
flush();
delete[] data();
}
void flush() {
if (size() == 0) return;
file_.write(data(), size());
clear();
}
template <typename... T>
friend ostream output_file(cstring_view path, T... params);
void close() {
flush();
file_.close();
}
/**
Formats ``args`` according to specifications in ``fmt`` and writes the
output to the file.
*/
template <typename... T> void print(format_string<T...> fmt, T&&... args) {
vformat_to(detail::buffer_appender<char>(*this), fmt,
fmt::make_format_args(args...));
}
};
/**
\rst
Opens a file for writing. Supported parameters passed in *params*:
* ``<integer>``: Flags passed to `open
<https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html>`_
(``file::WRONLY | file::CREATE | file::TRUNC`` by default)
* ``buffer_size=<integer>``: Output buffer size
**Example**::
auto out = fmt::output_file("guide.txt");
out.print("Don't {}", "Panic");
\endrst
*/
template <typename... T>
inline ostream output_file(cstring_view path, T... params) {
return {path, detail::ostream_params(params...)};
}
#endif // FMT_USE_FCNTL
FMT_MODULE_EXPORT_END
FMT_END_NAMESPACE
#endif // FMT_OS_H_

193
external/fmt/include/fmt/ostream.h vendored Normal file
View File

@ -0,0 +1,193 @@
// Formatting library for C++ - std::ostream support
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_OSTREAM_H_
#define FMT_OSTREAM_H_
#include <fstream>
#include <ostream>
#include "format.h"
FMT_BEGIN_NAMESPACE
template <typename OutputIt, typename Char> class basic_printf_context;
namespace detail {
// Checks if T has a user-defined operator<<.
template <typename T, typename Char, typename Enable = void>
class is_streamable {
private:
template <typename U>
static auto test(int)
-> bool_constant<sizeof(std::declval<std::basic_ostream<Char>&>()
<< std::declval<U>()) != 0>;
template <typename> static auto test(...) -> std::false_type;
using result = decltype(test<T>(0));
public:
is_streamable() = default;
static const bool value = result::value;
};
// Formatting of built-in types and arrays is intentionally disabled because
// it's handled by standard (non-ostream) formatters.
template <typename T, typename Char>
struct is_streamable<
T, Char,
enable_if_t<
std::is_arithmetic<T>::value || std::is_array<T>::value ||
std::is_pointer<T>::value || std::is_same<T, char8_type>::value ||
std::is_convertible<T, fmt::basic_string_view<Char>>::value ||
std::is_same<T, std_string_view<Char>>::value ||
(std::is_convertible<T, int>::value && !std::is_enum<T>::value)>>
: std::false_type {};
template <typename Char> FILE* get_file(std::basic_filebuf<Char>&) {
return nullptr;
}
struct dummy_filebuf {
FILE* _Myfile;
};
template <typename T, typename U = int> struct ms_filebuf {
using type = dummy_filebuf;
};
template <typename T> struct ms_filebuf<T, decltype(T::_Myfile, 0)> {
using type = T;
};
using filebuf_type = ms_filebuf<std::filebuf>::type;
FILE* get_file(filebuf_type& buf);
// Generate a unique explicit instantion in every translation unit using a tag
// type in an anonymous namespace.
namespace {
struct filebuf_access_tag {};
} // namespace
template <typename Tag, typename FileMemberPtr, FileMemberPtr file>
class filebuf_access {
friend FILE* get_file(filebuf_type& buf) { return buf.*file; }
};
template class filebuf_access<filebuf_access_tag,
decltype(&filebuf_type::_Myfile),
&filebuf_type::_Myfile>;
inline bool write(std::filebuf& buf, fmt::string_view data) {
print(get_file(buf), data);
return true;
}
inline bool write(std::wfilebuf&, fmt::basic_string_view<wchar_t>) {
return false;
}
// Write the content of buf to os.
// It is a separate function rather than a part of vprint to simplify testing.
template <typename Char>
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
if (const_check(FMT_MSC_VER)) {
auto filebuf = dynamic_cast<std::basic_filebuf<Char>*>(os.rdbuf());
if (filebuf && write(*filebuf, {buf.data(), buf.size()})) return;
}
const Char* buf_data = buf.data();
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
unsigned_streamsize size = buf.size();
unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
do {
unsigned_streamsize n = size <= max_size ? size : max_size;
os.write(buf_data, static_cast<std::streamsize>(n));
buf_data += n;
size -= n;
} while (size != 0);
}
template <typename Char, typename T>
void format_value(buffer<Char>& buf, const T& value,
locale_ref loc = locale_ref()) {
auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
auto&& output = std::basic_ostream<Char>(&format_buf);
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
if (loc) output.imbue(loc.get<std::locale>());
#endif
output << value;
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
}
} // namespace detail
// Formats an object of type T that has an overloaded ostream operator<<.
template <typename Char>
struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
template <typename T, typename OutputIt>
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) const
-> OutputIt {
auto buffer = basic_memory_buffer<Char>();
format_value(buffer, value, ctx.locale());
return formatter<basic_string_view<Char>, Char>::format(
{buffer.data(), buffer.size()}, ctx);
}
};
using ostream_formatter = basic_ostream_formatter<char>;
namespace detail {
// Formats an object of type T that has an overloaded ostream operator<<.
template <typename T, typename Char>
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
: basic_ostream_formatter<Char> {
using basic_ostream_formatter<Char>::format;
// DEPRECATED!
template <typename OutputIt>
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx) const
-> OutputIt {
auto buffer = basic_memory_buffer<Char>();
format_value(buffer, value, ctx.locale());
return std::copy(buffer.begin(), buffer.end(), ctx.out());
}
};
} // namespace detail
FMT_MODULE_EXPORT
template <typename Char>
void vprint(std::basic_ostream<Char>& os,
basic_string_view<type_identity_t<Char>> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
auto buffer = basic_memory_buffer<Char>();
detail::vformat_to(buffer, format_str, args);
detail::write_buffer(os, buffer);
}
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fmt::print(cerr, "Don't {}!", "panic");
\endrst
*/
FMT_MODULE_EXPORT
template <typename... T>
void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
vprint(os, fmt, fmt::make_format_args(args...));
}
FMT_MODULE_EXPORT
template <typename... Args>
void print(std::wostream& os,
basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
Args&&... args) {
vprint(os, fmt, fmt::make_format_args<buffer_context<wchar_t>>(args...));
}
FMT_END_NAMESPACE
#endif // FMT_OSTREAM_H_

657
external/fmt/include/fmt/printf.h vendored Normal file
View File

@ -0,0 +1,657 @@
// Formatting library for C++ - legacy printf implementation
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::max
#include <limits> // std::numeric_limits
#include <ostream>
#include "format.h"
FMT_BEGIN_NAMESPACE
FMT_MODULE_EXPORT_BEGIN
template <typename T> struct printf_formatter { printf_formatter() = delete; };
template <typename Char>
class basic_printf_parse_context : public basic_format_parse_context<Char> {
using basic_format_parse_context<Char>::basic_format_parse_context;
};
template <typename OutputIt, typename Char> class basic_printf_context {
private:
OutputIt out_;
basic_format_args<basic_printf_context> args_;
public:
using char_type = Char;
using format_arg = basic_format_arg<basic_printf_context>;
using parse_context_type = basic_printf_parse_context<Char>;
template <typename T> using formatter_type = printf_formatter<T>;
/**
\rst
Constructs a ``printf_context`` object. References to the arguments are
stored in the context object so make sure they have appropriate lifetimes.
\endrst
*/
basic_printf_context(OutputIt out,
basic_format_args<basic_printf_context> args)
: out_(out), args_(args) {}
OutputIt out() { return out_; }
void advance_to(OutputIt it) { out_ = it; }
detail::locale_ref locale() { return {}; }
format_arg arg(int id) const { return args_.get(id); }
FMT_CONSTEXPR void on_error(const char* message) {
detail::error_handler().on_error(message);
}
};
FMT_BEGIN_DETAIL_NAMESPACE
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template <bool IsSigned> struct int_checker {
template <typename T> static bool fits_in_int(T value) {
unsigned max = max_value<int>();
return value <= max;
}
static bool fits_in_int(bool) { return true; }
};
template <> struct int_checker<true> {
template <typename T> static bool fits_in_int(T value) {
return value >= (std::numeric_limits<int>::min)() &&
value <= max_value<int>();
}
static bool fits_in_int(int) { return true; }
};
class printf_precision_handler {
public:
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
int operator()(T value) {
if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(format_error("number is too big"));
return (std::max)(static_cast<int>(value), 0);
}
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
int operator()(T) {
FMT_THROW(format_error("precision is not integer"));
return 0;
}
};
// An argument visitor that returns true iff arg is a zero integer.
class is_zero_int {
public:
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
bool operator()(T value) {
return value == 0;
}
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
bool operator()(T) {
return false;
}
};
template <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {};
template <> struct make_unsigned_or_bool<bool> { using type = bool; };
template <typename T, typename Context> class arg_converter {
private:
using char_type = typename Context::char_type;
basic_format_arg<Context>& arg_;
char_type type_;
public:
arg_converter(basic_format_arg<Context>& arg, char_type type)
: arg_(arg), type_(type) {}
void operator()(bool value) {
if (type_ != 's') operator()<bool>(value);
}
template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)>
void operator()(U value) {
bool is_signed = type_ == 'd' || type_ == 'i';
using target_type = conditional_t<std::is_same<T, void>::value, U, T>;
if (const_check(sizeof(target_type) <= sizeof(int))) {
// Extra casts are used to silence warnings.
if (is_signed) {
arg_ = detail::make_arg<Context>(
static_cast<int>(static_cast<target_type>(value)));
} else {
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
arg_ = detail::make_arg<Context>(
static_cast<unsigned>(static_cast<unsigned_type>(value)));
}
} else {
if (is_signed) {
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_ = detail::make_arg<Context>(static_cast<long long>(value));
} else {
arg_ = detail::make_arg<Context>(
static_cast<typename make_unsigned_or_bool<U>::type>(value));
}
}
}
template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::value)>
void operator()(U) {} // No conversion needed for non-integral types.
};
// Converts an integer argument to T for printf, if T is an integral type.
// If T is void, the argument is converted to corresponding signed or unsigned
// type depending on the type specifier: 'd' and 'i' - signed, other -
// unsigned).
template <typename T, typename Context, typename Char>
void convert_arg(basic_format_arg<Context>& arg, Char type) {
visit_format_arg(arg_converter<T, Context>(arg, type), arg);
}
// Converts an integer argument to char for printf.
template <typename Context> class char_converter {
private:
basic_format_arg<Context>& arg_;
public:
explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {}
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
void operator()(T value) {
arg_ = detail::make_arg<Context>(
static_cast<typename Context::char_type>(value));
}
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
void operator()(T) {} // No conversion needed for non-integral types.
};
// An argument visitor that return a pointer to a C string if argument is a
// string or null otherwise.
template <typename Char> struct get_cstring {
template <typename T> const Char* operator()(T) { return nullptr; }
const Char* operator()(const Char* s) { return s; }
};
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
template <typename Char> class printf_width_handler {
private:
using format_specs = basic_format_specs<Char>;
format_specs& specs_;
public:
explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
unsigned operator()(T value) {
auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
if (detail::is_negative(value)) {
specs_.align = align::left;
width = 0 - width;
}
unsigned int_max = max_value<int>();
if (width > int_max) FMT_THROW(format_error("number is too big"));
return static_cast<unsigned>(width);
}
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
unsigned operator()(T) {
FMT_THROW(format_error("width is not integer"));
return 0;
}
};
// The ``printf`` argument formatter.
template <typename OutputIt, typename Char>
class printf_arg_formatter : public arg_formatter<Char> {
private:
using base = arg_formatter<Char>;
using context_type = basic_printf_context<OutputIt, Char>;
using format_specs = basic_format_specs<Char>;
context_type& context_;
OutputIt write_null_pointer(bool is_string = false) {
auto s = this->specs;
s.type = presentation_type::none;
return write_bytes(this->out, is_string ? "(null)" : "(nil)", s);
}
public:
printf_arg_formatter(OutputIt iter, format_specs& s, context_type& ctx)
: base{iter, s, locale_ref()}, context_(ctx) {}
OutputIt operator()(monostate value) { return base::operator()(value); }
template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)>
OutputIt operator()(T value) {
// MSVC2013 fails to compile separate overloads for bool and Char so use
// std::is_same instead.
if (std::is_same<T, Char>::value) {
format_specs fmt_specs = this->specs;
if (fmt_specs.type != presentation_type::none &&
fmt_specs.type != presentation_type::chr) {
return (*this)(static_cast<int>(value));
}
fmt_specs.sign = sign::none;
fmt_specs.alt = false;
fmt_specs.fill[0] = ' '; // Ignore '0' flag for char types.
// align::numeric needs to be overwritten here since the '0' flag is
// ignored for non-numeric types
if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)
fmt_specs.align = align::right;
return write<Char>(this->out, static_cast<Char>(value), fmt_specs);
}
return base::operator()(value);
}
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
OutputIt operator()(T value) {
return base::operator()(value);
}
/** Formats a null-terminated C string. */
OutputIt operator()(const char* value) {
if (value) return base::operator()(value);
return write_null_pointer(this->specs.type != presentation_type::pointer);
}
/** Formats a null-terminated wide C string. */
OutputIt operator()(const wchar_t* value) {
if (value) return base::operator()(value);
return write_null_pointer(this->specs.type != presentation_type::pointer);
}
OutputIt operator()(basic_string_view<Char> value) {
return base::operator()(value);
}
/** Formats a pointer. */
OutputIt operator()(const void* value) {
return value ? base::operator()(value) : write_null_pointer();
}
/** Formats an argument of a custom (user-defined) type. */
OutputIt operator()(typename basic_format_arg<context_type>::handle handle) {
auto parse_ctx =
basic_printf_parse_context<Char>(basic_string_view<Char>());
handle.format(parse_ctx, context_);
return this->out;
}
};
template <typename Char>
void parse_flags(basic_format_specs<Char>& specs, const Char*& it,
const Char* end) {
for (; it != end; ++it) {
switch (*it) {
case '-':
specs.align = align::left;
break;
case '+':
specs.sign = sign::plus;
break;
case '0':
specs.fill[0] = '0';
break;
case ' ':
if (specs.sign != sign::plus) {
specs.sign = sign::space;
}
break;
case '#':
specs.alt = true;
break;
default:
return;
}
}
}
template <typename Char, typename GetArg>
int parse_header(const Char*& it, const Char* end,
basic_format_specs<Char>& specs, GetArg get_arg) {
int arg_index = -1;
Char c = *it;
if (c >= '0' && c <= '9') {
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
int value = parse_nonnegative_int(it, end, -1);
if (it != end && *it == '$') { // value is an argument index
++it;
arg_index = value != -1 ? value : max_value<int>();
} else {
if (c == '0') specs.fill[0] = '0';
if (value != 0) {
// Nonzero value means that we parsed width and don't need to
// parse it or flags again, so return now.
if (value == -1) FMT_THROW(format_error("number is too big"));
specs.width = value;
return arg_index;
}
}
}
parse_flags(specs, it, end);
// Parse width.
if (it != end) {
if (*it >= '0' && *it <= '9') {
specs.width = parse_nonnegative_int(it, end, -1);
if (specs.width == -1) FMT_THROW(format_error("number is too big"));
} else if (*it == '*') {
++it;
specs.width = static_cast<int>(visit_format_arg(
detail::printf_width_handler<Char>(specs), get_arg(-1)));
}
}
return arg_index;
}
template <typename Char, typename Context>
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
basic_format_args<Context> args) {
using OutputIt = buffer_appender<Char>;
auto out = OutputIt(buf);
auto context = basic_printf_context<OutputIt, Char>(out, args);
auto parse_ctx = basic_printf_parse_context<Char>(format);
// Returns the argument with specified index or, if arg_index is -1, the next
// argument.
auto get_arg = [&](int arg_index) {
if (arg_index < 0)
arg_index = parse_ctx.next_arg_id();
else
parse_ctx.check_arg_id(--arg_index);
return detail::get_arg(context, arg_index);
};
const Char* start = parse_ctx.begin();
const Char* end = parse_ctx.end();
auto it = start;
while (it != end) {
if (!detail::find<false, Char>(it, end, '%', it)) {
it = end; // detail::find leaves it == nullptr if it doesn't find '%'
break;
}
Char c = *it++;
if (it != end && *it == c) {
out = detail::write(
out, basic_string_view<Char>(start, detail::to_unsigned(it - start)));
start = ++it;
continue;
}
out = detail::write(out, basic_string_view<Char>(
start, detail::to_unsigned(it - 1 - start)));
basic_format_specs<Char> specs;
specs.align = align::right;
// Parse argument index, flags and width.
int arg_index = parse_header(it, end, specs, get_arg);
if (arg_index == 0) parse_ctx.on_error("argument not found");
// Parse precision.
if (it != end && *it == '.') {
++it;
c = it != end ? *it : 0;
if ('0' <= c && c <= '9') {
specs.precision = parse_nonnegative_int(it, end, 0);
} else if (c == '*') {
++it;
specs.precision = static_cast<int>(
visit_format_arg(detail::printf_precision_handler(), get_arg(-1)));
} else {
specs.precision = 0;
}
}
auto arg = get_arg(arg_index);
// For d, i, o, u, x, and X conversion specifiers, if a precision is
// specified, the '0' flag is ignored
if (specs.precision >= 0 && arg.is_integral())
specs.fill[0] =
' '; // Ignore '0' flag for non-numeric types or if '-' present.
if (specs.precision >= 0 && arg.type() == detail::type::cstring_type) {
auto str = visit_format_arg(detail::get_cstring<Char>(), arg);
auto str_end = str + specs.precision;
auto nul = std::find(str, str_end, Char());
arg = detail::make_arg<basic_printf_context<OutputIt, Char>>(
basic_string_view<Char>(
str, detail::to_unsigned(nul != str_end ? nul - str
: specs.precision)));
}
if (specs.alt && visit_format_arg(detail::is_zero_int(), arg))
specs.alt = false;
if (specs.fill[0] == '0') {
if (arg.is_arithmetic() && specs.align != align::left)
specs.align = align::numeric;
else
specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types or if '-'
// flag is also present.
}
// Parse length and convert the argument to the required type.
c = it != end ? *it++ : 0;
Char t = it != end ? *it : 0;
using detail::convert_arg;
switch (c) {
case 'h':
if (t == 'h') {
++it;
t = it != end ? *it : 0;
convert_arg<signed char>(arg, t);
} else {
convert_arg<short>(arg, t);
}
break;
case 'l':
if (t == 'l') {
++it;
t = it != end ? *it : 0;
convert_arg<long long>(arg, t);
} else {
convert_arg<long>(arg, t);
}
break;
case 'j':
convert_arg<intmax_t>(arg, t);
break;
case 'z':
convert_arg<size_t>(arg, t);
break;
case 't':
convert_arg<std::ptrdiff_t>(arg, t);
break;
case 'L':
// printf produces garbage when 'L' is omitted for long double, no
// need to do the same.
break;
default:
--it;
convert_arg<void>(arg, c);
}
// Parse type.
if (it == end) FMT_THROW(format_error("invalid format string"));
char type = static_cast<char>(*it++);
if (arg.is_integral()) {
// Normalize type.
switch (type) {
case 'i':
case 'u':
type = 'd';
break;
case 'c':
visit_format_arg(
detail::char_converter<basic_printf_context<OutputIt, Char>>(arg),
arg);
break;
}
}
specs.type = parse_presentation_type(type);
if (specs.type == presentation_type::none)
parse_ctx.on_error("invalid type specifier");
start = it;
// Format argument.
out = visit_format_arg(
detail::printf_arg_formatter<OutputIt, Char>(out, specs, context), arg);
}
detail::write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
}
FMT_END_DETAIL_NAMESPACE
template <typename Char>
using basic_printf_context_t =
basic_printf_context<detail::buffer_appender<Char>, Char>;
using printf_context = basic_printf_context_t<char>;
using wprintf_context = basic_printf_context_t<wchar_t>;
using printf_args = basic_format_args<printf_context>;
using wprintf_args = basic_format_args<wprintf_context>;
/**
\rst
Constructs an `~fmt::format_arg_store` object that contains references to
arguments and can be implicitly converted to `~fmt::printf_args`.
\endrst
*/
template <typename... T>
inline auto make_printf_args(const T&... args)
-> format_arg_store<printf_context, T...> {
return {args...};
}
/**
\rst
Constructs an `~fmt::format_arg_store` object that contains references to
arguments and can be implicitly converted to `~fmt::wprintf_args`.
\endrst
*/
template <typename... T>
inline auto make_wprintf_args(const T&... args)
-> format_arg_store<wprintf_context, T...> {
return {args...};
}
template <typename S, typename Char = char_t<S>>
inline auto vsprintf(
const S& fmt,
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
-> std::basic_string<Char> {
basic_memory_buffer<Char> buffer;
vprintf(buffer, to_string_view(fmt), args);
return to_string(buffer);
}
/**
\rst
Formats arguments and returns the result as a string.
**Example**::
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
template <typename S, typename... T,
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {
using context = basic_printf_context_t<Char>;
return vsprintf(to_string_view(fmt), fmt::make_format_args<context>(args...));
}
template <typename S, typename Char = char_t<S>>
inline auto vfprintf(
std::FILE* f, const S& fmt,
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
-> int {
basic_memory_buffer<Char> buffer;
vprintf(buffer, to_string_view(fmt), args);
size_t size = buffer.size();
return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
? -1
: static_cast<int>(size);
}
/**
\rst
Prints formatted data to the file *f*.
**Example**::
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
template <typename S, typename... T, typename Char = char_t<S>>
inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {
using context = basic_printf_context_t<Char>;
return vfprintf(f, to_string_view(fmt),
fmt::make_format_args<context>(args...));
}
template <typename S, typename Char = char_t<S>>
inline auto vprintf(
const S& fmt,
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
-> int {
return vfprintf(stdout, to_string_view(fmt), args);
}
/**
\rst
Prints formatted data to ``stdout``.
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
template <typename S, typename... T, FMT_ENABLE_IF(detail::is_string<S>::value)>
inline auto printf(const S& fmt, const T&... args) -> int {
return vprintf(
to_string_view(fmt),
fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...));
}
template <typename S, typename Char = char_t<S>>
FMT_DEPRECATED auto vfprintf(
std::basic_ostream<Char>& os, const S& fmt,
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
-> int {
basic_memory_buffer<Char> buffer;
vprintf(buffer, to_string_view(fmt), args);
os.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
return static_cast<int>(buffer.size());
}
template <typename S, typename... T, typename Char = char_t<S>>
FMT_DEPRECATED auto fprintf(std::basic_ostream<Char>& os, const S& fmt,
const T&... args) -> int {
return vfprintf(os, to_string_view(fmt),
fmt::make_format_args<basic_printf_context_t<Char>>(args...));
}
FMT_MODULE_EXPORT_END
FMT_END_NAMESPACE
#endif // FMT_PRINTF_H_

586
external/fmt/include/fmt/ranges.h vendored Normal file
View File

@ -0,0 +1,586 @@
// Formatting library for C++ - experimental range support
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
//
// Copyright (c) 2018 - present, Remotion (Igor Schulz)
// All Rights Reserved
// {fmt} support for ranges, containers and types tuple interface.
#ifndef FMT_RANGES_H_
#define FMT_RANGES_H_
#include <initializer_list>
#include <tuple>
#include <type_traits>
#include "format.h"
FMT_BEGIN_NAMESPACE
namespace detail {
template <typename RangeT, typename OutputIterator>
OutputIterator copy(const RangeT& range, OutputIterator out) {
for (auto it = range.begin(), end = range.end(); it != end; ++it)
*out++ = *it;
return out;
}
template <typename OutputIterator>
OutputIterator copy(const char* str, OutputIterator out) {
while (*str) *out++ = *str++;
return out;
}
template <typename OutputIterator>
OutputIterator copy(char ch, OutputIterator out) {
*out++ = ch;
return out;
}
template <typename OutputIterator>
OutputIterator copy(wchar_t ch, OutputIterator out) {
*out++ = ch;
return out;
}
// Returns true if T has a std::string-like interface, like std::string_view.
template <typename T> class is_std_string_like {
template <typename U>
static auto check(U* p)
-> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
template <typename> static void check(...);
public:
static FMT_CONSTEXPR_DECL const bool value =
is_string<T>::value ||
std::is_convertible<T, std_string_view<char>>::value ||
!std::is_void<decltype(check<T>(nullptr))>::value;
};
template <typename Char>
struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};
template <typename T> class is_map {
template <typename U> static auto check(U*) -> typename U::mapped_type;
template <typename> static void check(...);
public:
#ifdef FMT_FORMAT_MAP_AS_LIST
static FMT_CONSTEXPR_DECL const bool value = false;
#else
static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value;
#endif
};
template <typename T> class is_set {
template <typename U> static auto check(U*) -> typename U::key_type;
template <typename> static void check(...);
public:
#ifdef FMT_FORMAT_SET_AS_LIST
static FMT_CONSTEXPR_DECL const bool value = false;
#else
static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
#endif
};
template <typename... Ts> struct conditional_helper {};
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
# define FMT_DECLTYPE_RETURN(val) \
->decltype(val) { return val; } \
static_assert( \
true, "") // This makes it so that a semicolon is required after the
// macro, which helps clang-format handle the formatting.
// C array overload
template <typename T, std::size_t N>
auto range_begin(const T (&arr)[N]) -> const T* {
return arr;
}
template <typename T, std::size_t N>
auto range_end(const T (&arr)[N]) -> const T* {
return arr + N;
}
template <typename T, typename Enable = void>
struct has_member_fn_begin_end_t : std::false_type {};
template <typename T>
struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())>>
: std::true_type {};
// Member function overload
template <typename T>
auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
template <typename T>
auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
// ADL overload. Only participates in overload resolution if member functions
// are not found.
template <typename T>
auto range_begin(T&& rng)
-> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
decltype(begin(static_cast<T&&>(rng)))> {
return begin(static_cast<T&&>(rng));
}
template <typename T>
auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
decltype(end(static_cast<T&&>(rng)))> {
return end(static_cast<T&&>(rng));
}
template <typename T, typename Enable = void>
struct has_const_begin_end : std::false_type {};
template <typename T, typename Enable = void>
struct has_mutable_begin_end : std::false_type {};
template <typename T>
struct has_const_begin_end<
T,
void_t<
decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
: std::true_type {};
template <typename T>
struct has_mutable_begin_end<
T, void_t<decltype(detail::range_begin(std::declval<T>())),
decltype(detail::range_end(std::declval<T>())),
enable_if_t<std::is_copy_constructible<T>::value>>>
: std::true_type {};
template <typename T>
struct is_range_<T, void>
: std::integral_constant<bool, (has_const_begin_end<T>::value ||
has_mutable_begin_end<T>::value)> {};
# undef FMT_DECLTYPE_RETURN
#endif
// tuple_size and tuple_element check.
template <typename T> class is_tuple_like_ {
template <typename U>
static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
template <typename> static void check(...);
public:
static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value;
};
// Check for integer_sequence
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
template <typename T, T... N>
using integer_sequence = std::integer_sequence<T, N...>;
template <size_t... N> using index_sequence = std::index_sequence<N...>;
template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
#else
template <typename T, T... N> struct integer_sequence {
using value_type = T;
static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
};
template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
template <typename T, size_t N, T... Ns>
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
template <typename T, T... Ns>
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
template <size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;
#endif
template <class Tuple, class F, size_t... Is>
void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) noexcept {
using std::get;
// using free function get<I>(T) now.
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
(void)_; // blocks warnings
}
template <class T>
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(
T const&) {
return {};
}
template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
const auto indexes = get_indexes(tup);
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
}
#if FMT_MSC_VER
// Older MSVC doesn't get the reference type correctly for arrays.
template <typename R> struct range_reference_type_impl {
using type = decltype(*detail::range_begin(std::declval<R&>()));
};
template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
using type = T&;
};
template <typename T>
using range_reference_type = typename range_reference_type_impl<T>::type;
#else
template <typename Range>
using range_reference_type =
decltype(*detail::range_begin(std::declval<Range&>()));
#endif
// We don't use the Range's value_type for anything, but we do need the Range's
// reference type, with cv-ref stripped.
template <typename Range>
using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
*out++ = ',';
*out++ = ' ';
return out;
}
template <typename Char, typename OutputIt>
auto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt {
return write_escaped_string(out, str);
}
template <typename Char, typename OutputIt, typename T,
FMT_ENABLE_IF(std::is_convertible<T, std_string_view<char>>::value)>
inline auto write_range_entry(OutputIt out, const T& str) -> OutputIt {
auto sv = std_string_view<Char>(str);
return write_range_entry<Char>(out, basic_string_view<Char>(sv));
}
template <typename Char, typename OutputIt, typename Arg,
FMT_ENABLE_IF(std::is_same<Arg, Char>::value)>
OutputIt write_range_entry(OutputIt out, const Arg v) {
return write_escaped_char(out, v);
}
template <
typename Char, typename OutputIt, typename Arg,
FMT_ENABLE_IF(!is_std_string_like<typename std::decay<Arg>::type>::value &&
!std::is_same<Arg, Char>::value)>
OutputIt write_range_entry(OutputIt out, const Arg& v) {
return write<Char>(out, v);
}
} // namespace detail
template <typename T> struct is_tuple_like {
static FMT_CONSTEXPR_DECL const bool value =
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
};
template <typename TupleT, typename Char>
struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
private:
// C++11 generic lambda for format().
template <typename FormatContext> struct format_each {
template <typename T> void operator()(const T& v) {
if (i > 0) out = detail::write_delimiter(out);
out = detail::write_range_entry<Char>(out, v);
++i;
}
int i;
typename FormatContext::iterator& out;
};
public:
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename FormatContext = format_context>
auto format(const TupleT& values, FormatContext& ctx) const
-> decltype(ctx.out()) {
auto out = ctx.out();
*out++ = '(';
detail::for_each(values, format_each<FormatContext>{0, out});
*out++ = ')';
return out;
}
};
template <typename T, typename Char> struct is_range {
static FMT_CONSTEXPR_DECL const bool value =
detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
!detail::is_map<T>::value &&
!std::is_convertible<T, std::basic_string<Char>>::value &&
!std::is_constructible<detail::std_string_view<Char>, T>::value;
};
namespace detail {
template <typename Context> struct range_mapper {
using mapper = arg_mapper<Context>;
template <typename T,
FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
static auto map(T&& value) -> T&& {
return static_cast<T&&>(value);
}
template <typename T,
FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
static auto map(T&& value)
-> decltype(mapper().map(static_cast<T&&>(value))) {
return mapper().map(static_cast<T&&>(value));
}
};
template <typename Char, typename Element>
using range_formatter_type = conditional_t<
is_formattable<Element, Char>::value,
formatter<remove_cvref_t<decltype(range_mapper<buffer_context<Char>>{}.map(
std::declval<Element>()))>,
Char>,
fallback_formatter<Element, Char>>;
template <typename R>
using maybe_const_range =
conditional_t<has_const_begin_end<R>::value, const R, R>;
} // namespace detail
template <typename R, typename Char>
struct formatter<
R, Char,
enable_if_t<
fmt::is_range<R, Char>::value
// Workaround a bug in MSVC 2019 and earlier.
#if !FMT_MSC_VER
&&
(is_formattable<detail::uncvref_type<detail::maybe_const_range<R>>,
Char>::value ||
detail::has_fallback_formatter<
detail::uncvref_type<detail::maybe_const_range<R>>, Char>::value)
#endif
>> {
using range_type = detail::maybe_const_range<R>;
using formatter_type =
detail::range_formatter_type<Char, detail::uncvref_type<range_type>>;
formatter_type underlying_;
bool custom_specs_ = false;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto it = ctx.begin();
auto end = ctx.end();
if (it == end || *it == '}') return it;
if (*it != ':')
FMT_THROW(format_error("no top-level range formatters supported"));
custom_specs_ = true;
++it;
ctx.advance_to(it);
return underlying_.parse(ctx);
}
template <typename FormatContext>
auto format(range_type& range, FormatContext& ctx) const
-> decltype(ctx.out()) {
#ifdef FMT_DEPRECATED_BRACED_RANGES
Char prefix = '{';
Char postfix = '}';
#else
Char prefix = detail::is_set<R>::value ? '{' : '[';
Char postfix = detail::is_set<R>::value ? '}' : ']';
#endif
detail::range_mapper<buffer_context<Char>> mapper;
auto out = ctx.out();
*out++ = prefix;
int i = 0;
auto it = detail::range_begin(range);
auto end = detail::range_end(range);
for (; it != end; ++it) {
if (i > 0) out = detail::write_delimiter(out);
if (custom_specs_) {
ctx.advance_to(out);
out = underlying_.format(mapper.map(*it), ctx);
} else {
out = detail::write_range_entry<Char>(out, *it);
}
++i;
}
*out++ = postfix;
return out;
}
};
template <typename T, typename Char>
struct formatter<
T, Char,
enable_if_t<detail::is_map<T>::value
// Workaround a bug in MSVC 2019 and earlier.
#if !FMT_MSC_VER
&& (is_formattable<detail::uncvref_type<T>, Char>::value ||
detail::has_fallback_formatter<detail::uncvref_type<T>,
Char>::value)
#endif
>> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <
typename FormatContext, typename U,
FMT_ENABLE_IF(
std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
const T, T>>::value)>
auto format(U& map, FormatContext& ctx) const -> decltype(ctx.out()) {
auto out = ctx.out();
*out++ = '{';
int i = 0;
for (const auto& item : map) {
if (i > 0) out = detail::write_delimiter(out);
out = detail::write_range_entry<Char>(out, item.first);
*out++ = ':';
*out++ = ' ';
out = detail::write_range_entry<Char>(out, item.second);
++i;
}
*out++ = '}';
return out;
}
};
template <typename Char, typename... T> struct tuple_join_view : detail::view {
const std::tuple<T...>& tuple;
basic_string_view<Char> sep;
tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
: tuple(t), sep{s} {}
};
template <typename Char, typename... T>
using tuple_arg_join = tuple_join_view<Char, T...>;
// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
// support in tuple_join. It is disabled by default because of issues with
// the dynamic width and precision.
#ifndef FMT_TUPLE_JOIN_SPECIFIERS
# define FMT_TUPLE_JOIN_SPECIFIERS 0
#endif
template <typename Char, typename... T>
struct formatter<tuple_join_view<Char, T...>, Char> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
}
template <typename FormatContext>
auto format(const tuple_join_view<Char, T...>& value,
FormatContext& ctx) const -> typename FormatContext::iterator {
return do_format(value, ctx,
std::integral_constant<size_t, sizeof...(T)>());
}
private:
std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
template <typename ParseContext>
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
std::integral_constant<size_t, 0>)
-> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename ParseContext, size_t N>
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
std::integral_constant<size_t, N>)
-> decltype(ctx.begin()) {
auto end = ctx.begin();
#if FMT_TUPLE_JOIN_SPECIFIERS
end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
if (N > 1) {
auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
if (end != end1)
FMT_THROW(format_error("incompatible format specs for tuple elements"));
}
#endif
return end;
}
template <typename FormatContext>
auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
std::integral_constant<size_t, 0>) const ->
typename FormatContext::iterator {
return ctx.out();
}
template <typename FormatContext, size_t N>
auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
std::integral_constant<size_t, N>) const ->
typename FormatContext::iterator {
auto out = std::get<sizeof...(T) - N>(formatters_)
.format(std::get<sizeof...(T) - N>(value.tuple), ctx);
if (N > 1) {
out = std::copy(value.sep.begin(), value.sep.end(), out);
ctx.advance_to(out);
return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
}
return out;
}
};
FMT_MODULE_EXPORT_BEGIN
/**
\rst
Returns an object that formats `tuple` with elements separated by `sep`.
**Example**::
std::tuple<int, char> t = {1, 'a'};
fmt::print("{}", fmt::join(t, ", "));
// Output: "1, a"
\endrst
*/
template <typename... T>
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
-> tuple_join_view<char, T...> {
return {tuple, sep};
}
template <typename... T>
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,
basic_string_view<wchar_t> sep)
-> tuple_join_view<wchar_t, T...> {
return {tuple, sep};
}
/**
\rst
Returns an object that formats `initializer_list` with elements separated by
`sep`.
**Example**::
fmt::print("{}", fmt::join({1, 2, 3}, ", "));
// Output: "1, 2, 3"
\endrst
*/
template <typename T>
auto join(std::initializer_list<T> list, string_view sep)
-> join_view<const T*, const T*> {
return join(std::begin(list), std::end(list), sep);
}
FMT_MODULE_EXPORT_END
FMT_END_NAMESPACE
#endif // FMT_RANGES_H_

236
external/fmt/include/fmt/xchar.h vendored Normal file
View File

@ -0,0 +1,236 @@
// Formatting library for C++ - optional wchar_t and exotic character support
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_XCHAR_H_
#define FMT_XCHAR_H_
#include <cwchar>
#include <tuple>
#include "format.h"
FMT_BEGIN_NAMESPACE
namespace detail {
template <typename T>
using is_exotic_char = bool_constant<!std::is_same<T, char>::value>;
}
FMT_MODULE_EXPORT_BEGIN
using wstring_view = basic_string_view<wchar_t>;
using wformat_parse_context = basic_format_parse_context<wchar_t>;
using wformat_context = buffer_context<wchar_t>;
using wformat_args = basic_format_args<wformat_context>;
using wmemory_buffer = basic_memory_buffer<wchar_t>;
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
// Workaround broken conversion on older gcc.
template <typename... Args> using wformat_string = wstring_view;
#else
template <typename... Args>
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
#endif
template <> struct is_char<wchar_t> : std::true_type {};
template <> struct is_char<detail::char8_type> : std::true_type {};
template <> struct is_char<char16_t> : std::true_type {};
template <> struct is_char<char32_t> : std::true_type {};
template <typename... Args>
constexpr format_arg_store<wformat_context, Args...> make_wformat_args(
const Args&... args) {
return {args...};
}
inline namespace literals {
constexpr auto operator"" _format(const wchar_t* s, size_t n)
-> detail::udl_formatter<wchar_t> {
return {{s, n}};
}
#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
return {s};
}
#endif
} // namespace literals
template <typename It, typename Sentinel>
auto join(It begin, Sentinel end, wstring_view sep)
-> join_view<It, Sentinel, wchar_t> {
return {begin, end, sep};
}
template <typename Range>
auto join(Range&& range, wstring_view sep)
-> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>,
wchar_t> {
return join(std::begin(range), std::end(range), sep);
}
template <typename T>
auto join(std::initializer_list<T> list, wstring_view sep)
-> join_view<const T*, const T*, wchar_t> {
return join(std::begin(list), std::end(list), sep);
}
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
auto vformat(basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args)
-> std::basic_string<Char> {
basic_memory_buffer<Char> buffer;
detail::vformat_to(buffer, format_str, args);
return to_string(buffer);
}
// Pass char_t as a default template parameter instead of using
// std::basic_string<char_t<S>> to reduce the symbol size.
template <typename S, typename... Args, typename Char = char_t<S>,
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> {
return vformat(to_string_view(format_str),
fmt::make_format_args<buffer_context<Char>>(args...));
}
template <typename Locale, typename S, typename Char = char_t<S>,
FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
detail::is_exotic_char<Char>::value)>
inline auto vformat(
const Locale& loc, const S& format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args)
-> std::basic_string<Char> {
return detail::vformat(loc, to_string_view(format_str), args);
}
template <typename Locale, typename S, typename... Args,
typename Char = char_t<S>,
FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
detail::is_exotic_char<Char>::value)>
inline auto format(const Locale& loc, const S& format_str, Args&&... args)
-> std::basic_string<Char> {
return detail::vformat(loc, to_string_view(format_str),
fmt::make_format_args<buffer_context<Char>>(args...));
}
template <typename OutputIt, typename S, typename Char = char_t<S>,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
detail::is_exotic_char<Char>::value)>
auto vformat_to(OutputIt out, const S& format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args)
-> OutputIt {
auto&& buf = detail::get_buffer<Char>(out);
detail::vformat_to(buf, to_string_view(format_str), args);
return detail::get_iterator(buf);
}
template <typename OutputIt, typename S, typename... Args,
typename Char = char_t<S>,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
detail::is_exotic_char<Char>::value)>
inline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt {
return vformat_to(out, to_string_view(fmt),
fmt::make_format_args<buffer_context<Char>>(args...));
}
template <typename S, typename... Args, typename Char, size_t SIZE,
typename Allocator, FMT_ENABLE_IF(detail::is_string<S>::value)>
FMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf,
const S& format_str, Args&&... args) ->
typename buffer_context<Char>::iterator {
detail::vformat_to(buf, to_string_view(format_str),
fmt::make_format_args<buffer_context<Char>>(args...), {});
return detail::buffer_appender<Char>(buf);
}
template <typename Locale, typename S, typename OutputIt, typename... Args,
typename Char = char_t<S>,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
detail::is_locale<Locale>::value&&
detail::is_exotic_char<Char>::value)>
inline auto vformat_to(
OutputIt out, const Locale& loc, const S& format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt {
auto&& buf = detail::get_buffer<Char>(out);
vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc));
return detail::get_iterator(buf);
}
template <
typename OutputIt, typename Locale, typename S, typename... Args,
typename Char = char_t<S>,
bool enable = detail::is_output_iterator<OutputIt, Char>::value&&
detail::is_locale<Locale>::value&& detail::is_exotic_char<Char>::value>
inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
Args&&... args) ->
typename std::enable_if<enable, OutputIt>::type {
return vformat_to(out, loc, to_string_view(format_str),
fmt::make_format_args<buffer_context<Char>>(args...));
}
template <typename OutputIt, typename Char, typename... Args,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
detail::is_exotic_char<Char>::value)>
inline auto vformat_to_n(
OutputIt out, size_t n, basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args)
-> format_to_n_result<OutputIt> {
detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out,
n);
detail::vformat_to(buf, format_str, args);
return {buf.out(), buf.count()};
}
template <typename OutputIt, typename S, typename... Args,
typename Char = char_t<S>,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
detail::is_exotic_char<Char>::value)>
inline auto format_to_n(OutputIt out, size_t n, const S& fmt,
const Args&... args) -> format_to_n_result<OutputIt> {
return vformat_to_n(out, n, to_string_view(fmt),
fmt::make_format_args<buffer_context<Char>>(args...));
}
template <typename S, typename... Args, typename Char = char_t<S>,
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
inline auto formatted_size(const S& fmt, Args&&... args) -> size_t {
detail::counting_buffer<Char> buf;
detail::vformat_to(buf, to_string_view(fmt),
fmt::make_format_args<buffer_context<Char>>(args...));
return buf.count();
}
inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {
wmemory_buffer buffer;
detail::vformat_to(buffer, fmt, args);
buffer.push_back(L'\0');
if (std::fputws(buffer.data(), f) == -1)
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
}
inline void vprint(wstring_view fmt, wformat_args args) {
vprint(stdout, fmt, args);
}
template <typename... T>
void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...));
}
template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
return vprint(wstring_view(fmt), fmt::make_wformat_args(args...));
}
/**
Converts *value* to ``std::wstring`` using the default format for type *T*.
*/
template <typename T> inline auto to_wstring(const T& value) -> std::wstring {
return format(FMT_STRING(L"{}"), value);
}
FMT_MODULE_EXPORT_END
FMT_END_NAMESPACE
#endif // FMT_XCHAR_H_

105
external/fmt/src/format.cc vendored Normal file
View File

@ -0,0 +1,105 @@
// Formatting library for C++
//
// Copyright (c) 2012 - 2016, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#include "fmt/format-inl.h"
FMT_BEGIN_NAMESPACE
namespace detail {
// DEPRECATED!
template <typename T = void> struct basic_data {
FMT_API static constexpr const char digits[100][2] = {
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
{'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
{'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
{'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
{'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
{'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
{'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
{'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
{'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
{'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
{'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
{'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
{'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
{'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
{'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
{'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
{'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
FMT_API static constexpr const char hex_digits[] = "0123456789abcdef";
FMT_API static constexpr const char signs[4] = {0, '-', '+', ' '};
FMT_API static constexpr const char left_padding_shifts[5] = {31, 31, 0, 1,
0};
FMT_API static constexpr const char right_padding_shifts[5] = {0, 31, 0, 1,
0};
FMT_API static constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
0x1000000u | ' '};
};
#ifdef FMT_SHARED
// Required for -flto, -fivisibility=hidden and -shared to work
extern template struct basic_data<void>;
#endif
#if __cplusplus < 201703L
// DEPRECATED! These are here only for ABI compatiblity.
template <typename T> constexpr const char basic_data<T>::digits[][2];
template <typename T> constexpr const char basic_data<T>::hex_digits[];
template <typename T> constexpr const char basic_data<T>::signs[];
template <typename T> constexpr const char basic_data<T>::left_padding_shifts[];
template <typename T>
constexpr const char basic_data<T>::right_padding_shifts[];
template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
#endif
template FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(
float x) noexcept;
template FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(
double x) noexcept;
} // namespace detail
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
int (*instantiate_format_float)(double, int, detail::float_specs,
detail::buffer<char>&) = detail::format_float;
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
template FMT_API detail::locale_ref::locale_ref(const std::locale& loc);
template FMT_API std::locale detail::locale_ref::get<std::locale>() const;
#endif
// Explicit instantiations for char.
template FMT_API auto detail::thousands_sep_impl(locale_ref)
-> thousands_sep_result<char>;
template FMT_API char detail::decimal_point_impl(locale_ref);
template FMT_API void detail::buffer<char>::append(const char*, const char*);
// DEPRECATED!
// There is no correspondent extern template in format.h because of
// incompatibility between clang and gcc (#2377).
template FMT_API void detail::vformat_to(
detail::buffer<char>&, string_view,
basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
template FMT_API int detail::format_float(double, int, detail::float_specs,
detail::buffer<char>&);
template FMT_API int detail::format_float(long double, int, detail::float_specs,
detail::buffer<char>&);
// Explicit instantiations for wchar_t.
template FMT_API auto detail::thousands_sep_impl(locale_ref)
-> thousands_sep_result<wchar_t>;
template FMT_API wchar_t detail::decimal_point_impl(locale_ref);
template FMT_API void detail::buffer<wchar_t>::append(const wchar_t*,
const wchar_t*);
template struct detail::basic_data<void>;
FMT_END_NAMESPACE

2
external/glslang vendored

@ -1 +1 @@
Subproject commit bcf6a2430e99e8fc24f9f266e99316905e6d5134
Subproject commit 6d41bb9c557c5a0eec61ffba1f775dc5f717a8f7

7897
external/stb/stb_image.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

@ -1 +1 @@
Subproject commit 89d366355e6fe1221c9be40bb2cf3716449e9a7e
Subproject commit a3dd2655a3a68c2a67c55a0f8b77dcb8b166ada2

File diff suppressed because it is too large Load Diff

View File

@ -4,13 +4,15 @@
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include <cstdint>
#ifndef _hq2x_h_
#define _hq2x_h_
bool8 S9xBlitHQ2xFilterInit (void);
void S9xBlitHQ2xFilterDeinit (void);
void HQ2X_16 (uint8 *, uint32, uint8 *, uint32, int, int);
void HQ3X_16 (uint8 *, uint32, uint8 *, uint32, int, int);
void HQ4X_16 (uint8 *, uint32, uint8 *, uint32, int, int);
bool S9xBlitHQ2xFilterInit(void);
void S9xBlitHQ2xFilterDeinit(void);
void HQ2X_16 (uint8_t *, int, uint8_t *, int, int, int);
void HQ3X_16 (uint8_t *, int, uint8_t *, int, int, int);
void HQ4X_16 (uint8_t *, int, uint8_t *, int, int, int);
#endif

238
fscompat.cpp Normal file
View File

@ -0,0 +1,238 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include <cstring>
#include <string>
#include "display.h"
#include "fscompat.h"
#include "port.h"
#include "memmap.h"
using std::string;
bool SplitPath::ext_is(const string &other)
{
if (strcasecmp(ext.c_str(), other.c_str()) == 0)
return true;
if (other[0] != '.' && (strcasecmp(other.c_str(), &(ext.c_str()[1])) == 0))
return true;
return false;
}
std::string makepath(const SplitPath &path)
{
return makepath(path.drive, path.dir, path.stem, path.ext);
}
std::string S9xGetFilename(string filename, string ext, enum s9x_getdirtype dirtype)
{
auto path = splitpath(filename);
auto dir = S9xGetDirectory(dirtype);
return makepath(path.drive, dir, path.stem, ext);
}
std::string S9xGetFilename(string ext, enum s9x_getdirtype dirtype)
{
return S9xGetFilename(Memory.ROMFilename, ext, dirtype);
}
std::string S9xBasename(std::string filename)
{
auto path = splitpath(filename);
return path.stem + path.ext;
}
std::string S9xBasenameNoExt(std::string filename)
{
return splitpath(filename).stem;
}
#if __cplusplus >= 201703L && 0
#include <filesystem>
namespace fs = std::filesystem;
SplitPath splitpath(string str)
{
SplitPath output{};
fs::path path(str);
if (path.has_root_name())
output.drive = path.root_name().string();
if (path.has_filename())
{
output.stem = path.stem().string();
output.ext = path.extension().string();
path.remove_filename();
}
if (!path.empty())
output.dir = path.string();
return output;
}
string makepath(const string &drive, const string &dir, const string &stem, const string &ext)
{
auto dot_position = ext.find('.');
if (dot_position == string::npos)
{
fs::path path(drive);
path = path / dir / stem;
path.replace_extension(ext);
return path.string();
}
auto filename = stem + ext;
fs::path path(drive);
path = path / dir / filename;
return path.string();
}
#else
constexpr auto npos = std::string::npos;
SplitPath splitpath(string path)
{
SplitPath output{};
#ifdef _WIN32
if (path.length() > 2 && path[1] == ':')
{
output.drive = path.substr(0, 2);
path = path.substr(2);
}
#endif
auto slash = path.rfind(SLASH_CHAR);
auto dot = path.rfind('.');
if (dot != npos && slash != npos && dot < slash)
{
dot = npos;
}
else if (dot != npos)
{
output.ext = path.substr(dot);
}
if (slash != npos)
{
output.dir = path.substr(0, slash + 1);
output.stem = path.substr(slash + 1, dot - slash - 1);
}
else
{
output.stem = path.substr(0, dot);
}
return output;
}
string makepath(const string &drive, const string &dir, const string &stem, const string &ext)
{
string output;
if (!drive.empty())
{
if (!(dir.length() > 2 && dir[1] == ':'))
{
output += drive + ":";
if (!dir.empty() && dir[0] != SLASH_CHAR)
output += SLASH_CHAR;
}
}
if (!dir.empty())
{
output += dir;
if (output[output.length() - 1] != SLASH_CHAR)
output += SLASH_CHAR;
}
if (!stem.empty())
{
output += stem;
}
if (!ext.empty())
{
if (ext.find('.') == string::npos)
output += '.';
output += ext;
}
return output;
}
#ifndef _WIN32
void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
{
char *slash = strrchr((char *)path, SLASH_CHAR);
char *dot = strrchr((char *)path, '.');
*drive = '\0';
if (dot && slash && dot < slash)
{
dot = 0;
}
if (!slash)
{
*dir = '\0';
strcpy(fname, path);
if (dot)
{
fname[dot - path] = '\0';
strcpy(ext, dot + 1);
}
else
{
*ext = '\0';
}
}
else
{
strcpy(dir, path);
dir[slash - path] = '\0';
strcpy(fname, slash + 1);
if (dot)
{
fname[(dot - slash) - 1] = '\0';
strcpy(ext, dot + 1);
}
else
{
*ext = '\0';
}
}
}
void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext)
{
if (dir && *dir)
{
strcpy(path, dir);
strcat(path, "/");
}
else
*path = '\0';
strcat(path, fname);
if (ext && *ext)
{
if (!strchr(ext, '.'))
strcat(path, ".");
strcat(path, ext);
}
}
#endif
#endif

52
fscompat.h Normal file
View File

@ -0,0 +1,52 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#pragma once
#ifdef __cplusplus
#include <string>
enum s9x_getdirtype
{
DEFAULT_DIR = 0,
HOME_DIR,
ROMFILENAME_DIR,
ROM_DIR,
SRAM_DIR,
SNAPSHOT_DIR,
SCREENSHOT_DIR,
SPC_DIR,
CHEAT_DIR,
PATCH_DIR,
BIOS_DIR,
LOG_DIR,
SAT_DIR,
LAST_DIR
};
struct SplitPath
{
bool ext_is(const std::string &ext);
std::string drive;
std::string dir;
std::string stem;
std::string ext;
};
SplitPath splitpath(std::string filename);
std::string makepath(const std::string &drive,
const std::string &directory,
const std::string &stem,
const std::string &extension);
std::string makepath(const SplitPath &);
std::string S9xBasename (std::string);
std::string S9xBasenameNoExt (std::string);
std::string S9xGetFilename (std::string ext, enum s9x_getdirtype dirtype);
std::string S9xGetFilename (std::string filename, std::string ext, enum s9x_getdirtype dirtype);
std::string S9xGetDirectory (enum s9x_getdirtype);
std::string S9xGetFilenameInc (std::string, enum s9x_getdirtype);
#endif

View File

@ -196,7 +196,7 @@ static void FxReset (struct FxInfo_s *psFxInfo)
else
{
b %= GSU.nRomBanks * 2;
GSU.apvRomBank[i] = &GSU.pvRom[(b << 16) + 0x200000];
GSU.apvRomBank[i] = &GSU.pvRom[(b << 16) + 0x800000];
}
}

125
gfx.cpp
View File

@ -49,15 +49,13 @@ bool8 S9xGraphicsInit (void)
S9xInitTileRenderer();
memset(BlackColourMap, 0, 256 * sizeof(uint16));
GFX.RealPPL = GFX.Pitch >> 1;
IPPU.OBJChanged = TRUE;
Settings.BG_Forced = 0;
S9xFixColourBrightness();
S9xBuildDirectColourMaps();
GFX.Screen = &GFX.ScreenBuffer[GFX.RealPPL * 32];
GFX.ZERO = (uint16 *) malloc(sizeof(uint16) * 0x10000);
GFX.ScreenSize = GFX.Pitch / 2 * SNES_HEIGHT_EXTENDED * (Settings.SupportHiRes ? 2 : 1);
GFX.SubScreen = (uint16 *) malloc(GFX.ScreenSize * sizeof(uint16));
GFX.ZBuffer = (uint8 *) malloc(GFX.ScreenSize);
GFX.SubZBuffer = (uint8 *) malloc(GFX.ScreenSize);
@ -118,27 +116,19 @@ void S9xGraphicsScreenResize (void)
IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
IPPU.InterlaceOBJ = Memory.FillRAM[0x2133] & 2;
IPPU.PseudoHires = Memory.FillRAM[0x2133] & 8;
if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires))
if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires)
{
GFX.RealPPL = GFX.Pitch >> 1;
IPPU.DoubleWidthPixels = TRUE;
IPPU.RenderedScreenWidth = SNES_WIDTH << 1;
}
else
{
#ifdef USE_OPENGL
if (Settings.OpenGLEnable)
GFX.RealPPL = SNES_WIDTH;
else
#endif
GFX.RealPPL = GFX.Pitch >> 1;
IPPU.DoubleWidthPixels = FALSE;
IPPU.RenderedScreenWidth = SNES_WIDTH;
}
if (Settings.SupportHiRes && IPPU.Interlace)
if (IPPU.Interlace)
{
GFX.PPL = GFX.RealPPL << 1;
IPPU.DoubleHeightPixels = TRUE;
@ -150,7 +140,7 @@ void S9xGraphicsScreenResize (void)
GFX.PPL = GFX.RealPPL;
IPPU.DoubleHeightPixels = FALSE;
IPPU.RenderedScreenHeight = PPU.ScreenHeight;
}
}
}
void S9xBuildDirectColourMaps (void)
@ -164,13 +154,12 @@ void S9xBuildDirectColourMaps (void)
void S9xStartScreenRefresh (void)
{
GFX.InterlaceFrame = !GFX.InterlaceFrame;
if (GFX.DoInterlace)
GFX.DoInterlace--;
if (IPPU.RenderThisFrame)
{
if (!GFX.DoInterlace || !GFX.InterlaceFrame)
if (!GFX.DoInterlace || !S9xInterlaceField())
{
if (!S9xInitUpdate())
{
@ -199,7 +188,7 @@ void S9xStartScreenRefresh (void)
}
if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0)
GFX.InfoString = NULL;
GFX.InfoString.clear();
IPPU.TotalEmulatedFrames++;
}
@ -210,7 +199,7 @@ void S9xEndScreenRefresh (void)
{
FLUSH_REDRAW();
if (GFX.DoInterlace && GFX.InterlaceFrame == 0)
if (GFX.DoInterlace && S9xInterlaceField() == 0)
{
S9xControlEOF();
S9xContinueUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight);
@ -324,7 +313,7 @@ static inline void RenderScreen (bool8 sub)
if (!sub)
{
GFX.S = GFX.Screen;
if (GFX.DoInterlace && GFX.InterlaceFrame)
if (GFX.DoInterlace && S9xInterlaceField())
GFX.S += GFX.RealPPL;
GFX.DB = GFX.ZBuffer;
GFX.Clip = IPPU.Clip[0];
@ -467,55 +456,31 @@ void S9xUpdateScreen (void)
PPU.RecomputeClipWindows = FALSE;
}
if (Settings.SupportHiRes)
if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires))
{
if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires))
// Have to back out of the regular speed hack
for (uint32 y = 0; y < GFX.StartY; y++)
{
#ifdef USE_OPENGL
if (Settings.OpenGLEnable && GFX.RealPPL == 256)
{
// Have to back out of the speed up hack where the low res.
// SNES image was rendered into a 256x239 sized buffer,
// ignoring the true, larger size of the buffer.
GFX.RealPPL = GFX.Pitch >> 1;
uint16 *p = GFX.Screen + y * GFX.PPL + 255;
uint16 *q = GFX.Screen + y * GFX.PPL + 510;
for (int32 y = (int32) GFX.StartY - 1; y >= 0; y--)
{
uint16 *p = GFX.Screen + y * GFX.PPL + 255;
uint16 *q = GFX.Screen + y * GFX.RealPPL + 510;
for (int x = 255; x >= 0; x--, p--, q -= 2)
*q = *(q + 1) = *p;
}
GFX.PPL = GFX.RealPPL; // = GFX.Pitch >> 1 above
}
else
#endif
// Have to back out of the regular speed hack
for (uint32 y = 0; y < GFX.StartY; y++)
{
uint16 *p = GFX.Screen + y * GFX.PPL + 255;
uint16 *q = GFX.Screen + y * GFX.PPL + 510;
for (int x = 255; x >= 0; x--, p--, q -= 2)
*q = *(q + 1) = *p;
}
IPPU.DoubleWidthPixels = TRUE;
IPPU.RenderedScreenWidth = 512;
for (int x = 255; x >= 0; x--, p--, q -= 2)
*q = *(q + 1) = *p;
}
if (!IPPU.DoubleHeightPixels && IPPU.Interlace && (PPU.BGMode == 5 || PPU.BGMode == 6))
{
IPPU.DoubleHeightPixels = TRUE;
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
GFX.PPL = GFX.RealPPL << 1;
GFX.DoInterlace = 2;
IPPU.DoubleWidthPixels = TRUE;
IPPU.RenderedScreenWidth = 512;
}
for (int32 y = (int32) GFX.StartY - 2; y >= 0; y--)
memmove(GFX.Screen + (y + 1) * GFX.PPL, GFX.Screen + y * GFX.RealPPL, GFX.PPL * sizeof(uint16));
}
if (!IPPU.DoubleHeightPixels && IPPU.Interlace && (PPU.BGMode == 5 || PPU.BGMode == 6))
{
IPPU.DoubleHeightPixels = TRUE;
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
GFX.PPL = GFX.RealPPL << 1;
GFX.DoInterlace = 2;
for (int32 y = (int32) GFX.StartY - 2; y >= 0; y--)
memmove(GFX.Screen + (y + 1) * GFX.PPL, GFX.Screen + y * GFX.RealPPL, GFX.PPL * sizeof(uint16));
}
if ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2131] & 0x3f))
@ -534,7 +499,7 @@ void S9xUpdateScreen (void)
const uint16 black = BUILD_PIXEL(0, 0, 0);
GFX.S = GFX.Screen + GFX.StartY * GFX.PPL;
if (GFX.DoInterlace && GFX.InterlaceFrame)
if (GFX.DoInterlace && S9xInterlaceField())
GFX.S += GFX.RealPPL;
for (uint32 l = GFX.StartY; l <= GFX.EndY; l++, GFX.S += GFX.PPL)
@ -595,7 +560,7 @@ static void SetupOBJ (void)
int inc = IPPU.InterlaceOBJ ? 2 : 1;
int startline = (IPPU.InterlaceOBJ && GFX.InterlaceFrame) ? 1 : 0;
int startline = (IPPU.InterlaceOBJ && S9xInterlaceField()) ? 1 : 0;
// OK, we have three cases here. Either there's no priority, priority is
// normal FirstSprite, or priority is FirstSprite+Y. The first two are
@ -642,8 +607,7 @@ static void SetupOBJ (void)
{
if (HPos < 0)
GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3;
else
if (HPos + GFX.OBJWidths[S] > 255)
else if (HPos + GFX.OBJWidths[S] > 255)
GFX.OBJVisibleTiles[S] = (256 - HPos + 7) >> 3;
else
GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3;
@ -714,8 +678,7 @@ static void SetupOBJ (void)
{
if (HPos < 0)
GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3;
else
if (HPos + GFX.OBJWidths[S] >= 257)
else if (HPos + GFX.OBJWidths[S] >= 257)
GFX.OBJVisibleTiles[S] = (257 - HPos + 7) >> 3;
else
GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3;
@ -792,10 +755,10 @@ static void DrawOBJS (int D)
void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32) = NULL;
int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1;
BG.InterlaceLine = GFX.InterlaceFrame ? 8 : 0;
BG.InterlaceLine = S9xInterlaceField() ? 8 : 0;
GFX.Z1 = 2;
int sprite_limit = (Settings.MaxSpriteTilesPerLine == 128) ? 128 : 32;
for (uint32 Y = GFX.StartY, Offset = Y * GFX.PPL; Y <= GFX.EndY; Y++, Offset += GFX.PPL)
{
int I = 0;
@ -927,7 +890,7 @@ static void DrawBackground (int bg, uint8 Zh, uint8 Zl)
for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
{
uint32 Y2 = HiresInterlace ? Y * 2 + GFX.InterlaceFrame : Y;
uint32 Y2 = HiresInterlace ? Y * 2 + S9xInterlaceField() : Y;
uint32 VOffset = LineData[Y].BG[bg].VOffset + (HiresInterlace ? 1 : 0);
uint32 HOffset = LineData[Y].BG[bg].HOffset;
int VirtAlign = ((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0);
@ -1321,7 +1284,7 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
{
uint32 Y2 = HiresInterlace ? Y * 2 + GFX.InterlaceFrame : Y;
uint32 Y2 = HiresInterlace ? Y * 2 + S9xInterlaceField() : Y;
uint32 VOff = LineData[Y].BG[2].VOffset - 1;
uint32 HOff = LineData[Y].BG[2].HOffset;
uint32 HOffsetRow = VOff >> Offset2Shift;
@ -1843,7 +1806,7 @@ static void S9xDisplayStringType (const char *string, int linesFromBottom, int p
static void DisplayTime (void)
{
char string[10];
time_t rawtime;
struct tm *timeinfo;
@ -2016,7 +1979,7 @@ static void DisplayWatchedAddresses (void)
break;
int32 displayNumber = 0;
char buf[32];
char buf[64];
for (int r = 0; r < watches[i].size; r++)
displayNumber += (Cheat.CWatchRAM[(watches[i].address - 0x7E0000) + r]) << (8 * r);
@ -2030,11 +1993,9 @@ static void DisplayWatchedAddresses (void)
{
if (watches[i].size == 1)
displayNumber = (int32) ((int8) displayNumber);
else
if (watches[i].size == 2)
else if (watches[i].size == 2)
displayNumber = (int32) ((int16) displayNumber);
else
if (watches[i].size == 3)
else if (watches[i].size == 3)
if (displayNumber >= 8388608)
displayNumber -= 16777216;
@ -2049,7 +2010,7 @@ void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int sca
{
if (Settings.DisplayTime)
DisplayTime();
if (Settings.DisplayFrameRate)
DisplayFrameRate();
@ -2062,8 +2023,8 @@ void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int sca
if (Settings.DisplayMovieFrame && S9xMovieActive())
S9xDisplayString(GFX.FrameDisplayString, 1, 1, false);
if (GFX.InfoString && *GFX.InfoString)
S9xDisplayString(GFX.InfoString, 5, 1, true);
if (!GFX.InfoString.empty())
S9xDisplayString(GFX.InfoString.c_str(), 5, 1, true);
}
static uint16 get_crosshair_color (uint8 color)

10
gfx.h
View File

@ -11,16 +11,17 @@
struct SGFX
{
const uint32 Pitch = sizeof(uint16) * MAX_SNES_WIDTH;
const uint32 RealPPL = MAX_SNES_WIDTH; // true PPL of Screen buffer
const uint32 ScreenSize = MAX_SNES_WIDTH * MAX_SNES_HEIGHT;
uint16 ScreenBuffer[MAX_SNES_WIDTH * (MAX_SNES_HEIGHT + 64)];
uint16 *Screen;
uint16 *SubScreen;
uint8 *ZBuffer;
uint8 *SubZBuffer;
uint32 Pitch;
uint32 ScreenSize;
uint16 *S;
uint8 *DB;
uint16 *ZERO;
uint32 RealPPL; // true PPL of Screen buffer
uint32 PPL; // number of pixels on each of Screen buffer
uint32 LinesPerTile; // number of lines in 1 tile (4 or 8 due to interlace)
uint16 *ScreenColors; // screen colors for rendering main
@ -29,7 +30,6 @@ struct SGFX
uint8 Z2; // depth to save
uint32 FixedColour;
uint8 DoInterlace;
uint8 InterlaceFrame;
uint32 StartY;
uint32 EndY;
bool8 ClipColors;
@ -63,7 +63,7 @@ struct SGFX
void (*DrawMode7BG2Math) (uint32, uint32, int);
void (*DrawMode7BG2Nomath) (uint32, uint32, int);
const char *InfoString;
std::string InfoString;
uint32 InfoStringTimeout;
char FrameDisplayString[256];
};

View File

@ -1,8 +1,7 @@
cmake_minimum_required(VERSION 3.20)
cmake_minimum_required(VERSION 3.18)
project(snes9x-gtk VERSION 1.61)
option(USE_OPENGL "Build support for OpenGL" ON)
option(USE_SLANG "Build support for slang-type shaders" ON)
option(USE_SLANG "Build support for Vulkan output and .slangp shaders" ON)
option(USE_XV "Build support for XVideo output" ON)
option(USE_PORTAUDIO "Build PortAudio sound driver" ON)
option(USE_ALSA "Build ALSA sound driver" ON)
@ -21,11 +20,16 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_INSTALL_DATADIR "snes9x" CACHE STRING "cheats.bml directory")
set(CMAKE_INSTALL_LOCALEDIR locale CACHE STRING "Locale directory")
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "One of: Debug Release RelWithDebInfo MinSizeRel" FORCE)
endif(NOT CMAKE_BUILD_TYPE)
string(APPEND DATADIR ${CMAKE_INSTALL_PREFIX} "/" ${CMAKE_INSTALL_DATAROOTDIR} "/" ${CMAKE_INSTALL_DATADIR})
string(APPEND LOCALEDIR ${CMAKE_INSTALL_PREFIX} "/" ${CMAKE_INSTALL_DATAROOTDIR} "/" ${CMAKE_INSTALL_LOCALEDIR})
add_compile_definitions(HAVE_LIBPNG
ZLIB SNES9X_GTK
NETPLAY_SUPPORT
JMA_SUPPORT
UNZIP_SUPPORT
HAVE_MKSTEMP
HAVE_STRINGS_H
@ -36,37 +40,41 @@ add_compile_definitions(HAVE_LIBPNG
SNES9XLOCALEDIR=\"${LOCALEDIR}\")
set(INCLUDES ../apu/bapu ../ src)
set(SOURCES)
set(ARGS -Wall -W -Wno-unused-parameter)
set(ARGS -Wall -Wno-unused-parameter)
set(LIBS)
set(DEFINES)
include(CheckIncludeFile)
include(FindGettext)
foreach(lang es fr_FR ja pt_BR ru sr@latin uk zh_CN)
GETTEXT_PROCESS_PO_FILES(${lang} ALL INSTALL_DESTINATION "share/locale/" PO_FILES po/${lang}.po)
GETTEXT_PROCESS_PO_FILES(${lang} ALL "share/locale/" PO_FILES po/${lang}.po)
install(FILES ${CMAKE_BINARY_DIR}/${lang}.gmo
DESTINATION ${LOCALEDIR}/${lang}/LC_MESSAGES
RENAME snes9x-gtk.mo
COMPONENT translations)
endforeach()
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2)
pkg_check_modules(GTK REQUIRED gtkmm-3.0 gthread-2.0 libpng)
pkg_check_modules(XRANDR REQUIRED xrandr)
find_library(X11 X11 REQUIRED)
find_library(XEXT Xext REQUIRED)
find_library(DL dl REQUIRED)
list(APPEND ARGS ${SDL2_CFLAGS} ${GTK_CFLAGS} ${XRANDR_CFLAGS})
list(APPEND LIBS ${X11} ${XEXT} ${DL} ${SDL2_LIBRARIES} ${GTK_LIBRARIES} ${XRANDR_LIBRARIES})
if(USE_OPENGL)
pkg_check_modules(EPOXY REQUIRED epoxy)
list(APPEND ARGS ${EPOXY_CFLAGS})
list(APPEND LIBS ${EPOXY_LIBRARIES})
list(APPEND SOURCES src/gtk_display_driver_opengl.cpp
src/gtk_glx_context.cpp
../shaders/glsl.cpp
../shaders/shader_helpers.cpp
src/gtk_shader_parameters.cpp)
list(APPEND DEFINES "USE_OPENGL")
endif()
pkg_check_modules(EPOXY REQUIRED epoxy)
list(APPEND ARGS ${EPOXY_CFLAGS})
list(APPEND LIBS ${EPOXY_LIBRARIES})
list(APPEND SOURCES src/gtk_display_driver_opengl.cpp
src/gtk_glx_context.cpp
../shaders/glsl.cpp
../shaders/shader_helpers.cpp
src/gtk_shader_parameters.cpp)
if(USE_SLANG)
list(APPEND SOURCES ../shaders/slang.cpp)
@ -88,6 +96,45 @@ if(USE_SLANG)
spirv-cross-cpp)
list(APPEND DEFINES "USE_SLANG")
list(APPEND INCLUDES "../external/glslang")
list(APPEND DEFINES "VK_USE_PLATFORM_XLIB_KHR"
"VK_USE_PLATFORM_WAYLAND_KHR"
"VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1"
"VMA_DYNAMIC_VULKAN_FUNCTIONS=1"
"VMA_STATIC_VULKAN_FUNCTIONS=0")
list(APPEND INCLUDES ../external/vulkan-headers/include)
list(APPEND INCLUDES ../external/VulkanMemoryAllocator-Hpp/include)
list(APPEND INCLUDES ../external/stb)
list(APPEND SOURCES ../external/stb/stb_image_implementation.cpp)
list(APPEND SOURCES ../vulkan/slang_helpers.cpp
../vulkan/slang_helpers.hpp
../vulkan/slang_shader.cpp
../vulkan/slang_shader.hpp
../vulkan/slang_preset.cpp
../vulkan/slang_preset.hpp
../vulkan/slang_preset_ini.cpp
../vulkan/slang_preset_ini.hpp
../vulkan/vulkan_hpp_storage.cpp
../vulkan/vk_mem_alloc_implementation.cpp
../vulkan/vulkan_context.cpp
../vulkan/vulkan_context.hpp
../vulkan/vulkan_texture.cpp
../vulkan/vulkan_texture.hpp
../vulkan/vulkan_swapchain.cpp
../vulkan/vulkan_swapchain.hpp
../vulkan/vulkan_slang_pipeline.cpp
../vulkan/vulkan_slang_pipeline.hpp
../vulkan/vulkan_pipeline_image.cpp
../vulkan/vulkan_pipeline_image.hpp
../vulkan/vulkan_shader_chain.cpp
../vulkan/vulkan_shader_chain.hpp
../vulkan/vulkan_simple_output.hpp
../vulkan/vulkan_simple_output.cpp
../vulkan/std_chrono_throttle.cpp
../vulkan/std_chrono_throttle.hpp
src/gtk_display_driver_vulkan.cpp
src/gtk_display_driver_vulkan.h)
endif()
if(USE_WAYLAND)
@ -95,7 +142,11 @@ if(USE_WAYLAND)
list(APPEND DEFINES "USE_WAYLAND")
list(APPEND SOURCES src/gtk_wayland_egl_context.cpp
src/gtk_wayland_egl_context.h
src/wayland-idle-inhibit-unstable-v1.c)
src/gtk_wayland_surface.cpp
src/gtk_wayland_surface.h
src/wayland-idle-inhibit-unstable-v1.c
src/viewporter-client-protocol.c
src/fractional-scale-v1.c)
list(APPEND ARGS ${WAYLAND_CFLAGS})
list(APPEND LIBS ${WAYLAND_LIBRARIES})
endif()
@ -195,6 +246,8 @@ list(APPEND SOURCES
src/gtk_display_driver_gtk.h
src/gtk_display_driver.h
src/gtk_display.h
src/threadpool.cpp
src/threadpool.h
src/gtk_file.cpp
src/gtk_file.h
src/gtk_builder_window.cpp
@ -259,7 +312,6 @@ list(APPEND SOURCES
../stream.cpp
../conffile.cpp
../bsx.cpp
../logger.cpp
../snapshot.cpp
../screenshot.cpp
../movie.cpp
@ -275,7 +327,7 @@ list(APPEND SOURCES
../netplay.cpp
../server.cpp
../loadzip.cpp
../compat.cpp
../fscompat.cpp
src/gtk_netplay_dialog.cpp
src/gtk_netplay_dialog.h
src/gtk_netplay.cpp
@ -283,6 +335,9 @@ list(APPEND SOURCES
src/background_particles.cpp
src/background_particles.h)
list(APPEND SOURCES ../external/fmt/src/format.cc)
list(APPEND INCLUDES ../external/fmt/include)
set(LIBJMA_SOURCES
../jma/s9x-jma.cpp
../jma/7zlzma.cpp
@ -297,6 +352,7 @@ set(LIBJMA_SOURCES
add_library(jma ${LIBJMA_SOURCES})
target_include_directories(jma PRIVATE ${INCLUDES})
target_compile_options(jma PUBLIC ${ARGS})
list(APPEND LIBS jma)
add_executable(sourcify src/sourcify.c)
@ -316,6 +372,26 @@ target_compile_options(snes9x-gtk PRIVATE ${ARGS})
target_link_libraries(snes9x-gtk PRIVATE ${LIBS})
target_compile_definitions(snes9x-gtk PRIVATE ${DEFINES})
if(USE_SLANG)
add_executable(slang_test ../vulkan/slang_helpers.cpp
../vulkan/slang_helpers.hpp
../vulkan/slang_shader.cpp
../vulkan/slang_shader.hpp
../vulkan/slang_preset.cpp
../vulkan/slang_preset.hpp
../vulkan/slang_preset_ini.cpp
../vulkan/slang_preset_ini.hpp
../vulkan/vulkan_hpp_storage.cpp
../vulkan/slang_preset_test.cpp
../conffile.cpp
../stream.cpp)
target_include_directories(slang_test PRIVATE ${INCLUDES})
target_compile_options(slang_test PRIVATE ${ARGS})
target_compile_definitions(slang_test PRIVATE ${DEFINES})
target_link_libraries(slang_test PRIVATE ${LIBS})
endif()
install(TARGETS snes9x-gtk)
install(FILES ../data/cheats.bml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_INSTALL_DATADIR})
install(FILES data/snes9x-gtk.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
@ -325,4 +401,4 @@ install(FILES data/snes9x_32x32.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/ico
install(FILES data/snes9x_64x64.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps RENAME snes9x.png)
install(FILES data/snes9x_128x128.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps RENAME snes9x.png)
install(FILES data/snes9x_256x256.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps RENAME snes9x.png)
install(FILES data/snes9x.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps)
install(FILES data/snes9x.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps)

View File

@ -1 +0,0 @@
../external

View File

@ -1,415 +0,0 @@
project('snes9x-gtk',
['c', 'cpp'],
version: '1.61',
meson_version: '>=0.56.2',
subproject_dir: 'external',
default_options: ['cpp_std=c++17'])
args = ['-DSNES9X_GTK', '-DUNZIP_SUPPORT', '-DNETPLAY_SUPPORT', '-DJMA_SUPPORT', '-Wall', '-W', '-Wno-unused-parameter']
srcs = []
deps = []
includes = ['../apu/bapu', '../', 'src']
warns = []
libs = []
prefix = get_option('prefix')
localedir = join_paths(prefix, get_option('localedir'))
datadir = get_option('datadir')
appdatadir = get_option ('appdatadir')
if appdatadir == ''
appdatadir = join_paths(prefix, datadir, 'snes9x')
else
appdatadir = join_paths(prefix, datadir, appdatadir)
endif
args += [ '-DDATADIR="' + appdatadir + '"', '-DSNES9XLOCALEDIR="' + localedir + '"' ]
subdir('data')
subdir('po')
sdl2_dep = dependency('sdl2')
deps += sdl2_dep
c_compiler = meson.get_compiler('c')
if c_compiler.version().version_compare('>=7.0.0') and c_compiler.get_id() == 'gcc'
args += '-Wno-format-truncation'
endif
gtk_dep = dependency('gtkmm-3.0', version: '>= 3.22')
deps += gtk_dep
gthread_dep = dependency('gthread-2.0')
deps += gthread_dep
x11_dep = c_compiler.find_library('X11')
xext_dep = c_compiler.find_library('Xext')
dl_dep = c_compiler.find_library('dl')
deps += x11_dep
deps += xext_dep
deps += dl_dep
xrandr_dep = dependency('xrandr')
deps += xrandr_dep
opengl = get_option('opengl')
if opengl
opengl_dep = dependency('epoxy', required: false)
if opengl_dep.found()
args += '-DUSE_OPENGL'
srcs += [ 'src/gtk_display_driver_opengl.cpp',
'src/gtk_display_driver_opengl.h',
'src/gtk_glx_context.cpp',
'src/gtk_glx_context.h',
'../shaders/glsl.cpp',
'../shaders/shader_helpers.cpp',
'src/gtk_shader_parameters.cpp' ]
deps += opengl_dep
else
opengl = false
warns += 'libepoxy not found. OpenGL will disabled.'
endif
endif
slang = get_option('slang')
if slang and opengl
cmake = import('cmake')
glslang_opt_var = cmake.subproject_options()
glslang_opt_var.add_cmake_defines({'BUILD_TESTING': false})
glslang_pro = cmake.subproject('glslang', options: glslang_opt_var)
# deps += glslang_pro.dependency('GenericCodeGen')
deps += glslang_pro.dependency('glslang')
# deps += glslang_pro.dependency('MachineIndependent')
deps += glslang_pro.dependency('OGLCompiler')
deps += glslang_pro.dependency('HLSL')
deps += glslang_pro.dependency('OSDependent')
deps += glslang_pro.dependency('SPIRV')
deps += glslang_pro.dependency('glslang-default-resource-limits')
spirv_cross_opt_var = cmake.subproject_options()
spirv_cross_opt_var.add_cmake_defines({'SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS': true})
spirv_cross_pro = cmake.subproject('SPIRV-Cross', options: spirv_cross_opt_var)
deps += spirv_cross_pro.dependency('spirv-cross-core')
deps += spirv_cross_pro.dependency('spirv-cross-glsl')
deps += spirv_cross_pro.dependency('spirv-cross-reflect')
deps += spirv_cross_pro.dependency('spirv-cross-cpp')
args += ['-DUSE_SLANG']
srcs += '../shaders/slang.cpp'
includes += '../external/glslang'
endif
wayland = get_option('wayland')
if wayland
wayland_client_dep = dependency('wayland-client', required: false)
wayland_dep = dependency('wayland-egl', required: false)
if wayland_dep.found() and wayland_client_dep.found()
args += '-DUSE_WAYLAND'
srcs += ['src/gtk_wayland_egl_context.cpp', 'src/gtk_wayland_egl_context.h', 'src/wayland-idle-inhibit-unstable-v1.c']
deps += [wayland_dep, wayland_client_dep]
else
wayland = false
warns += 'wayland-egl not found. Wayland will be disabled.'
endif
endif
xv = get_option('xv')
if xv
xv_dep = dependency('xv', required: false)
if xv_dep.found()
args += '-DUSE_XV'
srcs += ['src/gtk_display_driver_xv.cpp', 'src/gtk_display_driver_xv.h']
deps += xv_dep
else
xv = false
warns += 'XV/XVideo was not found. It will be disabled.'
endif
endif
portaudio = get_option('portaudio')
if portaudio
portaudio_dep = dependency('portaudio-2.0', version: '>= 10', required: false)
if portaudio_dep.found()
args += '-DUSE_PORTAUDIO'
srcs += ['src/gtk_sound_driver_portaudio.cpp', 'src/gtk_sound_driver_portaudio.h']
deps += portaudio_dep
else
portaudio = false
warns += 'PortAudio was not found. It will disabled.'
endif
endif
oss = get_option('oss')
if oss
if c_compiler.has_header('sys/soundcard.h')
args += '-DUSE_OSS'
srcs += ['src/gtk_sound_driver_oss.cpp', 'src/gtk_sound_driver_oss.h']
else
oss = false
warns += 'OSS not found. It will be disabled.'
endif
endif
alsa = get_option('alsa')
if alsa
alsa_dep = dependency('alsa', required: false)
if alsa_dep.found()
args += '-DUSE_ALSA'
srcs += ['src/gtk_sound_driver_alsa.cpp', 'src/gtk_sound_driver_alsa.h']
deps += alsa_dep
else
alsa = false
warns += 'ALSA not found. It will be disabled.'
endif
endif
pulseaudio = get_option('pulseaudio')
if pulseaudio
pulseaudio_dep = dependency('libpulse', required: false)
if pulseaudio_dep.found()
args += '-DUSE_PULSEAUDIO'
srcs += ['src/gtk_sound_driver_pulse.cpp', 'src/gtk_sound_driver_pulse.h']
deps += pulseaudio_dep
else
pulseaudio = false
warns += 'PulseAudio not found. Disabling.'
endif
endif
screenshot = get_option('screenshot')
if screenshot
screenshot_dep = dependency('libpng', required: false)
if screenshot_dep.found()
args += '-DHAVE_LIBPNG'
deps += screenshot_dep
else
screenshot = false
warns += 'libpng not found. Disabling screenshot support.'
endif
endif
systemzip_dep = dependency('minizip', required: false)
systemzip = get_option('system-zip')
if systemzip and systemzip_dep.found()
args += '-DSYSTEM_ZIP'
deps += systemzip_dep
else
systemzip = false
includes += '../unzip'
srcs += ['../unzip/unzip.c', '../unzip/ioapi.c', '../unzip/zip.c']
endif
zlib = get_option('zlib')
if zlib
zlib_dep = dependency('zlib', required: false)
if zlib_dep.found()
args += '-DZLIB'
deps += zlib_dep
else
zlib = false
warns += 'zlib not found. Disabling.'
endif
endif
if get_option('dangerous-hacks')
warns += 'Dangerous hacks are enabled. Don\'t complain if things break!'
args += '-DALLOW_CPU_OVERCLOCK'
endif
if get_option('hq2x')
args += '-DUSE_HQ2X'
srcs += ['../filter/hq2x.cpp', '../filter/hq2x.h']
endif
if get_option('xbrz')
args += '-DUSE_XBRZ'
srcs += ['../filter/xbrz.cpp', '../filter/xbrz.h', 'src/filter_xbrz.cpp', 'src/filter_xbrz.h']
endif
args += ['-DHAVE_MKSTEMP', '-DHAVE_STRINGS_H', '-DHAVE_STDINT_H', '-DRIGHTSHIFT_IS_SAR']
srcs += [
'src/gtk_sound_driver.h',
'../filter/2xsai.cpp',
'../filter/2xsai.h',
'../filter/epx.cpp',
'../filter/epx.h',
'src/filter_epx_unsafe.h',
'src/filter_epx_unsafe.cpp',
'src/gtk_binding.cpp',
'src/gtk_binding.h',
'src/gtk_cheat.cpp',
'src/gtk_cheat.h',
'src/gtk_config.cpp',
'src/gtk_config.h',
'src/gtk_control.cpp',
'src/gtk_control.h',
'src/gtk_display.cpp',
'src/gtk_display_driver_gtk.cpp',
'src/gtk_display_driver_gtk.h',
'src/gtk_display_driver.h',
'src/gtk_display.h',
'src/gtk_file.cpp',
'src/gtk_file.h',
'src/gtk_builder_window.cpp',
'src/gtk_builder_window.h',
'src/gtk_preferences.cpp',
'src/gtk_preferences.h',
'src/gtk_s9xcore.h',
'src/gtk_s9x.cpp',
'src/gtk_s9x.h',
'src/gtk_s9xwindow.cpp',
'src/gtk_s9xwindow.h',
'src/gtk_sound.cpp',
'src/gtk_sound.h',
'src/gtk_splash.cpp',
'../filter/snes_ntsc_config.h',
'../filter/snes_ntsc.h',
'../filter/snes_ntsc_impl.h',
'../filter/snes_ntsc.c',
'src/gtk_compat.h',
'src/gtk_sound_driver_sdl.h',
'src/gtk_sound_driver_sdl.cpp',
'../fxinst.cpp',
'../fxemu.cpp',
'../fxdbg.cpp',
'../c4.cpp',
'../c4emu.cpp',
'../apu/apu.cpp',
'../apu/bapu/dsp/sdsp.cpp',
'../apu/bapu/smp/smp.cpp',
'../apu/bapu/smp/smp_state.cpp',
'../msu1.cpp',
'../msu1.h',
'../dsp.cpp',
'../dsp1.cpp',
'../dsp2.cpp',
'../dsp3.cpp',
'../dsp4.cpp',
'../spc7110.cpp',
'../obc1.cpp',
'../seta.cpp',
'../seta010.cpp',
'../seta011.cpp',
'../seta018.cpp',
'../controls.cpp',
'../crosshairs.cpp',
'../cpu.cpp',
'../sa1.cpp',
'../debug.cpp',
'../sdd1.cpp',
'../tile.cpp',
'../tileimpl-n1x1.cpp',
'../tileimpl-n2x1.cpp',
'../tileimpl-h2x1.cpp',
'../srtc.cpp',
'../gfx.cpp',
'../memmap.cpp',
'../clip.cpp',
'../ppu.cpp',
'../dma.cpp',
'../snes9x.cpp',
'../globals.cpp',
'../stream.cpp',
'../conffile.cpp',
'../bsx.cpp',
'../logger.cpp',
'../snapshot.cpp',
'../screenshot.cpp',
'../movie.cpp',
'../statemanager.cpp',
'../sha256.cpp',
'../bml.cpp',
'../cpuops.cpp',
'../cpuexec.cpp',
'../sa1cpu.cpp',
'../cheats.cpp',
'../cheats2.cpp',
'../sdd1emu.cpp',
'../netplay.cpp',
'../server.cpp',
'../loadzip.cpp',
'../compat.cpp',
'src/gtk_netplay_dialog.cpp',
'src/gtk_netplay_dialog.h',
'src/gtk_netplay.cpp',
'src/gtk_netplay.h',
'src/background_particles.cpp',
'src/background_particles.h'
]
libjma_srcs = [
'../jma/s9x-jma.cpp',
'../jma/7zlzma.cpp',
'../jma/crc32.cpp',
'../jma/iiostrm.cpp',
'../jma/inbyte.cpp',
'../jma/jma.cpp',
'../jma/lzma.cpp',
'../jma/lzmadec.cpp',
'../jma/winout.cpp'
]
libjma = static_library('jma',
libjma_srcs,
c_args: args,
cpp_args: args,
include_directories: include_directories(includes))
libs += libjma
sourcify = executable('sourcify', 'src/sourcify.c', native: true)
gtk_snes9x_ui_cpp = custom_target('sourcify',
input: 'src/snes9x.ui',
output: 'gtk_snes9x_ui.cpp',
command: [sourcify, '@INPUT@', '@OUTPUT@', 'snes9x_ui'])
mini_icon = custom_target('mini_icon',
input: 'data/mini_icon.png',
output: 'mini_icon.cpp',
command: [sourcify, '@INPUT@', '@OUTPUT@', 'mini_icon'])
snes9x_gtk = executable('snes9x-gtk',
srcs,
gtk_snes9x_ui_cpp,
mini_icon,
c_args: args,
cpp_args: args,
dependencies: deps,
include_directories: include_directories(includes),
link_with: libs,
install: true)
summary = [
'Snes9x GTK+ Build Configuration',
'[Locations] prefix: ' + prefix,
' datadir: ' + datadir,
' appdatadir: ' + appdatadir,
' localedir: ' + localedir,
'[Options] Build type: ' + get_option('buildtype'),
' Wayland: ' + wayland.to_string(),
' OpenGL: ' + opengl.to_string(),
' slang shaders: ' + slang.to_string(),
' XVideo: ' + xv.to_string(),
' ALSA: ' + alsa.to_string(),
' Open Sound System: ' + oss.to_string(),
' PulseAudio: ' + pulseaudio.to_string(),
' PortAudio: ' + portaudio.to_string(),
' HQ2X filter: ' + get_option('hq2x').to_string(),
' xBRZ filter: ' + get_option('xbrz').to_string(),
' Screenshot saving: ' + screenshot.to_string(),
' zlib compression: ' + zlib.to_string(),
' System minizip: ' + systemzip.to_string(),
]
summary += warns
message('\n'.join(summary))

View File

@ -1,16 +0,0 @@
option('opengl', type: 'boolean', value: true, description: 'Build support for OpenGL')
option('slang', type: 'boolean', value: true, description: 'Build support for slang-type shaders')
option('xv', type: 'boolean', value: true, description: 'Build support for XV')
option('portaudio', type: 'boolean', value: true, description: 'Build PortAudio sound driver')
option('oss', type: 'boolean', value: true, description: 'Build OSS sound driver')
option('alsa', type: 'boolean', value: true, description: 'Build ALSA sound driver')
option('pulseaudio', type: 'boolean', value: true, description: 'Build PulseAudio sound driver')
option('debugger', type: 'boolean', value: true, description: 'Enable Snes9x Debugger')
option('hq2x', type: 'boolean', value: true, description: 'Enable the HQ2x filters')
option('xbrz', type: 'boolean', value: true, description: 'Enable the xBRZ filters')
option('zlib', type: 'boolean', value: true, description: 'Enable gzip compression')
option('system-zip', type: 'boolean', value: true, description: 'Build using system minizip library')
option('screenshot', type: 'boolean', value: true, description: 'Enable screenshots')
option('wayland', type: 'boolean', value: true, description: 'Build support for Wayland')
option('dangerous-hacks', type: 'boolean', value: false, description: 'Allow dangerous hacks to be enabled')
option('appdatadir', type: 'string' , value: '', description: 'Snes9x-only data directory (default: datadir/snes9x)')

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +0,0 @@
i18n = import('i18n')
add_project_arguments('-DGETTEXT_PACKAGE="snes9x-gtk"',
language: ['c', 'cpp']
)
i18n.gettext(meson.project_name(), preset: 'glib')

File diff suppressed because it is too large Load Diff

View File

@ -4,13 +4,6 @@
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include "snes9x.h"
#include "memmap.h"
#include "cpuops.h"
#include "dma.h"
#include "apu/apu.h"
#include "fxemu.h"
#include "snapshot.h"
#ifdef DEBUGGER
#include "debug.h"
#include "missing.h"
@ -23,11 +16,11 @@
#define AVERAGE_565(el0, el1) (((el0) & (el1)) + ((((el0) ^ (el1)) & 0xF7DE) >> 1))
/* Allows vertical overlap. We need this to avoid seams when threading */
void EPX_16_unsafe (uint8 *srcPtr,
uint32 srcPitch,
uint8 *dstPtr,
uint32 dstPitch,
int width,
void EPX_16_unsafe (uint8 *srcPtr,
int srcPitch,
uint8 *dstPtr,
int dstPitch,
int width,
int height)
{
uint16 colorX, colorA, colorB, colorC, colorD;
@ -120,9 +113,9 @@ void EPX_16_unsafe (uint8 *srcPtr,
/* Blends with edge pixel instead of just using it directly. */
void EPX_16_smooth_unsafe (uint8 *srcPtr,
uint32 srcPitch,
int srcPitch,
uint8 *dstPtr,
uint32 dstPitch,
int dstPitch,
int width,
int height)
{

View File

@ -7,7 +7,7 @@
#ifndef __FILTER_EPX_UNSAFE_H
#define __FILTER_EPX_UNSAFE_H
void EPX_16_unsafe (uint8 *, uint32, uint8 *, uint32, int, int);
void EPX_16_smooth_unsafe (uint8 *, uint32, uint8 *, uint32, int, int);
void EPX_16_unsafe (uint8 *, int, uint8 *, int, int, int);
void EPX_16_smooth_unsafe (uint8 *, int, uint8 *, int, int, int);
#endif /* __FILTER_EPX_UNSAFE_H */

View File

@ -103,17 +103,17 @@ void xBRZ(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int wi
}
}
void filter_2xBRZ(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
void filter_2xBRZ(uint8 *srcPtr, int srcPitch, uint8 *dstPtr, int dstPitch, int width, int height)
{
xBRZ(srcPtr, srcPitch, dstPtr, dstPitch, width, height, 2);
}
void filter_3xBRZ(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
void filter_3xBRZ(uint8 *srcPtr, int srcPitch, uint8 *dstPtr, int dstPitch, int width, int height)
{
xBRZ(srcPtr, srcPitch, dstPtr, dstPitch, width, height, 3);
}
void filter_4xBRZ(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
void filter_4xBRZ(uint8 *srcPtr, int srcPitch, uint8 *dstPtr, int dstPitch, int width, int height)
{
xBRZ(srcPtr, srcPitch, dstPtr, dstPitch, width, height, 4);
}

View File

@ -7,8 +7,8 @@
#ifndef _filter_xbrz_h_
#define _filter_xbrz_h_
void filter_2xBRZ (uint8 *, uint32, uint8 *, uint32, int, int);
void filter_3xBRZ (uint8 *, uint32, uint8 *, uint32, int, int);
void filter_4xBRZ (uint8 *, uint32, uint8 *, uint32, int, int);
void filter_2xBRZ (uint8 *, int, uint8 *, int, int, int);
void filter_3xBRZ (uint8 *, int, uint8 *, int, int, int);
void filter_4xBRZ (uint8 *, int, uint8 *, int, int, int);
#endif

View File

@ -0,0 +1,73 @@
/* Generated by wayland-scanner 1.19.0 */
/*
* Copyright © 2022 Kenny Levinsen
*
* 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 (including the next
* paragraph) 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.
*/
#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"
#ifndef __has_attribute
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
#endif
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
#else
#define WL_PRIVATE
#endif
extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface wp_fractional_scale_v1_interface;
static const struct wl_interface *fractional_scale_v1_types[] = {
NULL,
&wp_fractional_scale_v1_interface,
&wl_surface_interface,
};
static const struct wl_message wp_fractional_scale_manager_v1_requests[] = {
{ "destroy", "", fractional_scale_v1_types + 0 },
{ "get_fractional_scale", "no", fractional_scale_v1_types + 1 },
};
WL_PRIVATE const struct wl_interface wp_fractional_scale_manager_v1_interface = {
"wp_fractional_scale_manager_v1", 1,
2, wp_fractional_scale_manager_v1_requests,
0, NULL,
};
static const struct wl_message wp_fractional_scale_v1_requests[] = {
{ "destroy", "", fractional_scale_v1_types + 0 },
};
static const struct wl_message wp_fractional_scale_v1_events[] = {
{ "preferred_scale", "u", fractional_scale_v1_types + 0 },
};
WL_PRIVATE const struct wl_interface wp_fractional_scale_v1_interface = {
"wp_fractional_scale_v1", 1,
1, wp_fractional_scale_v1_requests,
1, wp_fractional_scale_v1_events,
};

View File

@ -0,0 +1,268 @@
/* Generated by wayland-scanner 1.19.0 */
#ifndef FRACTIONAL_SCALE_V1_CLIENT_PROTOCOL_H
#define FRACTIONAL_SCALE_V1_CLIENT_PROTOCOL_H
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @page page_fractional_scale_v1 The fractional_scale_v1 protocol
* Protocol for requesting fractional surface scales
*
* @section page_desc_fractional_scale_v1 Description
*
* This protocol allows a compositor to suggest for surfaces to render at
* fractional scales.
*
* A client can submit scaled content by utilizing wp_viewport. This is done by
* creating a wp_viewport object for the surface and setting the destination
* rectangle to the surface size before the scale factor is applied.
*
* The buffer size is calculated by multiplying the surface size by the
* intended scale.
*
* The wl_surface buffer scale should remain set to 1.
*
* If a surface has a surface-local size of 100 px by 50 px and wishes to
* submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should
* be used and the wp_viewport destination rectangle should be 100 px by 50 px.
*
* For toplevel surfaces, the size is rounded halfway away from zero. The
* rounding algorithm for subsurface position and size is not defined.
*
* @section page_ifaces_fractional_scale_v1 Interfaces
* - @subpage page_iface_wp_fractional_scale_manager_v1 - fractional surface scale information
* - @subpage page_iface_wp_fractional_scale_v1 - fractional scale interface to a wl_surface
* @section page_copyright_fractional_scale_v1 Copyright
* <pre>
*
* Copyright © 2022 Kenny Levinsen
*
* 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 (including the next
* paragraph) 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.
* </pre>
*/
struct wl_surface;
struct wp_fractional_scale_manager_v1;
struct wp_fractional_scale_v1;
#ifndef WP_FRACTIONAL_SCALE_MANAGER_V1_INTERFACE
#define WP_FRACTIONAL_SCALE_MANAGER_V1_INTERFACE
/**
* @page page_iface_wp_fractional_scale_manager_v1 wp_fractional_scale_manager_v1
* @section page_iface_wp_fractional_scale_manager_v1_desc Description
*
* A global interface for requesting surfaces to use fractional scales.
* @section page_iface_wp_fractional_scale_manager_v1_api API
* See @ref iface_wp_fractional_scale_manager_v1.
*/
/**
* @defgroup iface_wp_fractional_scale_manager_v1 The wp_fractional_scale_manager_v1 interface
*
* A global interface for requesting surfaces to use fractional scales.
*/
extern const struct wl_interface wp_fractional_scale_manager_v1_interface;
#endif
#ifndef WP_FRACTIONAL_SCALE_V1_INTERFACE
#define WP_FRACTIONAL_SCALE_V1_INTERFACE
/**
* @page page_iface_wp_fractional_scale_v1 wp_fractional_scale_v1
* @section page_iface_wp_fractional_scale_v1_desc Description
*
* An additional interface to a wl_surface object which allows the compositor
* to inform the client of the preferred scale.
* @section page_iface_wp_fractional_scale_v1_api API
* See @ref iface_wp_fractional_scale_v1.
*/
/**
* @defgroup iface_wp_fractional_scale_v1 The wp_fractional_scale_v1 interface
*
* An additional interface to a wl_surface object which allows the compositor
* to inform the client of the preferred scale.
*/
extern const struct wl_interface wp_fractional_scale_v1_interface;
#endif
#ifndef WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM
#define WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM
enum wp_fractional_scale_manager_v1_error {
/**
* the surface already has a fractional_scale object associated
*/
WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS = 0,
};
#endif /* WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM */
#define WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY 0
#define WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE 1
/**
* @ingroup iface_wp_fractional_scale_manager_v1
*/
#define WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_wp_fractional_scale_manager_v1
*/
#define WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE_SINCE_VERSION 1
/** @ingroup iface_wp_fractional_scale_manager_v1 */
static inline void
wp_fractional_scale_manager_v1_set_user_data(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) wp_fractional_scale_manager_v1, user_data);
}
/** @ingroup iface_wp_fractional_scale_manager_v1 */
static inline void *
wp_fractional_scale_manager_v1_get_user_data(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) wp_fractional_scale_manager_v1);
}
static inline uint32_t
wp_fractional_scale_manager_v1_get_version(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1)
{
return wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1);
}
/**
* @ingroup iface_wp_fractional_scale_manager_v1
*
* Informs the server that the client will not be using this protocol
* object anymore. This does not affect any other objects,
* wp_fractional_scale_v1 objects included.
*/
static inline void
wp_fractional_scale_manager_v1_destroy(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1)
{
wl_proxy_marshal((struct wl_proxy *) wp_fractional_scale_manager_v1,
WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY);
wl_proxy_destroy((struct wl_proxy *) wp_fractional_scale_manager_v1);
}
/**
* @ingroup iface_wp_fractional_scale_manager_v1
*
* Create an add-on object for the the wl_surface to let the compositor
* request fractional scales. If the given wl_surface already has a
* wp_fractional_scale_v1 object associated, the fractional_scale_exists
* protocol error is raised.
*/
static inline struct wp_fractional_scale_v1 *
wp_fractional_scale_manager_v1_get_fractional_scale(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1, struct wl_surface *surface)
{
struct wl_proxy *id;
id = wl_proxy_marshal_constructor((struct wl_proxy *) wp_fractional_scale_manager_v1,
WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE, &wp_fractional_scale_v1_interface, NULL, surface);
return (struct wp_fractional_scale_v1 *) id;
}
/**
* @ingroup iface_wp_fractional_scale_v1
* @struct wp_fractional_scale_v1_listener
*/
struct wp_fractional_scale_v1_listener {
/**
* notify of new preferred scale
*
* Notification of a new preferred scale for this surface that
* the compositor suggests that the client should use.
*
* The sent scale is the numerator of a fraction with a denominator
* of 120.
* @param scale the new preferred scale
*/
void (*preferred_scale)(void *data,
struct wp_fractional_scale_v1 *wp_fractional_scale_v1,
uint32_t scale);
};
/**
* @ingroup iface_wp_fractional_scale_v1
*/
static inline int
wp_fractional_scale_v1_add_listener(struct wp_fractional_scale_v1 *wp_fractional_scale_v1,
const struct wp_fractional_scale_v1_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) wp_fractional_scale_v1,
(void (**)(void)) listener, data);
}
#define WP_FRACTIONAL_SCALE_V1_DESTROY 0
/**
* @ingroup iface_wp_fractional_scale_v1
*/
#define WP_FRACTIONAL_SCALE_V1_PREFERRED_SCALE_SINCE_VERSION 1
/**
* @ingroup iface_wp_fractional_scale_v1
*/
#define WP_FRACTIONAL_SCALE_V1_DESTROY_SINCE_VERSION 1
/** @ingroup iface_wp_fractional_scale_v1 */
static inline void
wp_fractional_scale_v1_set_user_data(struct wp_fractional_scale_v1 *wp_fractional_scale_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) wp_fractional_scale_v1, user_data);
}
/** @ingroup iface_wp_fractional_scale_v1 */
static inline void *
wp_fractional_scale_v1_get_user_data(struct wp_fractional_scale_v1 *wp_fractional_scale_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) wp_fractional_scale_v1);
}
static inline uint32_t
wp_fractional_scale_v1_get_version(struct wp_fractional_scale_v1 *wp_fractional_scale_v1)
{
return wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_v1);
}
/**
* @ingroup iface_wp_fractional_scale_v1
*
* Destroy the fractional scale object. When this object is destroyed,
* preferred_scale events will no longer be sent.
*/
static inline void
wp_fractional_scale_v1_destroy(struct wp_fractional_scale_v1 *wp_fractional_scale_v1)
{
wl_proxy_marshal((struct wl_proxy *) wp_fractional_scale_v1,
WP_FRACTIONAL_SCALE_V1_DESTROY);
wl_proxy_destroy((struct wl_proxy *) wp_fractional_scale_v1);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -9,6 +9,7 @@
#include <string.h>
#include "gtk_s9x.h"
#include "gtk_binding.h"
#include "fmt/format.h"
Binding::Binding()
{
@ -17,7 +18,22 @@ Binding::Binding()
Binding::Binding(GdkEventKey *event)
{
event->keyval = gdk_keyval_to_lower(event->keyval);
GdkKeymapKey* keys;
guint* keyvals;
int n_entries;
gdk_keymap_get_entries_for_keycode(
gdk_keymap_get_for_display(top_level->window->get_display()->gobj()),
event->hardware_keycode,
&keys,
&keyvals,
&n_entries
);
event->keyval = keyvals[0];
g_free(keys);
g_free(keyvals);
value = BINDING_KEY | (event->keyval & BINDING_KEY_MASK);
/* Strip modifiers from modifiers */
@ -213,66 +229,53 @@ Binding::Binding(const char *raw_string)
std::string Binding::as_string()
{
char buf[PATH_MAX];
to_string(buf, false);
return std::string(buf);
return to_string(false);
}
void Binding::to_string(char *str, bool translate)
std::string Binding::to_string(bool translate)
{
char buf[256];
std::string str;
#undef _
#define _(String) translate ? gettext(String) : (String)
str[0] = '\0';
#undef maybegettext
#define maybegettext(String) translate ? gettext(String) : (String)
if (is_key())
{
char *keyval_name = NULL;
unsigned int keyval = gdk_keyval_to_lower(get_key());
keyval_name = gdk_keyval_name(keyval);
char *keyval_name = gdk_keyval_name(keyval);
if (keyval_name == NULL)
{
sprintf(buf, _("Unknown"));
}
if (keyval_name == nullptr)
str = maybegettext("Unknown");
else
{
memset(buf, 0, 256);
strncpy(buf,
keyval_name,
255);
}
str = keyval_name;
if (translate)
for (int i = 0; buf[i]; i++)
if (buf[i] == '_')
buf[i] = ' ';
for (char &c : str)
if (c == '_')
c = ' ';
sprintf(str, _("Keyboard %s%s%s%s"),
(value & BINDING_SHIFT) ? "Shift+" : "",
(value & BINDING_CTRL) ? "Ctrl+" : "",
(value & BINDING_ALT) ? "Alt+" : "",
buf);
str = fmt::format(maybegettext("Keyboard {}{}{}{}"),
(value & BINDING_SHIFT) ? "Shift+" : "",
(value & BINDING_CTRL) ? "Ctrl+" : "",
(value & BINDING_ALT) ? "Alt+" : "",
str);
}
else if (is_joy())
{
if ((get_key()) >= 512)
sprintf(buf,
_("Axis %u %s %u%%"),
get_axis(),
is_positive() ? "+" : "-",
get_threshold());
str = fmt::format(maybegettext("Axis {} {} {}%"),
get_axis(),
is_positive() ? "+" : "-",
get_threshold());
else
sprintf(buf, _("Button %u"), get_key());
str = fmt::format(maybegettext("Button {}"), get_key());
sprintf(str, _("Joystick %u %s"), get_device(), buf);
str = fmt::format(maybegettext("Joystick {} {}"), get_device(), str);
}
else
{
sprintf(str, _("Unset"));
}
str = maybegettext("Unset");
return str;
}

View File

@ -44,7 +44,7 @@ class Binding
Binding(unsigned int);
Binding();
Binding(const char *str);
void to_string(char *str, bool translate = true);
std::string to_string(bool translate = true);
std::string as_string();
unsigned int hex();
unsigned int base_hex();

View File

@ -93,6 +93,11 @@ void GtkBuilderWindow::set_entry_text(const char *name, const char *text)
get_object<Gtk::Entry>(name)->set_text(text);
}
void GtkBuilderWindow::set_entry_text(const char *name, const std::string &text)
{
get_object<Gtk::Entry>(name)->set_text(text);
}
float GtkBuilderWindow::get_slider(const char *name)
{
return get_object<Gtk::Range>(name)->get_value();

View File

@ -49,6 +49,7 @@ class GtkBuilderWindow
void set_check(const char *name, bool value);
void set_entry_value(const char *name, unsigned int value);
void set_entry_text(const char *name, const char *text);
void set_entry_text(const char *name, const std::string &text);
void set_combo(const char *name, unsigned char value);
void set_spin(const char *name, double value);
void set_slider(const char *name, float value);

View File

@ -132,20 +132,20 @@ void Snes9xCheats::show()
static void cheat_move(int src, int dst)
{
Cheat.g.insert(Cheat.g.begin() + dst, Cheat.g[src]);
Cheat.group.insert(Cheat.group.begin() + dst, Cheat.group[src]);
if (dst < src)
src++;
Cheat.g.erase(Cheat.g.begin() + src);
Cheat.group.erase(Cheat.group.begin() + src);
}
static void cheat_gather_enabled()
{
unsigned int enabled = 0;
for (unsigned int i = 0; i < Cheat.g.size(); i++)
for (unsigned int i = 0; i < Cheat.group.size(); i++)
{
if (Cheat.g[i].enabled && i >= enabled)
if (Cheat.group[i].enabled && i >= enabled)
{
cheat_move(i, enabled);
enabled++;
@ -199,22 +199,21 @@ void Snes9xCheats::refresh_tree_view()
auto list_size = store->children().size();
if (Cheat.g.size() == 0)
if (Cheat.group.size() == 0)
return;
for (unsigned int i = 0; i < Cheat.g.size() - list_size; i++)
for (unsigned int i = 0; i < Cheat.group.size() - list_size; i++)
store->append();
auto iter = store->children().begin();
for (unsigned int i = 0; i < Cheat.g.size (); i++)
for (unsigned int i = 0; i < Cheat.group.size (); i++)
{
char *str = S9xCheatGroupToText(i);
Glib::ustring description = Cheat.g[i].name[0] == '\0' ? "" :Cheat.g[i].name;
iter->set_value(COLUMN_ENABLED, Cheat.g[i].enabled);
auto str = S9xCheatGroupToText(i);
Glib::ustring description = Cheat.group[i].name[0] == '\0' ? "" :Cheat.group[i].name;
iter->set_value(COLUMN_ENABLED, Cheat.group[i].enabled);
iter->set_value(COLUMN_DESCRIPTION, description);
iter->set_value(COLUMN_CHEAT, Glib::ustring(str));
iter++;
delete[] str;
}
enable_dnd(true);
@ -228,15 +227,14 @@ void Snes9xCheats::add_code()
if (description.empty())
description = _("No description");
if (S9xAddCheatGroup(description.c_str(), code.c_str()) < 0)
if (S9xAddCheatGroup(description, code) < 0)
{
display_errorbox(_("Couldn't find any cheat codes in input."));
return;
}
auto parsed_code = S9xCheatGroupToText(Cheat.g.size() - 1);
auto parsed_code = S9xCheatGroupToText(Cheat.group.size() - 1);
set_entry_text("code_entry", parsed_code);
delete[] parsed_code;
get_object<Gtk::Entry>("code_entry")->grab_focus();
@ -247,7 +245,7 @@ void Snes9xCheats::add_code()
auto selection = get_object<Gtk::TreeView>("cheat_treeview")->get_selection();
Gtk::TreePath path;
path.push_back(Cheat.g.size() - 1);
path.push_back(Cheat.group.size() - 1);
selection->select(path);
auto adj = get_object<Gtk::ScrolledWindow>("cheat_scrolledwindow")->get_vadjustment();
@ -288,53 +286,27 @@ void Snes9xCheats::search_database()
int result;
int reason = 0;
filename = S9xGetDirectory(CHEAT_DIR);
filename += "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase(filename.c_str())))
for (const auto &dir : { S9xGetDirectory(CHEAT_DIR),
get_config_dir(),
std::string(DATADIR) })
{
refresh_tree_view();
return;
filename = dir + "/cheats.bml";
result = S9xImportCheatsFromDatabase(filename);
if (result == 0)
{
refresh_tree_view();
return;
}
if (result < reason)
reason = result;
}
if (result < reason)
reason = result;
filename = get_config_dir() + "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase(filename.c_str())))
{
refresh_tree_view();
return;
}
if (result < reason)
reason = result;
filename = std::string(DATADIR) + "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase(filename.c_str())))
{
refresh_tree_view();
return;
}
if (result < reason)
reason = result;
filename = S9xGetDirectory(ROM_DIR);
filename += "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase(filename.c_str())))
{
refresh_tree_view();
return;
}
if (result < reason)
reason = result;
auto dialog = Gtk::MessageDialog(*window.get(), reason == -1 ? _("Couldn't Find Cheats Database") : _("No Matching Game Found"), true);
dialog.set_secondary_text(reason == -1 ? _("The database file <b>cheats.bml</b> was not found. It is normally installed with "
"Snes9x, but you may also place a custom copy in your configuration or cheats directory.")
: _("No matching game was found in the databases. If you are using a non-official "
"translation or modified copy, you may be able to find and manually enter the codes."));
"translation or modified copy, you may be able to find and manually enter the codes."), true);
dialog.run();
dialog.hide();
}
@ -348,12 +320,10 @@ void Snes9xCheats::sort_cheats()
void Snes9xCheats::row_activated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column)
{
int index = get_index_from_path(path);
char *cheat_text;
cheat_text = S9xCheatGroupToText(index);
auto cheat_text = S9xCheatGroupToText(index);
set_entry_text("code_entry", cheat_text);
delete[] cheat_text;
set_entry_text("description_entry", Cheat.g[index].name);
set_entry_text("description_entry", Cheat.group[index].name);
}
void Snes9xCheats::toggle_code(const Glib::ustring &path)
@ -383,16 +353,15 @@ void Snes9xCheats::update_code()
if (description.empty())
description = _("No description");
auto parsed_code = S9xCheatValidate(code.c_str());
if (!parsed_code)
auto parsed_code = S9xCheatValidate(code);
if (parsed_code.empty())
{
display_errorbox(_("Couldn't find any cheat codes in input."));
return;
}
S9xModifyCheatGroup(index, description.c_str(), parsed_code);
S9xModifyCheatGroup(index, description, parsed_code);
set_entry_text("code_entry", parsed_code);
delete[] parsed_code;
get_object<Gtk::Entry>("code_entry")->grab_focus();
@ -401,9 +370,9 @@ void Snes9xCheats::update_code()
void Snes9xCheats::disable_all()
{
for (unsigned int i = 0; i < Cheat.g.size(); i++)
for (unsigned int i = 0; i < Cheat.group.size(); i++)
{
if (Cheat.g[i].enabled)
if (Cheat.group[i].enabled)
S9xDisableCheatGroup(i);
}

View File

@ -8,10 +8,11 @@
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <filesystem>
#include "fmt/format.h"
#include "gtk_config.h"
#include "gtk_s9x.h"
#include "gtk_sound.h"
#include "gtk_display.h"
#include "conffile.h"
#include "cheats.h"
@ -19,20 +20,7 @@
#include "netplay.h"
#include "controls.h"
static bool directory_exists(std::string str)
{
DIR *dir;
dir = opendir(str.c_str());
if (dir)
{
closedir(dir);
return true;
}
return false;
}
namespace fs = std::filesystem;
std::string get_config_dir()
{
@ -45,19 +33,21 @@ std::string get_config_dir()
return std::string{".snes9x"};
}
std::string config;
std::string legacy;
fs::path config = env_home;
fs::path legacy = config;
// If XDG_CONFIG_HOME is set, use that, otherwise guess default
if (!env_xdg_config_home)
{
(config += env_home) += "/.config/snes9x";
(legacy += env_home) += "/.snes9x";
config /= ".config/snes9x";
legacy /= ".snes9x";
}
else
config = std::string(env_xdg_config_home) + "/snes9x";
if (directory_exists(legacy) && !directory_exists(config))
{
config = env_xdg_config_home;
config /= "snes9x";
}
if (fs::exists(legacy) && !fs::exists(config))
return legacy;
return config;
@ -75,6 +65,16 @@ void S9xParsePortConfig(ConfigFile &conf, int pass)
Snes9xConfig::Snes9xConfig()
{
joystick_threshold = 40;
xrr_crtc_info = nullptr;
xrr_screen_resources = nullptr;
}
Snes9xConfig::~Snes9xConfig()
{
if (xrr_crtc_info)
XRRFreeCrtcInfo(xrr_crtc_info);
if (xrr_screen_resources)
XRRFreeScreenResources(xrr_screen_resources);
}
int Snes9xConfig::load_defaults()
@ -91,10 +91,11 @@ int Snes9xConfig::load_defaults()
rom_loaded = false;
multithreading = false;
splash_image = SPLASH_IMAGE_STARFIELD;
hw_accel = 0;
display_driver = "opengl";
allow_opengl = false;
allow_xv = false;
allow_xrandr = false;
auto_vrr = false;
force_inverted_byte_order = false;
hires_effect = HIRES_NORMAL;
pause_emulation_on_switch = false;
@ -148,16 +149,10 @@ int Snes9xConfig::load_defaults()
rewind_buffer_size = 0;
Settings.Rewinding = false;
#ifdef USE_OPENGL
sync_to_vblank = true;
use_pbos = true;
pbo_format = 0;
npot_textures = true;
use_shaders = false;
shader_filename.clear();
use_glfinish = false;
use_sync_control = false;
#endif
reduce_input_lag = false;
/* Snes9x Variables */
Settings.MouseMaster = true;
@ -177,7 +172,6 @@ int Snes9xConfig::load_defaults()
Settings.StopEmulation = true;
Settings.FrameTimeNTSC = 16639;
Settings.FrameTimePAL = 20000;
Settings.SupportHiRes = true;
Settings.FrameTime = Settings.FrameTimeNTSC;
Settings.BlockInvalidVRAMAccessMaster = true;
Settings.SoundSync = false;
@ -239,8 +233,9 @@ int Snes9xConfig::save_config_file()
outint("ScanlineFilterIntensity", scanline_filter_intensity, "0: 0%, 1: 12.5%, 2: 25%, 3: 50%, 4: 100%");
outint("HiresEffect", hires_effect, "0: Downscale to low-res, 1: Leave as-is, 2: Upscale low-res screens");
outint("NumberOfThreads", num_threads);
outint("HardwareAcceleration", hw_accel, "0: None, 1: OpenGL, 2: XVideo");
outstring("HardwareAcceleration", display_driver, "none, opengl, xv, vulkan");
outint("SplashBackground", splash_image, "0: Black, 1: Color bars, 2: Pattern, 3: Blue, 4: Default");
outbool("AutoVRR", auto_vrr, "Automatically use the best settings for variable sync in fullscreen mode");
section = "NTSC";
outstring("Hue", std::to_string(ntsc_setup.hue));
@ -256,17 +251,11 @@ int Snes9xConfig::save_config_file()
outbool("MergeFields", ntsc_setup.merge_fields);
outint("ScanlineIntensity", ntsc_scanline_intensity);
#ifdef USE_OPENGL
section = "OpenGL";
outbool("VSync", sync_to_vblank);
outbool("glFinish", use_glfinish);
outbool("SyncControl", use_sync_control);
outbool("UseNonPowerOfTwoTextures", npot_textures);
outbool("ReduceInputLag", reduce_input_lag);
outbool("EnableCustomShaders", use_shaders);
outbool("UsePixelBufferObjects", use_pbos);
outint("PixelBufferObjectBitDepth", pbo_format);
outstring("ShaderFile", shader_filename);
#endif
section = "Sound";
outbool("MuteSound", mute_sound);
@ -403,36 +392,31 @@ int Snes9xConfig::save_config_file()
int Snes9xConfig::load_config_file()
{
struct stat file_info;
ConfigFile cf;
load_defaults();
std::string path = get_config_dir();
fs::path path = get_config_dir();
if (stat(path.c_str(), &file_info))
if (!fs::exists(path))
{
if (mkdir(path.c_str(), 0755))
if (!fs::create_directory(path))
{
fprintf(stderr,
_("Couldn't create config directory: %s\n"),
path.c_str());
fmt::print(stderr, _("Couldn't create config directory: {}\n"), path.string());
return -1;
}
}
else
{
if (!(file_info.st_mode & 0700))
chmod(path.c_str(), file_info.st_mode | 0700);
if ((fs::status(path).permissions() & fs::perms::owner_write) == fs::perms::none)
fs::permissions(path, fs::perms::owner_write, fs::perm_options::add);
}
path = get_config_file_name();
if (stat(path.c_str(), &file_info))
{
// Write an on-disk config file if none exists.
if (!fs::exists(path))
save_config_file();
}
ConfigFile cf;
if (!cf.LoadFile(path.c_str()))
return -1;
@ -472,9 +456,10 @@ int Snes9xConfig::load_config_file()
inbool("ForceInvertedByteOrder", force_inverted_byte_order);
inbool("Multithreading", multithreading);
inint("NumberOfThreads", num_threads);
inint("HardwareAcceleration", hw_accel);
instr("HardwareAcceleration", display_driver);
inbool("BilinearFilter", Settings.BilinearFilter);
inint("SplashBackground", splash_image);
inbool("AutoVRR", auto_vrr);
section = "NTSC";
indouble("Hue", ntsc_setup.hue);
@ -490,17 +475,11 @@ int Snes9xConfig::load_config_file()
inbool("MergeFields", ntsc_setup.merge_fields);
inint("ScanlineIntensity", ntsc_scanline_intensity);
#ifdef USE_OPENGL
section = "OpenGL";
inbool("VSync", sync_to_vblank);
inbool("glFinish", use_glfinish);
inbool("SyncControl", use_sync_control);
inbool("UsePixelBufferObjects", use_pbos);
inint("PixelBufferObjectBitDepth", pbo_format);
inbool("UseNonPowerOfTwoTextures", npot_textures);
inbool("ReduceInputLag", reduce_input_lag);
inbool("EnableCustomShaders", use_shaders);
instr("ShaderFile", shader_filename);
#endif
section = "Sound";
inbool("MuteSound", mute_sound);
@ -664,11 +643,6 @@ int Snes9xConfig::load_config_file()
scale_method = 0;
#endif /* USE_XBRZ */
#ifdef USE_OPENGL
if (pbo_format != 32)
pbo_format = 16;
#endif
if (Settings.SkipFrames == THROTTLE_SOUND_SYNC)
Settings.SoundSync = true;
else

View File

@ -15,12 +15,6 @@
#include <string>
#include <array>
enum {
HWA_NONE = 0,
HWA_OPENGL = 1,
HWA_XV = 2
};
enum {
HIRES_MERGE = 0,
HIRES_NORMAL = 1,
@ -54,6 +48,7 @@ class Snes9xConfig
{
public:
Snes9xConfig();
~Snes9xConfig();
int load_config_file();
int save_config_file();
int load_defaults();
@ -76,6 +71,7 @@ class Snes9xConfig
int hires_effect;
bool force_inverted_byte_order;
int splash_image;
bool auto_vrr;
snes_ntsc_setup_t ntsc_setup;
int ntsc_format;
@ -92,7 +88,7 @@ class Snes9xConfig
float ntsc_merge_fields;
int ntsc_scanline_intensity;
int scanline_filter_intensity;
int hw_accel;
std::string display_driver;
bool allow_opengl;
bool allow_xv;
bool allow_xrandr;
@ -125,6 +121,7 @@ class Snes9xConfig
/* Operational */
std::vector<std::string> sound_drivers;
std::vector<std::string> display_drivers;
int sound_driver;
bool mute_sound;
bool mute_sound_turbo;
@ -154,17 +151,10 @@ class Snes9xConfig
XRRScreenResources *xrr_screen_resources;
XRRCrtcInfo *xrr_crtc_info;
#ifdef USE_OPENGL
bool sync_to_vblank;
bool use_pbos;
int pbo_format;
bool npot_textures;
bool use_shaders;
std::string shader_filename;
bool use_glfinish;
bool use_sync_control;
#endif
bool reduce_input_lag;
JoyDevices joysticks;
int joystick_threshold;

View File

@ -188,8 +188,6 @@ static void swap_controllers_1_2()
static void change_slot(int difference)
{
static char buf[256];
gui_config->current_save_slot += difference;
gui_config->current_save_slot %= 1000;
if (gui_config->current_save_slot < 0)
@ -197,8 +195,8 @@ static void change_slot(int difference)
if (!gui_config->rom_loaded)
return;
snprintf(buf, 256, "State Slot: %d", gui_config->current_save_slot);
S9xSetInfoString(buf);
auto info_string = "State Slot: " + std::to_string(gui_config->current_save_slot);
S9xSetInfoString(info_string.c_str());
GFX.InfoStringTimeout = 60;
}

File diff suppressed because it is too large Load Diff

View File

@ -47,36 +47,6 @@ enum {
NTSC_RGB = 2
};
enum {
ENDIAN_NORMAL = 0,
ENDIAN_SWAPPED = 1
};
enum {
JOB_FILTER = 0,
JOB_CONVERT = 1,
JOB_SCALE_AND_CONVERT = 2,
JOB_CONVERT_YUV = 3,
JOB_CONVERT_MASK = 4
};
typedef struct thread_job_t
{
int operation_type;
uint8 *src_buffer;
int src_pitch;
uint8 *dst_buffer;
int dst_pitch;
int width;
int height;
int bpp;
int inv_rmask;
int inv_gmask;
int inv_bmask;
volatile bool complete;
} thread_job_t;
struct S9xRect
{
int x;
@ -86,7 +56,6 @@ struct S9xRect
};
void S9xRegisterYUVTables(uint8 *y, uint8 *u, uint8 *v);
void S9xSetEndianess(int type);
double S9xGetAspect();
S9xRect S9xApplyAspect(int, int, int, int);
void S9xConvertYUV(void *src_buffer,
@ -118,8 +87,8 @@ void S9xFilter(uint8 *src_buffer,
int dst_pitch,
int &width,
int &height);
void get_filter_scale(int &width, int &height);
void S9xDisplayRefresh(int width, int height);
void apply_filter_scale(int &width, int &height);
void S9xDisplayRefresh();
void S9xReinitDisplay();
void S9xDisplayReconfigure();
void S9xQueryDrivers();

View File

@ -15,13 +15,14 @@ class S9xDisplayDriver
virtual ~S9xDisplayDriver()
{
}
virtual void refresh(int width, int height) = 0;
virtual void refresh() = 0;
virtual int init() = 0;
virtual void deinit() = 0;
virtual void update(uint16_t *buffer, int width, int height, int stride_in_pixels) = 0;
virtual void *get_parameters() = 0;
virtual void save(const char *filename) = 0;
virtual bool is_ready() = 0;
virtual bool can_throttle() { return false; };
protected:
Snes9xWindow *window;

View File

@ -4,7 +4,6 @@
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include "gtk_compat.h"
#include <cairo.h>
#include "gtk_display.h"
#include "gtk_display_driver_gtk.h"
@ -107,7 +106,7 @@ void S9xGTKDisplayDriver::clear()
S9xRect dst;
dst.w = window->last_width;
dst.h = window->last_height;
get_filter_scale(dst.w, dst.h);
apply_filter_scale(dst.w, dst.h);
dst = S9xApplyAspect(dst.w, dst.h, width, height);
if (dst.x > 0)
@ -132,7 +131,7 @@ void S9xGTKDisplayDriver::clear()
window->release_cairo();
}
void S9xGTKDisplayDriver::refresh(int width, int height)
void S9xGTKDisplayDriver::refresh()
{
clear();
}

View File

@ -14,7 +14,7 @@ class S9xGTKDisplayDriver : public S9xDisplayDriver
{
public:
S9xGTKDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height);
void refresh();
int init();
void deinit();
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);

View File

@ -4,7 +4,6 @@
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include "gtk_compat.h"
#include <dlfcn.h>
#include <sys/stat.h>
#include <fcntl.h>
@ -13,7 +12,6 @@
#include "gtk_display.h"
#include "gtk_display_driver_opengl.h"
#include "gtk_shader_parameters.h"
#include "shaders/shader_helpers.h"
static const GLchar *stock_vertex_shader_110 =
"#version 110\n"
@ -91,101 +89,41 @@ S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfi
void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
{
Gtk::Allocation allocation = drawing_area->get_allocation();
if (output_window_width != allocation.get_width() ||
output_window_height != allocation.get_height())
{
resize();
}
int scale_factor = drawing_area->get_scale_factor();
allocation.set_width(allocation.get_width() * scale_factor);
allocation.set_height(allocation.get_height() * scale_factor);
if (!legacy)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texmap);
GLint filter = Settings.BilinearFilter ? GL_LINEAR : GL_NEAREST;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
GLint clamp = (using_glsl_shaders || !npot) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
GLint clamp = (using_glsl_shaders) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
glClear(GL_COLOR_BUFFER_BIT);
S9xRect content = S9xApplyAspect(width, height, allocation.get_width(), allocation.get_height());
glViewport(content.x, allocation.get_height() - content.y - content.h, content.w, content.h);
S9xRect content = S9xApplyAspect(width, height, context->width, context->height);
glViewport(content.x, context->height - content.y - content.h, content.w, content.h);
window->set_mouseable_area(content.x, content.y, content.w, content.h);
update_texture_size(width, height);
if (using_pbos)
{
void *pbo_memory = NULL;
GLbitfield bits = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
if (config->pbo_format == 16)
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * 2, NULL, GL_STREAM_DRAW);
if (version >= 30)
pbo_memory = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, width * height * 2, bits);
else
pbo_memory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
for (int y = 0; y < height; y++)
{
uint16 *dst = (uint16_t *)pbo_memory + (width * y);
uint16 *src = &buffer[y * stride_in_pixels];
memcpy(dst, src, width * 2);
}
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB,
GL_UNSIGNED_SHORT_5_6_5, BUFFER_OFFSET(0));
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
else /* 32-bit color */
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * 4, NULL, GL_STREAM_DRAW);
if (version >= 30)
pbo_memory = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, width * height * 4, bits);
else
pbo_memory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
/* Pixel swizzling in software */
S9xSetEndianess(ENDIAN_NORMAL);
S9xConvert(buffer, pbo_memory, stride_in_pixels * 2, width * 4, width, height, 32);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
}
else
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride_in_pixels);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer);
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride_in_pixels);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer);
if (using_glsl_shaders)
{
glsl_shader->render(texmap, width, height, content.x, allocation.get_height() - content.y - content.h, content.w, content.h, S9xViewportCallback);
swap_buffers();
return;
glsl_shader->render(texmap, width, height, content.x, context->height - content.y - content.h, content.w, content.h, S9xViewportCallback);
}
else
{
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
swap_buffers();
}
@ -212,47 +150,17 @@ void S9xOpenGLDisplayDriver::update_texture_size(int width, int height)
{
if (width != texture_width || height != texture_height)
{
if (npot)
{
glBindTexture(GL_TEXTURE_2D, texmap);
glBindTexture(GL_TEXTURE_2D, texmap);
if (using_pbos && config->pbo_format == 32)
{
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_BGRA,
GL_UNSIGNED_BYTE,
NULL);
}
else
{
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB565,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
NULL);
}
coords[9] = 1.0f;
coords[10] = 1.0f;
coords[11] = 1.0f;
coords[14] = 1.0f;
}
else
{
coords[9] = height / 1024.0f;
coords[10] = width / 1024.0f;
coords[11] = height / 1024.0f;
coords[14] = width / 1024.0f;
}
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB565,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
NULL);
texture_width = width;
texture_height = height;
@ -273,7 +181,7 @@ void S9xOpenGLDisplayDriver::update_texture_size(int width, int height)
bool S9xOpenGLDisplayDriver::load_shaders(const char *shader_file)
{
setlocale(LC_ALL, "C");
setlocale(LC_NUMERIC, "C");
std::string filename(shader_file);
auto endswith = [&](std::string ext) -> bool {
@ -290,35 +198,23 @@ bool S9xOpenGLDisplayDriver::load_shaders(const char *shader_file)
if (glsl_shader->load_shader((char *)shader_file))
{
using_glsl_shaders = true;
npot = true;
if (glsl_shader->param.size() > 0)
window->enable_widget("shader_parameters_item", true);
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "");
return true;
}
delete glsl_shader;
}
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "");
return false;
}
bool S9xOpenGLDisplayDriver::opengl_defaults()
{
npot = false;
using_pbos = false;
if (config->use_pbos)
{
if (version >= 15)
using_pbos = true;
else
config->use_pbos = false;
}
using_glsl_shaders = false;
glsl_shader = NULL;
@ -330,13 +226,8 @@ bool S9xOpenGLDisplayDriver::opengl_defaults()
}
}
texture_width = 1024;
texture_height = 1024;
if (config->npot_textures)
{
npot = true;
}
texture_width = 256;
texture_height = 224;
if (legacy)
{
@ -405,52 +296,25 @@ bool S9xOpenGLDisplayDriver::opengl_defaults()
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (config->use_pbos)
{
glGenBuffers(1, &pbo);
glGenTextures(1, &texmap);
glGenTextures(1, &texmap);
glBindTexture(GL_TEXTURE_2D, texmap);
glTexImage2D(GL_TEXTURE_2D,
0,
config->pbo_format == 16 ? GL_RGB565 : GL_RGBA,
texture_width,
texture_height,
0,
config->pbo_format == 16 ? GL_RGB : GL_BGRA,
config->pbo_format == 16 ? GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE,
NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER,
texture_width * texture_height * 3,
NULL,
GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
else
{
glGenTextures(1, &texmap);
glBindTexture(GL_TEXTURE_2D, texmap);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB565,
texture_width,
texture_height,
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
NULL);
}
glBindTexture(GL_TEXTURE_2D, texmap);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB565,
texture_width,
texture_height,
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
NULL);
glClearColor(0.0, 0.0, 0.0, 0.0);
return true;
}
void S9xOpenGLDisplayDriver::refresh(int width, int height)
void S9xOpenGLDisplayDriver::refresh()
{
resize();
}
@ -459,8 +323,9 @@ void S9xOpenGLDisplayDriver::resize()
{
context->resize();
context->swap_interval(config->sync_to_vblank);
output_window_width = context->width;
output_window_height = context->height;
Gtk::Allocation allocation = drawing_area->get_allocation();
output_window_width = allocation.get_width();
output_window_height = allocation.get_height();
}
bool S9xOpenGLDisplayDriver::create_context()
@ -488,9 +353,6 @@ bool S9xOpenGLDisplayDriver::create_context()
if (!context->create_context())
return false;
output_window_width = context->width;
output_window_height = context->height;
context->make_current();
legacy = false;
@ -536,9 +398,15 @@ int S9xOpenGLDisplayDriver::init()
void S9xOpenGLDisplayDriver::swap_buffers()
{
if (Settings.SkipFrames == THROTTLE_TIMER_FRAMESKIP || Settings.SkipFrames == THROTTLE_TIMER)
{
throttle.set_frame_rate(Settings.PAL ? PAL_PROGRESSIVE_FRAME_RATE : NTSC_PROGRESSIVE_FRAME_RATE);
throttle.wait_for_frame_and_rebase_time();
}
context->swap_buffers();
if (config->use_glfinish && !config->use_sync_control)
if (config->reduce_input_lag)
{
usleep(0);
glFinish();
@ -558,12 +426,6 @@ void S9xOpenGLDisplayDriver::deinit()
delete glsl_shader;
}
if (using_pbos)
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glDeleteBuffers(1, &pbo);
}
glDeleteTextures(1, &texmap);
}
@ -590,9 +452,6 @@ int S9xOpenGLDisplayDriver::query_availability()
}
#endif
if (gui_config->hw_accel == HWA_OPENGL)
gui_config->hw_accel = HWA_NONE;
return 0;
}

View File

@ -23,6 +23,7 @@
#endif
#include "shaders/glsl.h"
#include "vulkan/std_chrono_throttle.hpp"
#define BUFFER_OFFSET(i) ((char *)(i))
@ -30,14 +31,15 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
{
public:
S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height);
int init();
void deinit();
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);
void *get_parameters();
void save(const char *filename);
void refresh() override;
int init() override;
void deinit() override;
void update(uint16_t *buffer, int width, int height, int stride_in_pixels) override;
void *get_parameters() override;
void save(const char *filename) override;
static int query_availability();
bool is_ready();
bool is_ready() override;
bool can_throttle() override { return true; };
private:
bool opengl_defaults();
@ -52,13 +54,10 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
GLint texture_width;
GLint texture_height;
GLuint texmap;
GLuint pbo;
bool legacy;
bool core;
int version;
bool npot;
bool using_pbos;
bool initialized;
bool using_glsl_shaders;
@ -70,6 +69,8 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
OpenGLContext *context;
Throttle throttle;
#ifdef GDK_WINDOWING_X11
GTKGLXContext glx;
#endif

View File

@ -0,0 +1,177 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include "gtk_compat.h"
#include "gtk_display.h"
#include "gtk_display_driver_vulkan.h"
#include "gtk_shader_parameters.h"
#include "snes9x.h"
#include "gfx.h"
#include "fmt/format.h"
S9xVulkanDisplayDriver::S9xVulkanDisplayDriver(Snes9xWindow *_window, Snes9xConfig *_config)
{
window = _window;
config = _config;
drawing_area = window->drawing_area;
gdk_window = nullptr;
gdk_display = nullptr;
context.reset();
}
S9xVulkanDisplayDriver::~S9xVulkanDisplayDriver()
{
}
void S9xVulkanDisplayDriver::refresh()
{
if (!context)
return;
context->swapchain->set_vsync(gui_config->sync_to_vblank);
int new_width, new_height;
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
{
wayland_surface->resize();
std::tie(new_width, new_height) = wayland_surface->get_size();
}
else
#endif
{
new_width = drawing_area->get_width() * drawing_area->get_scale_factor();
new_height = drawing_area->get_height() * drawing_area->get_scale_factor();
}
if (new_width != current_width || new_height != current_height)
{
context->recreate_swapchain(new_width, new_height);
context->wait_idle();
current_width = new_width;
current_height = new_height;
}
}
int S9xVulkanDisplayDriver::init()
{
current_width = drawing_area->get_width() * drawing_area->get_scale_factor();
current_height = drawing_area->get_height() * drawing_area->get_scale_factor();
context = std::make_unique<Vulkan::Context>();
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj()))
{
wayland_surface = std::make_unique<WaylandSurface>();
if (!wayland_surface->attach(GTK_WIDGET(drawing_area->gobj())))
{
return -1;
}
context->init_wayland(wayland_surface->display, wayland_surface->child, current_width, current_height);
}
#endif
if (GDK_IS_X11_WINDOW(drawing_area->get_window()->gobj()))
{
display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
xid = gdk_x11_window_get_xid(drawing_area->get_window()->gobj());
context->init_Xlib(display, xid);
}
device = context->device;
if (!gui_config->shader_filename.empty() && gui_config->use_shaders)
{
shaderchain = std::make_unique<Vulkan::ShaderChain>(context.get());
setlocale(LC_NUMERIC, "C");
if (!shaderchain->load_shader_preset(gui_config->shader_filename))
{
fmt::print("Couldn't load shader preset file\n");
shaderchain = nullptr;
setlocale(LC_NUMERIC, "");
}
else
{
window->enable_widget("shader_parameters_item", true);
setlocale(LC_NUMERIC, "");
return 0;
}
}
simple_output = std::make_unique<Vulkan::SimpleOutput>(context.get(), vk::Format::eR5G6B5UnormPack16);
return 0;
}
void S9xVulkanDisplayDriver::deinit()
{
if (!context)
return;
if (shaderchain)
gtk_shader_parameters_dialog_close();
context->wait_idle();
}
void S9xVulkanDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
{
if (!context)
return;
auto viewport = S9xApplyAspect(width, height, current_width, current_height);
bool retval = false;
if (shaderchain)
{
retval = shaderchain->do_frame_without_swap((uint8_t *)buffer, width, height, stride_in_pixels << 1, vk::Format::eR5G6B5UnormPack16, viewport.x, viewport.y, viewport.w, viewport.h);
}
else if (simple_output)
{
simple_output->set_filter(Settings.BilinearFilter);
retval = simple_output->do_frame_without_swap((uint8_t *)buffer, width, height, stride_in_pixels << 1, viewport.x, viewport.y, viewport.w, viewport.h);
}
if (retval)
{
if (Settings.SkipFrames == THROTTLE_TIMER || Settings.SkipFrames == THROTTLE_TIMER_FRAMESKIP)
{
throttle.set_frame_rate(Settings.PAL ? PAL_PROGRESSIVE_FRAME_RATE : NTSC_PROGRESSIVE_FRAME_RATE);
throttle.wait_for_frame_and_rebase_time();
}
context->swapchain->swap();
if (gui_config->reduce_input_lag)
context->wait_idle();
}
}
int S9xVulkanDisplayDriver::query_availability()
{
return 0;
}
void *S9xVulkanDisplayDriver::get_parameters()
{
if (shaderchain)
return &shaderchain->preset->parameters;
return nullptr;
}
void S9xVulkanDisplayDriver::save(const char *filename)
{
setlocale(LC_NUMERIC, "C");
if (shaderchain)
shaderchain->preset->save_to_file(filename);
setlocale(LC_NUMERIC, "");
}
bool S9xVulkanDisplayDriver::is_ready()
{
return true;
}

View File

@ -0,0 +1,53 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#pragma once
#include "gtk_s9x.h"
#include "gtk_display_driver.h"
#include "../../vulkan/vulkan_context.hpp"
#include "../../vulkan/vulkan_shader_chain.hpp"
#include "../../vulkan/vulkan_simple_output.hpp"
#include "../../vulkan/std_chrono_throttle.hpp"
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#include "gtk_wayland_surface.h"
#endif
class S9xVulkanDisplayDriver : public S9xDisplayDriver
{
public:
S9xVulkanDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
~S9xVulkanDisplayDriver();
void refresh() override;
int init() override;
void deinit() override;
void update(uint16_t *buffer, int width, int height, int stride_in_pixels) override;
void *get_parameters() override;
void save(const char *filename) override;
bool is_ready() override;
bool can_throttle() override { return true; }
static int query_availability();
private:
std::unique_ptr<Vulkan::Context> context;
vk::Device device;
GdkDisplay *gdk_display;
GdkWindow *gdk_window;
Display *display;
Window xid;
int current_width;
int current_height;
Throttle throttle;
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
std::unique_ptr<WaylandSurface> wayland_surface;
#endif
std::unique_ptr<Vulkan::ShaderChain> shaderchain;
std::unique_ptr<Vulkan::SimpleOutput> simple_output;
};

View File

@ -294,12 +294,6 @@ int S9xXVDisplayDriver::init()
this->rshift = this->bshift;
this->bshift = copy;
}
/* on big-endian Xv still seems to like LSB order */
if (config->force_inverted_byte_order)
S9xSetEndianess(ENDIAN_SWAPPED);
else
S9xSetEndianess(ENDIAN_NORMAL);
}
}
}
@ -313,21 +307,6 @@ int S9xXVDisplayDriver::init()
format = formats[i].id;
depth = formats[i].depth;
if (formats[i].byte_order == LSBFirst)
{
if (config->force_inverted_byte_order)
S9xSetEndianess(ENDIAN_SWAPPED);
else
S9xSetEndianess(ENDIAN_NORMAL);
}
else
{
if (config->force_inverted_byte_order)
S9xSetEndianess(ENDIAN_NORMAL);
else
S9xSetEndianess(ENDIAN_SWAPPED);
}
break;
}
}
@ -454,7 +433,7 @@ void S9xXVDisplayDriver::clear()
S9xRect dst;
dst.w = window->last_width;
dst.h = window->last_height;
get_filter_scale(dst.w, dst.h);
apply_filter_scale(dst.w, dst.h);
dst = S9xApplyAspect(dst.w, dst.h, width, height);
if (dst.x > 0)
@ -477,7 +456,7 @@ void S9xXVDisplayDriver::clear()
XSync(display, False);
}
void S9xXVDisplayDriver::refresh(int width, int height)
void S9xXVDisplayDriver::refresh()
{
clear();
}

View File

@ -21,7 +21,7 @@ class S9xXVDisplayDriver : public S9xDisplayDriver
{
public:
S9xXVDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height);
void refresh();
int init();
void deinit();
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);

View File

@ -6,6 +6,8 @@
#include <sys/stat.h>
#include <errno.h>
#include <string>
#include <filesystem>
#include "gtk_compat.h"
#include "gtk_s9x.h"
@ -14,181 +16,111 @@
#include "snapshot.h"
#include "cheats.h"
static char buf[PATH_MAX];
namespace fs = std::filesystem;
using namespace std::literals;
const char *S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype)
std::string S9xGetFilenameInc(std::string e, enum s9x_getdirtype dirtype)
{
static char filename[PATH_MAX + 1];
char dir[_MAX_DIR + 1];
char drive[_MAX_DRIVE + 1];
char fname[_MAX_FNAME + 1];
char ext[_MAX_EXT + 1];
unsigned int i = 0;
struct stat buf;
const char *d;
fs::path rom_filename(Memory.ROMFilename);
_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
d = S9xGetDirectory(dirtype);
fs::path filename_base(S9xGetDirectory(dirtype));
filename_base /= rom_filename.filename();
fs::path new_filename;
if (e[0] != '.')
e = "." + e;
int i = 0;
do
{
snprintf(filename, PATH_MAX, "%s" SLASH_STR "%s%03d%s", d, fname, i, e);
i++;
} while (stat(filename, &buf) == 0 && i != 0); /* Overflow? ...riiight :-) */
std::string new_extension = std::to_string(i);
while (new_extension.length() < 3)
new_extension = "0"s + new_extension;
new_extension += e;
return (filename);
new_filename = filename_base;
new_filename.replace_extension(new_extension);
i++;
} while (fs::exists(new_filename));
return new_filename;
}
const char *S9xGetDirectory(enum s9x_getdirtype dirtype)
std::string S9xGetDirectory(enum s9x_getdirtype dirtype)
{
static char path[PATH_MAX + 1];
std::string dirname;
switch (dirtype)
{
case HOME_DIR:
snprintf(path, PATH_MAX + 1, "%s", get_config_dir().c_str());
dirname = get_config_dir();
break;
case SNAPSHOT_DIR:
snprintf(path, PATH_MAX + 1, "%s", gui_config->savestate_directory.c_str());
dirname = gui_config->savestate_directory;
break;
case PATCH_DIR:
snprintf(path, PATH_MAX + 1, "%s", gui_config->patch_directory.c_str());
dirname = gui_config->patch_directory;
break;
case CHEAT_DIR:
snprintf(path, PATH_MAX + 1, "%s", gui_config->cheat_directory.c_str());
dirname = gui_config->cheat_directory;
break;
case SRAM_DIR:
snprintf(path, PATH_MAX + 1, "%s", gui_config->sram_directory.c_str());
dirname = gui_config->sram_directory;
break;
case SCREENSHOT_DIR:
case SPC_DIR:
snprintf(path, PATH_MAX + 1, "%s", gui_config->export_directory.c_str());
dirname = gui_config->export_directory;
break;
default:
path[0] = '\0';
dirname = "";
}
/* Check if directory exists, make it and/or set correct permissions */
if (dirtype != HOME_DIR && path[0] != '\0')
if (dirtype != HOME_DIR && dirname != "")
{
struct stat file_info;
fs::path path(dirname);
if (stat(path, &file_info) == -1)
if (!fs::exists(path))
{
mkdir(path, 0755);
chmod(path, 0755);
fs::create_directory(path);
}
else if ((fs::status(path).permissions() & fs::perms::owner_write) == fs::perms::none)
{
fs::permissions(path, fs::perms::owner_write, fs::perm_options::add);
}
else if (!(file_info.st_mode & 0700))
chmod(path, file_info.st_mode | 0700);
}
/* Anything else, use ROM filename path */
if (path[0] == '\0')
if (dirname == "" && !Memory.ROMFilename.empty())
{
char *loc;
fs::path path(Memory.ROMFilename);
strcpy(path, Memory.ROMFilename);
path.remove_filename();
loc = strrchr(path, SLASH_CHAR);
if (loc == NULL)
{
if (getcwd(path, PATH_MAX + 1) == NULL)
{
strcpy(path, getenv("HOME"));
}
}
if (!fs::is_directory(path))
dirname = fs::current_path();
else
{
path[loc - path] = '\0';
}
dirname = path;
}
return path;
}
const char *S9xGetFilename(const char *ex, enum s9x_getdirtype dirtype)
{
static char filename[PATH_MAX + 1];
char dir[_MAX_DIR + 1];
char drive[_MAX_DRIVE + 1];
char fname[_MAX_FNAME + 1];
char ext[_MAX_EXT + 1];
_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
snprintf(filename, sizeof(filename), "%s" SLASH_STR "%s%s",
S9xGetDirectory(dirtype), fname, ex);
return (filename);
}
const char *S9xBasename(const char *f)
{
const char *p;
if ((p = strrchr(f, '/')) != NULL || (p = strrchr(f, '\\')) != NULL)
return (p + 1);
return f;
}
const char *S9xBasenameNoExt(const char *f)
{
static char filename[PATH_MAX];
const char *base, *ext;
if (!(base = strrchr(f, SLASH_CHAR)))
base = f;
else
base += 1;
ext = strrchr(f, '.');
if (!ext)
snprintf(filename, PATH_MAX, "%s", base);
else
{
int len = ext - base;
strncpy(filename, base, len);
filename[len] = '\0';
}
return filename;
}
static int file_exists(const char *name)
{
FILE *f = NULL;
f = fopen(name, "r");
if (!f)
return 0;
else
{
fclose(f);
return 1;
}
return dirname;
}
bool8 S9xOpenSnapshotFile(const char *filename, bool8 read_only, STREAM *file)
{
#ifdef ZLIB
if (read_only)
{
if ((*file = OPEN_STREAM(filename, "rb")))
return (true);
else
fprintf(stderr,
"Failed to open file stream for reading. (%s)\n",
zError(errno));
fprintf(stderr, "Failed to open file stream for reading.\n");
}
else
{
@ -198,150 +130,93 @@ bool8 S9xOpenSnapshotFile(const char *filename, bool8 read_only, STREAM *file)
}
else
{
fprintf(stderr,
"Couldn't open stream with zlib. (%s)\n",
zError(errno));
fprintf(stderr, "Couldn't open stream with zlib.\n");
}
}
fprintf(stderr, "zlib: Couldn't open snapshot file:\n%s\n", filename);
fprintf(stderr, "Couldn't open snapshot file:\n%s\n", filename);
#else
char command[PATH_MAX];
if (read_only)
{
sprintf(command, "gzip -d <\"%s\"", filename);
if (*file = popen(command, "r"))
return (true);
}
else
{
sprintf(command, "gzip --best >\"%s\"", filename);
if (*file = popen(command, "wb"))
return (true);
}
fprintf(stderr, "gzip: Couldn't open snapshot file:\n%s\n", filename);
#endif
return (false);
return false;
}
void S9xCloseSnapshotFile(STREAM file)
{
#ifdef ZLIB
CLOSE_STREAM(file);
#else
pclose(file);
#endif
}
void S9xAutoSaveSRAM()
{
Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR));
S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR).c_str());
S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR).c_str());
}
void S9xLoadState(const char *filename)
void S9xLoadState(std::string filename)
{
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR).c_str());
if (S9xUnfreezeGame(filename))
if (S9xUnfreezeGame(filename.c_str()))
{
sprintf(buf, "%s loaded", filename);
S9xSetInfoString(buf);
auto info_string = filename + " loaded"s;
S9xSetInfoString(info_string.c_str());
}
else
{
fprintf(stderr, "Failed to load state file: %s\n", filename);
fprintf(stderr, "Failed to load state file: %s\n", filename.c_str());
}
}
void S9xSaveState(const char *filename)
void S9xSaveState(std::string filename)
{
if (S9xFreezeGame(filename))
if (S9xFreezeGame(filename.c_str()))
{
sprintf(buf, "%s saved", filename);
S9xSetInfoString(buf);
auto info_string = filename + " saved"s;
S9xSetInfoString(info_string.c_str());
}
else
{
fprintf(stderr, "Couldn't save state file: %s\n", filename);
fprintf(stderr, "Couldn't save state file: %s\n", filename.c_str());
}
}
static fs::path save_slot_path(int slot)
{
std::string extension = std::to_string(slot);
while (extension.length() < 3)
extension = "0"s + extension;
fs::path path(S9xGetDirectory(SNAPSHOT_DIR));
path /= fs::path(Memory.ROMFilename).filename();
path.replace_extension(extension);
return path;
}
/* QuickSave/Load from S9x base controls.cpp */
void S9xQuickSaveSlot(int slot)
{
char def[PATH_MAX];
char filename[PATH_MAX];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char ext[_MAX_EXT];
if (!gui_config->rom_loaded)
return;
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX, "%s%s%s.%03d",
S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def,
slot);
if (S9xFreezeGame(filename))
auto filename = save_slot_path(slot);
if (S9xFreezeGame(filename.c_str()))
{
snprintf(buf, PATH_MAX, "%s.%03d saved", def, slot);
S9xSetInfoString(buf);
auto info_string = filename.filename().string() + " saved";
S9xSetInfoString(info_string.c_str());
}
}
void S9xQuickLoadSlot(int slot)
{
char def[PATH_MAX];
char filename[PATH_MAX];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char ext[_MAX_EXT];
if (!gui_config->rom_loaded)
return;
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
auto filename = save_slot_path(slot);
snprintf(filename, PATH_MAX, "%s%s%s.%03d",
S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def,
slot);
if (fs::exists(filename))
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR).c_str());
if (file_exists(filename))
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame(filename))
if (S9xUnfreezeGame(filename.c_str()))
{
snprintf(buf, PATH_MAX, "%s.%03d loaded", def, slot);
S9xSetInfoString(buf);
return;
}
static const char *digits = "t123456789";
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX, "%s%s%s.zs%c",
S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR,
def, digits[slot]);
if (file_exists(filename))
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame(filename))
{
snprintf(buf, PATH_MAX,
"Loaded ZSNES freeze file %s.zs%c",
def, digits[slot]);
S9xSetInfoString(buf);
auto info_string = filename.filename().string() + " loaded";
S9xSetInfoString(info_string.c_str());
return;
}

View File

@ -6,11 +6,12 @@
#ifndef __GTK_FILE_H
#define __GTK_FILE_H
#include <string>
const char *S9xBasenameNoExt(const char *);
std::string S9xBasenameNoExt(std::string);
void S9xLoadState(const char *filename);
void S9xSaveState(const char *filename);
void S9xLoadState(std::string);
void S9xSaveState(std::string);
void S9xQuickSaveSlot(int slot);
void S9xQuickLoadSlot(int slot);

View File

@ -18,8 +18,6 @@ GTKGLXContext::GTKGLXContext()
version_major = -1;
version_minor = -1;
use_oml_sync_control = false;
ust = msc = sbc = 0;
}
GTKGLXContext::~GTKGLXContext()
@ -62,6 +60,7 @@ bool GTKGLXContext::attach(Display *dpy, Window xid)
}
fbconfig = fbconfigs[0];
free(fbconfigs);
return true;
}
@ -93,9 +92,6 @@ bool GTKGLXContext::create_context()
return false;
}
if (strstr(extensions, "GLX_OML_sync_control") && gui_config->use_sync_control)
use_oml_sync_control = true;
return true;
}
@ -116,24 +112,11 @@ void GTKGLXContext::resize()
void GTKGLXContext::swap_buffers()
{
if (use_oml_sync_control)
glXGetSyncValuesOML(display, xid, &ust, &msc, &sbc);
glXSwapBuffers(display, xid);
}
bool GTKGLXContext::ready()
{
if (use_oml_sync_control)
{
int64 ust, msc, sbc;
glXGetSyncValuesOML(display, xid, &ust, &msc, &sbc);
if (sbc != this->sbc || msc - this->msc > 2)
return true;
return false;
}
return true;
}

View File

@ -32,9 +32,6 @@ class GTKGLXContext : public OpenGLContext
int version_major;
int version_minor;
bool use_oml_sync_control;
int64_t ust, msc, sbc;
};
#endif

View File

@ -13,12 +13,12 @@
#include "gtk_sound.h"
#include "gtk_display.h"
#include "gtk_binding.h"
#include "fmt/format.h"
#include "snes9x.h"
#include "gfx.h"
#include "display.h"
#define SAME_AS_GAME _("Same location as current game")
#define SAME_AS_GAME gettext("Same location as current game")
static Snes9xPreferences *preferences = nullptr;
@ -98,8 +98,6 @@ Snes9xPreferences::Snes9xPreferences(Snes9xConfig *config)
#ifdef GDK_WINDOWING_X11
if (config->allow_xrandr)
{
char size_string[256];
for (int i = 0; i < config->xrr_screen_resources->nmode; i++)
{
XRRModeInfo *m = &config->xrr_screen_resources->modes[i];
@ -111,14 +109,12 @@ Snes9xPreferences::Snes9xPreferences(Snes9xConfig *config)
if (m->modeFlags & RR_DoubleClock)
dotClock *= 2;
snprintf(size_string,
256,
"%dx%d @ %.3fHz",
m->width,
m->height,
(double)dotClock / m->hTotal / m->vTotal);
auto str = fmt::format("{}x{} @ {:.3f}Hz",
m->width,
m->height,
(double)dotClock / m->hTotal / m->vTotal);
combo_box_append("resolution_combo", size_string);
combo_box_append("resolution_combo", str.c_str());
}
if (config->xrr_index > config->xrr_screen_resources->nmode)
@ -142,15 +138,20 @@ Snes9xPreferences::Snes9xPreferences(Snes9xConfig *config)
combo_box_append("scale_method_combo", _("4xBRZ"));
#endif
combo_box_append("hw_accel", _("None - Use software scaler"));
for (const auto &driver : config->display_drivers)
{
std::string entry;
if (driver == "opengl")
entry = _("OpenGL - Use 3D graphics hardware");
else if (driver == "xv")
entry = _("XVideo - Use hardware video blitter");
else if (driver == "vulkan")
entry = _("Vulkan");
else
entry = _("None - Use software scaler");
if (config->allow_opengl)
combo_box_append("hw_accel",
_("OpenGL - Use 3D graphics hardware"));
if (config->allow_xv)
combo_box_append("hw_accel",
_("XVideo - Use hardware video blitter"));
combo_box_append("hw_accel", entry.c_str());
}
for (auto &name : config->sound_drivers)
{
@ -177,9 +178,10 @@ void Snes9xPreferences::connect_signals()
get_object<Gtk::ComboBox>("hw_accel")->signal_changed().connect([&] {
int id = get_combo("hw_accel");
show_widget("bilinear_filter", id != HWA_XV);
show_widget("opengl_frame", id == HWA_OPENGL);
show_widget("xv_frame", id == HWA_XV);
show_widget("bilinear_filter", config->display_drivers[id] != "xv");
show_widget("opengl_frame", config->display_drivers[id] == "opengl" ||
config->display_drivers[id] == "vulkan");
show_widget("xv_frame", config->display_drivers[id] == "xv");
});
get_object<Gtk::Button>("reset_current_joypad")->signal_pressed().connect(sigc::mem_fun(*this, &Snes9xPreferences::reset_current_joypad));
@ -208,7 +210,7 @@ void Snes9xPreferences::connect_signals()
get_object<Gtk::Button>("about_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xPreferences::about_dialog));
get_object<Gtk::ToggleButton>("auto_input_rate")->signal_toggled().connect([&] {
auto toggle_button = get_object<Gtk::ToggleButton>("auto_input_rate");
enable_widget("sound_input_rate", toggle_button->get_active());
enable_widget("sound_input_rate", !toggle_button->get_active());
if (toggle_button->get_active())
set_slider("sound_input_rate", top_level->get_auto_input_rate());
});
@ -281,10 +283,8 @@ void Snes9xPreferences::game_data_browse(std::string folder)
void Snes9xPreferences::input_rate_changed()
{
double value = get_object<Gtk::HScale>("sound_input_rate")->get_value();
value = value / 32040.0 * 60.09881389744051;
char text[256];
snprintf(text, 256, "%.4f Hz", value);
get_object<Gtk::Label>("relative_video_rate")->set_label(text);
value = value / 32040.0 * NTSC_PROGRESSIVE_FRAME_RATE;
get_object<Gtk::Label>("relative_video_rate")->set_label(fmt::format("{:.4f}Hz", value));
}
bool Snes9xPreferences::key_pressed(GdkEventKey *event)
@ -333,7 +333,6 @@ bool Snes9xPreferences::key_pressed(GdkEventKey *event)
void Snes9xPreferences::shader_select()
{
#ifdef USE_OPENGL
auto entry = get_object<Gtk::Entry>("fragment_shader");
auto dialog = Gtk::FileChooserDialog(*window.get(), _("Select Shader File"));
@ -357,7 +356,6 @@ void Snes9xPreferences::shader_select()
if (!filename.empty())
entry->set_text(filename);
}
#endif
}
void Snes9xPreferences::load_ntsc_settings()
@ -433,7 +431,7 @@ void Snes9xPreferences::move_settings_to_dialog()
set_check("prevent_screensaver", config->prevent_screensaver);
set_check("force_inverted_byte_order", config->force_inverted_byte_order);
set_combo("playback_combo", 7 - config->sound_playback_rate);
set_combo("hw_accel", combo_value (config->hw_accel));
set_combo("hw_accel", combo_value (config->display_driver));
set_check("pause_emulation_on_switch", config->pause_emulation_on_switch);
set_spin ("num_threads", config->num_threads);
set_check("mute_sound_check", config->mute_sound);
@ -466,17 +464,13 @@ void Snes9xPreferences::move_settings_to_dialog()
set_combo ("frameskip_combo", Settings.SkipFrames);
set_check ("bilinear_filter", Settings.BilinearFilter);
set_check ("auto_vrr", config->auto_vrr);
#ifdef USE_OPENGL
set_check ("sync_to_vblank", config->sync_to_vblank);
set_check ("use_glfinish", config->use_glfinish);
set_check ("use_sync_control", config->use_sync_control);
set_check ("use_pbos", config->use_pbos);
set_combo ("pixel_format", config->pbo_format == 16 ? 0 : 1);
set_check ("npot_textures", config->npot_textures);
set_check ("reduce_input_lag", config->reduce_input_lag);
set_check ("use_shaders", config->use_shaders);
set_entry_text ("fragment_shader", config->shader_filename.c_str ());
#endif
set_spin ("joystick_threshold", config->joystick_threshold);
/* Control bindings */
@ -554,7 +548,7 @@ void Snes9xPreferences::get_settings_from_dialog()
if (config->multithreading != get_check("multithreading"))
gfx_needs_restart = true;
if (config->hw_accel != hw_accel_value (get_combo("hw_accel")))
if (config->display_driver != config->display_drivers[get_combo("hw_accel")])
gfx_needs_restart = true;
if (config->force_inverted_byte_order != get_check("force_inverted_byte_order"))
@ -575,6 +569,7 @@ void Snes9xPreferences::get_settings_from_dialog()
config->aspect_ratio = get_combo("aspect_ratio");
config->scale_method = get_combo("scale_method_combo");
config->hires_effect = get_combo("hires_effect");
config->auto_vrr = get_check("auto_vrr");
config->force_inverted_byte_order = get_check("force_inverted_byte_order");
Settings.AutoSaveDelay = get_entry_value("save_sram_after_sec");
config->multithreading = get_check("multithreading");
@ -595,7 +590,7 @@ void Snes9xPreferences::get_settings_from_dialog()
store_ntsc_settings();
config->ntsc_scanline_intensity = get_combo("ntsc_scanline_intensity");
config->scanline_filter_intensity = get_combo("scanline_filter_intensity");
config->hw_accel = hw_accel_value(get_combo("hw_accel"));
config->display_driver = config->display_drivers[get_combo("hw_accel")];
Settings.BilinearFilter = get_check("bilinear_filter");
config->num_threads = get_spin("num_threads");
config->default_esc_behavior = get_combo("default_esc_behavior");
@ -631,14 +626,7 @@ void Snes9xPreferences::get_settings_from_dialog()
Settings.InterpolationMethod = get_combo("sound_filter");
#endif
#ifdef USE_OPENGL
int pbo_format = get_combo("pixel_format") == 1 ? 32 : 16;
if (config->sync_to_vblank != get_check("sync_to_vblank") ||
config->use_sync_control != get_check("use_sync_control") ||
config->npot_textures != get_check("npot_textures") ||
config->use_pbos != get_check("use_pbos") ||
config->pbo_format != pbo_format ||
config->use_shaders != get_check("use_shaders") ||
(config->shader_filename.compare(get_entry_text("fragment_shader"))))
{
@ -646,14 +634,9 @@ void Snes9xPreferences::get_settings_from_dialog()
}
config->sync_to_vblank = get_check("sync_to_vblank");
config->use_pbos = get_check("use_pbos");
config->npot_textures = get_check("npot_textures");
config->use_shaders = get_check("use_shaders");
config->use_glfinish = get_check("use_glfinish");
config->use_sync_control = get_check("use_sync_control");
config->reduce_input_lag = get_check("reduce_input_lag");
config->shader_filename = get_entry_text ("fragment_shader");
config->pbo_format = pbo_format;
#endif
std::string new_sram_directory = get_entry_text("sram_directory");
config->savestate_directory = get_entry_text("savestate_directory");
@ -716,7 +699,7 @@ void Snes9xPreferences::get_settings_from_dialog()
}
S9xDisplayReconfigure();
S9xDisplayRefresh(top_level->last_width, top_level->last_height);
S9xDisplayRefresh();
S9xDeinitUpdate(top_level->last_width, top_level->last_height);
@ -726,28 +709,15 @@ void Snes9xPreferences::get_settings_from_dialog()
top_level->leave_fullscreen_mode();
}
int Snes9xPreferences::hw_accel_value(int combo_value)
int Snes9xPreferences::combo_value(std::string driver_name)
{
if (config->allow_opengl && config->allow_xv)
return combo_value;
else if (!config->allow_opengl && !config->allow_xv)
return 0;
else if (!config->allow_opengl && config->allow_xv)
return combo_value ? 2 : 0;
else
return combo_value ? 1 : 0;
}
for (size_t i = 0; i < config->display_drivers.size(); i++)
{
if (config->display_drivers[i] == driver_name)
return i;
}
int Snes9xPreferences::combo_value(int hw_accel)
{
if (config->allow_opengl && config->allow_xv)
return hw_accel;
else if (!config->allow_opengl && !config->allow_xv)
return 0;
else if (!config->allow_opengl && config->allow_xv)
return hw_accel == HWA_XV ? 1 : 0;
else
return hw_accel == HWA_OPENGL ? 1 : 0;
return 0;
}
void Snes9xPreferences::show()
@ -922,9 +892,7 @@ void Snes9xPreferences::clear_binding(const char *name)
if (b_links[i].button_name)
{
char buf[256];
unset.to_string(buf);
set_entry_text(b_links[i].button_name, buf);
set_entry_text(b_links[i].button_name, unset.to_string(true));
}
}
@ -936,14 +904,14 @@ void Snes9xPreferences::bindings_to_dialog(int joypad)
for (int i = 0; i < NUM_JOYPAD_LINKS; i++)
{
set_entry_text(b_links[i].button_name, bindings[i].as_string().c_str());
set_entry_text(b_links[i].button_name, bindings[i].to_string(true));
}
auto shortcut_names = &b_links[NUM_JOYPAD_LINKS];
for (int i = 0; shortcut_names[i].button_name; i++)
{
set_entry_text(shortcut_names[i].button_name, shortcut[i].as_string().c_str());
set_entry_text(shortcut_names[i].button_name, shortcut[i].to_string(true));
}
}

View File

@ -24,7 +24,7 @@ class Snes9xPreferences : public GtkBuilderWindow
int get_focused_binding();
void store_binding(const char *string, Binding binding);
int hw_accel_value(int combo_value);
int combo_value(int hw_accel);
int combo_value(std::string driver_name);
void focus_next();
void swap_with();
void clear_binding(const char *name);

View File

@ -6,8 +6,6 @@
#include <stdio.h>
#include <signal.h>
#include "giomm/application.h"
#include "glibmm/main.h"
#include "gtk_compat.h"
#include "gtk_config.h"
#include "gtk_s9x.h"
@ -34,8 +32,8 @@ static bool S9xIdleFunc();
static bool S9xPauseFunc();
static bool S9xScreenSaverCheckFunc();
Snes9xWindow *top_level;
Snes9xConfig *gui_config;
Snes9xWindow *top_level = nullptr;
Snes9xConfig *gui_config = nullptr;
StateManager state_manager;
gint64 frame_clock = -1;
gint64 pointer_timestamp = -1;
@ -49,7 +47,6 @@ static void S9xTerm(int signal)
int main(int argc, char *argv[])
{
struct sigaction sig_callback;
auto app = Gtk::Application::create("com.snes9x.gtk", Gio::APPLICATION_NON_UNIQUE);
setlocale(LC_ALL, "");
@ -57,7 +54,13 @@ int main(int argc, char *argv[])
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);
memset(&Settings, 0, sizeof(Settings));
struct sigaction sig_callback{};
sig_callback.sa_handler = S9xTerm;
sigaction(15, &sig_callback, NULL); // SIGTERM
sigaction(3, &sig_callback, NULL); // SIGQUIT
sigaction(2, &sig_callback, NULL); // SIGINT
Settings = {};
// Original config fills out values this port doesn't.
S9xLoadConfigFiles(argv, argc);
@ -75,23 +78,25 @@ int main(int argc, char *argv[])
settings->set_property("gtk-menu-images", gui_config->enable_icons);
settings->set_property("gtk-button-images", gui_config->enable_icons);
S9xReportControllers();
if (!Memory.Init() || !S9xInitAPU())
exit(3);
top_level = new Snes9xWindow(gui_config);
#ifdef GDK_WINDOWING_X11
if (!GDK_IS_X11_WINDOW(top_level->window->get_window()->gobj()))
XInitThreads();
#endif
// Setting fullscreen before showing the window avoids some flicker.
if ((gui_config->full_screen_on_open && rom_filename) || (gui_config->fullscreen))
top_level->window->fullscreen();
top_level->show();
S9xInitDisplay(argc, argv);
S9xPortSoundInit();
S9xReportControllers();
for (int port = 0; port < 2; port++)
{
enum controllers type;
@ -125,10 +130,6 @@ int main(int argc, char *argv[])
top_level->update_accelerators();
Settings.Paused = true;
Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 100);
Glib::signal_timeout().connect(sigc::ptr_fun(S9xScreenSaverCheckFunc), 10000);
S9xNoROMLoaded();
if (rom_filename)
@ -137,23 +138,18 @@ int main(int argc, char *argv[])
top_level->window->unfullscreen();
}
memset(&sig_callback, 0, sizeof(struct sigaction));
sig_callback.sa_handler = S9xTerm;
sigaction(15, &sig_callback, NULL); // SIGTERM
sigaction(3, &sig_callback, NULL); // SIGQUIT
sigaction(2, &sig_callback, NULL); // SIGINT
// Perform the complete fullscreen process, including mode sets, which
// didn't happen in the earlier Gtk call.
if (gui_config->fullscreen)
top_level->enter_fullscreen_mode();
gui_config->joysticks.flush_events();
if (rom_filename && *Settings.InitialSnapshotFilename)
S9xUnfreezeGame(Settings.InitialSnapshotFilename);
gui_config->joysticks.flush_events();
Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 100);
Glib::signal_timeout().connect(sigc::ptr_fun(S9xScreenSaverCheckFunc), 10000);
app->run(*top_level->window.get());
return 0;
}
@ -181,43 +177,9 @@ int S9xOpenROM(const char *rom_filename)
Settings.StopEmulation = !loaded;
if (!loaded && rom_filename)
{
char dir[_MAX_DIR + 1];
char drive[_MAX_DRIVE + 1];
char name[_MAX_FNAME + 1];
char ext[_MAX_EXT + 1];
char fname[_MAX_PATH + 1];
_splitpath(rom_filename, drive, dir, name, ext);
_makepath(fname, drive, dir, name, ext);
strcpy(fname, S9xGetDirectory(ROM_DIR));
strcat(fname, SLASH_STR);
strcat(fname, name);
if (ext[0])
{
strcat(fname, ".");
strcat(fname, ext);
}
_splitpath(fname, drive, dir, name, ext);
_makepath(fname, drive, dir, name, ext);
if ((Settings.StopEmulation = !Memory.LoadROM(fname)))
{
fprintf(stderr, _("Error opening: %s\n"), rom_filename);
loaded = false;
}
else
loaded = true;
}
if (loaded)
{
Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR));
Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR).c_str());
}
else
{
@ -260,12 +222,20 @@ void S9xNoROMLoaded()
{
S9xSoundStop();
gui_config->rom_loaded = false;
S9xDisplayRefresh(-1, -1);
S9xDisplayRefresh();
top_level->configure_widgets();
}
static bool S9xPauseFunc()
{
static bool first_clear = false;
if (!first_clear)
{
top_level->refresh();
first_clear = true;
}
S9xProcessEvents(true);
if (!S9xNetplayPush())
@ -340,8 +310,6 @@ static bool S9xIdleFunc()
return true;
}
S9xThrottle(Settings.SkipFrames);
if (!S9xNetplayPush())
{
if (Settings.Rewinding)
@ -360,7 +328,7 @@ static bool S9xIdleFunc()
if ((Settings.TurboMode || Settings.Rewinding) && gui_config->mute_sound_turbo)
Settings.Mute |= 0x80;
else
else
Settings.Mute &= ~0x80;
S9xMainLoop();
@ -400,64 +368,32 @@ void S9xParseArg(char **argv, int &i, int argc)
{
if (!strcasecmp(argv[i], "-filter"))
{
std::string filter_names[] =
{
"none",
"supereagle",
"2xsai",
"super2xsai",
"epx",
"epx_smooth",
"ntsc",
"scanlines",
"simple2x",
"simple3x",
"simple4x",
"hq2x",
"hq3x",
"hq4x",
"2xbrz",
"3xbrz",
"4xbrz"
};
if ((++i) < argc)
{
if (!strcasecmp(argv[i], "none"))
{
gui_config->scale_method = FILTER_NONE;
}
else if (!strcasecmp(argv[i], "supereagle"))
{
gui_config->scale_method = FILTER_SUPEREAGLE;
}
else if (!strcasecmp(argv[i], "2xsai"))
{
gui_config->scale_method = FILTER_2XSAI;
}
else if (!strcasecmp(argv[i], "super2xsai"))
{
gui_config->scale_method = FILTER_SUPER2XSAI;
}
#ifdef USE_HQ2X
else if (!strcasecmp(argv[i], "hq2x"))
{
gui_config->scale_method = FILTER_HQ2X;
}
else if (!strcasecmp(argv[i], "hq3x"))
{
gui_config->scale_method = FILTER_HQ3X;
}
else if (!strcasecmp(argv[i], "hq4x"))
{
gui_config->scale_method = FILTER_HQ4X;
}
#endif /* USE_HQ2X */
#ifdef USE_XBRZ
else if (!strcasecmp(argv[i], "2xbrz"))
{
gui_config->scale_method = FILTER_2XBRZ;
}
else if (!strcasecmp(argv[i], "3xbrz"))
{
gui_config->scale_method = FILTER_3XBRZ;
}
else if (!strcasecmp(argv[i], "4xbrz"))
{
gui_config->scale_method = FILTER_4XBRZ;
}
#endif /* USE_XBRZ */
else if (!strcasecmp(argv[i], "epx"))
{
gui_config->scale_method = FILTER_EPX;
}
else if (!strcasecmp(argv[i], "ntsc"))
{
gui_config->scale_method = FILTER_NTSC;
}
else
{
gui_config->scale_method = FILTER_NONE;
}
for (int f = 0; f < NUM_FILTERS; f++)
if (filter_names[f] == argv[i])
gui_config->scale_method = f;
}
}
else if (!strcasecmp(argv[i], "-mutesound"))
@ -520,6 +456,9 @@ static void S9xThrottle(int method)
}
else // THROTTLE_TIMER or THROTTLE_TIMER_FRAMESKIP
{
if (S9xDisplayGetDriver()->can_throttle())
return;
if (method == THROTTLE_TIMER_FRAMESKIP)
{
if (now - frame_clock > Settings.FrameTime)
@ -553,6 +492,7 @@ static void S9xThrottle(int method)
void S9xSyncSpeed()
{
S9xThrottle(Settings.SkipFrames);
}
static void S9xCheckPointerTimer()

View File

@ -18,7 +18,6 @@
#include "gfx.h"
#include "spc7110.h"
#include "controls.h"
#include "logger.h"
#include "cheats.h"
#include "movie.h"
#include "conffile.h"

View File

@ -5,6 +5,7 @@
\*****************************************************************************/
#include "gtk_compat.h"
#include "gtk_config.h"
#ifdef GDK_WINDOWING_X11
#include <X11/Xatom.h>
@ -16,9 +17,7 @@
#include <X11/extensions/Xvlib.h>
#endif
#ifdef USE_OPENGL
#include "gtk_shader_parameters.h"
#endif
#include "gtk_s9x.h"
#include "gtk_preferences.h"
@ -99,13 +98,7 @@ Snes9xWindow::Snes9xWindow(Snes9xConfig *config)
gtk_widget_realize(GTK_WIDGET(window->gobj()));
gtk_widget_realize(GTK_WIDGET(drawing_area->gobj()));
#ifndef USE_OPENGL
get_object<Gtk::Widget>("shader_parameters_separator")->hide();
get_object<Gtk::Widget>("shader_parameters_item")->hide();
#else
enable_widget("shader_parameters_item", false);
#endif
connect_signals();
@ -180,11 +173,9 @@ void Snes9xWindow::connect_signals()
S9xReset();
});
#ifdef USE_OPENGL
get_object<Gtk::MenuItem>("shader_parameters_item")->signal_activate().connect([&] {
gtk_shader_parameters_dialog(get_window());
});
#endif
const std::vector<const char *> port_items = { "joypad1", "mouse1", "superscope1", "joypad2", "mouse2", "multitap2", "superscope2", "nothingpluggedin2" };
for (auto &name : port_items)
@ -213,7 +204,7 @@ void Snes9xWindow::connect_signals()
});
get_object<Gtk::MenuItem>("load_state_undo")->signal_activate().connect([&] {
S9xUnfreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
S9xUnfreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR).c_str());
});
get_object<Gtk::MenuItem>("save_spc_item")->signal_activate().connect([&] {
@ -267,7 +258,7 @@ void Snes9xWindow::connect_signals()
toggle_ui();
});
for (int i = 1; i <= 5; i++)
for (int i = 1; i <= 10; i++)
{
std::string name = "exact_pixels_" + std::to_string(i) + "x_item";
get_object<Gtk::MenuItem>(name.c_str())->signal_activate().connect([i, this] {
@ -525,6 +516,7 @@ void Snes9xWindow::setup_splash()
return;
}
return;
for (int y = 0; y < 224; y++, screen_ptr += (GFX.Pitch / 2)) {
memset(screen_ptr, 0, 256 * sizeof(uint16));
@ -547,7 +539,7 @@ bool Snes9xWindow::draw(const Cairo::RefPtr<Cairo::Context> &cr)
setup_splash();
}
S9xDisplayRefresh(last_width, last_height);
S9xDisplayRefresh();
if (!(config->fullscreen))
{
@ -660,7 +652,7 @@ std::string Snes9xWindow::open_movie_dialog(bool readonly)
if (!readonly)
{
const char *default_name = S9xGetFilename(".smv", s9x_getdirtype::ROM_DIR);
auto default_name = S9xGetFilename(".smv", s9x_getdirtype::ROM_DIR);
dialog.set_current_name(default_name);
}
@ -784,7 +776,7 @@ void Snes9xWindow::load_state_dialog()
dialog.hide();
if (result == Gtk::RESPONSE_ACCEPT)
{
S9xLoadState(dialog.get_filename().c_str());
S9xLoadState(dialog.get_filename());
}
unpause_from_focus_change();
@ -846,7 +838,7 @@ void Snes9xWindow::save_state_dialog()
dialog.hide();
if (result == GTK_RESPONSE_ACCEPT)
S9xSaveState(dialog.get_filename().c_str());
S9xSaveState(dialog.get_filename());
unpause_from_focus_change();
}
@ -913,7 +905,7 @@ const char *markup = _(R"(<b>Information for %s</b>
char output[2048];
snprintf(output, 2048, markup,
Memory.ROMFilename,
Memory.ROMFilename.c_str(),
Memory.ROMName,
Memory.ROMSpeed,
((Memory.ROMSpeed & 0x10) != 0) ? "FastROM" : "SlowROM",
@ -1030,12 +1022,6 @@ void Snes9xWindow::reset_screensaver()
XResetScreenSaver(GDK_DISPLAY_XDISPLAY(gdk_display));
}
#endif
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_WINDOW(gdk_window))
{
// TODO screensaver for wayland
}
#endif
config->screensaver_needs_reset = false;
}
@ -1182,20 +1168,28 @@ void Snes9xWindow::enter_fullscreen_mode()
{
Display *dpy = gdk_x11_display_get_xdisplay(gdk_display);
auto xrr_screen_resources = XRRGetScreenResourcesCurrent(dpy, gdk_x11_window_get_xid(gdk_window));
auto xrr_crtc_info = XRRGetCrtcInfo(dpy,
xrr_screen_resources,
xrr_screen_resources->crtcs[0]);
gdk_display_sync(gdk_display);
if (XRRSetCrtcConfig(dpy,
config->xrr_screen_resources,
config->xrr_screen_resources->crtcs[0],
xrr_screen_resources,
xrr_screen_resources->crtcs[0],
CurrentTime,
config->xrr_crtc_info->x,
config->xrr_crtc_info->y,
config->xrr_screen_resources->modes[config->xrr_index].id,
config->xrr_crtc_info->rotation,
&config->xrr_crtc_info->outputs[0],
xrr_crtc_info->x,
xrr_crtc_info->y,
xrr_screen_resources->modes[config->xrr_index].id,
xrr_crtc_info->rotation,
&xrr_crtc_info->outputs[0],
1) != 0)
{
config->change_display_resolution = 0;
}
XRRFreeCrtcInfo(xrr_crtc_info);
XRRFreeScreenResources(xrr_screen_resources);
if (gui_config->auto_input_rate)
{
@ -1211,6 +1205,21 @@ void Snes9xWindow::enter_fullscreen_mode()
gdk_display_sync(gdk_display);
window->present();
if (config->auto_vrr)
{
autovrr_saved_frameskip = Settings.SkipFrames;
autovrr_saved_sound_input_rate = Settings.SoundInputRate;
autovrr_saved_sync_to_vblank = gui_config->sync_to_vblank;
autovrr_saved_sound_sync = Settings.SoundSync;
Settings.SoundSync = false;
Settings.SkipFrames = THROTTLE_TIMER;
Settings.SoundInputRate = 32040;
S9xUpdateDynamicRate(1, 2);
gui_config->sync_to_vblank = true;
S9xDisplayRefresh();
}
#ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_WINDOW(window->get_window()->gobj()) &&
config->default_esc_behavior != ESC_TOGGLE_MENUBAR)
@ -1223,6 +1232,7 @@ void Snes9xWindow::enter_fullscreen_mode()
config->fullscreen = 1;
config->rom_loaded = rom_loaded;
/* If we're running a game, disable ui when entering fullscreen */
if (!Settings.Paused && config->rom_loaded)
config->ui_visible = false;
@ -1237,6 +1247,16 @@ void Snes9xWindow::leave_fullscreen_mode()
if (!config->fullscreen)
return;
if (config->auto_vrr)
{
Settings.SkipFrames = autovrr_saved_frameskip;
Settings.SoundInputRate = autovrr_saved_sound_input_rate;
gui_config->sync_to_vblank = autovrr_saved_sync_to_vblank;
Settings.SoundSync = autovrr_saved_sound_sync;
S9xUpdateDynamicRate(1, 2);
S9xDisplayRefresh();
}
GdkDisplay *gdk_display = window->get_display()->gobj();
GdkWindow *gdk_window = window->get_window()->gobj();
@ -1368,6 +1388,18 @@ void Snes9xWindow::show()
});
recent_menu->show();
auto clear_recent = get_object<Gtk::MenuItem>("clear_recent_items");
clear_recent->signal_activate().connect([&] {
auto manager = Gtk::RecentManager::get_default();
auto items = manager->get_items();
for (auto &i : items)
{
auto groups = i->get_groups();
if (groups.end() != std::find_if(groups.begin(), groups.end(), [](Glib::ustring &name) -> bool { return name == "cartridge"; }))
manager->remove_item(i->get_uri());
}
});
}
}

View File

@ -89,6 +89,10 @@ class Snes9xWindow : public GtkBuilderWindow
int mouse_region_x, mouse_region_y;
int mouse_region_width, mouse_region_height;
int nfs_width, nfs_height, nfs_x, nfs_y;
int autovrr_saved_frameskip;
int autovrr_saved_sound_input_rate;
bool autovrr_saved_sync_to_vblank;
bool autovrr_saved_sound_sync;
int fullscreen_state;
int maximized_state;
bool focused;

View File

@ -5,6 +5,7 @@
\*****************************************************************************/
#include "gtk_sound_driver_sdl.h"
#include "SDL_audio.h"
#include "gtk_s9x.h"
#include "apu/apu.h"
#include "snes9x.h"
@ -31,6 +32,8 @@ void S9xSDLSoundDriver::samples_available()
mutex.lock();
buffer.push(temp, snes_samples_available);
if (Settings.DynamicRateControl)
S9xUpdateDynamicRate(buffer.space_empty(), buffer.buffer_size);
mutex.unlock();
}

View File

@ -9,73 +9,20 @@
#include "gtk_s9x.h"
#include "gtk_wayland_egl_context.h"
#include "wayland-idle-inhibit-unstable-v1.h"
static void wl_global(void *data,
struct wl_registry *wl_registry,
uint32_t name,
const char *interface,
uint32_t version)
{
WaylandEGLContext *wl = (WaylandEGLContext *)data;
if (!strcmp(interface, "wl_compositor"))
wl->compositor = (struct wl_compositor *)wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3);
else if (!strcmp(interface, "wl_subcompositor"))
wl->subcompositor = (struct wl_subcompositor *)wl_registry_bind(wl_registry, name, &wl_subcompositor_interface, 1);
else if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name))
wl->idle_inhibit_manager = (struct zwp_idle_inhibit_manager_v1 *)wl_registry_bind(wl_registry, name, &zwp_idle_inhibit_manager_v1_interface, 1);
}
static void wl_global_remove(void *data,
struct wl_registry *wl_registry,
uint32_t name)
{
}
static const struct wl_registry_listener wl_registry_listener = {
wl_global,
wl_global_remove
};
WaylandEGLContext::WaylandEGLContext()
{
display = NULL;
registry = NULL;
compositor = NULL;
subcompositor = NULL;
parent = NULL;
child = NULL;
region = NULL;
subsurface = NULL;
egl_display = NULL;
egl_surface = NULL;
egl_context = NULL;
egl_config = NULL;
egl_window = NULL;
use_sync_control = false;
ust = msc = sbc = 0;
idle_inhibit_manager = NULL;
idle_inhibitor = NULL;
x = 0;
y = 0;
}
WaylandEGLContext::~WaylandEGLContext()
{
if (idle_inhibitor)
zwp_idle_inhibitor_v1_destroy(idle_inhibitor);
if (idle_inhibit_manager)
zwp_idle_inhibit_manager_v1_destroy(idle_inhibit_manager);
if (subsurface)
wl_subsurface_destroy(subsurface);
if (region)
wl_region_destroy(region);
if (child)
wl_surface_destroy(child);
if (egl_context)
eglDestroyContext(egl_display, egl_context);
@ -93,41 +40,14 @@ bool WaylandEGLContext::attach(GtkWidget *widget)
if (!GDK_IS_WAYLAND_WINDOW(window))
return false;
gdk_window = window;
gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
display = gdk_wayland_display_get_wl_display(gdk_window_get_display(gdk_window));
parent = gdk_wayland_window_get_wl_surface(gdk_window);
registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &wl_registry_listener, this);
wl_display_roundtrip(display);
if (!compositor || !subcompositor)
return false;
child = wl_compositor_create_surface(compositor);
region = wl_compositor_create_region(compositor);
subsurface = wl_subcompositor_get_subsurface(subcompositor, child, parent);
wl_surface_set_input_region(child, region);
wl_subsurface_set_desync(subsurface);
wl_subsurface_set_position(subsurface, x, y);
if (idle_inhibit_manager && gui_config->prevent_screensaver)
{
printf("Inhibiting screensaver.\n");
zwp_idle_inhibit_manager_v1_create_inhibitor(idle_inhibit_manager, child);
}
wayland_surface = std::make_unique<WaylandSurface>();
wayland_surface->attach(widget);
return true;
}
bool WaylandEGLContext::create_context()
{
int scale = gdk_window_get_scale_factor(gdk_window);
gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
EGLint surface_attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_RED_SIZE, 8,
@ -150,10 +70,7 @@ bool WaylandEGLContext::create_context()
EGLint num_configs = 0;
if (!subsurface)
return false;
egl_display = eglGetDisplay((EGLNativeDisplayType)display);
egl_display = eglGetDisplay((EGLNativeDisplayType)wayland_surface->display);
eglInitialize(egl_display, NULL, NULL);
if (!eglChooseConfig(egl_display, surface_attribs, &egl_config, 1, &num_configs))
@ -163,7 +80,8 @@ bool WaylandEGLContext::create_context()
}
eglBindAPI(EGL_OPENGL_API);
egl_window = wl_egl_window_create(child, width * scale, height * scale);
std::tie(width, height) = wayland_surface->get_size();
egl_window = wl_egl_window_create(wayland_surface->child, width, height);
if (!egl_window)
{
printf("Couldn't create window.\n");
@ -188,52 +106,27 @@ bool WaylandEGLContext::create_context()
}
}
if (gui_config->use_sync_control && epoxy_has_egl_extension(egl_display, "EGL_CHROMIUM_sync_control"))
{
eglGetSyncValuesCHROMIUM = (PEGLGETSYNCVALUESCHROMIUM)eglGetProcAddress("eglGetSyncValuesCHROMIUM");
if (eglGetSyncValuesCHROMIUM)
use_sync_control = true;
}
wl_surface_set_buffer_scale(child, scale);
gdk_window_invalidate_rect(gdk_window, NULL, false);
return true;
}
void WaylandEGLContext::resize()
{
int scale;
gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
scale = gdk_window_get_scale_factor(gdk_window);
wl_egl_window_resize(egl_window, width * scale, height * scale, 0, 0);
wl_subsurface_set_position(subsurface, x, y);
wayland_surface->resize();
std::tie(width, height) = wayland_surface->get_size();
wl_egl_window_resize(egl_window, width, height, 0, 0);
make_current();
}
void WaylandEGLContext::swap_buffers()
{
if (use_sync_control)
eglGetSyncValuesCHROMIUM(egl_display, egl_surface, &ust, &msc, &sbc);
eglSwapBuffers(egl_display, egl_surface);
wl_surface_commit(child);
wl_surface_commit(wayland_surface->child);
}
bool WaylandEGLContext::ready()
{
if (use_sync_control)
{
EGLuint64KHR ust, msc, sbc;
eglGetSyncValuesCHROMIUM(egl_display, egl_surface, &ust, &msc, &sbc);
if (sbc != this->sbc || msc - this->msc > 2)
return true;
return false;
}
return true;
}

View File

@ -8,9 +8,11 @@
#define __GTK_WAYLAND_EGL_CONTEXT_H
#include "gtk_opengl_context.h"
#include "gtk_wayland_surface.h"
#include "gtk_compat.h"
#include <epoxy/egl.h>
#include <memory>
#include <wayland-egl.h>
class WaylandEGLContext : public OpenGLContext
@ -28,16 +30,6 @@ class WaylandEGLContext : public OpenGLContext
GdkWindow *gdk_window;
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
struct wl_subcompositor *subcompositor;
struct wl_surface *parent;
struct wl_surface *child;
struct wl_subsurface *subsurface;
struct wl_region *region;
EGLDisplay egl_display;
EGLSurface egl_surface;
EGLContext egl_context;
@ -45,13 +37,7 @@ class WaylandEGLContext : public OpenGLContext
wl_egl_window *egl_window;
typedef EGLBoolean (*PEGLGETSYNCVALUESCHROMIUM)(EGLDisplay, EGLSurface, EGLuint64KHR *, EGLuint64KHR *, EGLuint64KHR *);
PEGLGETSYNCVALUESCHROMIUM eglGetSyncValuesCHROMIUM;
bool use_sync_control;
EGLuint64KHR ust, msc, sbc;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
std::unique_ptr<WaylandSurface> wayland_surface;
};
#endif

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